![Terraform:如何动态生成 JSON 策略块?](https://linux22.com/image/774601/Terraform%EF%BC%9A%E5%A6%82%E4%BD%95%E5%8A%A8%E6%80%81%E7%94%9F%E6%88%90%20JSON%20%E7%AD%96%E7%95%A5%E5%9D%97%EF%BC%9F.png)
我有以下资源:
resource "aws_iam_user_policy" "ses_send_policy" {
count = var.enabled ? 1 : 0
name_prefix = var.user_policy_name_prefix
user = aws_iam_user.ses_smtp_user[0].name
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ses:SendEmail",
"ses:SendRawEmail"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"ses:FromAddress": [
"${var.user_email_address}"
]
}
}
}
]
}
EOF
}
我想问如何使策略中的“条件”块成为可选的并基于 bool 类型变量?我只想在 时才使用它var.condition = true
。
答案1
在文档aws_iam_user_policy
在回答这个问题时,主要用法示例显示policy
如下设置:
# Terraform's "jsonencode" function converts a # Terraform expression result to valid JSON syntax. policy = jsonencode({ Version = "2012-10-17" Statement = [ { Action = [ "ec2:Describe*", ] Effect = "Allow" Resource = "*" }, ] })
请注意,它建议使用功能jsonencode
来生成整个值,而不是尝试通过模板连接从各个部分构造 JSON,因为这样可以确保结果始终是有效的 JSON 语法。
它还其优点在于你可以使用任何表达式您需要对数据结构做出动态决策。在您的案例中,您已经从变量中获得了对用户电子邮件地址的动态引用,因此让我们首先将您所拥有的内容转换为更像文档中的示例的形式:
policy = jsonencode({
Version = 2012-10-17"
Statement = [
{
Effect = "Allow"
Action = [
"ses:SendEmail",
"ses:SendRawEmail",
]
Resource = "*"
Condition = {
StringEquals = {
"ses:FromAddress" = [
var.user_email_address,
]
}
}
}
]
})
请注意,该值现在以 Terraform 自己的表达式语法而不是 JSON 语法编写。Terraform 将在评估函数jsonencode
调用时自行构建有效的 JSON 语法。
您的新要求是在某些情况下完全省略。要将该要求描述为 Terraform 表达式,需要将描述始终存在的部分( 、和)Condition
的对象与描述可选部分的另一个表达式合并。Effect
Action
Resource
例如:
policy = jsonencode({
Version = 2012-10-17"
Statement = [
merge(
{
Effect = "Allow"
Action = [
"ses:SendEmail",
"ses:SendRawEmail",
]
Resource = "*"
},
coalesce(var.condition ? {
Condition = {
StringEquals = {
"ses:FromAddress" = [
var.user_email_address,
]
}
}
} : null, {}),
)
]
})
我在这里所做的更改有些微妙,并且由于其他内容均未更改,因此可能很难看出,因此这里有一个精简版本,其中一些先前的元素被注释替换,只是为了使新内容更加突出:
policy = jsonencode({
Version = 2012-10-17"
Statement = [
merge(
{
# (common attributes here)
},
coalesce(var.condition ? {
# (conditional attributes here)
} : null, {}),
)
]
})
功能merge
接受多个对象并返回一个包含所有对象元素的对象。在这种情况下,第二个参数merge
是一个更复杂的表达式,它根据条件值生成具有属性的对象Condition
或空对象。将空对象合并到对象中不会改变结果,因此在这种情况下,条件控制第二个参数是否会贡献任何属性。
答案2
您可以使用aws_iam_policy_document资源,并使条件块动态的。