For the last week or so I have been working on a Terraform module for deploying tasks to ECS. One of the most interesting problems that I came across while working on it was around creating IAM profiles. Each task that gets deployed needs to have a minimum set of permissions in their IAM profile, but some need to have more than others. After thinking about various ways to solve my problem, I decided to give dynamic blocks a try.
When writing IAM policies in Terraform, I prefer to do it in an aws_iam_policy_document
data block rather than in pure JSON or a template file since Terraform can validate the syntax in a data block. A typical policy might look something like this:
data "aws_iam_policy_document" "role_policy" {
statement {
effect = "Allow"
actions = [
"ec2:AuthorizeSecurityGroupIngress",
"ec2:Describe*",
"elasticloadbalancing:DeregisterInstancesFromLoadBalancer",
"elasticloadbalancing:DeregisterTargets",
"elasticloadbalancing:Describe*",
"elasticloadbalancing:RegisterInstancesWithLoadBalancer",
"elasticloadbalancing:RegisterTargets",
]
resources = ["*"]
}
}
The above policy is an example of something that I may want to attach to every task I launch so that it can update itself with a load balancer. So for me to be able to add a statement through my tfvars, I added a dynamic statement block to the bottom:
data "aws_iam_policy_document" "role_policy" {
statement {
effect = "Allow"
actions = [
"ec2:AuthorizeSecurityGroupIngress",
"ec2:Describe*",
"elasticloadbalancing:DeregisterInstancesFromLoadBalancer",
"elasticloadbalancing:DeregisterTargets",
"elasticloadbalancing:Describe*",
"elasticloadbalancing:RegisterInstancesWithLoadBalancer",
"elasticloadbalancing:RegisterTargets",
]
resources = ["*"]
}
dynamic "statement" {
for_each = var.task_iam_policies
content {
effect = lookup(statement.value, "effect", null)
actions = lookup(statement.value, "actions", null)
resources = lookup(statement.value, "resources", null)
}
}
}
This configuration allows me to configure a variable task_iam_policies
that contains any additional policy statements that I need to add:
task_iam_policies = [
{
effect = "Allow"
actions = [
"iam:PassRole",
"ec2:TerminateInstances",
"ec2:StopInstances",
"ec2:StartInstances",
"ec2:RunInstances",
"ec2:RequestSpotInstances",
"ec2:GetConsoleOutput",
"ec2:DescribeSubnets",
"ec2:DescribeSpotPriceHistory",
"ec2:DescribeSpotIstanceRequests",
"ec2:DescribeSecurityGroups",
"ec2:DescribeRegions",
"ec2:DescribeKeyPairs",
"ec2:DescribeInstances",
"ec2:DescribeImages",
"ec2:DescribeAvailabilityZones",
"ec2:DeleteTags",
"ec2:CreateTags",
"ec2:CancelSpotInstanceRequests",
]
resources = ["*"]
}
]
Now I can add as many statements as I need to my task when I deploy it.
Comments