How to pass variables to a JSON file in Terraform
Let’s say you are creating an IAM policy with Terraform by using a seperate json file which includes the statement for the policy.
In a typical statement we have 4 values to satisfy. These are Sid, Effect, Action and Resource.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Policy Name",
"Effect": "Allow",
"Action": [
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::mytestbucket"
]
}
]
}
How should we dynamically change Resource and Sid values in this statement?
Well, Terraform has a data resource called template_file. With this, we can easily pass parameters dynamically to our statement file.
Demo Time!
First, we need to create a user, policy and bucket. We will then use the bucket ARN in our statement. I am using variables for most of the things in order to have a clean code.
resource "aws_iam_user" "iam-user" {
name = var.iam_user_name
}
resource "aws_s3_bucket" "s3-bucket" {
bucket = "mytestbucket"
}
resource "aws_iam_user_policy" "iam-policy" {
name = var.iam_policy_name
user = aws_iam_user.iam-user.name
}
Normally we can attach the json policy with the following;
policy = file("/path/to/policy.json")
Since we want to pass parameters to the json file, we will use a data resource called “template_file”.
In order to use it, we must rename our json extension to tpl. With this we are stating that we want to use this file as a template.
Now we will modify our template file using interpolation syntax. We will pass parameters for both Sid and Resource.
"Statement": [
{
"Sid": "${sid-name}",
"Effect": "Allow",
"Action": [
"s3:ListBucket"
],
"Resource": [
"${resource-name}"
]
}
]
Back to our main file we will add template_file resource.
data "template_file" "iam-policy-template" {
template = file("/path/to/policy.tpl")
vars = {
sid-name = "Policy for S3 Access"
resource-name = aws_s3_bucket.sample_bucket.arn
}
}
Here we specified the vars block and inside we use the variables from the template file. Now we can use this data in our IAM policy resource.
Notice that we are accessing our template’s rendered version.
resource "aws_iam_user_policy" "iam-policy" {
name = var.iam_policy_name
user = aws_iam_user.iam-policy.name
policy = data.template_file.iam-policy-template.rendered
}