I'm using Terraform to create app registration and roles for our apps. But I cannot figure out how to do the same with Bicep. This is what's used today:
Step 1. Register the app in Active Directory, effectively creating an "app registration".
resource "azuread_application" "ad_app" {
name = local.full_app_name
type = "webapp/api"
owners = var.app_owners
}
Step 2: Create a role for our app
resource "azuread_application_app_role" "person_read" {
application_object_id = azuread_application.ad_app.id
allowed_member_types = ["Application"]
description = "Person Reader can search and read persons"
display_name = "Person Reader"
value = "Persons.Read"
}
Problem is I cannot figure out how to do those steps with Bicep (or ARM templates). I tried with 'Microsoft.Authorization/roleDefinitions', but it doesn't seem right. And I have no idea about how to do the app registration.
Unfortunately both are not directly supported in ARM template or Bicep. But You can use Deployment Scripts to create both using Bicep/ARM template.
Create Azure AD App registration using Bicep:
param name string
param location string = resourceGroup().location
param currentTime string = utcNow()
resource script 'Microsoft.Resources/deploymentScripts@2019-10-01-preview' = {
name: name
location: location
kind: 'AzurePowerShell'
identity: {
type: 'UserAssigned'
userAssignedIdentities: {
'${resourceId('app-reg-automation', 'Microsoft.ManagedIdentity/userAssignedIdentities', 'AppRegCreator')}': {}
}
}
properties: {
azPowerShellVersion: '5.0'
arguments: '-resourceName "${name}"'
scriptContent: '''
param([string] $resourceName)
$token = (Get-AzAccessToken -ResourceUrl https://graph.microsoft.com).Token
$headers = @{'Content-Type' = 'application/json'; 'Authorization' = 'Bearer ' + $token}
$template = @{
displayName = $resourceName
requiredResourceAccess = @(
@{
resourceAppId = "00000003-0000-0000-c000-000000000000"
resourceAccess = @(
@{
id = "e1fe6dd8-ba31-4d61-89e7-88639da4683d"
type = "Scope"
}
)
}
)
signInAudience = "AzureADMyOrg"
}
// Upsert App registration
$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 secret
$app = (Invoke-RestMethod -Method Get -Headers $headers -Uri "https://graph.microsoft.com/beta/applications/$($app.id)")
foreach ($password in $app.passwordCredentials) {
Write-Host "Deleting secret with id: $($password.keyId)"
$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
$DeploymentScriptOutputs = @{}
$DeploymentScriptOutputs['objectId'] = $app.id
$DeploymentScriptOutputs['clientId'] = $app.appId
$DeploymentScriptOutputs['clientSecret'] = $secret
$DeploymentScriptOutputs['principalId'] = $principal.id
// create app role
'''
cleanupPreference: 'OnSuccess'
retentionInterval: 'P1D'
forceUpdateTag: currentTime // ensures script will run every time
}
}
output objectId string = script.properties.outputs.objectId
output clientId string = script.properties.outputs.clientId
output clientSecret string = script.properties.outputs.clientSecret
output principalId string = script.properties.outputs.principalId
Reference:
Creating App Registration with ARM templates/Bicep | by Jon Reginbald
Creating a App Roles for Azure AD application:
I don't have much idea on this but I guess you can use the below script where //create app role is written in the above code:
$app = (Invoke-RestMethod -Method Get -Headers $headers -Uri "https://graph.microsoft.com/beta/applications/$($app.id)")
$body1 = @{
Id = [Guid]::NewGuid().ToString()
IsEnabled = true
AllowedMemberTypes =@("application")
Description = "My Role Description.."
DisplayName = "My Custom Role"
Value = "MyCustomRole"
}
$createapprole= Invoke-RestMethod -Method POST -Headers $headers -Uri "https://graph.microsoft.com/beta/applications/$($app.id)/appRoles" -Body ($body1 | ConvertTo-Json)
Reference:
appRole resource type
Update application
This is now possible using the Microsoft Graph Resource Provider (see documentation).
bicepconfig.json config file:{
"experimentalFeaturesEnabled": {
"extensibility": true
}
}
Then you can create an application and app roles like this:
extension microsoftGraph
resource application 'Microsoft.Graph/applications@beta' = {
displayName: 'My fisrt application'
uniqueName: 'my-uniquename'
appRoles: [
{
id: guid('my-uniquename', 'Persons.Read') // need unique guid with same value foir each deployment
isEnabled: true
displayName: 'Person Reader'
description: 'Person Reader can search and read persons'
value: 'Persons.Read'
allowedMemberTypes: [
'Application'
]
}
]
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With