Create An Azure Key Vault With Vault Access Policy And Add Secrets Using ARM Template

In this article, I will explain how we can create an Azure Key vault; add secrets to an Azure Key Vault, and how we can add a web app service principal into the vault access policy using simple ARM templates.

Before beginning to create an ARM template, the assumption here is that you should have a basic understanding of the structure of ARM templates and you already have a resource group.

The Context

For demonstration purposes, we will create a web app with a system-assigned identity and we will add web app service principal id to the key vault access policy. Similarly, we will create a storage account to demonstrate how we can easily add storage account connection string into key vault secret.

We will create the below resources in this article for better understanding purposes.

Resource Name Type reference
Key Vault Microsoft.KeyVault/vaults
Key Vault - Secret Microsoft.KeyVault/vaults/secrets
Storage Account Microsoft.Storage/storageAccounts
Web App Microsoft.Web/sites
App Service Plan Microsoft.Web/serverfarms

The below image represents the resources dependency of our ARM templates which we will build in subsequent steps.

And we will follow the below-maiming convention while creating resources using ARM. Image has been referred from Microsoft documentation.

Let’s build our template step by step for each resource.

Parameters & Variables

We are taking environment name as Input and in the variable, we will concatenate environment name with resources we are creating.

"parameters": {
    "envName": {
        "defaultValue": "uat",
        "type": "String"
    }
}, "variables": {
    "tenantId": "[subscription().tenantId]",
    "appServicePlanName": "[concat('plan-myapp-',parameters('envName'),'-',resourceGroup().location)]",
    "webAppName": "[concat('app-mywebapp-',parameters('envName'),'-',resourceGroup().location)]",
    "storageAccountName": "[concat('stmystorage',parameters('envName'),resourceGroup().location)]",
    "keyVaultName": "[concat('kv-myapps-',parameters('envName'),'-',resourceGroup().location)]"
},

Creating Key Vault with Vault Access Policy

To create a Key Vault with an access policy, we add the following resource to the ARM template.

First, we will create a web app with an app service plan.

{
    "type": "Microsoft.Web/serverfarms",
    "apiVersion": "2018-02-01",
    "name": "[variables('appServicePlanName')]",
    "location": "[resourceGroup().location]",
    "sku": {
        "name": "S1",
        "tier": "Standard",
        "size": "S1",
        "family": "S",
        "capacity": 1
    },
    "kind": "app"
}, {
    "type": "Microsoft.Web/sites",
    "apiVersion": "2018-11-01",
    "name": "[variables('webAppName')]",
    "location": "[resourceGroup().location]",
    "dependsOn": ["[resourceId('Microsoft.Web/serverfarms', variables('appServicePlanName'))]"],
    "kind": "app",
    "identity": {
        "type": "SystemAssigned"
    },
    "properties": {
        "name": "[variables('webAppName')]",
        "httpsOnly": true,
        "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('appServicePlanName'))]"
    }
},

Let’s create a key vault with an access policy. Here, we included an access policy as the service principal id of a web app that we are creating. This will ensure that our web app reads the connection string directly from Key Vault as we are implementing Managed Service Identity.

{
    "type": "Microsoft.KeyVault/vaults",
    "apiVersion": "2021-04-01-preview",
    "name": "[variables('keyVaultName')]",
    "location": "[resourceGroup().location]",
    "properties": {
        "sku": {
            "family": "A",
            "name": "Standard"
        },
        "tenantId": "[variables('tenantId')]",
        "accessPolicies": [{
            "tenantId": "[variables('tenantId')]",
            "objectId": "[reference(concat('Microsoft.Web/sites/',variables('webAppName')), '2018-11-01','Full').identity.principalId]",
            "permissions": {
                "keys": [],
                "secrets": ["Get"],
                "certificates": []
            }
        }],
        "enabledForDeployment": false,
        "enabledForDiskEncryption": false,
        "enabledForTemplateDeployment": false,
        "enableSoftDelete": true,
        "enableRbacAuthorization": false,
        "vaultUri": "[concat('https://' ,variables('keyVaultName'),'.vault.azure.net/')]",
        "provisioningState": "Succeeded"
    }
},

Adding Storage Account Connection string as a Secret

First, we will add a Storage Account resource to the ARM template.

{
    "type": "Microsoft.Storage/storageAccounts",
    "apiVersion": "2021-04-01",
    "name": "[variables('storageAccountName')]",
    "location": "[resourceGroup().location]",
    "sku": {
        "name": "Standard_LRS",
        "tier": "Standard"
    },
    "kind": "Storage",
    "properties": {
        "supportsHttpsTrafficOnly": true
    }
},

Now we will add a Secret called “StorageAccountConnectionString” that is depending on the Storage Account and the Key Vault defined earlier. The value of this secret is set with a connection string containing the access key of the Storage Account that we created earlier.

{
    "type": "Microsoft.KeyVault/vaults/secrets",
    "apiVersion": "2021-04-01-preview",
    "name": "[concat(variables('keyVaultName'), '/StorageAccountConnectionString')]",
    "location": "[resourceGroup().location]",
    "dependsOn": ["[resourceId('Microsoft.KeyVault/vaults', variables('keyVaultName'))]", "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"],
    "properties": {
        "value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';AccountKey=', listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')),'2017-06-01').keys[0].value)]"
    }
}

Deploying ARM Template using Azure CLI

Using Azure CLI, we will deploy this template. Here, my templates name is “ARM_KV_Template.json” and I have a resource group created already. First, I uploaded the JSON file using the upload option and then executed the below script in Bash.

az deployment group create --resource-group rg-myapps-uat-westus --template-file ARM_KV_Template.json

Create An Azure Key Vault With Vault Access Policy And Add Secrets Using ARM Template

Now if you go to the resources group, you will see all the resources are created successfully.

Create An Azure Key Vault With Vault Access Policy And Add Secrets Using ARM Template

Let’s check key vault secrets and access policies one by one.

Create An Azure Key Vault With Vault Access Policy And Add Secrets Using ARM Template

Create An Azure Key Vault With Vault Access Policy And Add Secrets Using ARM Template

Excellent! We are done with your implementation and we deployed Azure Key vault with an access policy and secret using ARM templates.

Hope you found this article useful.

Happy Learning!