You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Terraform AWS IAM角色模块重构:多策略输入报错排查

解决Terraform IAM模块接收Terragrunt传入多策略的JSON格式问题

问题根源

你遇到的"policy包含无效JSON策略:不允许前导空格字符"错误,本质是因为:

  • 用list(string)类型接收策略时,传入的格式化JSON(带缩进、换行)会保留多余空格,AWS IAM策略引擎会将这些空格视为非法字符
  • 直接用字符串传递JSON时,无法自动处理格式问题,导致验证失败

解决方案

重构模块时,调整变量结构、自动处理JSON格式,同时实现1个IAM角色关联1-10个策略的需求,具体步骤如下:

1. 修正变量定义

将原有的list(string)类型变量,改为带名称的结构化列表,方便for_each唯一标识每个策略,同时支持传入HCL对象或JSON字符串:

# variables.tf
variable "iam_policies" {
  type = list(object({
    name   = string # 策略唯一名称,用于for_each和资源命名
    policy = any    # 支持传入HCL对象或格式化JSON字符串
  }))
  description = "传入的IAM策略列表,最多支持10个"
  validation {
    condition     = length(var.iam_policies) <= 10 && length(var.iam_policies) >= 1
    error_message = "策略数量必须在1-10个之间。"
  }
}

variable "iam_role_name" {
  type        = string
  description = "IAM角色名称"
}

2. 处理JSON格式并创建IAM策略

使用jsonencode()函数自动将策略内容转换为AWS接受的紧凑JSON格式,同时用策略名称作为for_each的键,避免索引带来的资源重建问题:

# main.tf
# 创建IAM托管策略
resource "aws_iam_policy" "custom" {
  for_each = { for p in var.iam_policies : p.name => p }

  name        = each.value.name
  description = "Custom policy: ${each.value.name}"
  # 用jsonencode处理,不管传入的是HCL对象还是格式化字符串,都转成合法JSON
  policy      = jsonencode(each.value.policy)
}

# 创建IAM角色
resource "aws_iam_role" "main" {
  name = var.iam_role_name

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = "sts:AssumeRole"
        Effect = "Allow"
        Principal = {
          Service = "ec2.amazonaws.com" # 根据实际场景修改信任主体
        }
      }
    ]
  })
}

# 关联策略到角色
resource "aws_iam_role_policy_attachment" "custom" {
  for_each = aws_iam_policy.custom

  role       = aws_iam_role.main.name
  policy_arn = each.value.arn
}

3. Terragrunt调用示例

在Terragrunt配置中,可以灵活传入HCL对象或格式化JSON字符串:

# terragrunt.hcl
terraform {
  source = "../path/to/your/iam-module"
}

inputs = {
  iam_role_name = "my-app-role"
  iam_policies = [
    # 传入HCL对象(推荐,更易维护)
    {
      name   = "s3-read-access"
      policy = {
        Version = "2012-10-17"
        Statement = [
          {
            Effect   = "Allow"
            Action   = "s3:GetObject"
            Resource = "arn:aws:s3:::my-bucket/*"
          }
        ]
      }
    },
    # 传入格式化JSON字符串
    {
      name   = "lambda-invoke-access"
      policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "lambda:InvokeFunction",
      "Resource": "arn:aws:lambda:us-east-1:123456789012:function:my-function"
    }
  ]
}
EOF
    }
  ]
}

关键说明

  • jsonencode()会自动移除多余空格、换行,确保生成的JSON符合AWS IAM的格式要求,彻底解决前导空格问题
  • 用策略名称作为for_each键,当策略顺序调整时不会触发资源重建,比用列表索引更稳定
  • 变量验证规则确保策略数量在1-10个之间,符合需求

内容的提问来源于stack exchange,提问作者Oleksadr S

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 20:32:50