Terraform version: 0.11
I am running multiple eks clusters and trying to enable IAM Roles-based service account in all cluster following this doc: https://www.terraform.io/docs/providers/aws/r/eks_cluster.html#enabling-iam-roles-for-service-accounts
This works when I hardcode the cluster name in the policy statement and create multiple statements
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"
}
}
}
Since I have multiple clusters, I want to be able to generate the statement dynamically so I made the following changes:
I created a count
variable and changed values in principals and and condition
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 now is able to find the clusters BUT also generate multiple policies. And this will not work, since in the following syntax, the assume_role_policy doesn't take the list
resource "aws_iam_role" "example" {
assume_role_policy = "${data.aws_iam_policy_document.example_assume_role_policy.*.json}"
name = "example"
}
It seems like instead of creating multiple policies, I need to generate multiple statements in one policy (so I can add to one iam_role). Has anyone done something similar before ? Thanks.
The Statement element can contain a single statement or an array of individual statements. Each individual statement block must be enclosed in curly braces { }. For multiple statements, the array must be enclosed in square brackets [ ].
Terraform provides the dynamic block to create repeatable nested blocks within a resource. A dynamic block is similar to the for expression.
You only want one policy, so you should not use the count
argument in your policy.
What you want to have instead is multiple statements, like this
data "aws_iam_policy_document" "example" {
statement {
# ...
}
statement {
# ...
}
}
Now you could hard-code this directly (maybe that would be a good start to test if it works). If you want to generate this dynamically from a variable you would need a dynamic
-block as described here: https://www.terraform.io/docs/configuration/expressions.html
In your case that would probably be
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"
}
}
}
}
I think that "dynamic" is only available since TF 0.12, though.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With