diff --git a/modules/net-vpc-firewall/README.md b/modules/net-vpc-firewall/README.md index 83f8f7cd..a3ad750f 100644 --- a/modules/net-vpc-firewall/README.md +++ b/modules/net-vpc-firewall/README.md @@ -81,6 +81,49 @@ module "firewall" { # tftest:modules=1:resources=1 ``` + +### Rules Factory +The module includes a rules factory (see [Resource Factories](../../factories/)) for the massive creation of rules leveraging YaML configuration files. Each configuration file can optionally contain more than one rule which a structure that reflects the `custom_rules` variable. + +```hcl +module "firewall" { + source = "./modules/net-vpc-firewall" + project_id = "my-project" + network = "my-network" + data_folder = "config/firewall" + cidr_template_file = "config/cidr_template.yaml" +} +# tftest:skip +``` + +```yaml +# ./config/firewall/load_balancers.yaml +allow-healthchecks: + description: Allow ingress from healthchecks. + direction: INGRESS + action: allow + sources: [] + ranges: + - $healthchecks + targets: ["lb-backends"] + use_service_accounts: false + rules: + - protocol: tcp + ports: + - 80 + - 443 +``` + +```yaml +# ./config/cidr_template.yaml +healthchecks: + - 35.191.0.0/16 + - 130.211.0.0/22 + - 209.85.152.0/22 + - 209.85.204.0/22 + +``` + ## Variables @@ -89,7 +132,9 @@ module "firewall" { | network | Name of the network this set of firewall rules applies to. | string | ✓ | | | project_id | Project id of the project that holds the network. | string | ✓ | | | *admin_ranges* | IP CIDR ranges that have complete access to all subnets. | list(string) | | [] | +| *cidr_template_file* | Path for optional file containing name->cidr_list map to be used by the rules factory. | string | | null | | *custom_rules* | List of custom rule definitions (refer to variables file for syntax). | map(object({...})) | | {} | +| *data_folder* | Path for optional folder containing firewall rules defined as YaML objects used by the rules factory. | string | | null | | *http_source_ranges* | List of IP CIDR ranges for tag-based HTTP rule, defaults to the health checkers ranges. | list(string) | | ["35.191.0.0/16", "130.211.0.0/22", "209.85.152.0/22", "209.85.204.0/22"] | | *https_source_ranges* | List of IP CIDR ranges for tag-based HTTPS rule, defaults to the health checkers ranges. | list(string) | | ["35.191.0.0/16", "130.211.0.0/22", "209.85.152.0/22", "209.85.204.0/22"] | | *named_ranges* | Names that can be used of valid values for the `ranges` field of `custom_rules` | map(list(string)) | | ... | diff --git a/modules/net-vpc-firewall/main.tf b/modules/net-vpc-firewall/main.tf index c196e470..aac7b929 100644 --- a/modules/net-vpc-firewall/main.tf +++ b/modules/net-vpc-firewall/main.tf @@ -15,7 +15,7 @@ */ locals { - custom_rules = { + _custom_rules = { for id, rule in var.custom_rules : id => merge(rule, { # make rules a map so we use it in a for_each @@ -27,8 +27,36 @@ locals { ]) }) } + + cidrs = try({ for name, cidrs in yamldecode(file("${var.cidr_template_file}")) : + name => cidrs + }, {}) + + _factory_rules_raw = flatten([ + for file in try(fileset(var.data_folder, "**/*.yaml"), []) : [ + for key, ruleset in yamldecode(file("${var.data_folder}/${file}")) : + merge(ruleset, { + name = "${key}" + rules = { for index, ports in ruleset.rules : index => ports } + ranges = try(ruleset.ranges, null) == null ? null : flatten( + [for cidr in ruleset.ranges : + can(regex("^\\$", cidr)) + ? local.cidrs[trimprefix(cidr, "$")] + : [cidr] + ]) + extra_attributes = try(ruleset.extra_attributes, {}) + }) + ] + ]) + + _factory_rules = { + for d in local._custom_rules_raw : d["name"] => d + } + + custom_rules = merge(local._custom_rules, local._factory_rules) } + ############################################################################### # rules based on IP ranges ############################################################################### diff --git a/modules/net-vpc-firewall/variables.tf b/modules/net-vpc-firewall/variables.tf index 94755d2e..7a392a6d 100644 --- a/modules/net-vpc-firewall/variables.tf +++ b/modules/net-vpc-firewall/variables.tf @@ -39,6 +39,18 @@ variable "custom_rules" { default = {} } +variable "cidr_template_file" { + description = "Path for optional file containing name->cidr_list map to be used by the rules factory." + type = string + default = null +} + +variable "data_folder" { + description = "Path for optional folder containing firewall rules defined as YaML objects used by the rules factory." + type = string + default = null +} + variable "http_source_ranges" { description = "List of IP CIDR ranges for tag-based HTTP rule, defaults to the health checkers ranges." type = list(string) @@ -80,3 +92,4 @@ variable "ssh_source_ranges" { type = list(string) default = ["35.235.240.0/20"] } +