274 lines
13 KiB
Markdown
274 lines
13 KiB
Markdown
# Google Cloud VPC Firewall
|
|
|
|
This module allows creation and management of different types of firewall rules for a single VPC network:
|
|
|
|
- custom rules via the `egress_rules` and `ingress_rules` variables
|
|
- optional predefined rules that simplify prototyping via the `default_rules_config` variable
|
|
|
|
The predefined rules are enabled by default and set to the ranges of the GCP health checkers for HTTP/HTTPS, and the IAP forwarders for SSH. See the relevant section below on how to configure or disable them.
|
|
|
|
<!-- BEGIN TOC -->
|
|
- [Examples](#examples)
|
|
- [Minimal open firewall](#minimal-open-firewall)
|
|
- [Custom rules](#custom-rules)
|
|
- [Controlling or turning off default rules](#controlling-or-turning-off-default-rules)
|
|
- [Overriding default tags and ranges](#overriding-default-tags-and-ranges)
|
|
- [Disabling predefined rules](#disabling-predefined-rules)
|
|
- [Including source & destination ranges](#including-source-destination-ranges)
|
|
- [Rules Factory](#rules-factory)
|
|
- [Variables](#variables)
|
|
- [Outputs](#outputs)
|
|
<!-- END TOC -->
|
|
|
|
## Examples
|
|
|
|
### Minimal open firewall
|
|
|
|
This is often useful for prototyping or testing infrastructure, allowing open ingress from the private range, enabling SSH to private addresses from IAP, and HTTP/HTTPS from the health checkers.
|
|
|
|
```hcl
|
|
module "firewall" {
|
|
source = "./fabric/modules/net-vpc-firewall"
|
|
project_id = var.project_id
|
|
network = var.vpc.name
|
|
default_rules_config = {
|
|
admin_ranges = ["10.0.0.0/8"]
|
|
}
|
|
}
|
|
# tftest modules=1 resources=4 inventory=basic.yaml e2e
|
|
```
|
|
|
|
### Custom rules
|
|
|
|
This is an example of how to define custom rules, with a sample rule allowing open ingress for the NTP protocol to instances with the `ntp-svc` tag.
|
|
|
|
Some implicit defaults are used in the rules variable types and can be controlled by explicitly setting specific attributes:
|
|
|
|
- action is controlled via the `deny` attribute which defaults to `true` for egress and `false` for ingress
|
|
- priority defaults to `1000`
|
|
- destination ranges (for egress) and source ranges (for ingress) default to `["0.0.0.0/0"]` if not explicitly set or set to `null`, to disable the behaviour set ranges to the empty list (`[]`)
|
|
- rules default to all protocols if not set
|
|
|
|
```hcl
|
|
module "firewall" {
|
|
source = "./fabric/modules/net-vpc-firewall"
|
|
project_id = var.project_id
|
|
network = var.vpc.name
|
|
default_rules_config = {
|
|
admin_ranges = ["10.0.0.0/8"]
|
|
}
|
|
egress_rules = {
|
|
# implicit deny action
|
|
allow-egress-rfc1918 = {
|
|
deny = false
|
|
description = "Allow egress to RFC 1918 ranges."
|
|
destination_ranges = [
|
|
"10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"
|
|
]
|
|
}
|
|
allow-egress-tag = {
|
|
deny = false
|
|
description = "Allow egress from a specific tag to 0/0."
|
|
targets = ["target-tag"]
|
|
}
|
|
deny-egress-all = {
|
|
description = "Block egress."
|
|
}
|
|
}
|
|
ingress_rules = {
|
|
# implicit allow action
|
|
allow-ingress-ntp = {
|
|
description = "Allow NTP service based on tag."
|
|
targets = ["ntp-svc"]
|
|
rules = [{ protocol = "udp", ports = [123] }]
|
|
}
|
|
allow-ingress-tag = {
|
|
description = "Allow ingress from a specific tag."
|
|
source_ranges = []
|
|
sources = ["client-tag"]
|
|
targets = ["target-tag"]
|
|
}
|
|
}
|
|
}
|
|
# tftest modules=1 resources=9 inventory=custom-rules.yaml e2e
|
|
```
|
|
|
|
### Controlling or turning off default rules
|
|
|
|
Predefined rules can be controlled or turned off via the `default_rules_config` variable.
|
|
|
|
#### Overriding default tags and ranges
|
|
|
|
Each protocol rule has a default set of tags and ranges:
|
|
|
|
- the health check range and the `http-server`/`https-server` tag for HTTP/HTTPS, matching tags set via GCP console flags on GCE instances
|
|
- the IAP forwarders range and `ssh` tag for SSH
|
|
|
|
Default tags and ranges can be overridden for each protocol, like shown here for SSH:
|
|
|
|
```hcl
|
|
module "firewall" {
|
|
source = "./fabric/modules/net-vpc-firewall"
|
|
project_id = var.project_id
|
|
network = var.vpc.name
|
|
default_rules_config = {
|
|
ssh_ranges = ["10.0.0.0/8"]
|
|
ssh_tags = ["ssh-default"]
|
|
}
|
|
}
|
|
# tftest modules=1 resources=3 inventory=custom-ssh-default-rule.yaml e2e
|
|
```
|
|
|
|
#### Disabling predefined rules
|
|
|
|
Default rules can be disabled individually by specifying an empty set of ranges:
|
|
|
|
```hcl
|
|
module "firewall" {
|
|
source = "./fabric/modules/net-vpc-firewall"
|
|
project_id = var.project_id
|
|
network = var.vpc.name
|
|
default_rules_config = {
|
|
ssh_ranges = []
|
|
}
|
|
}
|
|
# tftest modules=1 resources=2 inventory=no-ssh-default-rules.yaml e2e
|
|
```
|
|
|
|
Or the entire set of rules can be disabled via the `disabled` attribute:
|
|
|
|
```hcl
|
|
module "firewall" {
|
|
source = "./fabric/modules/net-vpc-firewall"
|
|
project_id = var.project_id
|
|
network = var.vpc.name
|
|
default_rules_config = {
|
|
disabled = true
|
|
}
|
|
}
|
|
# tftest modules=0 resources=0 inventory=no-default-rules.yaml e2e
|
|
```
|
|
|
|
### Including source & destination ranges
|
|
|
|
Custom rules now support including both source & destination ranges in ingress and egress rules:
|
|
|
|
```hcl
|
|
module "firewall" {
|
|
source = "./fabric/modules/net-vpc-firewall"
|
|
project_id = var.project_id
|
|
network = var.vpc.name
|
|
default_rules_config = {
|
|
disabled = true
|
|
}
|
|
egress_rules = {
|
|
deny-egress-source-destination-ranges = {
|
|
description = "Deny egress using source and destination ranges"
|
|
source_ranges = ["10.132.0.0/20", "10.138.0.0/20"]
|
|
destination_ranges = ["172.16.0.0/12"]
|
|
}
|
|
}
|
|
ingress_rules = {
|
|
allow-ingress-source-destination-ranges = {
|
|
description = "Allow ingress using source and destination ranges"
|
|
source_ranges = ["172.16.0.0/12"]
|
|
destination_ranges = ["10.132.0.0/20", "10.138.0.0/20"]
|
|
}
|
|
}
|
|
}
|
|
# tftest modules=1 resources=2 inventory=local-ranges.yaml e2e
|
|
```
|
|
|
|
### Rules Factory
|
|
|
|
The module includes a rules factory (see [Resource Factories](../../blueprints/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 = "./fabric/modules/net-vpc-firewall"
|
|
project_id = var.project_id
|
|
network = var.vpc.name
|
|
factories_config = {
|
|
rules_folder = "configs/firewall/rules"
|
|
cidr_tpl_file = "configs/firewall/cidrs.yaml"
|
|
}
|
|
default_rules_config = { disabled = true }
|
|
}
|
|
# tftest modules=1 resources=3 files=lbs,cidrs inventory=factory.yaml
|
|
```
|
|
|
|
```yaml
|
|
# tftest-file id=lbs path=configs/firewall/rules/load_balancers.yaml
|
|
|
|
---
|
|
# Terraform will be unable to decode this file if it does not contain valid YAML
|
|
# You can retain `---` (start of the document) to indicate an empty document.
|
|
|
|
ingress:
|
|
allow-healthchecks:
|
|
description: Allow ingress from healthchecks.
|
|
source_ranges:
|
|
- healthchecks
|
|
targets: ["lb-backends"]
|
|
rules:
|
|
- protocol: tcp
|
|
ports:
|
|
- 80
|
|
- 443
|
|
allow-service-1-to-service-2:
|
|
description: Allow ingress from service-1 SA
|
|
targets: ["service-2"]
|
|
use_service_accounts: true
|
|
sources:
|
|
- service-1@project-id.iam.gserviceaccount.com
|
|
rules:
|
|
- protocol: tcp
|
|
ports:
|
|
- 80
|
|
- 443
|
|
egress:
|
|
block-telnet:
|
|
description: block outbound telnet
|
|
deny: true
|
|
rules:
|
|
- protocol: tcp
|
|
ports:
|
|
- 23
|
|
```
|
|
|
|
```yaml
|
|
# tftest-file id=cidrs path=configs/firewall/cidrs.yaml
|
|
|
|
---
|
|
# Terraform will be unable to decode this file if it does not contain valid YAML
|
|
# You can retain `---` (start of the document) to indicate an empty document.
|
|
|
|
healthchecks:
|
|
- 35.191.0.0/16
|
|
- 130.211.0.0/22
|
|
- 209.85.152.0/22
|
|
- 209.85.204.0/22
|
|
```
|
|
<!-- BEGIN TFDOC -->
|
|
|
|
## Variables
|
|
|
|
| name | description | type | required | default |
|
|
|---|---|:---:|:---:|:---:|
|
|
| [network](variables.tf#L110) | Name of the network this set of firewall rules applies to. | <code>string</code> | ✓ | |
|
|
| [project_id](variables.tf#L115) | Project id of the project that holds the network. | <code>string</code> | ✓ | |
|
|
| [default_rules_config](variables.tf#L17) | Optionally created convenience rules. Set the 'disabled' attribute to true, or individual rule attributes to empty lists to disable. | <code title="object({ admin_ranges = optional(list(string)) disabled = optional(bool, false) http_ranges = optional(list(string), [ "35.191.0.0/16", "130.211.0.0/22", "209.85.152.0/22", "209.85.204.0/22"] ) http_tags = optional(list(string), ["http-server"]) https_ranges = optional(list(string), [ "35.191.0.0/16", "130.211.0.0/22", "209.85.152.0/22", "209.85.204.0/22"] ) https_tags = optional(list(string), ["https-server"]) ssh_ranges = optional(list(string), ["35.235.240.0/20"]) ssh_tags = optional(list(string), ["ssh"]) })">object({…})</code> | | <code>{}</code> |
|
|
| [egress_rules](variables.tf#L37) | List of egress rule definitions, default to deny action. Null destination ranges will be replaced with 0/0. | <code title="map(object({ deny = optional(bool, true) description = optional(string) destination_ranges = optional(list(string)) disabled = optional(bool, false) enable_logging = optional(object({ include_metadata = optional(bool) })) priority = optional(number, 1000) source_ranges = optional(list(string)) targets = optional(list(string)) use_service_accounts = optional(bool, false) rules = optional(list(object({ protocol = string ports = optional(list(string)) })), [{ protocol = "all" }]) }))">map(object({…}))</code> | | <code>{}</code> |
|
|
| [factories_config](variables.tf#L60) | Paths to data files and folders that enable factory functionality. | <code title="object({ cidr_tpl_file = optional(string) rules_folder = string })">object({…})</code> | | <code>null</code> |
|
|
| [ingress_rules](variables.tf#L69) | List of ingress rule definitions, default to allow action. Null source ranges will be replaced with 0/0. | <code title="map(object({ deny = optional(bool, false) description = optional(string) destination_ranges = optional(list(string), []) # empty list is needed as default to allow deletion after initial creation with a value. See https://github.com/hashicorp/terraform-provider-google/issues/14270 disabled = optional(bool, false) enable_logging = optional(object({ include_metadata = optional(bool) })) priority = optional(number, 1000) source_ranges = optional(list(string)) sources = optional(list(string)) targets = optional(list(string)) use_service_accounts = optional(bool, false) rules = optional(list(object({ protocol = string ports = optional(list(string)) })), [{ protocol = "all" }]) }))">map(object({…}))</code> | | <code>{}</code> |
|
|
| [named_ranges](variables.tf#L93) | Define mapping of names to ranges that can be used in custom rules. | <code>map(list(string))</code> | | <code title="{ any = ["0.0.0.0/0"] dns-forwarders = ["35.199.192.0/19"] health-checkers = [ "35.191.0.0/16", "130.211.0.0/22", "209.85.152.0/22", "209.85.204.0/22" ] iap-forwarders = ["35.235.240.0/20"] private-googleapis = ["199.36.153.8/30"] restricted-googleapis = ["199.36.153.4/30"] rfc1918 = ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"] }">{…}</code> |
|
|
|
|
## Outputs
|
|
|
|
| name | description | sensitive |
|
|
|---|---|:---:|
|
|
| [default_rules](outputs.tf#L17) | Default rule resources. | |
|
|
| [rules](outputs.tf#L27) | Custom rule resources. | |
|
|
|
|
<!-- END TFDOC -->
|