Azure AD - Working across tenants using PowerShell
Working across various tenants programmatically in Azure AD could be relatively complex. Before even writing a script to do such operations, one must be very clear about a few concepts about Azure AD.
Azure AD application and service principal.
- An Azure AD application is defined by its one and only application object which resides in the Azure AD tenant where the application was registered.
- A Service Principal is an instance of an application that is within your Active Directory that is allowed access to one or more resources. The service principal object defines the policy and permissions for an application's use in a specific tenant.
- Consider the application object as the global representation of your application for use across all tenants, and the service principal as the local representation for use in a specific tenant.
- For detailed information I recommend you to read this Application and service principal objects in Azure Active Directory (Azure AD)
Types of scenarios for working across tenants
- Azure Resource Management (ARM) - CRUD operations over Resource Groups and resources inside it.
- Azure AD Management - CRUD operations over users, groups, permissions etc.
Regardless of the scenarios, you would like to work with; there are a few standard, one time steps required to achieve the desired.
Step 1 : Create an Azure AD application
Create an Azure AD application in your home tenant, and set the Multi-tenant property to true. This is how it should look.
Generate a key from the keys tab, and keep it safe with yourself
Set required permissions (Only if you would like to go with the second scenario i.e., Azure AD Management). In my case, I would like my application to read all users in the Active Directory.
When you register an application in Azure Portal, two objects are created: an application object, and a service principal object, in the tenant where you have registered the application.
Step 2: Create service principal in other tenants (As of now this could be done only through Powershell) However, there are two tales of PowerShell CmdLets as shown below to achieve the same.
Operation | Azure AD CmdLet | ARM CmdLet | Comments |
Login | Connect-AzureAD -TenantId $tenantId | Login-AzureRmAccount TenantId $tenantId | Use administrator account to login.Do NOT specify the tenant where you have registered the application in above step 1. |
Service Principal Creation | New-AzureADServicePrincipal -AppId $ApplicationId | New-AzureRmADServicePrincipal -ApplicationId $ApplicationId | Use the application id which you got from step 1.Please note of the object id of service principal |
Re-Check | GetAzureADServicePrincipal | Get-AzureRmADServicePrincipal | Use this command to confirm if service principal is created or not. |
Note: For AzureAD CmdLets, install module by typing command "Install-Module AzureAD"
Step 3: Assigning required permissions to your new service principal; For better understanding, I would say there are two kinds of permissions: Resource/Subscription role permissions and AD role permissions. Both have different significance and CmdLets.
AD Role Permissions | Resource/Subscription Role Permissions | Comments | |
Example | Read directory dataRead and write directory dataRead all users' basic profilesAnd soon | OwnerContributerReaderAnd soon | For full list of AD Permission see this Permission scopes | Graph API concepts For full list of Resource permissions see this Built-in roles for Azure role-based access control |
- Assign AD Role Permissions
Use Connect-AzureAD module
Run Get-AzureADDirectoryRoleTemplate
Pick the object id of the any role and run below command. (Like Directory Readers)
Enable-AzureADDirectoryRole -RoleTemplateId 88d8e3e3-8f55-4a1e-953a-9b9898b8876b
To confirm if it has been enabled run Get-AzureADDirectoryRole
Assign enabled role to our newly created service principal
Add-AzureADDirectoryRoleMember -ObjectId a000f74e-6c3a-48bf-9d12-da2ed552ac62 -RefObjectId $servicePrincipalObjectId
To confirm assignment run
Get-AzureADServicePrincipalMembership -ObjectId $servicePrincipalObjectId
- Assign Resource/Subscription Permission
- Use ARM CmdLets
- New-AzureRmRoleAssignment -ServicePrincipalName $servicePrincipalObjectId -RoleDefinitionName Owner -Scope [Subscription/ResourceGroup]
Step 4: Login with the service principal. Please note we do NOT have to use the objectid of the service principal. AppId will suffice.
- Using ARM CmdLet for accessing Subscription/Resources
- $secpasswd = ConvertTo-SecureString $GeneratedKeyFromStep1 -AsPlainText -Force
- $mycreds = New-Object System.Management.Automation.PSCredential ($AppIdGeneratedFromStep1, $secpasswd)
- Login-AzureRmAccount -ServicePrincipal -Tenant $TenantOnWhichServicePrincipalWasCreatedInStep2 -Credential $mycreds
- After successful login use any appropriate cmdlet to access the resources like Get-AzureRmResource
- Using AzureAD CmdLets for accessing directory data
Get access token
$AuthenticationResult = Invoke-RestMethod -Uri https://login.microsoftonline.com/$TenantId/oauth2/token?api-version=1.0 -Method Post -Body @{"grant_type" = "client_credentials"; "resource" = https://graph.windows.net; "client_id" = $AppIdGeneratedFromStep1; "client_secret" =$GeneratedKeyFromStep1}
Connect-AzureAD -TenantId $TenantOnWhichServicePrincipalWasCreatedInStep2 -AadAccessToken $AuthenticationResult.access_token -AccountId $AppIdGeneratedFromStep1
After successful login use any appropriate cmdlet to access the directory like Get-AzureADUser
Possible Errors
- You will get below error if you try to log in on another tenant before creating a service principal
- You will get the below error if you try to run any command before assigning the permissions
Feel free to ask any questions in the comments below. I will happy to answer :)
This article is also published on my personal blog https://www.exceptionlesscode.com/azure-ad-working-across-tenants-using-powershell/
Comments
- Anonymous
March 05, 2018
This step:Assign Resource/Subscription PermissionUse ARM CmdLetsNew-AzureRmRoleAssignment -ServicePrincipalName $servicePrincipalObjectId -RoleDefinitionName Owner -Scope [Subscription/ResourceGroup]is really unclear if I am using Azure AD powershell instead of ARM. Also, what would the resource be in this example?- Anonymous
March 05, 2018
The comment has been removed
- Anonymous