Search code examples
azureazure-pipelinesazure-resource-managerazure-keyvaultazure-rm-template

How to manage Azure Key Vault with secrets without values in ARM template?


So I wanna create an Azure Key Vault to manage and version my secrets, all in one place. I use arm templates to deploy all my resources and have written one one as such:

 {
    "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "keyVaultName": {
        "type": "string",
        "defaultValue": "mykeyvaultname",
        "metadata": {
            "description": "The name of the Key Vault to create."
        }
        },
        "secret1Name": {
        "type": "string",
        "defaultValue": "secret1Name",
        "metadata": {
            "description": "The name of the first secret to create."
        }
        },
        "secret1Value": {
        "type": "securestring",
        "defaultValue": "xxx",
        "metadata": {
            "description": "The value of the first secret."
        }
        },
        "secret2Name": {
        "type": "string",
        "defaultValue": "secret2Name",
        "metadata": {
            "description": "The name of the second secret to create."
        }
        },
        "secret2Value": {
        "type": "securestring",
       "defaultValue": "xxx",
        "metadata": {
            "description": "The value of the second secret."
        }
        }
    },
    "variables": {},
    "resources": [
        {
        "type": "Microsoft.KeyVault/vaults",
        "apiVersion": "2019-09-01",
        "name": "[parameters('keyVaultName')]",
        "location": "[resourceGroup().location]",
        "properties": {
            "sku": {
            "family": "A",
            "name": "standard"
            },
            "tenantId": "[subscription().tenantId]",
            "accessPolicies": []
        },
        "resources": [
            {
            "type": "secrets",
            "apiVersion": "2019-09-01",
            "name": "[concat(parameters('keyVaultName'), '/', parameters('secret1Name'))]",
            "location": "[resourceGroup().location]",
            "properties": {
                "value": "[parameters('secret1Value')]"
            }
            },
            {
            "type": "secrets",
            "apiVersion": "2019-09-01",
            "name": "[concat(parameters('keyVaultName'), '/', parameters('secret2Name'))]",
            "location": "[resourceGroup().location]",
            "properties": {
                "value": "[parameters('secret2Value')]"
            }
            }
        ]
        }
    ],
    "outputs": {}
    }

Espectation

My key vault is deployed along with my secrets without values. I will then be able to specify the values manually in my vault portal or via cli, saving me from having to specify my secrets in the arms template.

Reality Seems you can't deploy a secret using arms without a value. It's mandatory for the template. If I set a default dummy value, the value will replace the updated values in my key vault.

Research I haven't been able to find any reasonable solution for this.

KeyVault ARM template overrides secrets when re-deploying

This answer suggests you can use a condition tag, which sounds like a poor workaround that just adds more complexity for a very simple use case.

Creating an azure keyvault secret without value?

This one suggests defining my secrets in the azure pipeline variable library and overwriting them on deployment which, on top of forcing me to specify my secret values in two places, effectively means putting my secrets back in to my library variables which is exactly the thing i want to avoid by using azure secrets.

Elsewhere I've seen it suggested to populate my arm template parameters with secrets from key vault, which creates an odd catch 22 where I need a keyvault in order to get the secret values i need to deploy my keyvault.

I literally cannot proceed. How do I solve this?


Solution

  • If the point of populating the keyvault with empty values is to save time while entering them manually at a later point, I would refer to using az keyvault secret in the Azure CLI.

    This way you can deploy using arm templates, and automate population at a later point. This is a simple task using releases in Devops.