Using terraform I am creating a simple bucket and applying a simple bucket policy that allows a role and a user to get access to it. The role/user is different for each account that is being deployed.
# Creating buckets
resource "aws_s3_bucket" "buckets" {
for_each = var.s3_bucket_names
bucket = "${var.prefix}-${var.environment}-${lower(var.github_branch)}-${each.key}"
}
# Apply Bucket policy to buckets.
resource "aws_s3_bucket_policy" "allow_access_to_bucket" {
for_each = aws_s3_bucket.buckets
bucket = each.value.id
policy = templatefile("s3_policy.json", {
tmp_s3_arn = "${each.value.arn}",
object_access = "${var.s3_object_access}"
})
}
Then the policy is like:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "S3ObjectPermissions",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::${tmp_account}:role/role_case_one",
"arn:aws:sts::${tmp_account}:assumed-role/dev_role/[email protected]"]
},
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:PutObjectAcl",
"s3:DeleteObject"
],
"Resource": "${tmp_s3_arn}/*"
}
]
}
But I want to parametrize the principal as they may change on different accounts. I have tried to replace the list of principals for a list in terraform, but it is trying to "add" a new terraform with the information of the list.
I tried to pass just a string and the same, it tries to add the string ad additional principal.
~ Principal = {
~ AWS = [
- "arn:aws:iam::12345:role/role_case_one",
- "arn:aws:sts::12345:assumed-role/assumed-role/dev_role/[email protected]",
] -> "[arn:aws:iam::12345:role/role_case_one,arn:aws:iam::12345:assumed-role/assumed-role/dev_role/[email protected]]"
How can I achieve this?
I think what you want is to use the built-in jsonencode
function within the templated file. For example, something like this should work:
# Creating buckets
resource "aws_s3_bucket" "buckets" {
for_each = var.s3_bucket_names
bucket = "${var.prefix}-${var.environment}-${lower(var.github_branch)}-${each.key}"
}
# Apply Bucket policy to buckets.
resource "aws_s3_bucket_policy" "allow_access_to_bucket" {
for_each = aws_s3_bucket.buckets
bucket = each.value.id
policy = templatefile("s3_policy.json", {
tmp_s3_arn = each.value.arn
roles = ["arn:aws:iam::12345:role/role_case_one", "arn:aws:sts::12345:assumed-role/assumed-role/dev_role/[email protected]"]
})
}
The templated file should then look like the following:
${jsonencode({
"Version": "2012-10-17",
"Statement": [
{
"Sid": "S3ObjectPermissions",
"Effect": "Allow",
"Principal": {
"AWS": [ for role in roles:
role
]
},
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:PutObjectAcl",
"s3:DeleteObject"
],
"Resource": "${tmp_s3_arn}/*"
}
]
})}
You can also check more examples in the documentation. This works:
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# aws_s3_bucket.buckets["averyimportantbucketmarkoe"] will be created
+ resource "aws_s3_bucket" "buckets" {
+ acceleration_status = (known after apply)
+ acl = (known after apply)
+ arn = (known after apply)
+ bucket = "averyimportantbucketmarkoe"
+ bucket_domain_name = (known after apply)
+ bucket_prefix = (known after apply)
+ bucket_regional_domain_name = (known after apply)
+ force_destroy = false
+ hosted_zone_id = (known after apply)
+ id = (known after apply)
+ object_lock_enabled = (known after apply)
+ policy = (known after apply)
+ region = (known after apply)
+ request_payer = (known after apply)
+ tags_all = (known after apply)
+ website_domain = (known after apply)
+ website_endpoint = (known after apply)
}
# aws_s3_bucket_policy.allow_access_to_bucket["averyimportantbucketmarkoe"] will be created
+ resource "aws_s3_bucket_policy" "allow_access_to_bucket" {
+ bucket = (known after apply)
+ id = (known after apply)
+ policy = (known after apply)
}
Plan: 2 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
aws_s3_bucket.buckets["averyimportantbucketmarkoe"]: Creating...
aws_s3_bucket.buckets["averyimportantbucketmarkoe"]: Creation complete after 1s [id=averyimportantbucketmarkoe]
aws_s3_bucket_policy.allow_access_to_bucket["averyimportantbucketmarkoe"]: Creating...
aws_s3_bucket_policy.allow_access_to_bucket["averyimportantbucketmarkoe"]: Creation complete after 1s [id=averyimportantbucketmarkoe]
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.