Meteen naar de inhoud

Creating App Registration with ARM templates/Bicep

  • door
Creating App Registration with ARM templates/Bicep

At the time of writing there is no Azure Resource Manager (ARM) template that can create an app registration for your applications. This might be the missing piece to automating your whole infrastructure. This article will go through how you can automate the creation of app registrations using deployment scripts.

User assigned managed identity

First thing we need to do is to create a user assigned managed identity that will be used by our deployment script. Managed identities are used in Azure by your applications to obtain Azure AD tokens to access resources such as Azure Key Vault. There are a couple of ways to do this, but we’ll be using Azure Command-Line Interface. Use the following commands to create a resource group and a managed identity.

# Resource group for the managed identity
az group create --name app-reg-automation --location northeurope# User assigned managed identity
az identity create -g app-reg-automation -n AppRegCreator

Role assignment

Second step is to allow the newly created managed identity to create app registration. The simplest way is to assign the ‘Application administrator’ role to it. This role allows users to create and manage app registrations in your Azure Active Directory. Use the following command to assign the role.

az rest --method POST --uri 'https://graph.microsoft.com/beta/roleManagement/directory/roleAssignments' --body '{"principalId": "<Id of the managed identity>", "roleDefinitionId": "9b895d92-2cd3-44c7-9d02-a6ac2d5ea5c3"}'

The Script

Last step is the bicep deployment script file. Let’s start by designing our script. There are two kinds of deployment scripts Powershell and Azure CLI/bash. I’ll be creating a Powershell script since I use it day to day.

Graph API access token

We’ll need to retrieve an access token to interact with the Microsoft Graph API. This can be done using the Get-AzAccessToken function from Az.Accounts Powershell module. Next we’ll extract the token from the functions output and construct our HTTP header that we’ll use for all of our requests.

$token = (Get-AzAccessToken -ResourceUrl https://graph.microsoft.com).Token$headers = @{'Content-Type' = 'application/json'; 'Authorization' = 'Bearer ' + $token}

Upsert App registration

Using the header we can now create and update our app registration. Let’s first create an app registration template object that will be used to create and update app registrations.

$template = @{
displayName = $resourceName
requiredResourceAccess = @(
@{
resourceAppId = "00000003-0000-0000-c000-000000000000"
resourceAccess = @(
@{
id = "e1fe6dd8-ba31-4d61-89e7-88639da4683d"
type = "Scope"
}
)
}
)
signInAudience = "AzureADMyOrg"
}

Next up is creating or updating app registrations. We’ll start by checking whether the app registration exists and based on the outcome we update or create the app registration. We’ll also create a service principal for the app registrations If we are creating a new one.

$app = (Invoke-RestMethod -Method Get -Headers $headers -Uri "https://graph.microsoft.com/beta/applications?filter=displayName eq '$($resourceName)'").value
$principal = @{}if ($app) {
$ignore = Invoke-RestMethod -Method Patch -Headers $headers -Uri "https://graph.microsoft.com/beta/applications/$($app.id)" -Body ($template | ConvertTo-Json -Depth 10)
$principal = (Invoke-RestMethod -Method Get -Headers $headers -Uri "https://graph.microsoft.com/beta/servicePrincipals?filter=appId eq '$($app.appId)'").value
} else {
$app = (Invoke-RestMethod -Method Post -Headers $headers -Uri "https://graph.microsoft.com/beta/applications" -Body ($template | ConvertTo-Json -Depth 10))
$principal = Invoke-RestMethod -Method POST -Headers $headers -Uri "https://graph.microsoft.com/beta/servicePrincipals" -Body (@{ "appId" = $app.appId } | ConvertTo-Json)
}

Creating client secrets

To allow our application to authenticate itself we’ll need to create a client secret. The following code will delete existing secrets and create a new one.

// Creating client secret$app = (Invoke-RestMethod -Method Get -Headers $headers -Uri "https://graph.microsoft.com/beta/applications/$($app.id)")foreach ($password in $app.passwordCredentials) {
$body = @{
"keyId" = $password.keyId
}
$ignore = Invoke-RestMethod -Method POST -Headers $headers -Uri "https://graph.microsoft.com/beta/applications/$($app.id)/removePassword" -Body ($body | ConvertTo-Json)
}$body = @{
"passwordCredential" = @{
"displayName"= "Client Secret"
}
}$secret = (Invoke-RestMethod -Method POST -Headers $headers -Uri "https://graph.microsoft.com/beta/applications/$($app.id)/addPassword" -Body ($body | ConvertTo-Json)).secretText

Script output

Last step in the script is to output the client id and client secret. This is done so that the intended application resource can use it to authenticate itself. Additionally, the client id can be used to grant the application access to Azure resources, such as giving the application access to an Azure Key Vault.

$DeploymentScriptOutputs = @{}    $DeploymentScriptOutputs['objectId'] = $app.id
$DeploymentScriptOutputs['clientId'] = $app.appId
$DeploymentScriptOutputs['clientSecret'] = $secret
$DeploymentScriptOutputs['principalId'] = $principal.id

Putting it all together

In the identity section we specify the previously created user assigned managed identity.https://reginbald.medium.com/media/0a2085cfc85155c894ee1c8767b30917

Conclusion

This journey started when I discovered the limitation that Azure Container Instances within a VNET can’t use system assigned managed identities. I think this is a simple approach to generating app registrations and can be called with any of your resource deployments that need an app registration.

Hope this short article helps you get started automating app registrations. 🎈 Let me know if there is something I can do to improve the article or script