skip to Main Content

I feel like I’m stuck in a catch 22 with how Microsoft has implemented this functionality in the Container App templates. The issue, it seems to me, is that is actually validates the secret access as part of the template deploment… which creates the issue of the Managed Identity (system) not actually yet existing since the app hasn’t been created, thus no way to assign that identity RBAC to the Keyvault, thus validation failes.

Am I missing something here, or is the process really going to require 2 templates… 1 with no secret references, just to "create" the thing, and then a second to actually properly configure it now that the managed identity is availabe?

The following field(s) are either invalid or missing. Field 'configuration.secrets' is invalid with details: 'Invalid value: "mysecret-name": 
Unable to get value using Managed identity system for secret mysecret-name. Error: unable to fetch secret 'mysecret-name' using Managed identity 'system'';.
"configuration": {
  "secrets": [
    {
      "name": "mysecret-name",
      "keyVaultUrl": "[concat('https://',variables('vaultname'),'.vault.azure.net/secrets/mysecret')]",
      "identity": "system"
    }
  ]
}

2

Answers


  1. Using a user-assigned managed identity will solve your problem:

    1. Create a user-assigned managed identity.
    2. Grant KV secrets read permission to the identity.
    3. Create the container app.

    Using Bicep, that would look like that:

    key vault role assignment module:

    // key-vault-role-assignment.bicep
    param keyVaultName string
    param principalId string
    param principalType string = 'ServicePrincipal'
    param roleIds array
    
    resource keyVault 'Microsoft.KeyVault/vaults@2023-02-01' existing = {
      name: keyVaultName
    }
    
    resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for roleId in roleIds: {
      name: guid(subscription().subscriptionId, resourceGroup().name, keyVaultName, roleId, principalId)
      scope: keyVault
      properties: {
        roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleId)
        principalId: principalId
        principalType: principalType
      }
    }]
    

    and your main template:

    // main.bicep
    param location string = resourceGroup().location
    param identityName string
    param keyVaultName string
    param containerAppEnvName string
    param containerAppName string
    
    // Create the identity
    resource identity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = {
      name: identityName
      location: location
    }
    
    // Grant KV RBAC to the identity
    module kvRbac 'key-vault-role-assignment.bicep' = {
     name: '${identityName}-${keyVaultName}-rbac'
     params: {
      keyVaultName: keyVaultName
      principalId: identity.properties.principalId
      roleIds: [ '4633458b-17de-408a-b874-0445c86b69e6' ] // Key vault secret user
     }
    }
    
    // Create the container app env
    resource containerAppEnv 'Microsoft.App/managedEnvironments@2023-05-01' = {
      name: containerAppEnvName
      ...
    }
    
    // Create the container app and assigned the identity
    resource containerApp 'Microsoft.App/containerApps@2023-05-01' = {
      name: containerAppName
      location: location
      dependsOn: [
        kvRbac
      ]
      identity: {
        type: 'UserAssigned'
        userAssignedIdentities: {
          '${identity.id}': {}
        }
      }
      properties: {
        environmentId: containerAppEnv.id
        workloadProfileName: 'Consumption'
        configuration: {
          ...
          secrets: [
            {
              name: 'applicationinsights-connection-string'
              keyVaultUrl: 'https://${keyVaultName}${environment().suffixes.keyvaultDns}/secrets/mysecret'
              identity: identity.id
            }
          ]
        }
        ...
      }
    }
    

    Az CLI / Az Powershell supports natively bicep but you could always generate the related ARM template using az bicep build:

    az bicep build --file main.bicep
    
    Login or Signup to reply.
  2. One alternative is to do a nested deployment with the principalID as output to the main/master template, but i guess then yes, you do need "two" templates

    ex:

    output  webAppMSI string = webApp.identity.principalId
    

    or use bicep modules, here is a good sample:

    https://blog.johnfolberth.com/chicken-and-the-egg-how-to-handle-bicep-interdependencies/

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search