Reputation: 2575
I have an aws_iam_user_policy
resource in terraform as follows:
resource "aws_iam_user_policy" "pol" {
name = "policy"
user = aws_iam_user.singleuser.name
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:List*"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::toybucket-development/*",
"arn:aws:s3:::toybucket-staging/*",
"arn:aws:s3:::toybucket-production/*"
]
}
]
}
EOF
}
The resources with development
, staging
and production
are something I'm hoping to put in one line through using a list variable with the values development
, staging
and production
and somehow looping through them, but I'm unsure of how to do this within the EOF
. I know normally you can loop through such list variable but that's in normal terraform and not when you have this EOF
with a string that represents a json. Would anyone know of a solution?
Upvotes: 1
Views: 1740
Reputation: 901
I'm a big fan of using the data source aws_iam_policy_document
for creating all kind of iam policy like resources. In combination with a locals
using the formatlist
function you can achieve your desired result.
This could look like this:
locals {
resource_arns = formatlist("arn:aws:s3:::toybucket-%s/*", ["development", "staging", "production"])
}
data "aws_iam_policy_document" "policy" {
statement {
actions = ["s3:List*"]
effect = "Allow"
resources = [local.resource_arns]
}
}
resource "aws_iam_polcy" "pol" {
name = "policy"
user = aws_iam_user.singleuser.name
policy = data.aws_iam_policy_document.policy.json
}
Upvotes: 1
Reputation: 28854
You can do this most easily with a Terraform template, and the templatefile
function. The templatefile
function invocation would appear like:
resource "aws_iam_user_policy" "pol" {
name = "policy"
user = aws_iam_user.singleuser.name
policy = templatefile("${path.module}/policy.tmpl", { envs = ["development", "staging", "production"] }
}
The documentation for the function is probably helpful.
The template would appear like:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:List*"
],
"Effect": "Allow",
"Resource": [
%{~ for env in envs ~}
"arn:aws:s3:::toybucket-${env}/*"%{ if env != envs[length(envs) - 1] },%{ endif }
%{~ endfor ~}
]
}
]
}
That check at the end for adding a comma only if it is not the last element to ensure JSON format syntax is not super great. However, there is no easy check in Terraform DSL for whether a list/slice (latter being implicitly derived from Golang) is the last element, and using jsonencode
would require placing the entire ARN in the variable list.
If envs = ["arn:aws:s3:::toybucket-development/*", "arn:aws:s3:::toybucket-staging/*", "arn:aws:s3:::toybucket-production/*"]
, then you could jsonencode(envs)
.
Upvotes: 2