Problem
I’m having a problem that’s similar to the one described in Retrieve a secret from a keyvault and use it as input for Synapse Workspace creation in Bicep.
(Though I’m afraid I won’t be able to continue the conversation there because I don’t have enough rep.)
Keyvaults and virtual machines must be generated in the same single deployment template file. The password for the VM’s local admin should be established using a secret produced in the keyvault bicep module file. Although it is not required that the secret be produced at the keyvault module level, I do not believe that there is any other way to ensure that the deployment is secure.
This is the section of the main bicep template that is relevant:
module kv './modules/keyvault.bicep' = {
name: '${deployment().name}-kv'
scope: rg
params: {
keyvaultName: kvName
createLocalAdmin: true
}
}
resource kvRef 'Microsoft.KeyVault/vaults@2019-09-01' existing = {
name: kvName
scope: rg
}
module vm './modules/vm.bicep' = {
name: '${deployment().name}-vm-${vm.hostShortName}'
scope: rg
params: {
adminPassword: kvRef.getSecret('localadmin')
adminUsername: 'localadmin'
}
dependsOn: [
network
kv
]
}
When I deploy the bicep, I receive the following error: The given KeyVault ‘KEYVAULT ID>’ could not be discovered. The template works great if I replace kvRef.getSecret(‘localadmin’) with a random valued string.
This can be solved using the ARM template, for example:
"adminPassword": {"Value":{
"reference": {
"keyVault": {
"id":"concat(subscription().Id,'/resourceGroups/',variables('rgName'),'/providers/Microsoft.KeyVault/vaults/',reference('deploy-keyvault').outputs.KeyvaultName.value)]"
},
"secretName": "[variables('localAdminSecretname')]"
}
}
}
Is there a method to use the same approach in biceps as in the ARM example, or is there another way to do this?
Asked by Sam Hall
Solution #1
This is a difficulty with parallelism and order of operations.
module kv './modules/keyvault.bicep' = {
name: '${deployment().name}-kv'
scope: rg
params: {
keyvaultName: kvName
createLocalAdmin: true
}
}
resource kvRef 'Microsoft.KeyVault/vaults@2019-09-01' existing = {
name: kvName
scope: rg
}
Each module is deployed as a sub-deployment, which can execute in parallel. To generate dependsOn references, Bicep relies on reference usage. For example, if your module outputs a name property, refer to it as follows:
resource kvRef 'Microsoft.KeyVault/vaults@2019-09-01' existing = {
name: kv.outputs.name
scope: rg
}
Bicep would be able to understand that one has to run before the other automatically. Since you’re not doing that, you have to explicitly tell it.
The solution is to add a dependsOn to your existing keyvault, which tells it to wait for the previous module to finish before proceeding.
resource kvRef 'Microsoft.KeyVault/vaults@2019-09-01' existing = {
name: kvName
scope: rg
dependsOn: [ kv ]
}
Answered by Daniel Mann
Solution #2
Perhaps you could divide the deployment of Key Vault and the resources that require the instance you just built as follows:
Answered by Mário Meyrelles
Post is based on https://stackoverflow.com/questions/70436348/retrieving-key-vault-secret-from-a-keyvault-created-in-same-bicep