net-vpc-firewall mini rules-factory

This commit is contained in:
Simone Ruffilli 2021-12-07 13:26:21 +01:00
parent 6315410642
commit b1ff592990
3 changed files with 87 additions and 1 deletions

View File

@ -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
```
<!-- BEGIN TFDOC -->
## Variables
@ -89,7 +132,9 @@ module "firewall" {
| network | Name of the network this set of firewall rules applies to. | <code title="">string</code> | ✓ | |
| project_id | Project id of the project that holds the network. | <code title="">string</code> | ✓ | |
| *admin_ranges* | IP CIDR ranges that have complete access to all subnets. | <code title="list&#40;string&#41;">list(string)</code> | | <code title="">[]</code> |
| *cidr_template_file* | Path for optional file containing name->cidr_list map to be used by the rules factory. | <code title="">string</code> | | <code title="">null</code> |
| *custom_rules* | List of custom rule definitions (refer to variables file for syntax). | <code title="map&#40;object&#40;&#123;&#10;description &#61; string&#10;direction &#61; string&#10;action &#61; string &#35; &#40;allow&#124;deny&#41;&#10;ranges &#61; list&#40;string&#41;&#10;sources &#61; list&#40;string&#41;&#10;targets &#61; list&#40;string&#41;&#10;use_service_accounts &#61; bool&#10;rules &#61; list&#40;object&#40;&#123;&#10;protocol &#61; string&#10;ports &#61; list&#40;string&#41;&#10;&#125;&#41;&#41;&#10;extra_attributes &#61; map&#40;string&#41;&#10;&#125;&#41;&#41;">map(object({...}))</code> | | <code title="">{}</code> |
| *data_folder* | Path for optional folder containing firewall rules defined as YaML objects used by the rules factory. | <code title="">string</code> | | <code title="">null</code> |
| *http_source_ranges* | List of IP CIDR ranges for tag-based HTTP rule, defaults to the health checkers ranges. | <code title="list&#40;string&#41;">list(string)</code> | | <code title="">["35.191.0.0/16", "130.211.0.0/22", "209.85.152.0/22", "209.85.204.0/22"]</code> |
| *https_source_ranges* | List of IP CIDR ranges for tag-based HTTPS rule, defaults to the health checkers ranges. | <code title="list&#40;string&#41;">list(string)</code> | | <code title="">["35.191.0.0/16", "130.211.0.0/22", "209.85.152.0/22", "209.85.204.0/22"]</code> |
| *named_ranges* | Names that can be used of valid values for the `ranges` field of `custom_rules` | <code title="map&#40;list&#40;string&#41;&#41;">map(list(string))</code> | | <code title="&#123;&#10;any &#61; &#91;&#34;0.0.0.0&#47;0&#34;&#93;&#10;dns-forwarders &#61; &#91;&#34;35.199.192.0&#47;19&#34;&#93;&#10;health-checkers &#61; &#91;&#34;35.191.0.0&#47;16&#34;, &#34;130.211.0.0&#47;22&#34;, &#34;209.85.152.0&#47;22&#34;, &#34;209.85.204.0&#47;22&#34;&#93;&#10;iap-forwarders &#61; &#91;&#34;35.235.240.0&#47;20&#34;&#93;&#10;private-googleapis &#61; &#91;&#34;199.36.153.8&#47;30&#34;&#93;&#10;restricted-googleapis &#61; &#91;&#34;199.36.153.4&#47;30&#34;&#93;&#10;rfc1918 &#61; &#91;&#34;10.0.0.0&#47;8&#34;, &#34;172.16.0.0&#47;12&#34;, &#34;192.168.0.0&#47;16&#34;&#93;&#10;&#125;">...</code> |

View File

@ -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
###############################################################################

View File

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