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

Terraform创建KMS Key报错‘策略含无效主体’原因排查问询

KMS密钥创建报错排查:Policy contains a statement with one or more invalid principals

问题描述

我在使用两段不同的Terraform代码创建KMS密钥时,均触发相同错误:Policy contains a statement with one or more invalid principals。多次尝试仍未定位原因,想确认KMS策略是否禁止使用通配符?该报错发生在创建用于批量配置资源权限的权限栈过程中。

报错信息

│ Error: updating KMS Key (ssss-cdb7-xxx-a58c-ss): updating policy: MalformedPolicyDocumentException: Policy contains a statement with one or more invalid principals.
│ 
│   with module.kms.aws_kms_key.sns-encryption-key,
│   on kms/main.tf line 181, in resource "aws_kms_key" "sns-encryption-key":
│  181: resource "aws_kms_key" "sns-encryption-key" {

两段Terraform代码

第一段代码

resource "aws_kms_key" "sns-encryption-key" {
  description             = "This key is used to encrypt sns queue"
  deletion_window_in_days = 7
  enable_key_rotation     = true
  policy                  = jsonencode({
    Version   = "2012-10-17"
    Statement = [
      {
        Effect    = "Allow"
        Principal = {
          Service = "s3.amazonaws.com"
        }
        Action = [
          "kms:GenerateDataKey*",
          "kms:Decrypt"
        ]
        Resource = "*"
      },
      {
        Effect    = "Allow"
        Principal = {
          AWS = [
            "arn:aws:iam::${var.account_id}:role/${var.env_name}*",
            "arn:aws:iam::${var.account_id}:root"
          ]
        }
        Action = [
          "kms:*",
        ]
        Resource = "*"
      },
    ]
  })

  tags = {
    Environment     = var.env_name
    EnvironmentType = var.env_type
    CreatedAt       = timestamp()
  }
  lifecycle {
    prevent_destroy = true
  }
}

第二段代码

resource "aws_kms_key" "sns-encryption-key" {
  description             = "This key is used to encrypt sns queue"
  deletion_window_in_days = 7
  enable_key_rotation    = true
      # Version = "2012-10-17",
      # Id      = "key-policy-1",
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect = "Allow"
        Resource = "*"
        Action = ["kms:GenerateDataKey*", "kms:Decrypt", "kms:Encrypt"]
        Principal = {
          Service = "s3.amazonaws.com"
        }
      },
      {
        Effect  = "Allow"
        Principal = {
          AWS = "arn:aws:iam::${var.account_id}:role/*" 
        }
        Action = [ "kms:*" ]
        Resource = "*"
      },
      {
        Effect    = "Allow"
        Principal = {
          AWS = "arn:aws:iam::${var.account_id}:root"
        }
        Action = ["kms:*"]
        Resource = "*"
      }
    ]
  })

  tags = {
    Environment     = var.env_name
    EnvironmentType = var.env_type
    CreatedAt       = timestamp()
  }
  lifecycle {
    prevent_destroy = true
  }
}

问题原因与解决方法

KMS密钥策略允许使用通配符,报错并非通配符本身导致,而是违反了KMS策略的核心规则:策略中Resource字段不能用*指代当前密钥,必须明确指定密钥自身的ARN。当设置Resource = "*"时,KMS无法正确识别目标密钥,进而触发Principal验证失败。

修正步骤

  1. 在策略中替换所有Resource = "*"为当前KMS密钥的ARN,可直接使用Terraform内置的aws_kms_key.sns-encryption-key.arn引用。
  2. 确保包含根用户的语句合法(你的代码中已正确配置根用户ARN,无需修改)。

修正后的示例代码

resource "aws_kms_key" "sns-encryption-key" {
  description             = "This key is used to encrypt sns queue"
  deletion_window_in_days = 7
  enable_key_rotation     = true
  policy                  = jsonencode({
    Version   = "2012-10-17"
    Statement = [
      {
        Effect    = "Allow"
        Principal = {
          Service = "s3.amazonaws.com"
        }
        Action = [
          "kms:GenerateDataKey*",
          "kms:Decrypt"
        ]
        Resource = aws_kms_key.sns-encryption-key.arn
      },
      {
        Effect    = "Allow"
        Principal = {
          AWS = [
            "arn:aws:iam::${var.account_id}:role/${var.env_name}*",
            "arn:aws:iam::${var.account_id}:root"
          ]
        }
        Action = [
          "kms:*",
        ]
        Resource = aws_kms_key.sns-encryption-key.arn
      },
    ]
  })

  tags = {
    Environment     = var.env_name
    EnvironmentType = var.env_type
    CreatedAt       = timestamp()
  }
  lifecycle {
    prevent_destroy = true
  }
}

额外注意事项

  • Terraform会自动处理当前资源ARN的内部引用,不会引发循环依赖;若出现异常,可改用aws_caller_identity数据源结合密钥ID构造ARN。
  • 你代码中使用的角色ARN前缀通配符(如${var.env_name}*、role/*)是合法的,KMS支持此类IAM身份的前缀匹配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 14:27:01