How to deploy NamedValues from KeyVault in APIm using Bicep

Introduction

I recently had a bit of a … run in … with deploying Named Values in APIm. These values are connected to a keyvault. This is a very good strategy for keeping keys and passwords centralized and secret. I have done this before, but was trying to use Bicep this time, but in doing so I got an error.

The error

This is the error: Can not find Managed Identity with provided IdentityClientId : <Principal ID goes here>

What I was trying to do

I was trying to add the Named Value and KeyVault connection using this bicep:

resource ApimNamedValue 'Microsoft.ApiManagement/service/namedValues@2021-04-01-preview' =  {
  parent: ApimInstance
  name: 'BackEndAPIKey'
  properties: {
    displayName: 'BackEndAPIKey'
    secret: true
    keyVault:{
      secretIdentifier: '${MyKeyVault.properties.vaultUri}secrets/BackEndAPIKey'
      identityClientId: APIminstance.identity.principalId
    }
  }
}

resource ApimInstance 'Microsoft.ApiManagement/service@2021-04-01-preview' existing ={
  name: 'ApimInstanceName'
}

resource MyKeyVault 'Microsoft.KeyVault/vaults@2019-09-01'  existing = {
  scope: resourceGroup(KeyVaultRGName)
  name: keyVaultName
}

I am using “references” to existing instances of a KeyVault (row 19) and an APIm (row 15).
There is just one thing wrong with it: You cannot suppliy the ClientID by submitting the PrincipalID (sometimes also called ObjectID). That is what triggers the error.

The solution

I got the solution directly from Adrian Hall (thank you).
It is down to a misunderstanding of the documentation. You are supposed to supply a ClientID if you want to use another identity than the APIm identity. If you want to use the identity of the APIm you are trying to deploy a named value for: Simply omit the property.

TLDR; remove row 9 from the Bicep code above and everything will work.

Just a short thing about access

To get the APIm instance to read values from the KeyVault, you need to add it to your Access Policies for the KeyVault. You can achieve this by adding the following Bicep code to your deployment.

// APIm reference
resource APIminstance 'Microsoft.ApiManagement/service@2021-04-01-preview' existing = {
  name: 'APImInstanceName'
  scope: resourceGroup('APImRGName')
}

// Keyvault config
resource MyKeyvault 'Microsoft.KeyVault/vaults@2021-06-01-preview' existing = {
  name: 'KeyVaultName'
}

resource KeyVaultSetting 'Microsoft.KeyVault/vaults/accessPolicies@2021-06-01-preview' = {
  name: 'add'
  parent: MyKeyvault
  properties: {
    accessPolicies: [
      {
        objectId: APIminstance.identity.principalId
        tenantId: APIminstance.identity.tenantId
        permissions: {
          'keys': []
          'secrets': [
            'list'
            'get'
          ]
          'certificates': []
        }
      }
    ]
  }
}