0
votes

I am creating an ARM template that deploys a lot of resources in different resource groups. Actually, the resource groups themselves are part of the deployment. In a simple version, I create only two resource groups (masterRG and dependentRG), and then create two nested (inline) deployments. The first inline deployment puts a storage account (testsadj1604) in masterRG. This deployment is dependent on masterRG.

The second deployment creates a keyvault and tries to store a connectionstring from testsadj1604 in that vault.

In my real case, I have more resourceGroups and I actually try deploy a Function App that has the connectionstring as 'appsetting'. The methodology is the same though.

The error I get is the following:

Deployment failed. Correlation ID: 9c359e8e-8657-4756-a5a3-f9c5698fbb46. {
  "error": {
    "code": "ResourceNotFound",
    "message": "The Resource 'Microsoft.Storage/storageAccounts/testsadj1604' under resource group '<null>' was not found."
  }
}

This is my code:

{
  "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {},
  "resources": [
    {
      "type": "Microsoft.Resources/resourceGroups",
      "apiVersion": "2018-05-01",
      "name": "masterRG",
      "location": "West Europe",
      "properties": {}
    },
    {
      "type": "Microsoft.Resources/resourceGroups",
      "apiVersion": "2018-05-01",
      "name": "dependentRG",
      "location": "West Europe",
      "properties": {}
    },
    {
      "name": "masterRgDeployment",
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2019-10-01",
      "resourceGroup": "masterRG",
      "dependsOn": [
        "masterRG"
      ],
      "properties": {
        "mode": "Incremental",
        "template": {
          "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
          "contentVersion": "1.0.0.0",
          "resources": [
            {
              "apiVersion": "2019-06-01",
              "type": "Microsoft.Storage/storageAccounts",
              "name": "testsadj1604",
              "location": "West Europe",
              "sku": {
                "name": "Standard_GRS"
              },
              "kind": "StorageV2",
              "properties": {
                "supportsHttpsTrafficOnly": true
              }
            }
          ]
        }
      }
    },
    {
      "name": "dependentRgDeployment",
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2019-10-01",
      "resourceGroup": "dependentRG",
      "dependsOn": [
        "dependentRG",
        "masterRgDeployment"
      ],
      "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",
              "name": "kvaNameTest1604",
              "apiVersion": "2015-06-01",
              "location": "West Europe",
              "properties": {
                "enabledForDeployment": false,
                "enabledForDiskEncryption": false,
                "enabledForTemplateDeployment": true,
                "tenantId": "[subscription().tenantId]",
                "accessPolicies": [
                  {
                    "objectId": "fc05639d-70eb-4175-a89b-eab7f883c691",
                    "tenantId": "[subscription().tenantId]",
                    "permissions": {
                      "keys": [
                        "get",
                        "list",
                        "update"
                      ],
                      "secrets": [
                        "get",
                        "list",
                        "update"
                      ]
                    }
                  }
                ],
                "sku": {
                  "name": "Standard",
                  "family": "A"
                },
                "networkAcls": {
                  "defaultAction": "Allow",
                  "bypass": "AzureServices"
                }
              }
            },
            {
              "type": "Microsoft.KeyVault/vaults/secrets",
              "name": "kvaNameTest1604/saConnectionString",
              "apiVersion": "2018-02-14",
              "location": "West Europe",
              "dependsOn": [
                "[resourceId('Microsoft.KeyVault/vaults', 'kvaNameTest1604')]"
              ],
              "properties": {
                "value": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', 'testsadj1604'), '2019-06-01').keys[0].value]"
              }
            }
          ]
        }
      }
    }
  ]
}

I am pretty sure the error comes from the listKeys() at the bottom, going on my daylong trial-and-error (and Google frenzy) in my real template. Using listKeys() and nested deployments is a drag, but I really don't see why it shouldn't work. I made sure there is a dependsOn in the second deployment.

This is wrecking my brain, is there any way I can use nested (inline) templates and reference the storage account keys that are in a different resourcegroup (but part of the overall deployment)? I also tried to create an output in the first deployment and reference that in the second but that had no effect. I am at a total loss, any help is welcome!

1
Could you please tell me how you deploy the template?Jim Xu
Besides, could you tell me if the storage account and key vault are in the same group?Jim Xu
I use Az CLI (az deployment sub create), the SA and KV are not in the same resourcegroup. (I noticed I had a mistake in my template that deployed the second deployment to masterRG as well, that should have been dependentRG and is now fixed :))JarroVGIT
Since the issue has been resolved by yourself, could you please post your answer?Jim Xu
This issue has not been fixed, I noticed a typo in my code while answering your questions, but that had no effect. The issue remains :(JarroVGIT

1 Answers

2
votes

There are a few things you need to do for this to work in a single template:

  1. on your keyvault secret deployment set this property:
    "expressionEvaluationOptions": {
      "scope": "inner"
    },

That will delay evaluation of the expression until that deployment begins.

  1. when you set #1, you need to define parameters for the values you need (you can no longer use "global" params/vars), you could hardcode all the strings like in your example, but I'm guessing that's not what you do in the "real" deployment. Define the params and pass the values into that deployment.
  2. your listKeys() call needs to include the full resourceId of the storageAccount, since it is in a separate/distinct deployment - so you need to provide the resourceGroup name param - if you cross subscriptions in the deployment (your sample didn't) you need to provide the subscriptionId param.

Below is a working example...

{
  "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "storageAccountName": {
      "type": "string",
      "defaultValue": "[concat('scratch', uniqueString(newGuid()))]"
    }
   },
  "resources": [
    {
      "type": "Microsoft.Resources/resourceGroups",
      "apiVersion": "2018-05-01",
      "name": "masterRG",
      "location": "West Europe",
      "properties": {
      }
    },
    {
      "type": "Microsoft.Resources/resourceGroups",
      "apiVersion": "2018-05-01",
      "name": "dependentRG",
      "location": "West Europe",
      "properties": {
      }
    },
    {
      "name": "masterRgDeployment",
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2019-10-01",
      "resourceGroup": "masterRG",
      "dependsOn": [
        "masterRG"
      ],
      "properties": {
        "mode": "Incremental",
        "template": {
          "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
          "contentVersion": "1.0.0.0",
          "resources": [
            {
              "apiVersion": "2019-06-01",
              "type": "Microsoft.Storage/storageAccounts",
              "name": "[parameters('storageAccountName')]",
              "location": "West Europe",
              "sku": {
                "name": "Standard_GRS"
              },
              "kind": "StorageV2",
              "properties": {
                "supportsHttpsTrafficOnly": true
              }
            }
          ]
        }
      }
    },
    {
      "name": "dependentRgDeployment",
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2019-10-01",
      "resourceGroup": "dependentRG",
      "dependsOn": [
        "dependentRG",
        "masterRgDeployment"
      ],
      "properties": {
        "mode": "Incremental",
        "expressionEvaluationOptions": {
          "scope": "inner"
        },
        "parameters":{
          "storageAccountName": {
            "value": "[parameters('storageAccountName')]"
          },
          "storageAccountResourceGroupName": {
            "value": "masterRG"
          }
        },
        "template": {
          "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
          "contentVersion": "1.0.0.0",
          "parameters": {
            "storageAccountName": {
              "type": "string"
            },
            "storageAccountResourceGroupName": {
              "type": "string"
            }
          },
          "variables": {
            "vaultName": "[concat('kv-', parameters('storageAccountName'))]"
          },
          "resources": [
            {
              "type": "Microsoft.KeyVault/vaults",
              "name": "[variables('vaultName')]",
              "apiVersion": "2019-09-01",
              "location": "West Europe",
              "properties": {
                "enabledForDeployment": false,
                "enabledForDiskEncryption": false,
                "enabledForTemplateDeployment": true,
                "tenantId": "[subscription().tenantId]",
                "accessPolicies": [ ],
                "sku": {
                  "name": "Standard",
                  "family": "A"
                },
                "networkAcls": {
                  "defaultAction": "Allow",
                  "bypass": "AzureServices"
                }
              }
            },
            {
              "type": "Microsoft.KeyVault/vaults/secrets",
              "name": "[concat(variables('vaultName'), '/saConnectionString')]",
              "apiVersion": "2019-09-01",
              "location": "West Europe",
              "dependsOn": [
                "[resourceId('Microsoft.KeyVault/vaults', variables('vaultName'))]"
              ],
              "properties": {
                "value": "[listKeys(resourceId(parameters('storageAccountResourceGroupName'),'Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2019-06-01').keys[0].value]"
              }
            }
          ]
        }
      }
    }
  ]
}