Terraform使用for_each调用IAM策略数据源时JSON策略无效问题排查
问题
在aws_ssoadmin_permission_set_inline_policy资源中,尝试用for_each遍历本地变量permission_sets_name中的名称,对应引用同名的aws_iam_policy_document数据源。但用format函数拼接data.aws_iam_policy_document.%s.json时,Terraform提示“inline_policy包含无效JSON策略”;直接硬编码数据源名称(如data.aws_iam_policy_document.emobg-sso-billing-admin.json)则能正常运行。
相关代码:
data "aws_iam_policy_document" "emobg-sso-billing-admin" { statement { sid = "VisualEditor0" effect = "Allow" actions = [ "aws-marketplace:*", "aws-portal:*", "budgets:*" ] resources = [ "*", ] } } data "aws_iam_policy_document" "emobg-sso-billing-audit" { statement { sid = "VisualEditor0" effect = "Allow" actions = [ "support:*", "tag:*", "s3:*" ] resources = [ "*", ] } } resource "aws_ssoadmin_permission_set" "emobg" { for_each = toset(local.permission_sets_name) name = each.key description = each.key instance_arn = local.sso_instance_arn session_duration = local.session_duration } resource "aws_ssoadmin_permission_set_inline_policy" "emobg" { for_each = toset(local.permission_sets_name) inline_policy = format("data.aws_iam_policy_document.%s.json", each.key) # <-- 不生效 # inline_policy = data.aws_iam_policy_document.emobg-sso-billing-admin.json # <-- 生效 instance_arn = local.sso_instance_arn permission_set_arn = aws_ssoadmin_permission_set.emobg[each.key].arn } locals { session_duration = "PT8H" permission_sets_name = [ "emobg-sso-billing-admin", "emobg-sso-billing-audit", ] }
错误信息:
2022-11-01T01:19:43.923+0100 [ERROR] vertex "aws_ssoadmin_permission_set_inline_policy.emobg[\"emobg-sso-billing-admin\"]" error: "inline_policy" contains an invalid JSON policy 2022-11-01T01:19:43.923+0100 [ERROR] vertex "aws_ssoadmin_permission_set_inline_policy.emobg (expand)" error: "inline_policy" contains an invalid JSON policy ╷ │ Error: "inline_policy" contains an invalid JSON policy │ │ with aws_ssoadmin_permission_set_inline_policy.emobg["emobg-sso-billing-admin"], │ on permission_set.tf line 13, in resource "aws_ssoadmin_permission_set_inline_policy" "emobg": │ 13: inline_policy = format("data.aws_iam_policy_document.%s.json", each.value)
疑惑:逻辑上两种方式应该一致,为何JSON策略会无效?
解决方法
你用format函数生成的是字符串字面量(比如"data.aws_iam_policy_document.emobg-sso-billing-admin.json"),而不是Terraform对数据源属性的引用。Terraform会把这个字符串直接当作JSON策略内容,显然这不是合法的JSON,所以报错。
要动态引用同名的数据源属性,需要用Terraform的动态索引语法,直接通过数据源的索引访问:
修正后的代码
修改aws_ssoadmin_permission_set_inline_policy中的inline_policy字段:
resource "aws_ssoadmin_permission_set_inline_policy" "emobg" { for_each = toset(local.permission_sets_name) inline_policy = data.aws_iam_policy_document[each.key].json # 正确的动态引用方式 instance_arn = local.sso_instance_arn permission_set_arn = aws_ssoadmin_permission_set.emobg[each.key].arn }
原理说明
- Terraform中,当资源/数据源的名称是动态值时,不能用
.拼接字符串来引用,而要通过[动态键]的索引语法访问。 data.aws_iam_policy_document[each.key]会找到名称匹配each.key的数据源实例,再访问其.json属性,得到真正的JSON策略内容,这样就能被Terraform正确识别。
内容的提问来源于stack exchange,提问作者Bakka
相关产品推荐
相关产品推荐

