如何使用用户管理的身份部署 ARM 模板并分配订阅级别角色?

How to deploy ARM template with user managed identity and assign a subscription level role?

下面的 ARM 模板应该创建以下资源:

resource group
    - user managed identity
       - subscription level Contributor role assignment

当前部署失败并出现错误 "error": { "code": "ResourceGroupNotFound", "message": "Resource group 'rg-myproject-deploy' could not be found." } 显然是因为角色分配步骤似乎没有遵守 dependsOn 应该强制执行的语句,它应该只在资源组创建后发生.有没有办法在一个 ARM 模板中部署所有这些资源?

{
  "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "projectName": {
      "type": "string",
      "defaultValue": "myproject",
      "maxLength": 11,
      "metadata": {
        "description": "The name of the project"
      }
    },
    "location": {
      "type": "string",
      "defaultValue": "westus2",
      "metadata": {
        "description": "The region were to deploy assets"
      }
    }
  },
  "variables": {
    "resourceGroupName": "[concat('rg-', parameters('projectName'), '-deploy')]",
    "managedIdentityName": "[concat('msi-', parameters('projectName'), '-deploy')]",
    "bootstrapRoleAssignmentId": "[guid(subscription().id, 'contributor')]",
    "contributorRoleDefinitionId": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]",
    "managedIdentityId": "[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', variables('resourceGroupName'), '/providers/Microsoft.ManagedIdentity/userAssignedIdentities/', variables('managedIdentityName'))]"
  },
  "resources": [
    {
      "type": "Microsoft.Resources/resourceGroups",
      "apiVersion": "2019-10-01",
      "name": "[variables('resourceGroupName')]",
      "location": "[parameters('location')]",
      "properties": {}
    },
    {
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2019-10-01",
      "name": "deployment-assets-except-role-assignment",
      "resourceGroup": "[variables('resourceGroupName')]",
      "dependsOn": [
        "[resourceId('Microsoft.Resources/resourceGroups/', variables('resourceGroupName'))]"
      ],
      "properties": {
        "mode": "Incremental",
        "template": {
          "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
          "contentVersion": "1.0.0.0",
          "parameters": {},
          "variables": {},
          "resources": [
            {
              "type": "Microsoft.ManagedIdentity/userAssignedIdentities",
              "name": "[variables('managedIdentityName')]",
              "apiVersion": "2018-11-30",
              "location": "[parameters('location')]"
            }
          ],
          "outputs": {}
        }
      }
    }
    ,
    {
      "type": "Microsoft.Authorization/roleAssignments",
      "apiVersion": "2017-09-01",
      "name": "[variables('bootstrapRoleAssignmentId')]",
      "dependsOn": [
        "[subscriptionResourceId('Microsoft.Resources/resourceGroups', variables('resourceGroupName'))]",
        "deployment-assets-except-role-assignment"
      ],
      "properties": {
        "roleDefinitionId": "[variables('contributorRoleDefinitionId')]",
        "principalId": "[reference(variables('managedIdentityId'), '2018-11-30').principalId]",
        "principalType": "ServicePrincipal",
        "scope": "[subscription().id]"
      }
    }
  ],
  "outputs": {}
}

我认为你 运行 喜欢这个:

https://bmoore-msft.blog/2020/07/26/resource-not-found-dependson-is-not-working/

修复比我想象的要复杂一些,但总结一下:

  1. 提供 MI 的嵌套部署必须设置为内部范围评估
  2. 从该部署中输出 principalId 并在您的引用中使用它(即不要直接引用)

由于#1,我移动了一些东西 (params/vars)

{
    "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
      "projectName": {
        "type": "string",
        "defaultValue": "myproject",
        "maxLength": 11,
        "metadata": {
          "description": "The name of the project"
        }
      },
      "location": {
        "type": "string",
        "defaultValue": "westus2",
        "metadata": {
          "description": "The region were to deploy assets"
        }
      }
    },
    "variables": {
      "identityDeploymentName": "deployment-assets-except-role-assignment",
      "resourceGroupName": "[concat('rg-', parameters('projectName'), '-deploy')]",
      "managedIdentityName": "[concat('msi-', parameters('projectName'), '-deploy')]",
      "managedIdentityId": "[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', variables('resourceGroupName'), '/providers/Microsoft.ManagedIdentity/userAssignedIdentities/', variables('managedIdentityName'))]",
      "bootstrapRoleAssignmentId": "[guid(subscription().id, variables('contributorRoleDefinitionId'),variables('managedIdentityId'))]",
      "contributorRoleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]",
    },
    "resources": [
      {
        "type": "Microsoft.Resources/resourceGroups",
        "apiVersion": "2019-10-01",
        "name": "[variables('resourceGroupName')]",
        "location": "[parameters('location')]",
        "properties": {}
      },
      {
        "type": "Microsoft.Resources/deployments",
        "apiVersion": "2019-10-01",
        "name": "[variables('identityDeploymentName')]",
        "resourceGroup": "[variables('resourceGroupName')]",
        "dependsOn": [
          "[resourceId('Microsoft.Resources/resourceGroups', variables('resourceGroupName'))]"
        ],
        "properties": {
          "mode": "Incremental",
          "expressionEvaluationOptions":{
              "scope": "inner"
          },
          "parameters": {
              "location": {
                  "value": "[parameters('location')]" 
              },
              "managedIdentityName": {
                  "value": "[variables('managedIdentityName')]" 
              }
          },
          "template": {
            "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
            "contentVersion": "1.0.0.0",
            "parameters": {
                "location": {
                    "type": "string"
                },
                "managedIdentityName": {
                    "type": "string"
                }
            },
            "variables": {},
            "resources": [
              {
                "type": "Microsoft.ManagedIdentity/userAssignedIdentities",
                "name": "[parameters('managedIdentityName')]",
                "apiVersion": "2018-11-30",
                "location": "[parameters('location')]"
              }
            ],
            "outputs": {
                "principalId": {
                    "type": "string",
                    "value": "[reference(parameters('managedIdentityName')).principalId]"
                }
            }
          }
        }
      }
      ,
      {
        "type": "Microsoft.Authorization/roleAssignments",
        "apiVersion": "2020-04-01-preview",
        "name": "[variables('bootstrapRoleAssignmentId')]",
        "dependsOn": [
          "[subscriptionResourceId('Microsoft.Resources/resourceGroups', variables('resourceGroupName'))]",
          "[variables('identityDeploymentName')]"
        ],
        "properties": {
          "roleDefinitionId": "[variables('contributorRoleDefinitionId')]",
          "principalId": "[reference(variables('identityDeploymentName')).outputs.principalId.value]",
          "principalType": "ServicePrincipal",
          "scope": "[subscription().id]"
        }
      }
    ]
  }