Files
Julio Castillo bc5b203a8f Add toggle to tfdoc to remove type hints (#3842)
* Add toggle to tfdoc to remove type hints

* Update all readmes

* Fix python formatting
2026-04-08 11:08:18 +00:00

531 lines
17 KiB
Markdown

# Firewall Policies
This module allows creation and management of two different firewall policy types:
- a [hierarchical policy](https://cloud.google.com/firewall/docs/firewall-policies) in a folder or organization, or
- a [global](https://cloud.google.com/vpc/docs/network-firewall-policies) or [regional](https://cloud.google.com/vpc/docs/regional-firewall-policies) network policy
The module also manages policy rules via code or a factory, and optional policy attachments. The interface deviates slightly from the [`net-vpc-firewall`](../net-vpc-firewall/) module since the underlying resources and API objects are different.
The module also makes fewer assumptions about implicit defaults, only using one to set `match.layer4_configs` to `[{ protocol = "all" }]` if no explicit set of protocols and ports has been specified.
<!-- BEGIN TOC -->
- [Examples](#examples)
- [Hierarchical Policy](#hierarchical-policy)
- [Global Network policy](#global-network-policy)
- [Regional Network policy](#regional-network-policy)
- [Packet Mirroring Rules](#packet-mirroring-rules)
- [Packet Mirroring Rules](#packet-mirroring-rules)
- [Factory](#factory)
- [Firewall Rule Factory Schema](#firewall-rule-factory-schema)
- [Dynamic Rule Matching](#dynamic-rule-matching)
- [Ingress Rules](#ingress-rules)
- [Egress Rules](#egress-rules)
- [Rule-Level Mappings](#rule-level-mappings)
- [Variables](#variables)
- [Outputs](#outputs)
<!-- END TOC -->
## Examples
### Hierarchical Policy
```hcl
module "firewall-policy" {
source = "./fabric/modules/net-firewall-policy"
name = "test-1"
parent_id = "folders/1234567890"
attachments = {
test = "folders/4567890123"
}
egress_rules = {
smtp = {
priority = 900
match = {
destination_ranges = ["0.0.0.0/0"]
layer4_configs = [{ protocol = "tcp", ports = ["25"] }]
}
}
}
ingress_rules = {
icmp = {
priority = 1000
match = {
source_ranges = ["0.0.0.0/0"]
layer4_configs = [{ protocol = "icmp" }]
}
}
mgmt = {
priority = 1001
enable_logging = true
match = {
source_ranges = ["10.1.1.0/24"]
}
}
ssh = {
priority = 1002
enable_logging = true
match = {
source_ranges = ["10.0.0.0/8"]
source_tags = ["tagValues/123456"]
layer4_configs = [{ protocol = "tcp", ports = ["22"] }]
}
}
}
}
# tftest modules=1 resources=6 inventory=hierarchical.yaml
```
### Global Network policy
```hcl
module "vpc" {
source = "./fabric/modules/net-vpc"
project_id = "my-project"
name = "my-network"
}
module "firewall-policy" {
source = "./fabric/modules/net-firewall-policy"
name = "test-1"
parent_id = "my-project"
region = "global"
attachments = {
my-vpc = module.vpc.self_link
}
egress_rules = {
smtp = {
priority = 900
match = {
destination_ranges = ["0.0.0.0/0"]
layer4_configs = [{ protocol = "tcp", ports = ["25"] }]
}
}
}
ingress_rules = {
icmp = {
priority = 1000
match = {
source_ranges = ["0.0.0.0/0"]
layer4_configs = [{ protocol = "icmp" }]
}
}
mgmt = {
priority = 1001
enable_logging = true
match = {
source_ranges = ["10.1.1.0/24"]
}
}
ssh = {
priority = 1002
enable_logging = true
match = {
source_ranges = ["10.0.0.0/8"]
# source_tags = ["tagValues/123456"]
layer4_configs = [{ protocol = "tcp", ports = ["22"] }]
}
}
}
}
# tftest modules=2 resources=10 inventory=global-net.yaml
```
### Regional Network policy
```hcl
module "vpc" {
source = "./fabric/modules/net-vpc"
project_id = "my-project"
name = "my-network"
}
module "firewall-policy" {
source = "./fabric/modules/net-firewall-policy"
name = "test-1"
parent_id = "my-project"
region = "europe-west8"
attachments = {
my-vpc = module.vpc.self_link
}
egress_rules = {
smtp = {
priority = 900
match = {
destination_ranges = ["0.0.0.0/0"]
layer4_configs = [{ protocol = "tcp", ports = ["25"] }]
}
}
}
ingress_rules = {
icmp = {
priority = 1000
match = {
source_ranges = ["0.0.0.0/0"]
layer4_configs = [{ protocol = "icmp" }]
}
}
}
}
# tftest modules=2 resources=8 inventory=regional-net.yaml
```
### Packet Mirroring Rules
### Packet Mirroring Rules
Packet mirroring rules can be defined using the `ingress_mirroring_rules` and `egress_mirroring_rules` variables. This is supported only for Global Network Policies.
```hcl
resource "google_network_security_security_profile" "default" {
provider = google-beta
name = "sec-profile"
parent = var.organization_id
type = "CUSTOM_MIRRORING"
custom_mirroring_profile {
mirroring_endpoint_group = "xxx"
}
}
resource "google_network_security_security_profile_group" "default" {
provider = google-beta
name = "sec-profile-group"
parent = var.organization_id
custom_mirroring_profile = google_network_security_security_profile.default.id
}
module "firewall-policy" {
source = "./fabric/modules/net-firewall-policy"
name = "test-mirroring"
parent_id = "my-project"
region = "global"
attachments = {
my-vpc = var.vpc.self_link
}
security_profile_group_ids = {
my-spg = "//networksecurity.googleapis.com/${google_network_security_security_profile_group.default.id}"
}
ingress_mirroring_rules = {
rule-1 = {
priority = 1000
action = "mirror"
description = "Mirror all traffic"
match = {
source_ranges = ["0.0.0.0/0"]
layer4_configs = [
{ protocol = "tcp", ports = ["80", "443"] }
]
}
security_profile_group = "//networksecurity.googleapis.com/${google_network_security_security_profile_group.default.id}"
}
}
}
# tftest inventory=mirroring.yaml
```
### Factory
Similarly to other modules, a rules factory is also included here to allow route management via descriptive configuration files.
Factory configuration is via three optional attributes in the `rules_factory_config` variable:
- `cidr_file_path` specifying the path to a mapping of logical names to CIDR ranges, used for source and destination ranges in rules when available
- `egress_rules_file_path` specifying the path to the egress rules file
- `ingress_rules_file_path` specifying the path to the ingress rules file
- `ingress_mirroring_rules_file_path` specifying the path to the mirroring rules file
- `egress_mirroring_rules_file_path` specifying the path to the mirroring rules file
Factory rules are merged with rules declared in code, with the latter taking precedence where both use the same key.
Also, the factory applies implicit defaults: `action` defaults to `deny` for egress and `allow` for ingress, while omitting `layer4_configs` makes the rule match all protocols.
This is an example of a simple factory:
```hcl
module "firewall-policy" {
source = "./fabric/modules/net-firewall-policy"
name = "test-1"
parent_id = "folders/1234567890"
attachments = {
test = "folders/4567890123"
}
ingress_rules = {
ssh = {
priority = 1002
match = {
source_ranges = ["10.0.0.0/8"]
layer4_configs = [{ protocol = "tcp", ports = ["22"] }]
}
}
}
factories_config = {
cidr_file_path = "configs/cidrs.yaml"
egress_rules_file_path = "configs/egress.yaml"
ingress_rules_file_path = "configs/ingress.yaml"
}
}
# tftest modules=1 resources=6 files=cidrs,egress,ingress inventory=factory.yaml
```
```yaml
rfc1918:
- 10.0.0.0/8
- 172.16.0.0/12
- 192.168.0.0/24
gke-nodes-range:
- 10.0.1.0/24
# tftest-file id=cidrs path=configs/cidrs.yaml
```
```yaml
smtp:
priority: 900
match:
destination_ranges:
- rfc1918
layer4_configs:
- protocol: tcp
ports:
- 25
# tftest-file id=egress path=configs/egress.yaml schema=firewall-policy-rules.schema.json
```
```yaml
icmp:
priority: 1000
match:
source_ranges:
- 10.0.0.0/8
layer4_configs:
- protocol: icmp
issue-1995:
priority: 10020
description: Allow intra-cluster communication required by k8s networking model
enable_logging: true
target_service_accounts:
- sa-gke-cluster@burner-project.iam.gserviceaccount.com
match:
source_ranges:
- gke-nodes-range
layer4_configs:
- protocol: tcp
ports:
- 1-65535
- protocol: udp
ports:
- 1-65535
- protocol: icmp
# tftest-file id=ingress path=configs/ingress.yaml schema=firewall-policy-rules.schema.json
```
```yaml
icmp:
priority: 1000
match:
source_ranges:
- 10.0.0.0/8
layer4_configs:
- protocol: icmp
issue-1995:
priority: 10020
description: Allow intra-cluster communication required by k8s networking model
enable_logging: true
target_service_accounts:
- sa-gke-cluster@burner-project.iam.gserviceaccount.com
match:
source_ranges:
- gke-nodes-range
layer4_configs:
- protocol: tcp
ports:
- 1-65535
- protocol: udp
ports:
- 1-65535
- protocol: icmp
# tftest-file id=ingress path=configs/ingress.yaml schema=firewall-policy-rules.schema.json
```
You might need to reference external security profile groups in your firewall rules, using their Terraform ids. For example, `//networksecurity.googleapis.com/${google_network_security_security_profile_group.security_profile_group.id}`. To do so, list your security profile groups in the `security_profile_group_ids` map variable. Then reference them by key from your factories.
```hcl
module "vpc" {
source = "./fabric/modules/net-vpc"
project_id = "my-project"
name = "my-network"
}
resource "google_network_security_security_profile" "security_profile" {
name = "security-profile"
type = "THREAT_PREVENTION"
parent = var.organization_id
location = "global"
}
resource "google_network_security_security_profile_group" "security_profile_group" {
name = "security-profile-group"
parent = var.organization_id
location = "global"
description = "Sample security profile group."
threat_prevention_profile = google_network_security_security_profile.security_profile.id
}
resource "google_network_security_security_profile" "mirror_profile" {
provider = google-beta
name = "sec-profile"
parent = var.organization_id
type = "CUSTOM_MIRRORING"
custom_mirroring_profile {
mirroring_endpoint_group = "xxx"
}
}
resource "google_network_security_security_profile_group" "mirror_profile_group" {
provider = google-beta
name = "sec-profile-group"
parent = var.organization_id
custom_mirroring_profile = google_network_security_security_profile.mirror_profile.id
}
module "firewall-policy" {
source = "./fabric/modules/net-firewall-policy"
name = "fw-policy"
parent_id = "my-project"
security_profile_group_ids = {
http-sg = "//networksecurity.googleapis.com/${google_network_security_security_profile_group.security_profile_group.id}"
mirror-sg = "//networksecurity.googleapis.com/${google_network_security_security_profile_group.mirror_profile_group.id}"
}
attachments = {
my-vpc = module.vpc.self_link
}
factories_config = {
ingress_rules_file_path = "configs/ingress-spg.yaml"
ingress_mirroring_rules_file_path = "configs/mirror-spg.yaml"
}
}
# tftest modules=2 resources=11 files=ingress-spg,mirror-spg inventory=factory-spg.yaml
```
```yaml
# tftest-file id=ingress-spg path=configs/ingress-spg.yaml
http:
priority: 1000
action: apply_security_profile_group
security_profile_group: http-sg
match:
source_ranges:
- 10.0.0.0/8
layer4_configs:
- protocol: tcp
ports:
- 80
```
```yaml
# tftest-file id=mirror-spg path=configs/mirror-spg.yaml schema=firewall-policy-mirroring-rules.schema.json
mirror-ssh:
priority: 1000
action: mirror
security_profile_group: mirror-sg
match:
source_ranges:
- 10.0.0.0/8
layer4_configs:
- protocol: tcp
ports:
- 22
```
#### Firewall Rule Factory Schema
The following schema outlines all available fields for defining a rule within a factory YAML file. Use this as a reference, and note the inline comments for fields that apply only to specific policy types.
```yaml
rule-name:
priority:
action:
description:
disabled:
enable_logging:
security_profile_group: # Not for Regional policies
target_service_accounts: []
target_tags: []
target_resources: [] # For Hierarchical policies only
tls_inspect: # Not for Regional policies
match:
source_ranges: []
destination_ranges: []
source_tags: [] # Not for Hierarchical policies
threat_intelligences: []
fqdns: []
address_groups: []
region_codes: []
layer4_configs:
- protocol:
ports: []
```
### Dynamic Rule Matching
This module simplifies firewall rule creation by using generic, context-aware variables within the `match` block. Based on the rule's specified `direction` (`INGRESS` or `EGRESS`), the module maps these generic variables to the correct source- (`src_*`) or destination-specific (`dest_*`) arguments in the underlying resource.
The tables below provide a complete reference for these dynamic mappings.
#### Ingress Rules
`direction = "INGRESS"`
| Module Variable (`match.*`) | Mapped Resource Attribute |
| :--- | :--- |
| `address_groups` | `src_address_groups` |
| `fqdns` | `src_fqdns` |
| `region_codes` | `src_region_codes` |
| `source_tags` | `src_secure_tags` |
| `threat_intelligences` | `src_threat_intelligences` |
#### Egress Rules
`direction = "EGRESS"`
| Module Variable (`match.*`) | Mapped Resource Attribute |
| :--- | :--- |
| `address_groups` | `dest_address_groups` |
| `fqdns` | `dest_fqdns` |
| `region_codes` | `dest_region_codes` |
| `threat_intelligences` | `dest_threat_intelligences` |
#### Rule-Level Mappings
The following variable is defined at the top level of the rule (not within the `match` block) and is mapped directly, regardless of the rule's direction.
| Module Variable | Mapped Resource Attribute |
| :--- | :--- |
| `target_tags` | `target_secure_tags` |
<!-- BEGIN TFDOC -->
## Variables
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [name](variables.tf#L197) | Policy name. | <code>string</code> | ✓ | |
| [parent_id](variables.tf#L203) | Parent node where the policy will be created, `folders/nnn` or `organizations/nnn` for hierarchical policy, project id for a network policy. | <code>string</code> | ✓ | |
| [attachments](variables.tf#L17) | Ids of the resources to which this policy will be attached, in descriptive name => self link format. Specify folders or organization for hierarchical policy, VPCs for network policy. | <code>map&#40;string&#41;</code> | | <code>&#123;&#125;</code> |
| [context](variables.tf#L24) | Context-specific interpolations. | <code>object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [description](variables.tf#L40) | Policy description. | <code>string</code> | | <code>null</code> |
| [egress_mirroring_rules](variables.tf#L46) | List of egress packet mirroring rule definitions, action can be 'mirror', 'do_not_mirror', or 'goto_next'. | <code>map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [egress_rules](variables.tf#L77) | List of egress rule definitions, action can be 'allow', 'deny', 'goto_next' or 'apply_security_profile_group'. The match.layer4configs map is in protocol => optional [ports] format. | <code>map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [factories_config](variables.tf#L115) | Paths to folders for the optional factories. | <code>object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [ingress_mirroring_rules](variables.tf#L128) | List of ingress packet mirroring rule definitions, action can be 'mirror', 'do_not_mirror', or 'goto_next'. | <code>map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [ingress_rules](variables.tf#L159) | List of ingress rule definitions, action can be 'allow', 'deny', 'goto_next' or 'apply_security_profile_group'. | <code>map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [region](variables.tf#L209) | Policy region. Leave null for hierarchical policy, set to 'global' for a global network policy. | <code>string</code> | | <code>null</code> |
| [security_profile_group_ids](variables.tf#L215) | The optional security groups ids to be referenced in factories. | <code>map&#40;string&#41;</code> | | <code>&#123;&#125;</code> |
## Outputs
| name | description | sensitive |
|---|---|:---:|
| [id](outputs.tf#L17) | Fully qualified firewall policy id. | |
<!-- END TFDOC -->