如何用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
相关产品推荐
相关产品推荐

