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.

  1. 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.
  2. 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.
  3. 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.
  4. 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

  1. Azure Resource Management (ARM) - CRUD operations over Resource Groups and resources inside it.
  2. 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

  1. Create an Azure AD application in your home tenant, and set the Multi-tenant property to true. This is how it should look.

  2. Generate a key from the keys tab, and keep it safe with yourself

  3. 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.

  4. 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 data

Read and write directory data

Read all users' basic profiles

And soon

Owner

Contributer

Reader

And 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

  1. 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

  2. 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.

  1. 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
  2. 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

  1. You will get below error if you try to log in on another tenant before creating a service principal

  2. 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 http://www.exceptionlesscode.com/azure-ad-working-across-tenants-using-powershell/

Comments (0)

Skip to main content