This module allows creation and management of two different firewall policy types:
- a hierarchical policy in a folder or organization, or
- a global or regional 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
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.
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
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=9 inventory=global-net.yaml
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=7 inventory=regional-net.yaml
Similarly to other modules, a rules factory (see Resource Factories) 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 availableegress_rules_file_path
specifying the path to the egress rules fileingress_rules_file_path
specifying the path to the ingress rules file
Factory rules are merged with rules declared in code, with the latter taking precedence where both use the same key.
This is an example of a simple factory:
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
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
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
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:
- [email protected]
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.
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 = "organizations/0123456789"
location = "global"
}
resource "google_network_security_security_profile_group" "security_profile_group" {
name = "security-profile-group"
parent = "organizations/0123456789"
location = "global"
description = "Sample security profile group."
threat_prevention_profile = google_network_security_security_profile.security_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}"
}
attachments = {
my-vpc = module.vpc.self_link
}
factories_config = {
ingress_rules_file_path = "configs/ingress-spg.yaml"
}
}
# tftest modules=2 resources=8 files=ingress-spg inventory=factory-spg.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
name | description | type | required | default |
---|---|---|---|---|
name | Policy name. | string |
✓ | |
parent_id | Parent node where the policy will be created, folders/nnn or organizations/nnn for hierarchical policy, project id for a network policy. |
string |
✓ | |
attachments | 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. | map(string) |
{} |
|
description | Policy description. | string |
null |
|
egress_rules | 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. | map(object({…})) |
{} |
|
factories_config | Paths to folders for the optional factories. | object({…}) |
{} |
|
ingress_rules | List of ingress rule definitions, action can be 'allow', 'deny', 'goto_next' or 'apply_security_profile_group'. | map(object({…})) |
{} |
|
region | Policy region. Leave null for hierarchical policy, set to 'global' for a global network policy. | string |
null |
|
security_profile_group_ids | The optional security groups ids to be referenced in factories. | map(string) |
{} |
name | description | sensitive |
---|---|---|
id | Fully qualified firewall policy id. |