如何在Azure现有订阅中强制执行VM角色策略并排除特定资源组
在Azure所有订阅强制执行VM角色策略并排除指定资源组的实现方案
PowerShell 预处理:批量获取订阅列表
要覆盖所有现有订阅,先通过PowerShell批量获取订阅ID,导出为JSON文件供Terraform遍历使用:
- 登录Azure账号:
Connect-AzAccount
- 获取所有订阅并导出(可按需过滤排除特定订阅):
# 提取订阅ID和名称,可添加Where-Object过滤不需要的订阅 $subscriptions = Get-AzSubscription | Select-Object Id, Name # 导出到当前目录的subscriptions.json文件 $subscriptions | ConvertTo-Json -Depth 10 | Out-File "./subscriptions.json"
Terraform 核心部署脚本
1. 基础配置
读取订阅列表,定义要排除的资源组,配置Azure Provider:
terraform { required_providers { azurerm = { source = "hashicorp/azurerm" version = ">= 3.0.0" } } } # 读取订阅列表 locals { subscriptions = jsondecode(file("./subscriptions.json")) # 填写需要排除的资源组名称,支持多个 excluded_resource_groups = ["rg-exclude-prod", "rg-test-01"] } provider "azurerm" { features {} }
2. 遍历订阅分配角色(带资源组排除)
使用for_each遍历每个订阅,通过not_scopes参数指定要排除的资源组:
# 给指定主体分配VM相关角色,排除目标资源组 resource "azurerm_role_assignment" "vm_contributor" { for_each = { for sub in local.subscriptions : sub.Id => sub } scope = "/subscriptions/${each.value.Id}" role_definition_name = "Virtual Machine Contributor" # 替换为你需要的VM角色 principal_id = "xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx" # 替换为目标主体ID(用户/组/服务主体) # 生成要排除的资源组范围列表 not_scopes = [ for rg in local.excluded_resource_groups : "/subscriptions/${each.value.Id}/resourceGroups/${rg}" ] }
3. 自定义强制执行角色(可选)
如果需要更严格的规则(比如禁止删除VM),可以创建自定义角色再分配:
# 创建自定义VM强制执行角色 resource "azurerm_role_definition" "vm_enforce_role" { for_each = { for sub in local.subscriptions : sub.Id => sub } scope = "/subscriptions/${each.value.Id}" name = "VM-Enforce-Policy" description = "禁止删除VM的强制执行角色" permissions { actions = [ "Microsoft.Compute/virtualMachines/read", "Microsoft.Compute/virtualMachines/write", # 添加允许的操作 ] not_actions = [ "Microsoft.Compute/virtualMachines/delete", # 添加要禁止的操作,实现强制执行 ] } assignable_scopes = ["/subscriptions/${each.value.Id}"] } # 分配自定义强制执行角色 resource "azurerm_role_assignment" "vm_enforce_assignment" { for_each = { for sub in local.subscriptions : sub.Id => sub } scope = "/subscriptions/${each.value.Id}" role_definition_id = azurerm_role_definition.vm_enforce_role[each.key].id principal_id = "xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx" not_scopes = [ for rg in local.excluded_resource_groups : "/subscriptions/${each.value.Id}/resourceGroups/${rg}" ] }
执行流程
- 运行PowerShell脚本获取订阅列表并导出
- 修改Terraform脚本中的
principal_id、excluded_resource_groups、角色名称等参数 - 执行Terraform命令:
terraform init terraform plan terraform apply
内容的提问来源于stack exchange,提问作者tinku
相关产品推荐
相关产品推荐

