Search code examples
azureazure-functionsazure-resource-managerazure-keyvault

Need guidance on how to create Access Policy for Key Vault in a different group from ARM Template deployment


I have a resource group (A) containing an existing Key Vault with secrets that are used by multiple applications (in various resource groups).

I have an ARM Template that creates a Function App in another resource group (B). During the deployment of this Function App (via ARM Template deployment, for B), I would like to grant access to the Key Vault in A, by adding a new Access Policy to the Key Vault in resource group A.

I have major problem accomplishing this.

This is a slimmed down template definition for the Function App:

"resources": [
    {
      "type": "Microsoft.Web/sites",
      "apiVersion": "2021-03-01",
      "name": "[parameters('functionAppName')]",
      "kind": "functionapp",
      "location": "[parameters('location')]",
      "identity": {
        "type": "SystemAssigned"
      },
      ... (unrelated)
    },
    {
      "type": "Microsoft.KeyVault/vaults/accessPolicies",
      "apiVersion": "2019-09-01",
      "name": "[concat(parameters('keyVaultName'), '/add')]",
      "location": "[resourceGroup().location]",
      "properties": {
        "accessPolicies": [
          {
            "tenantId": "[tenant().tenantId]",
            "objectId": "[reference(resourceId('Microsoft.Web/sites', parameters('functionAppName')), '2019-08-01').identity.principalId]",
            "permissions": {
              "secrets": [
                "get",
                "list"
              ]
            }
          }
        ]
      },
      "dependsOn": [
        "[resourceId('Microsoft.Web/sites', parameters('functionAppName'))]"
      ]
    }

The parameters in use (keyVaultName, functionAppName) are all valid.

The problem seem to be in the scope of the deployment itself, which is Resource Group.

I have tried setting scope on the Microsoft.KeyVault/vaults/accessPolicies resource itself, but that doesn't work - there seem to be some sort of a mismatch between scopes.

My questions are as follows:

  1. Is it at all possible to achieve?
  2. Do I have to change the scope of the deployment itself (from Resource Group to Subscription (or whatever it is called))?
  3. If so - how would I go about defining the scopes? Would I have to define a scope for each resource (for now, there's only two resources in the template, but it will most likely end up having more)

Solution

  • You can create a nested deployment targeting the resource group of the Key Vault. The nested deployment method allows you to include the access policy in a template scoped to the Function App's resource group, ensuring that the Key Vault access policy gets applied to the Function App's identity, even if it resides in a different resource group.

    {
        "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
        "contentVersion": "1.0.0.0",
        "parameters": {
          "functionAppName": {
            "type": "string",
            "defaultValue": "venkatfunctionapptestg",
            "metadata": {
              "description": "The name of the Function App to be created."
            }
          },
          "location": {
            "type": "string",
            "defaultValue": "East US",
            "metadata": {
              "description": "The Azure region where the Function App will be deployed."
            }
          },
          "keyVaultName": {
            "type": "string",
            "defaultValue": "keyvauldemo",
            "metadata": {
              "description": "The name of the existing Key Vault."
            }
          },
          "keyVaultResourceGroupName": {
            "type": "string",
            "defaultValue": "Storage-RG",
            "metadata": {
              "description": "The name of the resource group where the Key Vault is located."
            }
          }
        },
        "resources": [
          {
            "type": "Microsoft.Web/sites",
            "apiVersion": "2021-03-01",
            "name": "[parameters('functionAppName')]",
            "location": "[parameters('location')]",
            "identity": {
              "type": "SystemAssigned"
            },
            "properties": {}
          },
          {
            "type": "Microsoft.Resources/deployments",
            "apiVersion": "2021-04-01",
            "name": "GrantKeyVaultAccessPolicy",
            "resourceGroup": "[parameters('keyVaultResourceGroupName')]",
            "dependsOn": [
              "[resourceId('Microsoft.Web/sites', parameters('functionAppName'))]"
            ],
            "properties": {
              "mode": "Incremental",
              "template": {
                "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
                "contentVersion": "1.0.0.0",
                "resources": [
                  {
                    "type": "Microsoft.KeyVault/vaults/accessPolicies",
                    "apiVersion": "2019-09-01",
                    "name": "[concat(parameters('keyVaultName'), '/add')]",
                    "properties": {
                      "accessPolicies": [
                        {
                          "tenantId": "[tenant().tenantId]",
                          "objectId": "[reference(resourceId('Microsoft.Web/sites', parameters('functionAppName')), '2021-03-01', 'Full').identity.principalId]",
                          "permissions": {
                            "secrets": [
                              "get",
                              "list"
                            ]
                          }
                        }
                      ]
                    }
                  }
                ]
              }
            }
          }
        ]
      }
    
    az deployment group create --resource-group "Venkat-RG" --template-file "Keyvault.json"
    

    Output:

    enter image description here

    After running the code, the function app with an identity has been created.

    enter image description here

    TheFunction App's identity has been added to the Key Vault access policies with get and list permissions.

    enter image description here