I have a policy defined in terraform for AWS resources like so:
device-status-policy = <<EOF
{"Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "iot:Connect", "Resource": "arn:aws:iot:us-west-2:foobaraccountid:client/device-status-qa*" }, { "Effect": "Allow", "Action": [ "iot:Publish", "iot:Receive", "iot:Subscribe" ] }
EOF
I would like Resource part of it to be a variable, like so (psuedo-code)
device-status-policy = <<EOF
{"Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "iot:Connect", "Resource": "$SOMEVAR/device-status-qa*" }, { "Effect": "Allow", "Action": [ "iot:Publish", "iot:Receive", "iot:Subscribe" ] }
EOF
Any help is appreciated. Thanks.
String interpolation using the ${ ... }
syntax is the smallest change from a literal JSON string, but it runs the risk of challenges with producing correct JSON syntax if e.g. the strings being inserted contain backslashes and quote marks that the JSON parser could misinterpret.
Terraform's jsonencode
function can be a good compromise, because Terraform has an object syntax that is very similar to JSON and thus the ability to quickly understand what JSON structure it's producing is preserved while at the same time allowing arbitrary Terraform expressions, whose results will be automatically encoded using correct JSON syntax:
device-status-policy = jsonencode({
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "iot:Connect",
"Resource": "${SOMEVAR}/device-status-qa*"
},
{
"Effect": "Allow",
"Action": [ "iot:Publish", "iot:Receive", "iot:Subscribe" ]
}
]
})
Note that the above is using a variant form of the Terraform language object syntax which uses colons instead of equals signs; both are valid, and using colons here helps the input resemble JSON and therefore makes it easier to adapt JSON you already wrote (as I did here) without a lot of rewriting.
However, the "${SOMEVAR}/device-status-qa*"
sequence is understood by Terraform as a quoted template expression rather than as a literal string, and so it will evaluate SOMEVAR
and include the result in the Resource
value before serializing the whole resulting string using JSON syntax. Although it seems unlikely in this particular case, if the SOMEVAR
result were a string containing a "
then the JSON encoding would automatically escape it as \"
to ensure that the result is valid syntax.
For larger data structures where it improves readability to factor them out into a separate file, the templatefile
function documentation includes some examples of calling jsonencode
from inside an external template too, with similar results.