Search code examples
azureazure-resource-managerazure-keyvaultazure-bicepazure-container-apps

Add certificate from Azure Keyvault to Azure Container Environment with Bicep


I need a mechanism to download a .pfx certificate from Keyvault and to then upload it to an Azure Container Environment, all via Bicep. This will minimise any manual intervention when the certificate is updated.

I am currently adding a certificate to my Azure Container Environment using the base64 encoded value I manually converted using powershell. As follows:

resource certificate 'Microsoft.App/managedEnvironments/certificates@2022-06-01-preview' = {
  parent: env
  location: location
  name: 'ta-cert'
  properties: {
    password: certificatePassword
    value: '<base64>'
  }
}

What I would like to try and achieve is to download the pfx file from Keyvault and convert to base64 (maybe by using a powershell command embedded in bicep) all within the Bicep file, which can then be used in the code above.

If anyone has done this before would be really grateful to see the implementation.


Solution

  • If your certificate is stored as a certificate in key vault, it is already base64 encoded and accessible as a key vault secret (see Composition of a Certificate).

    You can use the bicep getSecret function to pass the certificate to the container app environment:

    containerapp-env-certificate.bicep module:

    param containerAppEnvName string
    param location string = resourceGroup().location
    param certificateName string
    
    @secure()
    param certificateValue string
    
    resource containerAppEnv 'Microsoft.App/managedEnvironments@2022-03-01' existing = {
      name: containerAppEnvName
    }
    
    resource certificate 'Microsoft.App/managedEnvironments/certificates@2022-06-01-preview' = {
      parent: containerAppEnv
      location: location
      name: certificateName
      properties: {
        // Dont need password here
        value: certificateValue
      }
    }
    

    From your main.bicep template, you can invoke it like that:

    param containerAppEnvName string
    param location string = resourceGroup().location
    
    param keyVaultName string
    param keyVaultCertificateName string
    
    // Get a reference to key vault
    resource keyVault 'Microsoft.KeyVault/vaults@2019-09-01' existing = {
      name: keyVaultName
    }
    
    module certificate 'containerapp-env-certificate.bicep' = {
      name: 'containerapp-env-certificate'
      params: {
        containerAppEnvName: containerAppEnvName
        certificateName: 'ta-cert'
        location: location
        // Get the certificate as a base64 secret
        certificateValue: keyVault.getSecret(keyVaultCertificateName)    
      }
    }