bicep icon indicating copy to clipboard operation
bicep copied to clipboard

Cant create a KeyVault and use its getSecret method in the same template

Open ernestoak opened this issue 1 year ago • 15 comments

Bicep version run bicep --version via the Bicep CLI, az bicep version via the AZ CLI or via VS code by navigating to the extensions tab and searching for Bicep

Describe the bug

  • On issue 9175 of this repo, @alex-frankel mentions that you can (indeed) use an existing keyVault with the existing keyword to retreive a secret and pass it onto a module.
  • It is also possible to deploy a keyVault without using it, and later add the resources that require the secret from the keyVault
  • The problem is when you want to create a keyVault and use it on the same deployment

To Reproduce The main.bicep file looks like this:

//1. Generate a secret (used initially)
@secure()
param initialSecret string = newGuid()
param tenantId string = subscription().tenantId
param location string = resourceGroup().location
//2. Key Vault
resource KeyVault 'Microsoft.KeyVault/vaults@2019-09-01' = {
  name: 'example'
  location: location
  properties: {
    enabledForDeployment: true
    enabledForTemplateDeployment: true
    enabledForDiskEncryption: true
    tenantId: tenantId
    sku: {
      name: 'standard'
      family: 'A'
    }
  }
}
resource secret 'Microsoft.KeyVault/vaults/secrets@2022-07-01' = {
  name: 'secret'
  parent: KeyVault
  properties: {
    contentType: 'text/plain'
    attributes: {
      enabled: true
    }
    value: initialSecret
  }
}

//3. USE THE SECRET
module example 'example.bicep' = {
  name: 'example'
  params: {
    secret: KeyVault.getSecret('secret')
  }
}

The dummy module saved in example.bicep looks like this:

@secure()
param secret string

Execute using CLI

az deployment group create -g xxxxxxxxxx -f ./main.bicep

Result is:

{"code": "KeyVaultParameterReferenceNotFound", "message": "The specified KeyVault '/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/xxxxxxxxxx/providers/Microsoft.KeyVault/vaults/example' could not be found. Please see https://aka.ms/arm-keyvault for usage details."}

Additional context The obvious workarounds are either:

  • Comment out the module that uses the getSecret, deploy, then uncomment and re-deploy
  • Separate the keyVault and secrets, deploy separately. Then in the main.bicep file import the keyVault using the existing keyword

The problem of the workarounds are:

  • Two step deployment and dependency managed OUTSIDE the code. This is confusing and annoying.
  • Deletion of the keyVault when using --mode Complete. I.e. you ideally want to manage all creations and deletions in one place

ernestoak avatar Apr 28 '23 13:04 ernestoak

@ernestoak If you redeploy the template (with no changes) after seeing the KeyVaultParameterReferenceNotFound error, does the deployment succeed? I suspect this may be a consistency issue with Key Vault (that might be solved either by the Key Vault service or with something like #1013).

jeskew avatar Apr 28 '23 17:04 jeskew

I think this is also related to #7402. My guess is we are calling key vault for the .getSecret() function at the start of the deployment.

alex-frankel avatar May 01 '23 21:05 alex-frankel

@ernestoak If you redeploy the template (with no changes) after seeing the KeyVaultParameterReferenceNotFound error, does the deployment succeed? I suspect this may be a consistency issue with Key Vault (that might be solved either by the Key Vault service or with something like #1013).

No, the deployment fails. If it helps, it also fails when using the --confirm-with-what-if flag and with the complete mode

Screenshot 2023-05-02 131451

ernestoak avatar May 02 '23 12:05 ernestoak

I think this is also related to #7402. My guess is we are calling key vault for the .getSecret() function at the start of the deployment.

This would make sense to me as even if you are explicitly declaring the dependencies with dependsOn it fails despite the resource graph being rendered correctly in Visual Studio Code

ernestoak avatar May 02 '23 12:05 ernestoak

@ernestoak If you redeploy the template (with no changes) after seeing the KeyVaultParameterReferenceNotFound error, does the deployment succeed? I suspect this may be a consistency issue with Key Vault (that might be solved either by the Key Vault service or with something like #1013).

No, the deployment fails. If it helps, it also fails when using the --confirm-with-what-if flag and with the complete mode

Screenshot 2023-05-02 131451

@ernestoak - is the Key Vault and secret getting deployed before the failure in the initial deployment? If not, then it makes sense that it continues failing. If the key vault and secret are getting deployed, then I think we need to investigate a little bit more what is happening.

alex-frankel avatar May 02 '23 15:05 alex-frankel

@ernestoak - is the Key Vault and secret getting deployed before the failure in the initial deployment? If not, then it makes sense that it continues failing. If the key vault and secret are getting deployed, then I think we need to investigate a little bit more what is happening.

@alex-frankel - No, what I would like is to be able to deploy the Key Vault and Secret at the same time as the rest of the infrastructure. As you mention here and in other tickets, I can get around the issue either by:

  1. deploying with separate files (and import using the existing keyword)
  2. comment out the sections using getSecret, deploy, un-comment those sections, re-deploy

However:

  • option 1 makes it impossible to use "Complete" mode and the workaround is to manage your resources manually
  • option 2 means you have to manually manage a multi-step deployment into a fresh new environment

Bicep already goes a long way in improving the deployment process so in the grand scheme of things this is a minor issue, but the fact that you need to choose between manually handle deletions or manually handle initial deployments seems to go a bit against the principle of Infrastructure As Code.

ernestoak avatar May 02 '23 15:05 ernestoak

@ernestoak looking at the original example you shared, one problem I see is that the example module only depends on the keyvault and not the secret.

Out of interest, does the following make a difference?

//1. Generate a secret (used initially)
@secure()
param initialSecret string = newGuid()
param tenantId string = subscription().tenantId
param location string = resourceGroup().location
//2. Key Vault
resource KeyVault 'Microsoft.KeyVault/vaults@2019-09-01' = {
  name: 'example'
  location: location
  properties: {
    enabledForDeployment: true
    enabledForTemplateDeployment: true
    enabledForDiskEncryption: true
    tenantId: tenantId
    sku: {
      name: 'standard'
      family: 'A'
    }
  }
}
resource secret 'Microsoft.KeyVault/vaults/secrets@2022-07-01' = {
  name: 'secret'
  parent: KeyVault
  properties: {
    contentType: 'text/plain'
    attributes: {
      enabled: true
    }
    value: initialSecret
  }
}

//3. USE THE SECRET
module example 'example.bicep' = {
  name: 'example'
  params: {
    secret: KeyVault.getSecret(secret.name)
  }
}

anthony-c-martin avatar May 17 '23 19:05 anthony-c-martin

Hi @anthony-c-martin, thanks for looking into this!

I just tried using both the secret.name reference and the error is the same. Maybe useful to know that I had already tried before using dependsOn and it was the same error.

Thanks again!

ernestoak avatar May 23 '23 16:05 ernestoak

Hi ernestoak, this issue has been marked as stale because it was labeled as requiring author feedback but has not had any activity for 4 days. It will be closed if no further activity occurs within 3 days of this comment. Thanks for contributing to bicep! :smile: :mechanical_arm:

ghost avatar Jun 01 '23 04:06 ghost

Hello! Can we please keep this open?

ernestoak avatar Jun 01 '23 09:06 ernestoak

Hello! Can we please keep this open?

Yes, absolutely. The bot is being a tad overzealous, and I think this issue may have been mislabeled.

I was able to reproduce the behavior reported and found that the KeyVaultParameterReferenceNotFound error is raised during preflight validation, which recursively validates nested deployments. When the nested deployment corresponding to the example module is examined, validation fails because the keyvault doesn't exist (because template deployment hasn't started yet -- only validation). Running az deployment group create with --debug logging enabled, I was able to verify that the KeyVaultParameterReferenceNotFound is returned for the request to https://management.azure.com/subscriptions/<subscription id>/resource-groups/<group name>/providers/Microsoft.Resources/deployments/<deployment name>/validate, which the CLI executes before starting the deployment. There's no way to do this via the CLI, but I was also able to verify that if you skip the preflight validation request, the deployment succeeds.

Since this bug is only encountered when a reference to a template-managed Key Vault crosses a module boundary, one other potential workaround would be to move the contents of the example module to the main template. But that's really only feasible if the module is small and isn't reused.

jeskew avatar Jun 01 '23 14:06 jeskew

I find that deploying the bicep file directly from VSCode doesn't cause the validation error. I think this deployment method bypass "preflight validation". You can try this as workaround, maybe.

image

zukakosan avatar Aug 24 '23 02:08 zukakosan

Are there any progress on this bug ?

emilPandektes avatar Feb 06 '24 08:02 emilPandektes

Yes keen to get an update here, I don't want to skip whatif validation of my entire deployment pipeline to get around a single error relating to the keyvault

marshalexander99 avatar Mar 06 '24 16:03 marshalexander99

Still keen to get an update btw!

ernestoak avatar Mar 06 '24 17:03 ernestoak

is it possible to skip pre-fight validation by modifying the code?

ManosL avatar Mar 13 '24 11:03 ManosL

Looks like this is a duplicate of #4081 @alex-frankel ?

That is a much older issue and I'm sort of annoyed this seemingly logical use case isn't functioning and I now have to figure out some overcomplicated workaround.

ferrydeboer avatar May 31 '24 09:05 ferrydeboer