terraform:有没有一种动态创建IAM策略语句的方法?

时间:2020-06-03 23:05:52

标签: amazon-web-services terraform amazon-iam terraform-provider-aws terraform0.11

Terraform版本:0.11

我正在运行多个eks群集,并尝试在遵循此文档的所有群集中启用基于IAM角色的服务帐户: https://www.terraform.io/docs/providers/aws/r/eks_cluster.html#enabling-iam-roles-for-service-accounts

当我在策略语句中对群集名称进行硬编码并创建多个语句时,此方法有效

data "aws_iam_policy_document" "example_assume_role_policy" {

# for cluster 1

  statement {
    actions = ["sts:AssumeRoleWithWebIdentity"]
    effect  = "Allow"

    condition {
      test     = "StringEquals"
      variable = "${replace(aws_iam_openid_connect_provider.example1.url, "https://", "")}:sub"
      values   = ["system:serviceaccount:kube-system:aws-node"]
    }

    principals {
      identifiers = ["${aws_iam_openid_connect_provider.example1.arn}"]
      type        = "Federated"
    }
  }
}

由于我有多个集群,所以我希望能够动态生成该语句 因此我进行了以下更改:

我创建了一个count变量,并更改了主体和条件的值

count = "${length(var.my_eks_cluster)}" 

    condition {
      test     = "StringEquals"
      variable = "${replace(element(aws_iam_openid_connect_provider.*.url, count.index), "https://", "")}:sub"
      values   = ["system:serviceaccount:kube-system:aws-node"]
    }

    principals {
      identifiers = ["${element(aws_iam_openid_connect_provider.*.url, count.index)}"]
      type        = "Federated"
    }

Terraform现在能够找到群集,但它也会生成多个策略。 而且这是行不通的,因为在以下语法中,假定的_role_policy不接受列表

resource "aws_iam_role" "example" {
  assume_role_policy = "${data.aws_iam_policy_document.example_assume_role_policy.*.json}"
  name               = "example"
}

似乎不需要创建多个策略,而是需要在一个策略中生成多个语句(因此我可以添加到一个iam_role中)。有人做过类似的事情吗?谢谢。

1 个答案:

答案 0 :(得分:5)

您只需要一项策略,因此您不应在策略中使用count参数。 相反,您想要的是多个语句,像这样

data "aws_iam_policy_document" "example" {
  statement {
    # ...
  }
  statement {
    # ...
  }
}

现在您可以直接对此进行硬编码(也许这将是测试它是否有效的一个很好的开始)。如果要从变量动态生成此代码,则需要一个dynamic块,如下所述:https://www.terraform.io/docs/configuration/expressions.html

在您的情况下,可能是

data "aws_iam_policy_document" "example" {
  dynamic "statement" {
    for_each = aws_iam_openid_connect_provider

    content {
      actions = ["sts:AssumeRoleWithWebIdentity"]
      effect  = "Allow"

      condition {
        test     = "StringEquals"
        variable = "${replace(statement.value.url, "https://", "")}:sub"
          values   = ["system:serviceaccount:kube-system:aws-node"]
      }

      principals {
        identifiers = ["${statement.value.arn}"]
        type        = "Federated"
      }      
    }
  }
}

不过,我认为“动态”仅自TF 0.12起可用。