Reputation: 119
Here's an example access policy resource using Zscaler's ZPA Terraform provider. My question is, how can I define the three conditions as a locals variable that can be used as dynamic block with a for_each? I need to include these same conditions blocks in dozens/hundreds of access policy resources, and it would be nice if I didn't have to copy/paste that entire section of code.
resource "zpa_policy_access_rule" "policy-name" {
name = "policy-name"
description = "description"
action = "ALLOW"
default_rule = false
lss_default_rule = false
operator = "AND"
conditions {
negated = false
operator = "OR"
operands {
object_type = "POSTURE"
lhs = data.zpa_posture_profile.lvl_1_check_1.posture_udid
rhs = true
}
operands {
object_type = "POSTURE"
lhs = data.zpa_posture_profile.lvl_1_check_2.posture_udid
rhs = true
}
operands {
object_type = "POSTURE"
lhs = data.zpa_posture_profile.lvl_1_check_3.posture_udid
rhs = true
}
}
conditions {
negated = false
operator = "OR"
operands {
object_type = "POSTURE"
lhs = data.zpa_posture_profile.lvl_2_check_1.posture_udid
rhs = true
}
operands {
object_type = "POSTURE"
lhs = data.zpa_posture_profile.lvl_2_check_2.posture_udid
rhs = true
}
}
conditions {
negated = false
operator = "AND"
operands {
object_type = "POSTURE"
lhs = data.zpa_posture_profile.lvl_3_check_1.posture_udid
rhs = true
}
operands {
object_type = "POSTURE"
lhs = data.zpa_posture_profile.lvl_3_check_2.posture_udid
rhs = true
}
}
}
I figured out how to create locals for the "operands" contained within the "conditions" blocks, for example:
locals {
LEVEL_1_CHECKS = [
{
object_type = "POSTURE"
rhs = true
lhs = data.zpa_posture_profile.lvl_1_check_1.posture_udid
},
{
object_type = "POSTURE"
rhs = true
lhs = data.zpa_posture_profile.lvl_1_check_2.posture_udid
},
{
object_type = "POSTURE"
rhs = true
lhs = data.zpa_posture_profile.lvl_1_check_3.posture_udid
}
]
LEVEL_2_CHECKS = [
{
object_type = "POSTURE"
rhs = true
lhs = data.zpa_posture_profile.lvl_2_check_1.posture_udid
},
{
object_type = "POSTURE"
rhs = true
lhs = data.zpa_posture_profile.lvl_2_check_2.posture_udid
}
]
LEVEL_3_CHECKS = [
{
object_type = "POSTURE"
rhs = true
lhs = data.zpa_posture_profile.lvl_3_check_1.posture_udid
},
{
object_type = "POSTURE"
rhs = true
lhs = data.zpa_posture_profile.lvl_3_check_2.posture_udid
}
]
}
However, I'm still stuck with a lot of repeating code when creating new policy resources:
resource "zpa_policy_access_rule" "policy-name" {
name = "policy-name"
description = "description"
action = "ALLOW"
default_rule = false
lss_default_rule = false
operator = "AND"
conditions {
negated = false
operator = "OR"
dynamic "operands" {
for_each = local.LEVEL_1_CHECKS
content {
object_type = operands.value.object_type
rhs = operands.value.rhs
lhs = operands.value.lhs
}
}
}
conditions {
negated = false
operator = "AND"
dynamic "operands" {
for_each = local.LEVEL_2_CHECKS
content {
object_type = operands.value.object_type
rhs = operands.value.rhs
lhs = operands.value.lhs
}
}
}
conditions {
negated = false
operator = "OR"
dynamic "operands" {
for_each = local.LEVEL_3_CHECKS
content {
object_type = operands.value.object_type
rhs = operands.value.rhs
lhs = operands.value.lhs
}
}
}
}
How can I define all of the "conditions" blocks using locals? They never change, so I'm assuming this should be a straightforward task, but as it is now I'm going to have to copy/paste 50+ lines into every new resource to define these items.
This is using the Zscaler ZPA Terraform provider: https://registry.terraform.io/providers/zscaler/zpa/latest
Upvotes: 0
Views: 1675
Reputation: 238189
You can nest dynamic blocks. This will allow you to have one local variable, instead of three:
locals {
LEVEL_CHECKS = {
LEVEL_1_CHECKS = {
negated = false
operator = "OR"
checks = [
{
object_type = "POSTURE"
rhs = true
lhs = data.zpa_posture_profile.lvl_1_check_1.posture_udid
},
{
object_type = "POSTURE"
rhs = true
lhs = data.zpa_posture_profile.lvl_1_check_2.posture_udid
},
{
object_type = "POSTURE"
rhs = true
lhs = data.zpa_posture_profile.lvl_1_check_3.posture_udid
}
]
},
LEVEL_2_CHECKS = {
negated = false
operator = "AND"
checks = [
{
object_type = "POSTURE"
rhs = true
lhs = data.zpa_posture_profile.lvl_2_check_1.posture_udid
},
{
object_type = "POSTURE"
rhs = true
lhs = data.zpa_posture_profile.lvl_2_check_2.posture_udid
}
]
},
LEVEL_3_CHECKS = {
negated = false
operator = "OR"
checks = [
{
object_type = "POSTURE"
rhs = true
lhs = data.zpa_posture_profile.lvl_3_check_1.posture_udid
},
{
object_type = "POSTURE"
rhs = true
lhs = data.zpa_posture_profile.lvl_3_check_2.posture_udid
}
]
}
}
}
then
dynamic "conditions" {
for_each = local.LEVEL_CHECKS
content {
negated = conditions.value.negated
operator = conditions.value.operator
dynamic "operands" {
for_each = conditions.value.checks
content {
object_type = operands.value.object_type
rhs = operands.value.rhs
lhs = operands.value.lhs
}
}
}
}
Upvotes: 1