Martin Wickman
Martin Wickman

Reputation: 19925

How do I use Bicep (or ARM) to create a MS Entra app registration and roles?

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.

Upvotes: 18

Views: 15822

Answers (2)

Thomas
Thomas

Reputation: 29736

This is now possible using the Microsoft Graph Resource Provider (see documentation).

  1. You would need to install or upgrade latest bicep version.
  2. As per may 2024, this feature is in plublic preview so you would need ot configure experimentation feature. Create/update 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'
      ]
    }
  ]
}

Upvotes: 6

Ansuman Bal
Ansuman Bal

Reputation: 11451

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

Upvotes: 16

Related Questions