diff --git a/README.md b/README.md index 55463138..0aed0639 100644 --- a/README.md +++ b/README.md @@ -162,7 +162,7 @@ You need the following permissions to run this module. | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.9.0 | -| [ibm](#requirement\_ibm) | >= 1.78.4, < 2.0.0 | +| [ibm](#requirement\_ibm) | >= 1.87.3, < 2.0.0 | | [time](#requirement\_time) | >= 0.9.1, < 1.0.0 | ### Modules diff --git a/security_group.tf b/security_group.tf index 190948a4..21426bc5 100644 --- a/security_group.tf +++ b/security_group.tf @@ -64,138 +64,61 @@ locals { } } -resource "ibm_is_security_group_rule" "security_group_rules" { - for_each = local.security_group_rules - group = ibm_is_security_group.security_group[each.value.sg_name].id - direction = each.value.direction - remote = each.value.source - local = each.value.local - ip_version = each.value.ip_version - - - ############################################################################## - # Dynamically create ICMP Block - ############################################################################## - - dynamic "icmp" { - - # Runs a for each loop, if the rule block contains icmp, it looks through the block - # Otherwise the list will be empty - - for_each = ( - # Only allow creation of icmp rules if all of the keys are not null. - # This allows the use of the optional variable in landing zone patterns - # to convert to a single typed list by adding `null` as the value. - each.value.icmp == null - ? [] - : length([ - for value in ["type", "code"] : - true if lookup(each.value["icmp"], value, null) == null - ]) == 2 - ? [] # if all values null empty array - : [each.value] +locals { + # True when tcp block has at least one non-null port value + sg_rule_has_tcp = { + for k, v in local.security_group_rules : k => ( + v.tcp != null && + length([for x in ["port_min", "port_max"] : true if lookup(v["tcp"], x, null) != null]) > 0 ) - # Conditionally add content if sg has icmp - content { - type = lookup( - each.value["icmp"], - "type", - null - ) - code = lookup( - each.value["icmp"], - "code", - null - ) - } } - ############################################################################## - - ############################################################################## - # Dynamically create TCP Block - ############################################################################## - - dynamic "tcp" { - - # Runs a for each loop, if the rule block contains tcp, it looks through the block - # Otherwise the list will be empty - - for_each = ( - # Only allow creation of tcp rules if all of the keys are not null. - # This allows the use of the optional variable in landing zone patterns - # to convert to a single typed list by adding `null` as the value. - # the default behavior will be to set `null` `port_min` values to 1 if null - # and `port_max` to 65535 if null - each.value.tcp == null - ? [] - : length([ - for value in ["port_min", "port_max"] : - true if lookup(each.value["tcp"], value, null) == null - ]) == 2 - ? [] # if all values null empty array - : [each.value] + # True when udp block has at least one non-null port value + sg_rule_has_udp = { + for k, v in local.security_group_rules : k => ( + v.udp != null && + length([for x in ["port_min", "port_max"] : true if lookup(v["udp"], x, null) != null]) > 0 ) - - # Conditionally adds content if sg has tcp - content { - port_min = lookup( - each.value["tcp"], - "port_min", - null - ) - - port_max = lookup( - each.value["tcp"], - "port_max", - null - ) - } } - ############################################################################## - - ############################################################################## - # Dynamically create UDP Block - ############################################################################## - - dynamic "udp" { - - # Runs a for each loop, if the rule block contains udp, it looks through the block - # Otherwise the list will be empty - - for_each = ( - # Only allow creation of udp rules if all of the keys are not null. - # This allows the use of the optional variable in landing zone patterns - # to convert to a single typed list by adding `null` as the value. - # the default behavior will be to set `null` `port_min` values to 1 if null - # and `port_max` to 65535 if null - each.value.udp == null - ? [] - : length([ - for value in ["port_min", "port_max"] : - true if lookup(each.value["udp"], value, null) == null - ]) == 2 - ? [] # if all values null empty array - : [each.value] + # True when icmp block has at least one non-null type/code value + sg_rule_has_icmp = { + for k, v in local.security_group_rules : k => ( + v.icmp != null && + length([for x in ["type", "code"] : true if lookup(v["icmp"], x, null) != null]) > 0 ) - - # Conditionally adds content if sg has udp - content { - port_min = lookup( - each.value["udp"], - "port_min", - null - ) - port_max = lookup( - each.value["udp"], - "port_max", - null - ) - } } +} + +resource "ibm_is_security_group_rule" "security_group_rules" { + for_each = local.security_group_rules + group = ibm_is_security_group.security_group[each.value.sg_name].id + direction = each.value.direction + remote = each.value.source + local = each.value.local + ip_version = each.value.ip_version - ############################################################################## + protocol = ( + local.sg_rule_has_tcp[each.key] ? "tcp" : + local.sg_rule_has_udp[each.key] ? "udp" : + local.sg_rule_has_icmp[each.key] ? "icmp" : + null + ) + + port_min = ( + local.sg_rule_has_tcp[each.key] ? lookup(each.value["tcp"], "port_min", null) : + local.sg_rule_has_udp[each.key] ? lookup(each.value["udp"], "port_min", null) : + null + ) + + port_max = ( + local.sg_rule_has_tcp[each.key] ? lookup(each.value["tcp"], "port_max", null) : + local.sg_rule_has_udp[each.key] ? lookup(each.value["udp"], "port_max", null) : + null + ) + + type = local.sg_rule_has_icmp[each.key] ? lookup(each.value["icmp"], "type", null) : null + code = local.sg_rule_has_icmp[each.key] ? lookup(each.value["icmp"], "code", null) : null } diff --git a/version.tf b/version.tf index ed675b17..30c01227 100644 --- a/version.tf +++ b/version.tf @@ -4,7 +4,7 @@ terraform { # Use "greater than or equal to" range in modules ibm = { source = "IBM-Cloud/ibm" - version = ">= 1.78.4, < 2.0.0" + version = ">= 1.87.3, < 2.0.0" } time = { source = "hashicorp/time"