如何为资源组内新建VM自动授予Azure Storage Account访问权限
实现Azure资源组内新建VM自动获取存储账户访问权限
方案1:使用Azure Policy自动分配角色
通过自定义deployIfNotExists类型的Policy,在资源组内新建VM(且启用系统分配托管身份)时,自动为其授予目标存储账户的Blob数据访问权限。
步骤说明
- 准备Policy定义:创建如下自定义Policy(可根据需求调整权限角色),保存为
policy.json:
{ "properties": { "displayName": "自动为资源组内VM分配存储账户Blob访问权限", "policyType": "Custom", "mode": "Indexed", "description": "为目标资源组内新建、启用系统分配托管身份的VM,自动分配Storage Blob Data Contributor角色,使其可访问指定存储账户", "parameters": { "storageAccountId": { "type": "String", "metadata": { "description": "目标存储账户的资源ID" } }, "roleDefinitionId": { "type": "String", "defaultValue": "/providers/Microsoft.Authorization/roleDefinitions/ba92f5b4-2d11-453d-a403-e96b0029c9fe", "metadata": { "description": "Storage Blob Data Contributor角色的ID" } } }, "policyRule": { "if": { "allOf": [ { "field": "type", "equals": "Microsoft.Compute/virtualMachines" }, { "field": "resourceGroup", "equals": "[resourceGroup().name]" }, { "field": "identity.type", "contains": "SystemAssigned" } ] }, "then": { "effect": "deployIfNotExists", "details": { "type": "Microsoft.Authorization/roleAssignments", "roleDefinitionId": "[parameters('roleDefinitionId')]", "existenceCondition": { "allOf": [ { "field": "Microsoft.Authorization/roleAssignments/principalId", "equals": "[reference(field('id'), '2021-03-01').identity.principalId]" }, { "field": "Microsoft.Authorization/roleAssignments/scope", "equals": "[parameters('storageAccountId')]" } ] }, "deployment": { "properties": { "mode": "incremental", "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "parameters": { "storageAccountId": { "type": "string" }, "roleDefinitionId": { "type": "string" }, "vmPrincipalId": { "type": "string" } }, "resources": [ { "type": "Microsoft.Authorization/roleAssignments", "apiVersion": "2020-04-01-preview", "name": "[guid(parameters('storageAccountId'), parameters('roleDefinitionId'), parameters('vmPrincipalId'))]", "scope": "[parameters('storageAccountId')]", "properties": { "roleDefinitionId": "[parameters('roleDefinitionId')]", "principalId": "[parameters('vmPrincipalId')]", "principalType": "ServicePrincipal" } } ] }, "parameters": { "storageAccountId": { "value": "[parameters('storageAccountId')]" }, "roleDefinitionId": { "value": "[parameters('roleDefinitionId')]" }, "vmPrincipalId": { "value": "[reference(field('id'), '2021-03-01').identity.principalId]" } } } } } } } } }
- 创建并分配Policy:
- 通过Azure CLI执行
az policy definition create --name "AutoAssignStorageAccessToVM" --display-name "自动为VM分配存储账户权限" --rules policy.json --mode Indexed创建Policy定义 - 执行
az policy assignment create --name "AssignAutoStorageAccessPolicy" --policy "AutoAssignStorageAccessToVM" --resource-group <你的资源组名称> --params "{\"storageAccountId\": {\"value\": \"/subscriptions/<订阅ID>/resourceGroups/<资源组名称>/providers/Microsoft.Storage/storageAccounts/<存储账户名称>\"}}",将Policy绑定到目标资源组
- 通过Azure CLI执行
- 强制VM启用系统托管身份:可额外创建一个Policy,确保资源组内新建VM默认启用系统分配托管身份,避免因未启用MI导致权限分配失败。
方案2:使用Event Grid + Azure Function触发权限分配
通过监听资源组内的VM创建事件,触发Azure Function自动完成角色分配操作,灵活性更高。
步骤说明
创建Event Grid订阅:
- 在Azure Portal进入目标资源组,创建Event Grid订阅
- 事件类型选择
Microsoft.Resources.ResourceWriteSuccess,添加筛选条件:resourceType等于Microsoft.Compute/virtualMachines - 端点类型选择
Azure Function,关联新建的Function
编写Azure Function逻辑:
以下是Python版本的Function示例,需为Function的系统托管身份授予"角色分配管理员"权限(或仅在目标存储账户上的角色分配权限):
import os import azure.functions as func from azure.mgmt.authorization import AuthorizationManagementClient from azure.mgmt.compute import ComputeManagementClient from azure.identity import DefaultAzureCredential def main(event: func.EventGridEvent): event_data = event.get_json() vm_resource_id = event_data['resourceUri'] vm_name = vm_resource_id.split('/')[-1] resource_group = os.environ['RESOURCE_GROUP_NAME'] # 获取VM的系统托管身份Principal ID credential = DefaultAzureCredential() compute_client = ComputeManagementClient(credential, os.environ['AZURE_SUBSCRIPTION_ID']) vm = compute_client.virtual_machines.get(resource_group, vm_name) if not vm.identity or 'SystemAssigned' not in vm.identity.type: print(f"VM {vm_name}未启用系统托管身份,跳过权限分配") return principal_id = vm.identity.principal_id # 为VM的MI分配存储账户Blob访问角色 auth_client = AuthorizationManagementClient(credential, os.environ['AZURE_SUBSCRIPTION_ID']) role_definition_id = "/providers/Microsoft.Authorization/roleDefinitions/ba92f5b4-2d11-453d-a403-e96b0029c9fe" storage_account_id = os.environ['STORAGE_ACCOUNT_ID'] role_assignment_name = os.urandom(16).hex() auth_client.role_assignments.create( scope=storage_account_id, role_assignment_name=role_assignment_name, parameters={ 'role_definition_id': role_definition_id, 'principal_id': principal_id, 'principal_type': 'ServicePrincipal' } ) print(f"已成功为VM {vm_name}的托管身份分配存储账户访问权限")
- 配置Function应用设置:添加
AZURE_SUBSCRIPTION_ID、RESOURCE_GROUP_NAME、STORAGE_ACCOUNT_ID三个环境变量,对应你的Azure订阅ID、目标资源组名称、存储账户资源ID。
注意事项
- 权限最小化:优先使用
Storage Blob Data Contributor角色,避免授予过高权限 - 托管身份依赖:两种方案均要求VM启用系统分配托管身份,若需支持无MI的VM,可改为使用用户分配托管身份
- 测试验证:新建VM后,前往存储账户的"访问控制(IAM)"页面,检查是否存在对应VM托管身份的角色分配
内容的提问来源于stack exchange,提问作者Serge Br
相关产品推荐
相关产品推荐

