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

Terraform创建AWS IAM策略失败:策略文档格式错误

问题描述

尝试通过Terraform模块为多个ECR仓库创建AWS IAM策略,terraform plan执行无异常,但terraform apply时返回以下错误:

Error: error creating IAM policy ecr-repo-user-policy: MalformedPolicyDocument: Syntax errors in policy.

使用AWS控制台创建内容完全一致的策略可正常生效,尝试调整关键字大小写、增删逗号后问题仍未解决。

相关代码及输出如下:

Terraform模块调用

module "cocos-ecr-all-repo-policy" {
  count      = (data.aws_region.current.name == "eu-central-1" ? 1 : 0)
  source     = "./modules/ecr-policies/ecr-all-repo-policy"
  account_id = data.aws_caller_identity.current.account_id
}

原始模块代码

variable "account_id" {
  type        = string
  description = "AWS account id"
}

resource "aws_iam_policy" "iam-policy" {
  name = "ecr-repo-user-policy"
  description = "IAM policy for ecr users"

  tags = {
    Creator = "terraform"
  }

  policy = jsonencode({
    Version   = "2012-10-17"
    statement = [
      {
        sid       = "EcrRepositoryAccess"
        effect    = "Allow"
        action   = [
          "ecr:DescribeImages",
          "ecr:ListTagsForResource",
          "ecr:ListImages",
          "ecr:PutImage",
          "ecr:GetDownloadUrlForLayer",
          "ecr:BatchGetImage",
          "ecr:BatchCheckLayerAvailability",
          "ecr:BatchDeleteImage",
          "ecr:InitiateLayerUpload",
          "ecr:UploadLayerPart",
          "ecr:CompleteLayerUpload",
        ]
        resources = [
          "arn:aws:ecr:*:${var.account_id}:repository/repo1/*",
          "arn:aws:ecr:*:${var.account_id}:repository/repo2/*",
        ]
      },
      {
        sid       = "EcrToken"
        effect    = "Allow"
        actions   = [
          "ecr:GetAuthorizationToken",
        ]
        resources = [
          "*",
        ]
      }
    ]
  })

}

控制台可正常生效的策略

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "ecr:DescribeImages",
                "ecr:ListTagsForResource",
                "ecr:ListImages",
                "ecr:PutImage",
                "ecr:GetDownloadUrlForLayer",
                "ecr:BatchGetImage",
                "ecr:BatchCheckLayerAvailability",
                "ecr:InitiateLayerUpload",
                "ecr:UploadLayerPart",
                "ecr:CompleteLayerUpload"
            ],
            "Resource": [
                "arn:aws:ecr:*:<AWS account id>:repository/repo1/*",
                "arn:aws:ecr:*:<AWS account id>:repository/repo2/*"
            ]
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": "ecr:GetAuthorizationToken",
            "Resource": "*"
        }
    ]
}
问题根源

AWS IAM策略的JSON关键字严格区分大小写,必须遵循官方规定的驼峰命名格式。原始代码中存在多处关键字大小写错误:

  • 顶级键statement应为Statement(首字母大写)
  • Statement对象内的键:
    • sid → Sid
    • effect → Effect
    • action/actions → Action(无论单个或多个操作,键名统一使用单数Action)
    • resources → Resource(无论单个或多个资源,键名统一使用单数Resource)

Terraform的jsonencode会保留原始键名的大小写,但AWS策略引擎无法识别这些不符合规范的关键字,因此抛出格式错误。

修正后的模块代码
variable "account_id" {
  type        = string
  description = "AWS account id"
}

resource "aws_iam_policy" "iam-policy" {
  name        = "ecr-repo-user-policy"
  description = "IAM policy for ecr users"

  tags = {
    Creator = "terraform"
  }

  policy = jsonencode({
    Version   = "2012-10-17"
    Statement = [
      {
        Sid       = "EcrRepositoryAccess"
        Effect    = "Allow"
        Action    = [
          "ecr:DescribeImages",
          "ecr:ListTagsForResource",
          "ecr:ListImages",
          "ecr:PutImage",
          "ecr:GetDownloadUrlForLayer",
          "ecr:BatchGetImage",
          "ecr:BatchCheckLayerAvailability",
          "ecr:BatchDeleteImage",
          "ecr:InitiateLayerUpload",
          "ecr:UploadLayerPart",
          "ecr:CompleteLayerUpload",
        ]
        Resource = [
          "arn:aws:ecr:*:${var.account_id}:repository/repo1/*",
          "arn:aws:ecr:*:${var.account_id}:repository/repo2/*",
        ]
      },
      {
        Sid       = "EcrToken"
        Effect    = "Allow"
        Action    = [
          "ecr:GetAuthorizationToken",
        ]
        Resource = [
          "*",
        ]
      }
    ]
  })
}
验证说明

修正后,生成的策略JSON结构与AWS控制台的规范格式完全一致,执行terraform apply即可正常创建IAM策略。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 02:50:51