Azure Verified Modules
Glossary GitHub GitHub Issues Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

Last updated: 11 Dec 2024

Bicep Interfaces

Legacy content

The content on this website has been deprecated and will be removed in the future.

Please refer to the new documentation under the Bicep Interfaces chapter for the most up-to-date information.

This page details the Bicep-specific interfaces/schemas for AVM Resource Modules features/extension resources.


Secrets export

Secrets used inside a module can be exported to a Key Vault reference provided as per the below schema. This implementation provides a secure way around the current limitation of Bicep on providing a secure template output (that can be used for secrets).

The user must

  • provide the resource Id to a Key Vault. The principal used for the deployment must be allowed to set secrets in this Key Vault.
  • provide a name for each secret they want to store (opt-in). The module will suggest which secrets are available via the implemented user-defined type.

The module returns an output table where the key is the name of the secret the user provided, and the value contains both the secret’s resource Id and URI.

The feature must be implemented as per the below schema. Diversions are only allowed in places marked as >text< to ensure a consistent user experience across modules.

  // ============== //
  //   Parameters   //
  // ============== //
  
  @description('Optional. Key vault reference and secret settings for the module\'s secrets export.')
  param secretsExportConfiguration secretsExportConfigurationType?
  
  // ============= //
  //   Resources   //
  // ============= //
  
  module secretsExport 'modules/keyVaultExport.bicep' = if (secretsExportConfiguration != null) {
    name: '${uniqueString(deployment().name, location)}-secrets-kv'
    scope: resourceGroup(
      split((secretsExportConfiguration.?keyVaultResourceId ?? '//'), '/')[2],
      split((secretsExportConfiguration.?keyVaultResourceId ?? '////'), '/')[4]
    )
    params: {
      keyVaultName: last(split(secretsExportConfiguration.?keyVaultResourceId ?? '//', '/'))
      secretsToSet: union(
        [],
        contains(secretsExportConfiguration!, '>secretToExport1<Name')
          ? [
              {
                name: secretsExportConfiguration!.>secretToExport1<Name
                value: >secretReference1< // e.g., >singularMainResourceType<.listKeys().primaryMasterKey
              }
            ]
          : [],
        contains(secretsExportConfiguration!, '>secretToExport2<Name')
          ? [
              {
                name: secretsExportConfiguration!.>secretToExport2<Name
                value:>secretReference2<  // e.g., >singularMainResourceType<.listKeys().secondaryMasterKey
              }
            ]
          : []
          // (...)
      )
    }
  }
  
  // =========== //
  //   Outputs   //
  // =========== //
  
  import { secretsOutputType } from 'br/public:avm/utl/types/avm-common-types:>version<'
  @description('A hashtable of references to the secrets exported to the provided Key Vault. The key of each reference is each secret\'s name.')
  output exportedSecrets secretsOutputType = (secretsExportConfiguration != null)
    ? toObject(secretsExport.outputs.secretsSet, secret => last(split(secret.secretResourceId, '/')), secret => secret)
    : {}
  
  // =============== //
  //   Definitions   //
  // =============== //
  
  @export()
  type secretsExportConfigurationType = {
    @description('Required. The resource ID of the key vault where to store the secrets of this module.')
    keyVaultResourceId: string
  
    @description('Optional. The >secretToExport1< secret name to create.')
    >secretToExport1<Name: string?
  
    @description('Optional. The >secretToExport2< secret name to create.')
    >secretToExport2<Name: string?
  
    // (...)
  }
  
secretsExportConfiguration: {
    keyVaultResourceId: '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.KeyVault/vaults/{keyVaultName}'
    >secretToExport1<Name: 'myPrimarySecret'
    >secretToExport2<Name: 'mySecondarySecret'
    // (...)
  }
  

  // ============== //
  //   Parameters   //
  // ============== //
  
  @description('Required. The name of the Key Vault to set the secrets in.')
  param keyVaultName string
  
  import { secretToSetType } from 'br/public:avm/utl/types/avm-common-types:>version<'
  @description('Required. The secrets to set in the Key Vault.')
  param secretsToSet secretToSetType[]
  
  // ============= //
  //   Resources   //
  // ============= //
  
  resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' existing = {
    name: keyVaultName
  }
  
  resource secrets 'Microsoft.KeyVault/vaults/secrets@2023-07-01' = [
    for secret in secretsToSet: {
      name: secret.name
      parent: keyVault
      properties: {
        value: secret.value
      }
    }
  ]
  
  // =========== //
  //   Outputs   //
  // =========== //
  
  import { secretSetOutputType } from 'br/public:avm/utl/types/avm-common-types:>version<'
  @description('The references to the secrets exported to the provided Key Vault.')
  output secretsSet secretSetOutputType[] = [
    #disable-next-line outputs-should-not-contain-secrets // Only returning the references, not a secret value
    for index in range(0, length(secretsToSet ?? [])): {
      secretResourceId: secrets[index].id
      secretUri: secrets[index].properties.secretUri
      secretUriWithVersion: secrets[index].properties.secretUriWithVersion
    }
  ]
  

When using a module that implements the above interface, you can access its outputs for example in the following ways:


  // Get all exported secret references
  output exportedSecrets object = >deploymentReference<.outputs.exportedSecrets
  
  // Get the resource Id of just the secret with name >secretToExport1<Name
  output specificSecret string = >deploymentReference<.outputs.exportedSecrets.>secretToExport1<Name.secretResourceId
  
  // Get the resource Ids of all secrets set
  output exportedSecretResourceIds array = map(
    items(>deploymentReference<.outputs.exportedSecrets),
    item => item.value.secretResourceId
  )
  

Which returns a JSON-formatted output like