Azure / arm-ttk

Azure Resource Manager Template Toolkit
https://aka.ms/arm-ttk
MIT License
441 stars 188 forks source link

extensionResourceId from Bicep flagged in ARM-TTK #765

Open chgeuer opened 7 months ago

chgeuer commented 7 months ago

Bicep generates code which gets rejected by ARM-TTK; unclear how to work around that.

In a Bicep template, I'm using the getSecret function to fetch a secret from an existing KeyVault, to get KeyVault access, and pass it as parameter to a nested template:

resource publisherKeyVaultWithBootstrapSecret 'Microsoft.KeyVault/vaults@2023-07-01' existing = {
  name: meteringConfiguration.publisherVault.vaultName
  scope: resourceGroup(meteringConfiguration.publisherVault.publisherSubscription, meteringConfiguration.publisherVault.vaultResourceGroupName)
}

module setupMeteredBillingConfigurationModule './nestedtemplates/meteredBillingDependencies.bicep' = {
  name: '...'
  params: {
    bootstrapSecretValue: publisherKeyVaultWithBootstrapSecret.getSecret(meteringConfiguration.publisherVault.bootstrapSecretName)
  }
}

When Bicep compiles this, it results in the following ARM template, which uses the extensionResourceId function to reference the KeyVault:

"parameters": {
 "bootstrapSecretValue": {
    "reference": {
        "keyVault": {
           "id": "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('meteringConfiguration').publisherVault.publisherSubscription, variables('meteringConfiguration').publisherVault.vaultResourceGroupName), 'Microsoft.KeyVault/vaults', variables('meteringConfiguration').publisherVault.vaultName)]"
        },
        "secretName": "[variables('meteringConfiguration').publisherVault.bootstrapSecretName]"
    }
 }

Unfortunately, this Bicep-generated code is flagged by ARM-TTK validation tool as not OK, because it calls concat() or format() within extensionResourceId(). This regex in ARM TTK flags it as an error:

https://github.com/Azure/arm-ttk/blob/master/arm-ttk/testcases/deploymentTemplate/ResourceIds-should-not-contain.test.ps1#L31

As a workaround, I can replace

extensionResourceId(
    format('/subscriptions/{0}/resourceGroups/{1}', 
        variables('meteringConfiguration').publisherVault.publisherSubscription, 
        variables('meteringConfiguration').publisherVault.vaultResourceGroupName
    ), 
    'Microsoft.KeyVault/vaults', 
    variables('meteringConfiguration').publisherVault.vaultName
)

with


resourceId(
    variables('meteringConfiguration').publisherVault.publisherSubscription, 
    variables('meteringConfiguration').publisherVault.vaultResourceGroupName, 
    'Microsoft.KeyVault/vaults', 
    variables('meteringConfiguration').publisherVault.vaultName
)

So in JSON:

{
    "old": "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('meteringConfiguration').publisherVault.publisherSubscription, parameters('meteringConfiguration').publisherVault.vaultResourceGroupName), 'Microsoft.KeyVault/vaults', parameters('meteringConfiguration').publisherVault.vaultName)]"

    "new": "[resourceId(variables('meteringConfiguration').publisherVault.publisherSubscription, variables('meteringConfiguration').publisherVault.vaultResourceGroupName, 'Microsoft.KeyVault/vaults', variables('meteringConfiguration').publisherVault.vaultName)]"
}