Home > database >  How to reference System Assigned Identity in Bicep when deploying Key Vault Access Policy
How to reference System Assigned Identity in Bicep when deploying Key Vault Access Policy

Time:08-15

For a project I want to deploy three related resources to Azure through Bicep templates: 1) App Service with System Assigned Managed Identity, 2) Key Vault and 3) Access policy for the App Service (step 1) to the Key Vault (step 2).

The AppService deployment outputs the principalId of the System Assigned Identity which is then later on used when deploying the KeyVaultAccessPolicy.

However, when I run the AZ CLI (az deployment sub create --location WestEurope --template-file ./main.bicep --parameters ./parameters/parameters-dev.json) to deploy this to Azure I get the following error:

'The language expression property 'outputs' doesn't exist, available properties are 'templateHash, parameters, mode, provisioningState, timestamp, duration, correlationId, providers, dependencies, outputResources'.

Does anyone have an idea why referencing the principalId of the App Service does not work here? Many thanks for any help.

Modules and main.bicep:

main.bicep

module appService 'modules/appService.bicep' = {
  name:  'deployAppService'
  scope: resourceGroup(appServiceResourceGroup)
  params: {
    name: appServiceName
    location: appServiceLocation
    alwaysOn: appServiceAlwaysOn
    apimIpAddress: appServiceApimIpAddress
    appServicePlanResourceGroup: appServicePlanResourceGroup
    appServicePlanName: appServicePlanName
  }
}

module keyVault 'modules/keyVault.bicep' = {
  name: 'deployKeyVault'
  scope: resourceGroup(appServiceResourceGroup)
  params: {
    name: keyVaultName
    dependsOn: [ appService ]
    location: appServiceLocation
  }
}

module keyVaultAccessPolicy 'modules/keyVaultAccessPolicy.bicep' = {
  name: 'deployKeyVaultAccessPolicy'
  scope: resourceGroup(appServiceResourceGroup)
  params: {
    name: '${appServiceName}-ap'
    dependsOn: [ keyVault ]
    objectId: appService.outputs.appServiceManagedIdentity
  }
}

appService.bicep

resource appService 'Microsoft.Web/sites@2020-12-01' = {
  name: name
  location: location
  kind: 'app'
  identity: {
    type: 'SystemAssigned'
  }
  properties: {
    serverFarmId: '${subscription().id}/resourceGroups/${appServicePlanResourceGroup}/providers/Microsoft.Web/serverfarms/${appServicePlanName}'
    enabled: true
  }
}

output appServiceManagedIdentity string = appService.identity.principalId

keyVault.bicep

resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = {
  name: name
  location: location
  dependsOn: dependsOn
  properties: {
    enabledForDeployment: true
    enabledForTemplateDeployment: true
    enabledForDiskEncryption: true
    tenantId: subscription().tenantId
    accessPolicies: []
    sku: {
      name: 'standard'
      family: 'A'
    }
  }
}

keyVaultAccessPolicy.bicep

resource keyVaultAccessPolicy 'Microsoft.KeyVault/vaults/accessPolicies@2022-07-01' = {
  name: name
  dependsOn: dependsOn
  properties: {
    accessPolicies: [
      {
        tenantId: subscription().tenantId
        objectId: objectId
        permissions: {
          secrets: [
            'get'
          ]
        }
      }
    ]
  }
}

CodePudding user response:

Already found the answer:

  1. I missed that modules already contain an dependsOn property and so there is no need to pass the dependencies as param.
  2. The KeyVaultAccessPolicy's name did not contain a reference to the parent resource (KeyVault), see name: '${keyVaultName}/add' below

See working modules and main.bicep below:

main.bicep

module appService 'modules/appService.bicep' = {
  name:  'deployAppService'
  scope: resourceGroup(appServiceResourceGroup)
  params: {
    name: appServiceName
    location: appServiceLocation
    alwaysOn: appServiceAlwaysOn
    apimIpAddress: appServiceApimIpAddress
    appServicePlanResourceGroup: appServicePlanResourceGroup
    appServicePlanName: appServicePlanName
  }
}

module keyVault 'modules/keyVault.bicep' = {
  scope: resourceGroup(appServiceResourceGroup)
  name: 'keyVaultDeploy'
  params: {
    location: appServiceLocation
    name: keyVaultName
  }
}

module keyVaultAccessPolicy 'modules/keyVaultAccessPolicy.bicep' = {
  scope: resourceGroup(appServiceResourceGroup)
  name: 'keyVaultAccessPolicyDeploy'
  dependsOn: [
    keyVault
  ]
  params: {
    keyVaultName: keyVaultName
    objectId: appService.outputs.appServiceManagedIdentity
  }
}

appService.bicep

resource appService 'Microsoft.Web/sites@2020-12-01' = {
  name: name
  location: location
  kind: 'app'
  identity: {
    type: 'SystemAssigned'
  }
  properties: {
    // left out 
  }
}

output appServiceManagedIdentity string = appService.identity.principalId

keyVault.bicep

resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = {
  name: name
  location: location
  properties: {
    enabledForDeployment: true
    enabledForTemplateDeployment: true
    enabledForDiskEncryption: true
    tenantId: subscription().tenantId
    accessPolicies: []
    sku: {
      name: 'standard'
      family: 'A'
    }
  }
}

keyVaultAccessPolicy.bicep

resource keyVaultAccessPolicy 'Microsoft.KeyVault/vaults/accessPolicies@2022-07-01' = {
  name: '${keyVaultName}/add'
  properties: {
    accessPolicies: [
      {
        tenantId: subscription().tenantId
        objectId: objectId
        permissions: {
          secrets: [
            'get'
          ]
        }
      }
    ]
  }
}
  • Related