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

如何用Terraform Data重写IAM角色策略并解决创建报错

问题描述

原本通过jsonencode编写的IAM角色信任策略代码如下:

assume_role_policy = jsonencode({
  "Version" : "2012-10-17",
  "Statement" : [
    {
      "Action" : "sts:AssumeRoleWithWebIdentity",
      "Condition" : {
        "StringEquals" : {
          "${replace(module.complete_eks_cluster.identity[0].oidc[0].issuer, "https://", "")}:aud" : "sts.amazonaws.com",
          "${replace(module.complete_eks_cluster.identity[0].oidc[0].issuer, "https://", "")}:sub" : "system:serviceaccount:kube-system:ebs-csi-controller-sa"
        }
      },
      "Effect" : "Allow",
      "Sid" : "EBSDriverRole",
      "Principal" : {
        "Federated" : module.complete_eks_cluster.oidc_arn[0]
      }
    },
  ]
})

尝试用Terraform的data数据源重构策略,编写的代码如下:

data "aws_iam_policy_document" "ebs_csi_driver" {
  statement {
    actions = ["sts:AssumeRoleWithWebIdentity"]
    
    condition {
      test     = "StringEquals"
      variable = "${replace(module.eks_cluster.identity[0].oidc[0].issuer, "https://", "")}:aud"
      values   = ["sts.amazonaws.com"]
    }
    
    condition {
      test     = "StringEquals"
      variable = "${replace(module.eks_cluster.identity[0].oidc[0].issuer, "https://", "")}:sub"
      values   = ["system:serviceaccount:kube-system:ebs-csi-controller-sa"]
    }
  }
}
    
resource "aws_iam_policy" "ebs_csi_driver_policy" {
  name   = "${var.cluster_name}-ebs-csi-driver-policy"
  policy = data.aws_iam_policy_document.ebs_csi_driver.json
}
    
resource "aws_iam_role" "ebs_csi_driver_role" {
  name                 = var.is_rapid ? "CUSPFE-${var.cluster_name}-ebs-csi-driver-role" : "${var.cluster_name}-vpc-cni-driver-role"
  assume_role_policy   = data.aws_iam_policy_document.ebs_csi_driver.json
  permissions_boundary = var.is_rapid ? var.rapid_role_permissions_boundary : null
  tags                 = local.tags
}
    
resource "aws_iam_role_policy_attachment" "ebs_csi_driver" {
  role       = aws_iam_role.ebs_csi_driver_role.name
  policy_arn = aws_iam_policy.ebs_csi_driver_policy.arn
}

执行时出现两个错误:

│ Error: creating IAM Policy (eks-ebs-csi-driver-policy): MalformedPolicyDocument: Policy statement must contain resources.
│     status code: 400, request id: 754503a6-6130-44a0-880a-c7cde1f0e73b
│ 
│   with module.eks.aws_iam_policy.ebs_csi_driver_policy,
│   on .terraform/modules/eks/iam.tf line 20, in resource "aws_iam_policy" "ebs_csi_driver_policy":
│   20: resource "aws_iam_policy" "ebs_csi_driver_policy" {
│ 
╵
╷
│ Error: creating IAM Role (eks-ebs-csi-driver-role): MalformedPolicyDocument: Missing required field Principal
│     status code: 400, request id: c4ebff87-a8b3-4028-b3d5-1bdcfca167b1
│ 
│   with module.eks.aws_iam_role.ebs_csi_driver_role,
│   on .terraform/modules/eks/iam.tf line 25, in resource "aws_iam_role" "ebs_csi_driver_role":
│   25: resource "aws_iam_role" "ebs_csi_driver_role" {
解决方案

这两个错误源于混淆了IAM角色信任策略和IAM权限策略的用途,以及重构时遗漏了必要字段:

错误1:IAM权限策略缺少Resources字段

aws_iam_policy是用来定义权限策略的,这类策略必须指定Resources(允许/拒绝访问的资源),但你当前的aws_iam_policy_document是用来做角色信任策略的(控制谁能扮演该角色),不适合直接作为权限策略使用。

如果EBS CSI驱动需要权限,你应该单独定义权限策略(比如允许操作EBS资源的策略),而不是复用信任策略的文档。

错误2:角色信任策略缺少Principal字段

你的data "aws_iam_policy_document" "ebs_csi_driver"里没有定义principal块,而角色的assume_role_policy(信任策略)必须指定允许扮演角色的主体(Principal),也就是原代码里的OIDC联邦身份提供商。

修正后的完整代码

# 1. 定义角色信任策略(允许EBS CSI服务账号扮演角色)
data "aws_iam_policy_document" "ebs_csi_assume_role" {
  statement {
    actions = ["sts:AssumeRoleWithWebIdentity"]
    
    # 补充缺失的Principal块
    principals {
      type        = "Federated"
      identifiers = [module.eks_cluster.oidc_arn[0]]
    }
    
    condition {
      test     = "StringEquals"
      variable = "${replace(module.eks_cluster.identity[0].oidc[0].issuer, "https://", "")}:aud"
      values   = ["sts.amazonaws.com"]
    }
    
    condition {
      test     = "StringEquals"
      variable = "${replace(module.eks_cluster.identity[0].oidc[0].issuer, "https://", "")}:sub"
      values   = ["system:serviceaccount:kube-system:ebs-csi-controller-sa"]
    }
  }
}

# 2. 定义EBS CSI驱动需要的权限策略(示例,根据实际需求调整)
data "aws_iam_policy_document" "ebs_csi_permissions" {
  statement {
    actions = [
      "ec2:CreateSnapshot",
      "ec2:AttachVolume",
      "ec2:DetachVolume",
      "ec2:ModifyVolume",
      "ec2:DescribeVolumes",
      "ec2:DescribeSnapshots",
      "ec2:DescribeAvailabilityZones",
      "ec2:DescribeVolumeStatus"
    ]
    resources = ["*"]
    effect    = "Allow"
  }
}

resource "aws_iam_policy" "ebs_csi_driver_policy" {
  name   = "${var.cluster_name}-ebs-csi-driver-policy"
  policy = data.aws_iam_policy_document.ebs_csi_permissions.json
}

resource "aws_iam_role" "ebs_csi_driver_role" {
  name                 = var.is_rapid ? "CUSPFE-${var.cluster_name}-ebs-csi-driver-role" : "${var.cluster_name}-ebs-csi-driver-role"
  # 使用正确的信任策略文档
  assume_role_policy   = data.aws_iam_policy_document.ebs_csi_assume_role.json
  permissions_boundary = var.is_rapid ? var.rapid_role_permissions_boundary : null
  tags                 = local.tags
}

resource "aws_iam_role_policy_attachment" "ebs_csi_driver" {
  role       = aws_iam_role.ebs_csi_driver_role.name
  policy_arn = aws_iam_policy.ebs_csi_driver_policy.arn
}

额外说明

  • 修正了角色名称的笔误:原代码中else分支是vpc-cni-driver-role,改为ebs-csi-driver-role避免混淆。
  • 权限策略的actions和resources可以根据EBS CSI驱动的官方文档调整,确保权限最小化。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 02:53:15