Search code examples
azureazure-resource-managerazure-keyvaultazure-bicep

Assign ManagedID to KeyVault Access Policy


I have a bicep template that creates 2 webApps and a KeyVault. Each WebApp is created with a managedID which I need to add to Keyvault so the webapp can pull in the secrets.

But when creating 2 webapps, I can't work out how to assign both ManagedIDs to KeyVault.

The bicep template is using modules

  name: 'ciKeyVault'
  params: {
    keyVaultName: keyVaultName
    aclBypass: keyVaultSettings.aclBypass
    aclDefaultAction: keyVaultSettings.aclDefaultAction
    enabledForDeployment: keyVaultSettings.enabledForDeployment
    enabledForDiskEncryption: keyVaultSettings.enabledForDiskEncryption
    enabledForTemplateDeployment: keyVaultSettings.enabledForTemplateDeployment
    keyPermissions: keyVaultSettings.keyPermissions
    keyVaultSettings: keyVaultSettings
    secretsPermissions: keyVaultSettings.secretsPermissions
    skuFamily: keyVaultSettings.skuFamily
    skuName: keyVaultSettings.skuName
    tenantId: subscription().tenantId
    objectId: 'b71e61c4-7cff-41d0-8370-a7d9c01dde84'
  }
}

and the objectId needs to be retrieved from the AppService Deployment. using this module:

module AppService '../../../Modules/Azure.App.Service.template.bicep' = [for i in range(0, length(webAppSettings.webApps)): { 
  name: webAppSettings.webApps[i].Name
  dependsOn: [
    frontEndAppServicePlan
  ]
  params: {
    webAppName: webAppSettings.webApps[i].appServiceType == 'functionApp' ? toLower('fnc-${webAppSettings.webApps[i].name}-${resourceGroupNameSuffix}') : toLower('web-${webAppSettings.webApps[i].name}-${resourceGroupNameSuffix}')
    hostingPlan:  frontEndAppServicePlan.outputs.hostingPlanId
    virtualNetworkResourceGroup: virtualNetworkResourceGroup
    environmentName:environmentName
    webAppSettings:webAppSettings
    appServiceType: webAppSettings.webApps[i].appServiceType
    LinuxFX:webAppSettings.webApps[i].LinuxFX
    appSettings:webAppSettings.webapps[i].appSettings
  }
}]

Its fine when its a single appService cause I can reference the ID using output usid string = AppServices.identity.principalId

but when I have 2 appServices I can't work out how to pass in both IDs

Any ideas?

Cheers


Solution

  • Let's say you have a module Azure.App.Service.template.bicep that looks like that:

    param webAppName string
    ...
    
    // Create the web app
    resource webApp 'Microsoft.Web/sites@2020-09-01' = {
      name: webAppName
      location: resourceGroup().location
      identity: {
        type: 'SystemAssigned'
      }
      ...
    }
    
    output usid string = webApp.identity.principalId 
    

    In the parent template you can create an array of module to create your webapps (the same way you are doing it) and then create an access policies resource to grant access to key vault to all the web apps.

    ...
    // Create the app services
    module AppServices '../../../Modules/Azure.App.Service.template.bicep' = [for webApp in webAppSettings.webApps: {
      name: webApp.Name
      params: {
        webAppName: webApp.Name
        ...
      }
    }]
    
    resource keyVault 'Microsoft.KeyVault/vaults/accessPolicies@2019-09-01' existing = {
      name: keyVaultName
    }
    
    // Granting the app services access ot key vault
    resource appServicesKeyVaultAccessPolicies 'Microsoft.KeyVault/vaults/accessPolicies@2019-09-01' = {
      name: 'add'
      parent: keyVault
      properties: {
        accessPolicies: [for i in range(0, length(webAppSettings.webApps)): {
          tenantId: subscription().tenantId
          objectId: AppServices[i].outputs.usid
          permissions: {
            secrets: keyVaultSettings.secretsPermissions
            keys: keyVaultSettings.keyPermissions
          }
        }]
      }
    }