Terraform AzureRM报错:不支持azurerm_resource_group_policy_assignment资源类型
azurerm_resource_group_policy_assignment资源类型? 问题背景
尝试通过Terraform在资源组(RG)级别设置策略规则,主代码与模块代码如下,运行时触发错误:
主代码
locals { tenant_id = "xxxxxxxxxxxx" subscription_id = var.env == "dev" ? "xxxxxxxx" : "xxxxxxxxxxx" aad_group = "xxxxxxxxxxxxx" # az_nemolink_data_engineers } locals { common_tags = { "Application Name" = "${var.env == "dev" ? "dev nll-001" : "prd nll-001"}" "Environment" = "${var.env == "dev" ? "DEV" : "PRD"}" } common_dns_tags = { "Environment" = "${var.env == "dev" ? "DEV" : ""}" } } provider "azuread" { client_id = var.azure_client_id client_secret = var.azure_client_secret tenant_id = var.azure_tenant_id } # PROVIDER REGISTRATION provider "azurerm" { storage_use_azuread = false skip_provider_registration = true features {} tenant_id = local.tenant_id subscription_id = local.subscription_id client_id = var.azure_client_id client_secret = var.azure_client_secret } # LOCALS locals { location = "West Europe" } # MODULES module "subnet_ranges" { source = "hashicorp/subnets/cidr" base_cidr_block = var.base_cidr_block networks = [ { name = "vm-endpoint" new_bits = 5 # 28 bits => 16 adresses } ] } ########### Resource Group ############# resource "azurerm_resource_group" "dataplatform" { name = "rg-xxx-xxx-${var.env}" location = "West Europe" } module "policy_deny_public_storage_account" { source = "./policies/policy_storage_account" count = try(var.deploy_policies.policy_deny_public_storage_account, false) == true ? 1 : 0 resource_groups = azurerm_resource_group.dataplatform.name }
模块代码
resource "azurerm_policy_definition" "policy_deny_public_storage_account" { name = "DenyPublicStorageAccount" policy_type = "Custom" mode = "Indexed" display_name = "Restrict Public-Facing Storage Accounts - Terraform" description = "This policies denies that storage accounts in the given scope can be reached from their public endpoint" metadata = <<METADATA { "category": "MDP-Security" } METADATA policy_rule = <<POLICY_RULE { "if": { "allOf": [ { "field": "type", "equals": "Microsoft.Storage/storageAccounts" }, { "field": "Microsoft.Storage/storageAccounts/networkAcls.defaultAction", "notequals": "Deny" } ] }, "then": { "effect": "deny" } } POLICY_RULE } resource "azurerm_resource_group_policy_assignment" "deny_public_storage_accounts" { for_each = var.resource_groups name = format("DenyPublicStorageAccounts-%s", each.value.name) resource_group_id = each.value.id # not_scopes = var.security_policy_deny_public_storage_accounts_excluded policy_definition_id = azurerm_policy_definition.policy_deny_public_storage_account.id description = "Policy Assignment to restrict public-facing Storage Accounts" display_name = format("Terraform - Deny Public-Facing Storage Accounts - %s", each.value.name) }
错误信息
│ Error: Invalid resource type
│
│ on policies\policy_storage_account\main.tf line 41, in resource "azurerm_resource_group_policy_assignment" "deny_public_storage_accounts":
│ 41: resource "azurerm_resource_group_policy_assignment" "deny_public_storage_accounts" {
│
│ The provider hashicorp/azurerm does not support resource type "azurerm_resource_group_policy_assignment".
原因分析
这个错误确实是AzureRM Provider版本导致的:
azurerm_resource_group_policy_assignment是AzureRM Provider v2.x及更早版本的专属资源类型,用于资源组级别的策略分配。- 在AzureRM Provider v3.x及以后版本中,官方将订阅、资源组等不同层级的策略分配资源合并为通用的
azurerm_policy_assignment,通过scope参数指定作用范围,不再区分层级专属资源。
解决方案
1. 升级AzureRM Provider版本
确保你的Terraform配置中使用v3.x及以上版本的AzureRM Provider,可在versions.tf中定义版本约束:
terraform { required_providers { azurerm = { source = "hashicorp/azurerm" version = ">= 3.0.0" } } }
2. 修改模块中的策略分配资源
将azurerm_resource_group_policy_assignment替换为通用的azurerm_policy_assignment,并通过scope参数指定资源组ID:
resource "azurerm_policy_assignment" "deny_public_storage_accounts" { for_each = var.resource_groups name = format("DenyPublicStorageAccounts-%s", each.value.name) scope = each.value.id policy_definition_id = azurerm_policy_definition.policy_deny_public_storage_account.id description = "Policy Assignment to restrict public-facing Storage Accounts" display_name = format("Terraform - Deny Public-Facing Storage Accounts - %s", each.value.name) }
3. 修正主代码的参数传递
主代码中当前传递的resource_groups是资源组名称,需要改为传递完整的资源组对象,确保模块能获取到资源组ID:
module "policy_deny_public_storage_account" { source = "./policies/policy_storage_account" count = try(var.deploy_policies.policy_deny_public_storage_account, false) == true ? 1 : 0 resource_groups = { azurerm_resource_group.dataplatform.name = azurerm_resource_group.dataplatform } }
4. 同步模块变量定义
在模块的variables.tf中,更新resource_groups变量的类型,以接收资源组对象:
variable "resource_groups" { type = map(object({ id = string name = string })) description = "Map of resource group objects to assign the policy to" }
补充说明
如果因特殊需求必须保留旧版AzureRM Provider,需锁定版本为v2.x,但旧版本已停止维护,存在安全与功能缺失风险,建议优先升级到最新稳定版。
内容的提问来源于stack exchange,提问作者Greencolor

