1
votes

as part of a deployment I'm doing I want to deploy a Key vault into a resource group, create some secrets and then deploy a SQL server into another resource group using one of these secrets as the admin password. The following is a snippet of the resources I am using to do this:

{
  "type": "Microsoft.KeyVault/vaults",
  "name": "[variables('KeyVaultName')]",
  "apiVersion": "2015-06-01",
  "location": "[resourceGroup().location]",
  "properties": {
    "enabledForTemplateDeployment": "true",
    "accessPolicies": "[variables('KeyVaultAccessPolicies')]",
    "tenantId": "[parameters('TenantId')]",
    "sku": {
      "name": "Standard",
      "family": "A"
    }
  }
},
{
  "type": "Microsoft.KeyVault/vaults/secrets",
  "name": "[concat(variables('KeyVaultName'), '/secretname')]",
  "apiVersion": "2015-06-01",
  "properties": {
    "value": "<a randomised value>"
  },
  "dependsOn": [
    "[concat('Microsoft.KeyVault/vaults/', variables('KeyVaultName'))]"
  ]
},
{
  "apiVersion": "2017-05-10",
  "name": "deploy",
  "type": "Microsoft.Resources/deployments",
  "resourceGroup": "<another resource group>",
  "properties": {
    "mode": "Incremental",
    "templateLink": {
      "uri": "<my linked template>",
      "contentVersion": "1.0.0.0"
    },
    "parameters": {
      "SQLServerAdminPasswordSecretName": {
        "value": "secretname"
      }
    }
  },
  "dependsOn": [
    "[resourceId('Microsoft.KeyVault/vaults/secrets', variables('KeyVaultName'), 'secretname')]"
  ]
}

My linked template is also has a deployment which looks a bit like the following:

{
    "apiVersion": "2017-05-10",
    "name": "sql-server-deployment",
    "type": "Microsoft.Resources/deployments",
    "properties": {
        "mode": "Incremental",
        "templateLink": {
            "uri": "<another linked tempalate>",
            "contentVersion": "1.0.0.0"
        },
        "parameters": {
            "SQLServerName": {
                "value": "[variables('SQLServerName')]"
            },
            "SQLServerAdminPassword": {
                "reference": {
                    "keyVault": {
                        "id": "[resourceId(parameters('ParentResourceGroupName'), 'Microsoft.KeyVault/vaults', parameters('ParentKeyVaultName'))]"
                    },
                    "secretName": "[parameters('SQLServerAdminPasswordSecretName')]"
                }
            }
        }
    }
}

This reference is currently killing my entire deployment saying:

"The specified KeyVault '/subscriptions/[subscription id]/resourceGroups/[parent resource group]/providers/Microsoft.KeyVault/vaults/[my keyvault]' could not be found."

If I remove the Keyvault reference in my linked template the error goes away.

What is confusing to me is that the linked template deployment depends on the key vault secret, which in turn depends on the key vault, yet nothing is being deployed because the key vault reference is trying to be resolved before anything else.

Am I missing something obvious or is this a flaw in ARM templates?

Thanks in advance

1

1 Answers

0
votes

Parameter references are evaluated at "compile" time (i.e. validation), so the vault does need to exist when the template is validated. You might be able to pull this off by nesting a few levels deep and using output references from the nested deployment. You'd need to do something like this:

  • Nest the vault setup and output the vaultId
  • nested the SQL Server deployment into a "level 1" nesting
  • in the parameters for the above bullet, reference the output in step 1
  • nest another deployment with the parameter reference constructed from the vaultId in the "level 1" nesting

That said, I'm interested in why you'd want to do this... normally the vault reference is used to keep a secret out of plain text/json. Since you're passing the secret value into the deployment at the top level, you already have the value. There's no reason to reference it from the vault since you already have it...