【问题标题】:How to conditionally provision N role assignments for storage accounts with ARM Template copy?如何使用 ARM 模板副本有条件地为存储帐户提供 N 个角色分配?
【发布时间】:2021-08-11 02:27:54
【问题描述】:

我正在尝试预配 N 个存储帐户、N 个角色分配(每个存储帐户 1 个)以授予对特定身份的访问权限,但仅有条件地部署角色分配。存储帐户和身份已经存在,并且它们的模板逻辑已经工作了一段时间。

如果我尝试部署以下模板 sn-p,我在“'[concat(parameters('BackupStorageAccountRoleAssignmentsDeployment')[0].AccountName, '/Microsoft.Authorization/', guid(parameters('BackupStorageAccountRoleAssignmentsDeployment')[0].Name))]'" 当角色分配的输入数组为空时。

我已经在使用技巧将长度为 0 的副本强制为长度 = 1,然后在某个条件下保护部署。我尝试了使用大小为 1 的默认数组的变体,将我的角色分配部分移动到一个嵌套模板中,并手动将我的循环展开为 4 个角色分配。无论如何,我遇到了同样的错误。这个 sn-p 有什么问题?

{
    "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "RoleAssignments": {
            "type": "array"
        },
        "IdentityName": {
            "type": "string"
        },
        "StorageAccounts": {
            "type": "array"
        }
    },
    "variables": {
        "IdentityResourceId": "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('IdentityName'))]"
    },
    "resources": [
        { // Everything related to role assignments chokes completely, even if I unroll the loop
            "dependsOn": [
                "[variables('IdentityResourceId')]",
                "storageaccountcopy"
            ],
            "copy": {
                "name": "RoleAssignmentsCopy",
                "count": "[max(length(parameters('BackupStorageAccountRoleAssignmentsDeployment')), 1)]"
            },
            "condition": "[greater(length(parameters('RoleAssignments')), 0)]",
            "type": "Microsoft.Storage/storageAccounts/providers/roleAssignments",
            "apiVersion": "2020-04-01-preview",
            "name": "[concat(parameters('RoleAssignments')[copyIndex()].AccountName, '/Microsoft.Authorization/', guid(parameters('RoleAssignments')[copyIndex()].Name))]",
            "properties": {
                "roleDefinitionId": "[parameters('RoleAssignments')[copyIndex()].RoleDefinitionId]",
                "principalId": "[if(and(empty(parameters('RoleAssignments')[copyIndex()].ResourceId), not(empty(parameters('RoleAssignments')[copyIndex()].PrincipalId))), 
                                parameters('RoleAssignments')[copyIndex()].PrincipalId, 
                                reference(parameters('RoleAssignments')[copyIndex()].ResourceId, '2018-11-30').PrincipalId)]",
                "scope": "[parameters('RoleAssignments')[copyIndex()].Scope]",
                "principalType": "[parameters('RoleAssignments')[copyIndex()].PrincipalType]"
            }
        },
        {   // Everthing related to storage account provisioning works fine, this was existing code
            "condition": "[and(greater(length(parameters('StorageAccounts')), 0), not(parameters('SkipStorageAccountProvisioning')), equals(parameters('StorageAccountProvisioningDefault'), 'true'))]",
            "copy": {
                "name": "storageaccountcopy",
                "count": "[length(parameters('StorageAccounts'))]"
            },
            "type": "Microsoft.Storage/storageAccounts",
            "apiVersion": "2019-06-01",
            "name": "[parameters('StorageAccounts')[copyIndex()].AccountName]",
            "location": "[resourceGroup().location]",
            "sku": {
                "name": "[if(equals(parameters('StorageAccounts')[copyIndex()].AccountTypeOverride, parameters('StorageAccountTypeOverrideDefault')), parameters('StorageAccounts')[copyIndex()].AccountType, parameters('StorageAccounts')[copyIndex()].AccountTypeOverride)]",
                "tier": "Standard"
            },
            "kind": "[parameters('StorageAccounts')[copyIndex()].AccountKind]",
            "properties": {
                "networkAcls": {
                    "bypass": "AzureServices",
                    "virtualNetworkRules": [],
                    "ipRules": [],
                    "defaultAction": "Allow"
                },
                "supportsHttpsTrafficOnly": true,
                "encryption": {
                    "services": {
                        "file": {
                            "keyType": "Account",
                            "enabled": true
                        },
                        "blob": {
                            "keyType": "Account",
                            "enabled": true
                        }
                    },
                    "keySource": "Microsoft.Storage"
                }
            }
        }
    ]
}

编辑:

根据反馈,我尝试将 sn-p 移动到嵌套模板中。失败并出现完全相同的错误,The template resource '[concat(parameters('RoleAssignments')[copyIndex()].AccountName, '/Microsoft.Authorization/', guid(parameters('BackupStorageAccountRoleAssignments')[copyIndex()].Name))]' at line '1' and column '837' is not valid: The language expression property array index '0' is out of bounds..

{
      "dependsOn": [
        "[variables('IdentityResourceId')]"
      ],
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2020-10-01",
      "name": "RoleAssignmentsDeployment",
      "properties": {
        "mode": "Incremental",
        "expressionEvaluationOptions": {
          "scope": "inner"
        },
        "parameters": {
          "RoleAssignments": {
            "value": "[parameters('RoleAssignmentsDeployment')]"
          }
        },
        "template": {
          "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
          "contentVersion": "1.0.0.0",
          "parameters": {
            "RoleAssignments": {
              "type": "array"
            }
          },
          "resources": [
            {
              "dependsOn": [
                "[resourceId('Microsoft.Storage/storageAccounts', parameters('RoleAssignments')[copyIndex()].AccountName)]"
              ],
              "copy": {
                "name": "RoleAssignmentsDeploymentCopy",
                "count": "[max(length(parameters('RoleAssignments')), 1)]"
              },
              "condition": "[greater(length(parameters('RoleAssignments')), 0)]",
              "type": "Microsoft.Storage/storageAccounts/providers/roleAssignments",
              "apiVersion": "2020-10-01",
              "name": "[concat(parameters('RoleAssignments')[copyIndex()].AccountName, '/Microsoft.Authorization/', guid(parameters('RoleAssignments')[copyIndex()].Name))]",
              "properties": {
                "scope": "[parameters('RoleAssignments')[copyIndex()].Scope]",
                "principalType": "[parameters('RoleAssignments')[copyIndex()].PrincipalType]",
                "roleDefinitionId": "[parameters('RoleAssignments')[copyIndex()].RoleDefinitionId]",

                "principalId": "[if(and(empty(parameters('RoleAssignments')[copyIndex()].ResourceId), not(empty(parameters('RoleAssignments')[copyIndex()].PrincipalId))), 
                                    parameters('RoleAssignments')[copyIndex()].PrincipalId, 
                                    reference(parameters('RoleAssignments')[copyIndex()].ResourceId, '2020-10-01').PrincipalId)]"
              }
            }
          ]
        }
      }
    }

【问题讨论】:

    标签: azure azure-resource-manager arm-template


    【解决方案1】:

    已知零长度数组上的复制循环问题,Microsoft 团队已在其路线图上修复该问题。

    目前的解决方案是将循环移动到嵌套部署中,将数组作为参数和条件传递给嵌套部署,并检查数组是否为空。虽然我不确定部署是否必须在内部范围内。可以肯定的是,它适用于设置为内部的变量范围。

    【讨论】:

    • 感谢帮助,但遗憾的是没有改变。即使使用 "[max(length(parameters('RoleAssignments')), 1)]" 和内部范围的模板,我也会收到关于零长度副本的相同错误
    • 线索是不要在嵌套部署中执行条件过滤器。您检查部署本身的条件。
    【解决方案2】:

    所以有几种方法可以解决这个问题。我很难让 Miq 的建议按照我想要的方式工作。不过,我确实找到了另一种解决方法;在模板中使用一个变量来确保输入数组总是被填充

    注意事项:

    • 参数上的常规“defaultValue”属性将不起作用,如果传递空数组,则不会应用默认值。您需要使用一些 if 块来计算单元素数组作为无操作部署的默认值

    • ARM 在“编译”时扩展模板。因此,您会根据模板的替换值得到“0 超出范围”错误,而不是在实际部署开始时。问题是我试图使用零长度副本,并且我在特殊的 ARM 函数/项目(如 referencedependsOn)中引用了 copyindex()

    {
        "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
        "contentVersion": "1.0.0.0",
        "parameters": {
            "RoleAssignments": {
                "type": "array"
            },
            "IdentityName": {
                "type": "string"
            },
            "StorageAccounts": {
                "type": "array"
            },
            "Enabled": {
                "type: "bool"
            }
        },
        "variables": {
            "IdentityResourceId": "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('IdentityName'))]",
             "ComputedRoleAssignments": "[if(greater(length(parameters('RoleAssignments')), 0), 
                                                  parameters('RoleAssignments'), 
                                                  createArray(createObject('AccountName', 'dummy', 'Name', 'dummy', 'ResourceId', 'dummy', 'RoleDefinitionId', 'dummy', 'PrincipalType', 'dummy', 'Scope', 'dummy', 'PrincipalId', 'dummy')))]"
    
        },
        "resources": [
            { // Everything related to role assignments chokes completely, even if I unroll the loop
                "dependsOn": [
                    "[variables('IdentityResourceId')]",
                    "storageaccountcopy"
                ],
                "copy": {
                    "name": "RoleAssignmentsCopy",
                    "count": "[length(variables('ComputedRoleAssignments'))]"
                }, // Conditionally deploy based on parameters, but use the value from computed variables
                "condition": "[and(greater(length(parameters('RoleAssignments')), 0), parameters('Enabled'))]",
                "type": "Microsoft.Storage/storageAccounts/providers/roleAssignments",
                "apiVersion": "2020-04-01-preview",
                "name": "[concat(variables('ComputedRoleAssignments')[copyIndex()].AccountName, '/Microsoft.Authorization/', guid(variables('ComputedRoleAssignments')[copyIndex()].Name))]",
                "properties": {
                    "roleDefinitionId": "[variables('ComputedRoleAssignments')[copyIndex()].RoleDefinitionId]",
                    "principalId": "[if(and(empty(parameters('ComputedRoleAssignments')[copyIndex()].ResourceId), not(empty(parameters('ComputedRoleAssignments')[copyIndex()].PrincipalId))), 
                                    variables('ComputedRoleAssignments')[copyIndex()].PrincipalId, 
                                    reference(variables('ComputedRoleAssignments')[copyIndex()].ResourceId, '2018-11-30').PrincipalId)]",
                    "scope": "[variables('ComputedRoleAssignments')[copyIndex()].Scope]",
                    "principalType": "[variables('ComputedRoleAssignments')[copyIndex()].PrincipalType]"
                }
            },
            {   // Everthing related to storage account provisioning works fine, this was existing code
                "condition": "[and(greater(length(parameters('StorageAccounts')), 0), not(parameters('SkipStorageAccountProvisioning')), equals(parameters('StorageAccountProvisioningDefault'), 'true'))]",
                "copy": {
                    "name": "storageaccountcopy",
                    "count": "[length(parameters('StorageAccounts'))]"
                },
                "type": "Microsoft.Storage/storageAccounts",
                "apiVersion": "2019-06-01",
                "name": "[parameters('StorageAccounts')[copyIndex()].AccountName]",
                "location": "[resourceGroup().location]",
                "sku": {
                    "name": "[if(equals(parameters('StorageAccounts')[copyIndex()].AccountTypeOverride, parameters('StorageAccountTypeOverrideDefault')), parameters('StorageAccounts')[copyIndex()].AccountType, parameters('StorageAccounts')[copyIndex()].AccountTypeOverride)]",
                    "tier": "Standard"
                },
                "kind": "[parameters('StorageAccounts')[copyIndex()].AccountKind]",
                "properties": {
                    "networkAcls": {
                        "bypass": "AzureServices",
                        "virtualNetworkRules": [],
                        "ipRules": [],
                        "defaultAction": "Allow"
                    },
                    "supportsHttpsTrafficOnly": true,
                    "encryption": {
                        "services": {
                            "file": {
                                "keyType": "Account",
                                "enabled": true
                            },
                            "blob": {
                                "keyType": "Account",
                                "enabled": true
                            }
                        },
                        "keySource": "Microsoft.Storage"
                    }
                }
            }
        ]
    }
    

    【讨论】:

      猜你喜欢
      • 2021-06-23
      • 1970-01-01
      • 2019-07-30
      • 1970-01-01
      • 2018-02-09
      • 1970-01-01
      • 2022-08-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多