|
| 1 | +--- |
| 2 | +title: Monitor delegation changes in your managing tenant |
| 3 | +description: Learn how to monitor delegation activity from customer tenants to your managing tenant. |
| 4 | +ms.date: 03/16/2020 |
| 5 | +ms.topic: conceptual |
| 6 | +--- |
| 7 | + |
| 8 | +# Monitor delegation changes in your managing tenant |
| 9 | + |
| 10 | +As a service provider, you may want to be aware when customer subscriptions or resource groups are delegated to your tenant through [Azure delegated resource management](../concepts/azure-delegated-resource-management.md), or when previously delegated resources are removed. |
| 11 | + |
| 12 | +In the managing tenant, the [Azure activity log](../../azure-monitor/platform/platform-logs-overview.md) tracks delegation activity at the tenant level. This logged activity includes any added or removed delegations from all customer tenants. |
| 13 | + |
| 14 | +This topic explains the permissions needed to monitor delegation activity to your tenant (across all of your customers) and the best practices for doing so. It also includes a sample script that shows one method for querying and reporting on this data. |
| 15 | + |
| 16 | +> [!IMPORTANT] |
| 17 | +> All of these steps must be performed in your managing tenant, rather than in any customer tenants. |
| 18 | +
|
| 19 | +## Enable access to tenant-level data |
| 20 | + |
| 21 | +To access tenant-level Activity Log data, an account must be assigned the [Monitoring Reader](../../role-based-access-control/built-in-roles.md#monitoring-reader) built-in role at root scope (/). This assignment must be performed by a user who has the Global Administrator role with additional elevated access. |
| 22 | + |
| 23 | +### Elevate access for a Global Administrator account |
| 24 | + |
| 25 | +To assign a role at root scope (/), you will need to have the Global Administrator role with elevated access. This elevated access should be added only when you need to make the role assignment, then removed when you are done. |
| 26 | + |
| 27 | +For detailed instructions on adding and removing elevation, see [Elevate access to manage all Azure subscriptions and management groups](../../role-based-access-control/elevate-access-global-admin.md). |
| 28 | + |
| 29 | +After you elevate your access, your account will have the User Access Administrator role in Azure at root scope. This role assignment allows you to view all resources and assign access in any subscription or management group in the directory, as well as to make role assignments at root scope. |
| 30 | + |
| 31 | +### Create a new service principal account to access tenant-level data |
| 32 | + |
| 33 | +Once you have elevated your access, you can assign the appropriate permissions to an account so that it can query tenant-level activity log data. This account will need to have the [Monitoring Reader](../../role-based-access-control/built-in-roles.md#monitoring-reader) built-in role assigned at the root scope of your managing tenant. |
| 34 | + |
| 35 | +> [!IMPORTANT] |
| 36 | +> Granting a role assignment at root scope means that the same permissions will apply to every resource in the tenant. |
| 37 | +
|
| 38 | +Because this is a broad level of access, we recommend that you assign this role to a service principal account, rather than to an individual user or to a group. Additionally, we recommend the following best practices: |
| 39 | + |
| 40 | +- [Create a new service principal account](../../active-directory/develop/howto-create-service-principal-portal.md) to be used only for this function, rather than assigning this role to an existing service principal used for other automation. |
| 41 | +- Be sure that this service principal does not have access to any delegated customer resources. |
| 42 | +- [Use a certificate to authenticate](../../active-directory/develop/howto-create-service-principal-portal.md#certificates-and-secrets) and [store it securely in Azure Key Vault](../../key-vault/key-vault-best-practices.md). |
| 43 | +- Limit the users who have access to act on behalf of the service principal. |
| 44 | + |
| 45 | +Use one of the following methods to make the root scope assignments. |
| 46 | + |
| 47 | +#### PowerShell |
| 48 | + |
| 49 | +```azurepowershell-interactive |
| 50 | +# Log in first with Connect-AzAccount if you're not using Cloud Shell |
| 51 | +
|
| 52 | +New-AzRoleAssignment -SignInName <yourLoginName> -Scope "/" -RoleDefinitionName "Monitoring Reader" -ApplicationId $servicePrincipal.ApplicationId |
| 53 | +``` |
| 54 | + |
| 55 | +#### Azure CLI |
| 56 | + |
| 57 | +```azurecli-interactive |
| 58 | +# Log in first with az login if you're not using Cloud Shell |
| 59 | +
|
| 60 | +az role assignment create --assignee 00000000-0000-0000-0000-000000000000 --role "Monitoring Reader" --scope "/" |
| 61 | +``` |
| 62 | + |
| 63 | +### Remove elevated access for the Global Administrator account |
| 64 | + |
| 65 | +After you've created your service principal account and assigned the Monitoring Reader role at root scope, be sure to [remove the elevated access](../../role-based-access-control/elevate-access-global-admin.md#remove-elevated-access) for the Global Administrator account, as this level of access will no longer be needed. |
| 66 | + |
| 67 | +## Query the activity log |
| 68 | + |
| 69 | +Once you've created a new service principal account with Monitoring Reader access to the root scope of your managing tenant, you can use it to query and report on delegation activity in your tenant. |
| 70 | + |
| 71 | +The sample below uses Azure PowerShell to query the past 1 day of activity and reports on any added or removed delegations (or attempts that were not successful). It queries the [Tenant Activity Log](https://docs.microsoft.com/rest/api/monitor/TenantActivityLogs/List) data, then constructs the following values to report on delegations that are added or removed: |
| 72 | + |
| 73 | +- **DelegatedResourceId**: The ID of the delegated subscription or resource group |
| 74 | +- **CustomerTenantId**: The customer tenant ID |
| 75 | +- **CustomerSubscriptionId**: The subscription ID that was delegated or that contains the resource group that was delegated |
| 76 | +- **CustomerDelegationStatus**: The status change for the delegated resource (succeeded or failed) |
| 77 | +- **EventTimeStamp**: The date and time at which the delegation change was logged |
| 78 | + |
| 79 | +When querying this data, keep in mind: |
| 80 | + |
| 81 | +- If multiple resource groups are delegated in a single deployment, separate entries will be returned for each resource group. |
| 82 | +- Changes made to a previous delegation (such as updating the permission structure) will be logged as an added delegation. |
| 83 | +- As noted above, an account must have the Monitoring Reader built-in role at root scope (/) in order to access this tenant-level data. |
| 84 | +- You can use this data in your own workflows and reporting. For example, you can use the [HTTP Data Collector API (public preview)](../../azure-monitor/platform/data-collector-api.md) to log data to Azure Monitor from a REST API client, then use [action groups](../../azure-monitor/platform/action-groups.md) to create notifications or alerts. |
| 85 | + |
| 86 | +```azurepowershell-interactive |
| 87 | +# Log in first with Connect-AzAccount if you're not using Cloud Shell |
| 88 | +
|
| 89 | +# Azure Lighthouse: Query Tenant Activity Log for registered/unregistered delegations for the past 1 day |
| 90 | +
|
| 91 | +$GetDate = (Get-Date).AddDays((-1)) |
| 92 | +
|
| 93 | +$dateFormatForQuery = $GetDate.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ") |
| 94 | +
|
| 95 | +# Getting Azure context for the API call |
| 96 | +$currentContext = Get-AzContext |
| 97 | +
|
| 98 | +# Fetching new token |
| 99 | +$azureRmProfile = [Microsoft.Azure.Commands.Common.Authentication.Abstractions.AzureRmProfileProvider]::Instance.Profile |
| 100 | +$profileClient = [Microsoft.Azure.Commands.ResourceManager.Common.RMProfileClient]::new($azureRmProfile) |
| 101 | +$token = $profileClient.AcquireAccessToken($currentContext.Tenant.Id) |
| 102 | +
|
| 103 | +$listOperations = @{ |
| 104 | + Uri = "https://management.azure.com/providers/microsoft.insights/eventtypes/management/values?api-version=2015-04-01&`$filter=eventTimestamp ge '$($dateFormatForQuery)'" |
| 105 | + Headers = @{ |
| 106 | + Authorization = "Bearer $($token.AccessToken)" |
| 107 | + 'Content-Type' = 'application/json' |
| 108 | + } |
| 109 | + Method = 'GET' |
| 110 | +} |
| 111 | +$list = Invoke-RestMethod @listOperations |
| 112 | +$showOperations = $list.value |
| 113 | +
|
| 114 | +if ($showOperations.operationName.value -eq "Microsoft.Resources/tenants/register/action") |
| 115 | +{ |
| 116 | + $registerOutputs = $showOperations | Where-Object -FilterScript {$_.eventName.value -eq "EndRequest" -and $_.resourceType.value -and $_.operationName.value -eq "Microsoft.Resources/tenants/register/action"} |
| 117 | + foreach ($registerOutput in $registerOutputs) |
| 118 | + { |
| 119 | + $registerOutputdata = [pscustomobject]@{ |
| 120 | + Event = "An Azure customer has delegated resources to your tenant"; |
| 121 | + DelegatedResourceId = $registerOutput.description |%{$_.split('"')[11]}; |
| 122 | + CustomerTenantId = $registerOutput.description |%{$_.split('"')[7]}; |
| 123 | + CustomerSubscriptionId = $registerOutput.subscriptionId; |
| 124 | + CustomerDelegationStatus = $registerOutput.status.value; |
| 125 | + EventTimeStamp = $registerOutput.eventTimestamp; |
| 126 | + } |
| 127 | + $registerOutputdata | Format-List |
| 128 | + } |
| 129 | +} |
| 130 | +if ($showOperations.operationName.value -eq "Microsoft.Resources/tenants/unregister/action") |
| 131 | +{ |
| 132 | + $unregisterOutputs = $showOperations | Where-Object -FilterScript {$_.eventName.value -eq "EndRequest" -and $_.resourceType.value -and $_.operationName.value -eq "Microsoft.Resources/tenants/unregister/action"} |
| 133 | + foreach ($unregisterOutput in $unregisterOutputs) |
| 134 | + { |
| 135 | + $unregisterOutputdata = [pscustomobject]@{ |
| 136 | + Event = "An Azure customer has removed delegated resources from your tenant"; |
| 137 | + DelegatedResourceId = $unregisterOutput.description |%{$_.split('"')[11]}; |
| 138 | + CustomerTenantId = $unregisterOutput.description |%{$_.split('"')[7]}; |
| 139 | + CustomerSubscriptionId = $unregisterOutput.subscriptionId; |
| 140 | + CustomerDelegationStatus = $unregisterOutput.status.value; |
| 141 | + EventTimeStamp = $unregisterOutput.eventTimestamp; |
| 142 | + } |
| 143 | + $unregisterOutputdata | Format-List |
| 144 | + } |
| 145 | +} |
| 146 | +else |
| 147 | +{ |
| 148 | + Write-Output "No new delegation changes." |
| 149 | +} |
| 150 | +
|
| 151 | +
|
| 152 | +``` |
| 153 | + |
| 154 | +## Next steps |
| 155 | + |
| 156 | +- Learn how to onboard customers to [Azure delegated resource management](../concepts/azure-delegated-resource-management.md). |
| 157 | +- Learn about [Azure Monitor](../../azure-monitor/index.yml) and the [Azure activity log](../../azure-monitor/platform/platform-logs-overview.md). |
0 commit comments