bicep
bicep copied to clipboard
Cant create a KeyVault and use its getSecret method in the same template
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 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).
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.
@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
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 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
@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.
@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:
- deploying with separate files (and import using the
existing
keyword) - 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 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)
}
}
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!
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:
Hello! Can we please keep this open?
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.
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.
Are there any progress on this bug ?
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
Still keen to get an update btw!
is it possible to skip pre-fight validation by modifying the code?
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.