I call a file to be rendered like so
resource "aws_organizations_policy" "backup_policy" {
name = "organization_backup_policy"
description = "Organization wide backup policy"
type = "BACKUP_POLICY"
content = jsonencode(templatefile("${path.module}/policies/backup-policy.json.tftpl", {
vault_name = aws_backup_vault.central_backup_vault.name
backup_operator_role_name = aws_iam_role.backup_operator.name
backup_tag_key = "Backup"
backup_tag_value = "true"
}))
}
The template itself:
{
"plans": {
"BackupPlan00": {
"regions": {
"@@assign": [
"eu-central-1"
]
},
"rules": {
"BackupRule00": {
"target_backup_vault_name": {
"@@assign": ${vault_name}"
}
}
},
"backup_plan_tags": {
"backup-plan-tag": {
"tag_key": {
"@@assign": "backup-plan-tag"
},
"tag_value": {
"@@assign": "backup-plan-key"
}
}
},
"selections": {
"tags": {
"ResourceAssignment00": {
"iam_role_arn": {
"@@assign": "arn:aws:iam::$account:role/${backup_operator_role_name}"
},
"tag_key": {
"@@assign": "${backup_tag_key}"
},
"tag_value": {
"@@assign": [
"${backup_tag_value}"
]
}
}
}
}
}
}
}
EDIT
Funny enough, when I have a plan JSON file such as backup.json
{
"plans": {
"BackupPlan00": {
"regions": {
"@@append": [
"eu-central-1",
"eu-west-3"
]
},
"rules": {
"BackupRule00": {
"target_backup_vault_name": {
"@@assign": "CentralVault"
}
}
},
"backup_plan_tags": {
"backup-plan-tag": {
"tag_key": {
"@@assign": "backup-plan-tag"
},
"tag_value": {
"@@assign": "backup-plan-key"
}
}
},
"selections": {
"tags": {
"ResourceAssignment00": {
"iam_role_arn": {
"@@assign": "arn:aws:iam::$account:role/BackupOperator"
},
"tag_key": {
"@@assign": "Backup"
},
"tag_value": {
"@@assign": [
"true"
]
}
}
}
}
}
}
}
With no variable interpolation or anythings, it still fails
resource "aws_organizations_policy" "backup_policy" {
provider = aws.primary_region
name = "organization_backup_policy"
description = "Organization wide backup policy"
type = "BACKUP_POLICY"
content = jsonencode(templatefile("${path.module}/policies/backup.json", {}))
}
ā Error: updating Organizations Policy (p-89ql027feq): operation error Organizations: UpdatePolicy, https response error StatusCode: 400, RequestID: 2ed05a2d-b829-46fc-a18c-78105ae710a0, MalformedPolicyDocumentException: The provided policy document does not meet the requirements of the specified policy type.
What do I miss?
Using jsonencode
with the result of templatefile
is typically a mistake, because the result of templatefile
is always a string and so applying jsonencode
to that would produce a JSON-encoded version of that string.
If your goal is to generate JSON from the template then the operations need to happen in the opposite order: the jsonencode
call must happen inside the template, so that the template's rendered result is the desired JSON document.
For example, you might write your template like this:
${jsonencode({
plans = {
"BackupPlan00" = {
regions = {
"@@assign" = [
"eu-central-1",
]
}
rules = {
"BackupRule00" = {
target_backup_vault_name = {
"@@assign" = vault_name
}
}
}
backup_plan_tags = {
"backup-plan-tag" = {
tag_key = {
"@@assign" = "backup-plan-tag"
}
tag_value = {
"@@assign" = "backup-plan-key"
}
}
}
selections = {
tags = {
"ResourceAssignment00" = {
iam_role_arn = {
"@@assign" = "arn:aws:iam::$account:role/${backup_operator_role_name}"
}
tag_key = {
"@@assign" = backup_tag_key
}
tag_value = {
"@@assign" = [
backup_tag_value,
]
}
}
}
}
}
}
})}
The entire body of the template is now just a call to the jsonencode
function, so the template's rendered result will be a valid JSON document.
You can assign the template result directly to the argument that expects JSON, without any further encoding:
content = templatefile("${path.module}/policies/backup-policy.json.tftpl", {
vault_name = aws_backup_vault.central_backup_vault.name
backup_operator_role_name = aws_iam_role.backup_operator.name
backup_tag_key = "Backup"
backup_tag_value = "true"
})