<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="https://www.w3.org/2005/Atom" xmlns:sy="https://purl.org/rss/1.0/modules/syndication/" xmlns:dc="https://purl.org/dc/elements/1.1/" xmlns:content="https://purl.org/rss/1.0/modules/content/" xmlns:wfw="https://wellformedweb.org/CommentAPI/" xmlns:slash="https://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>Exception &lt; Code</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/ankitsharma/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/ankitsharma/feed.xml</link>
    <description>keep trying…</description>
    <lastBuildDate>Wed, 17 Apr 2019 03:48:21 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Azure AD - Working across tenants using PowerShell</title>
      <link>https://docs.microsoft.com/archive/blogs/ankitsharma/azure-ad-working-across-tenants-using-powershell</link>
      <pubDate>Fri, 25 Aug 2017 13:29:09 GMT</pubDate>
      <dc:creator><![CDATA[aforank]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/ankitsharma/?p=205</guid>
      <description><![CDATA[Working across various tenants programmatically in Azure AD could be relatively complex. Before even...]]></description>
      <content:encoded><![CDATA[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.

<strong>Azure AD application and service principal.</strong>
<ol>
 	<li>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.</li>
 	<li>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.</li>
 	<li>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.</li>
 	<li>For detailed information I recommend you to read this <a href="https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-application-objects">Application and service principal objects in Azure Active Directory (Azure AD)</a></li>
</ol>
<strong>Types of scenarios for working across tenants</strong>
<ol>
 	<li>Azure Resource Management (ARM) - CRUD operations over Resource Groups and resources inside it.</li>
 	<li>Azure AD Management - CRUD operations over users, groups, permissions etc.</li>
</ol>
Regardless of the scenarios, you would like to work with; there are a few standard, one time steps required to achieve the desired.

<strong>Step 1 : Create an Azure AD application</strong>
<ol>
 	<li>Create an Azure AD application in your home tenant, and set the Multi-tenant property to true. This is how it should look.
<p style="margin-left: 27pt"><img src="https://msdnshared.blob.core.windows.net/media/2017/08/129.png" alt="" /></p>
</li>
 	<li>
<p style="margin-left: 27pt">Generate a key from the keys tab, and keep it safe with yourself<img src="https://msdnshared.blob.core.windows.net/media/2017/08/216.png" alt="" /></p>
</li>
 	<li>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.
<p style="margin-left: 27pt"><img src="https://msdnshared.blob.core.windows.net/media/2017/08/321.png" alt="" /></p>
</li>
 	<li>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.</li>
</ol>
<strong>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.</strong>
<div>
<table style="border-collapse: collapse" border="0"><colgroup> <col style="width: 137px" /> <col style="width: 224px" /> <col style="width: 256px" /> <col style="width: 317px" /></colgroup>
<tbody valign="top">
<tr>
<td style="border: solid #a3a3a3 1.0pt;padding: 7px">Operation</td>
<td style="border-top: solid #a3a3a3 1.0pt;border-left: none;border-bottom: solid #a3a3a3 1.0pt;border-right: solid #a3a3a3 1.0pt;padding: 7px">Azure AD CmdLet</td>
<td style="border-top: solid #a3a3a3 1.0pt;border-left: none;border-bottom: solid #a3a3a3 1.0pt;border-right: solid #a3a3a3 1.0pt;padding: 7px">ARM CmdLet</td>
<td style="border-top: solid #a3a3a3 1.0pt;border-left: none;border-bottom: solid #a3a3a3 1.0pt;border-right: solid #a3a3a3 1.0pt;padding: 7px">Comments</td>
</tr>
<tr>
<td style="border-top: none;border-left: solid #a3a3a3 1.0pt;border-bottom: solid #a3a3a3 1.0pt;border-right: solid #a3a3a3 1.0pt;padding: 7px">Login</td>
<td style="border-top: none;border-left: none;border-bottom: solid #a3a3a3 1.0pt;border-right: solid #a3a3a3 1.0pt;padding: 7px">Connect-AzureAD -TenantId $tenantId</td>
<td style="border-top: none;border-left: none;border-bottom: solid #a3a3a3 1.0pt;border-right: solid #a3a3a3 1.0pt;padding: 7px">Login-AzureRmAccount TenantId $tenantId</td>
<td style="border-top: none;border-left: none;border-bottom: solid #a3a3a3 1.0pt;border-right: solid #a3a3a3 1.0pt;padding: 7px">Use administrator account to login.

Do NOT specify the tenant where you have registered the application in above step 1.</td>
</tr>
<tr>
<td style="border-top: none;border-left: solid #a3a3a3 1.0pt;border-bottom: solid #a3a3a3 1.0pt;border-right: solid #a3a3a3 1.0pt;padding: 7px">Service Principal Creation</td>
<td style="border-top: none;border-left: none;border-bottom: solid #a3a3a3 1.0pt;border-right: solid #a3a3a3 1.0pt;padding: 7px">New-AzureADServicePrincipal -AppId $ApplicationId</td>
<td style="border-top: none;border-left: none;border-bottom: solid #a3a3a3 1.0pt;border-right: solid #a3a3a3 1.0pt;padding: 7px">New-AzureRmADServicePrincipal -ApplicationId $ApplicationId</td>
<td style="border-top: none;border-left: none;border-bottom: solid #a3a3a3 1.0pt;border-right: solid #a3a3a3 1.0pt;padding: 7px">Use the application id which you got from step 1.

Please note of the object id of service principal</td>
</tr>
<tr>
<td style="border-top: none;border-left: solid #a3a3a3 1.0pt;border-bottom: solid #a3a3a3 1.0pt;border-right: solid #a3a3a3 1.0pt;padding: 7px">Re-Check</td>
<td style="border-top: none;border-left: none;border-bottom: solid #a3a3a3 1.0pt;border-right: solid #a3a3a3 1.0pt;padding: 7px">GetAzureADServicePrincipal</td>
<td style="border-top: none;border-left: none;border-bottom: solid #a3a3a3 1.0pt;border-right: solid #a3a3a3 1.0pt;padding: 7px">Get-AzureRmADServicePrincipal</td>
<td style="border-top: none;border-left: none;border-bottom: solid #a3a3a3 1.0pt;border-right: solid #a3a3a3 1.0pt;padding: 7px">Use this command to confirm if service principal is created or not.</td>
</tr>
</tbody>
</table>
</div>
Note: For AzureAD CmdLets, install module by typing command "Install-Module AzureAD"

<strong>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. </strong>
<div>
<table style="border-collapse: collapse" border="0"><colgroup> <col style="width: 83px" /> <col style="width: 179px" /> <col style="width: 224px" /> <col style="width: 441px" /></colgroup>
<tbody valign="top">
<tr>
<td style="border: solid #a3a3a3 1.0pt;padding: 7px"></td>
<td style="border-top: solid #a3a3a3 1.0pt;border-left: none;border-bottom: solid #a3a3a3 1.0pt;border-right: solid #a3a3a3 1.0pt;padding: 7px">AD Role Permissions</td>
<td style="border-top: solid #a3a3a3 1.0pt;border-left: none;border-bottom: solid #a3a3a3 1.0pt;border-right: solid #a3a3a3 1.0pt;padding: 7px">Resource/Subscription Role Permissions</td>
<td style="border-top: solid #a3a3a3 1.0pt;border-left: none;border-bottom: solid #a3a3a3 1.0pt;border-right: solid #a3a3a3 1.0pt;padding: 7px">Comments</td>
</tr>
<tr>
<td style="border-top: none;border-left: solid #a3a3a3 1.0pt;border-bottom: solid #a3a3a3 1.0pt;border-right: solid #a3a3a3 1.0pt;padding: 7px">Example</td>
<td style="border-top: none;border-left: none;border-bottom: solid #a3a3a3 1.0pt;border-right: solid #a3a3a3 1.0pt;padding: 7px">Read directory data

Read and write directory data

Read all users' basic profiles

And soon</td>
<td style="border-top: none;border-left: none;border-bottom: solid #a3a3a3 1.0pt;border-right: solid #a3a3a3 1.0pt;padding: 7px">Owner

Contributer

Reader

And soon</td>
<td style="border-top: none;border-left: none;border-bottom: solid #a3a3a3 1.0pt;border-right: solid #a3a3a3 1.0pt;padding: 7px">For full list of AD Permission see this <a href="https://msdn.microsoft.com/en-us/library/azure/ad/graph/howto/azure-ad-graph-api-permission-scopes">Permission scopes | Graph API concepts </a>

For full list of Resource permissions see this <a href="https://docs.microsoft.com/en-us/azure/active-directory/role-based-access-built-in-roles">Built-in roles for Azure role-based access control</a></td>
</tr>
</tbody>
</table>
</div>
<ol>
 	<li><strong>Assign AD Role Permissions</strong>
<ul>
 	<li>Use Connect-AzureAD module</li>
 	<li>Run Get-AzureADDirectoryRoleTemplate
<img src="https://msdnshared.blob.core.windows.net/media/2017/08/413.png" alt="" /></li>
 	<li>
<div>Pick the object id of the any role and run below command. (Like Directory Readers)</div>
<p style="margin-left: 27pt">Enable-AzureADDirectoryRole -RoleTemplateId 88d8e3e3-8f55-4a1e-953a-9b9898b8876b</p>
</li>
 	<li>
<div>To confirm if it has been enabled run Get-AzureADDirectoryRole</div>
<img src="https://msdnshared.blob.core.windows.net/media/2017/08/59.png" alt="" /></li>
 	<li>
<div>Assign enabled role to our newly created service principal</div>
<p style="margin-left: 27pt">Add-AzureADDirectoryRoleMember -ObjectId a000f74e-6c3a-48bf-9d12-da2ed552ac62 -RefObjectId $servicePrincipalObjectId</p>
</li>
 	<li>
<div>To confirm assignment run</div>
<p style="margin-left: 27pt">Get-AzureADServicePrincipalMembership -ObjectId $servicePrincipalObjectId</p>
</li>
</ul>
</li>
 	<li><strong>Assign Resource/Subscription Permission</strong>
<ul>
 	<li>Use ARM CmdLets</li>
 	<li>New-AzureRmRoleAssignment -ServicePrincipalName $servicePrincipalObjectId -RoleDefinitionName Owner -Scope [Subscription/ResourceGroup]</li>
</ul>
</li>
</ol>
<strong>Step 4: Login with the service principal. Please note we do NOT have to use the objectid of the service principal. AppId will suffice.</strong>
<ol>
 	<li><strong>Using ARM CmdLet for accessing Subscription/Resources</strong>
<ul>
 	<li>$secpasswd = ConvertTo-SecureString $GeneratedKeyFromStep1 -AsPlainText -Force</li>
 	<li>
<div>$mycreds = New-Object System.Management.Automation.PSCredential ($AppIdGeneratedFromStep1, $secpasswd)</div></li>
 	<li>
<div>Login-AzureRmAccount -ServicePrincipal -Tenant $TenantOnWhichServicePrincipalWasCreatedInStep2 -Credential $mycreds</div></li>
 	<li>After successful login use any appropriate cmdlet to access the resources like Get-AzureRmResource</li>
</ul>
</li>
 	<li><strong>Using AzureAD CmdLets for accessing directory data</strong>
<ul>
 	<li>
<div>Get access token</div>
$AuthenticationResult = Invoke-RestMethod -Uri <a href="https://login.microsoftonline.com/$TenantId/oauth2/token?api-version=1.0">https://login.microsoftonline.com/$TenantId/oauth2/token?api-version=1.0</a> -Method Post -Body @{"grant_type" = "client_credentials"; "resource" = <a href="https://graph.windows.net">https://graph.windows.net</a>; "client_id" = $AppIdGeneratedFromStep1; "client_secret" =$GeneratedKeyFromStep1}</li>
 	<li>
<div>Connect-AzureAD -TenantId $TenantOnWhichServicePrincipalWasCreatedInStep2 -AadAccessToken $AuthenticationResult.access_token -AccountId $AppIdGeneratedFromStep1</div></li>
 	<li>After successful login use any appropriate cmdlet to access the directory like Get-AzureADUser</li>
</ul>
</li>
</ol>
<strong>Possible Errors</strong>
<ol>
 	<li>
<div>You will get below error if you try to log in on another tenant before creating a service principal</div>
<img src="https://msdnshared.blob.core.windows.net/media/2017/08/68.png" alt="" /></li>
 	<li>
<div>You will get the below error if you try to run any command before assigning the permissions</div>
<img src="https://msdnshared.blob.core.windows.net/media/2017/08/77.png" alt="" /></li>
</ol>
Feel free to ask any questions in the comments below. I will happy to answer :)

This article is also published on my personal blog <a href="https://www.exceptionlesscode.com/azure-ad-working-across-tenants-using-powershell/">https://www.exceptionlesscode.com/azure-ad-working-across-tenants-using-powershell/</a>]]></content:encoded>
    </item>
  </channel>
</rss>