Developments in Digital
Developments in Digital

Assigning Azure Blueprints with Microsoft Graph

In order to assign a blueprint, you can follow the instructions provided by the official Microsoft docs.

However, one of the steps required is to give the Azure Blueprint service principal Owner rights on the subscription to which you are assigning the blueprint.

The article mentions the use of the Azure AD Graph API, however this has now been replaced with Microsoft Graph.

The steps therefore to assign a blueprint, are the following:

  1. Register an application that has permission to read directory information.
  2. Generate an access token using the registered app and the client credentials flow
  3. Use the access token to call the Microsoft Graph API to get the id of the Azure Blueprint service principal within a tenant
  4. Give the Azure Blueprint service principal Owner rights on the subscription
  5. Assign the blueprint to the subscription

Register an Application

  1. Go to the Azure portal
  2. Select Azure Active Directory -> App Registrations -> New Application Registration
  3. Give the application a name
  4. Select Web app / API as the application type
  5. Enter e.g. http://localhost as the sign-on URL
  6. Select Create

Give the Application Permissions

  1. Select the application under Azure Active Directory -> App Registrations
  2. Select Settings
  3. Select Required permissions
  4. Select Add -> Select an API -> Microsoft Graph
  5. Under Select Permissions choose Read directory data

Generate an Access Token

To generate an access token, you need the following information:

  1. Domain tenant (Azure Active Directory -> Custom Domains -> primary domain, e.g. foo.onmicrosoft.com)
  2. Client id (Azure Active Directory -> App Registrations -> Select app -> Application Id)
  3. Client secret (Azure Active Directory -> App Registrations -> Select app -> Settings -> Keys - Enter key name -> Select duration (e.g. 1 year) -> Save)

With these pieces of information, you can generate an access token for the Microsoft Graph resource using the client credentials flow in PowerShell:

function Get-ClientCredentialsAccessToken {
    param(
        [Parameter(Mandatory = $true)] [string] $TenantDomain,
        [Parameter(Mandatory = $true)] [string] $ClientId,
        [Parameter(Mandatory = $true)] [string] $ClientSecret
    )

    $loginURL = "https://login.microsoft.com"

    $body = @{
        grant_type    = "client_credentials";
        resource      = "https://graph.microsoft.com";
        client_id     = $ClientId;
        client_secret = $ClientSecret
    }

    $oauth = Invoke-RestMethod -Method Post -Uri $loginURL/$TenantDomain/oauth2/token?api-version=1.0 -Body $body

    return $oauth.access_token
}

Get the Azure Blueprint Service Principal Id

With the access token, you can now call the Microsoft Graph API to get the id of the Azure Blueprint service principal within your tenant.

The Azure Blueprint service principal has a known application id of f71766dc-90d9-4b7d-bd9d-4499c4331c3f. However, the service principal id varies for each tenant, so we can use the Microsoft Graph API to get the service principal filtered by known app id:

$uri = "https://graph.microsoft.com/beta/servicePrincipals?`$filter=appId eq 'f71766dc-90d9-4b7d-bd9d-4499c4331c3f'"

The id returned in the response will be the service principal id. We can then use New-AzureRmRoleAssignment to assign the service principal Owner rights on the subscription:

function Set-AzureBlueprintSubscriptionOwnerRights {
    param(
        [Parameter(Mandatory = $true)][string] $AccessToken,
        [Parameter(Mandatory = $true)][string] $SubscriptionId
    )

    $uri = "https://graph.microsoft.com/beta/servicePrincipals?`$filter=appId eq 'f71766dc-90d9-4b7d-bd9d-4499c4331c3f'"

    $headers = @{
        'Content-Type'  = 'application/json'
        'Authorization' = 'Bearer ' + $AccessToken
    }

    $response = Invoke-RestMethod -Uri $uri -Method Get -Headers $headers
    $bluePrintServicePrincipal = $response.value

    $subScope = "/subscriptions/$SubscriptionId"
    New-AzureRmRoleAssignment -Scope $subScope -RoleDefinitionName "Owner" -ObjectId $bluePrintServicePrincipal.id
}

The blueprint can now be assigned to the subscription, using the assignment process documented in the official Microsoft docs.