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"]
}
+