Actually i want to rewrite from scratch code from 0.11 to 0.12 version. And cant figure out how to iterate over list that terraform creates several templates files and substitute subnet to policy file
Terraform Configuration Files
terraform 0.11
data "template_file" "this_code_build_networkinterface_policy" {
count = "${length(var.vpc_private_subnets)}"
template = "${file("${path.module}/codebuild_subnet_policy.json.tpl")}"
vars {
region = "${var.region}"
user = "${data.aws_caller_identity.aws_user_info.account_id}"
subnet = "${var.vpc_private_subnets[count.index]}"
}
}
terraform 0.12
data "template_file" "this_code_build_networkinterface_policy" {
count = length(var.vpc_private_subnets)
template = file("${path.module}/codebuild_subnet_policy.json.tpl")
vars = {
region = var.region
user = data.aws_caller_identity.aws_user_info.account_id
subnets = var.vpc_private_subnets[count.index]
}
}
json.tpl file
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:CreateNetworkInterfacePermission"
],
"Resource": "arn:aws:ec2:${region}:${user}:network-interface/*",
"Condition": {
"StringEquals": {
"ec2:Subnet": [
"arn:aws:ec2:${region}:${user}:subnet/${subnet}"
],
"ec2:AuthorizedService": "codebuild.amazonaws.com"
}
}
}
]
}
Error: Incorrect attribute value type
on modules/_ci_cd/build.tf line 30, in data “template_file” “this_code_build_networkinterface_policy”:
30: vars = {
Inappropriate value for attribute “vars”: element “subnets”: string required.
Hi! This works fine for me locally (once I renamed “subnets” to “subnet”, to match the variable used in your template). Are you getting an error?
As @mildwonkey noted, there doesn’t seem to be anything obviously incorrect here, so if you can share an error message that’d be great.
With that said, on the topic of “rewriting for 0.12” I think there are some good opportunities for simplification here once you have completed your upgrade.
The primary thing I would recommend is to move away from templating JSON using template_file
and to use the jsonencode
function instead. That way you don’t need to worry about the JSON syntax yourself and can just describe the values you want to encode:
locals {
account_id = data.aws_caller_identity.aws_user_info.account_id
}
resource "aws_iam_policy" "example" {
# ...
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = ["ec2:CreateNetworkInterfacePermission"]
Resource = "arn:aws:ec2:${var.region}:${local.account_id}:network-interface/*"
Condition = {
StringEquals = {
"ec2:Subnet" = [
for s in var.vpc_private_subnets :
"arn:aws:ec2:${var.region}:${local.account_id}:subnet/${s}"
]
"ec2:AuthorizedService": "codebuild.amazonaws.com"
}
}
},
]
})
}
If having the policy template in a separate file is important, you can achieve a similar result using Terraform 0.12’s built in templatefile
function (which is the replacement for the template_file
data source) and call jsonencode
from inside the template:
${jsonencode({
Version = "2012-10-17"
Statement = [
# etc, etc
]
})}
resource "aws_iam_policy" "example" {
# ...
policy = templatefile("${path.module}/codebuild_subnet_policy.json.tpl", {
region = var.region
user = data.aws_caller_identity.aws_user_info.account_id
subnets = var.vpc_private_subnets
})
}
2 Likes
Ok, I’ve fixed as you advised. @apparentlymart
Error: Invalid template interpolation value
on modules/_ci_cd/build.tf line 51, in resource "aws_iam_role_policy" "this_code_build_policy_subnet":
51: "arn:aws:ec2:${var.region}:${local.account_id}:subnet/${s}"
Cannot include the given value in a string template: string required.
I think need to mention that var.vpc_subnets comes from another terraform state file and i referenced it via remote state call. Maybe problem is here ?
I found problem in remote state returned values
private_subnets = [
[
“subnet-03c44xxxxxxx”,
“subnet-0fb62dcxxxxx”,
“subnet-022930xxxxx”,
“subnet-09f03937xxx”,
],
]
I return list of lists. So i fixed output.tf file and seem like all is OK.