Add support for mirroring rules to modules/net-firewall-policy (#3636)
* Add support for mirroring rules to net-firewall-policy * Split mirroring rules * Add schema * Sort variables
This commit is contained in:
@@ -14,6 +14,8 @@ The module also makes fewer assumptions about implicit defaults, only using one
|
||||
- [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)
|
||||
@@ -168,6 +170,60 @@ module "firewall-policy" {
|
||||
# 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.
|
||||
@@ -177,6 +233,8 @@ Factory configuration is via three optional attributes in the `rules_factory_con
|
||||
- `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.
|
||||
@@ -260,6 +318,35 @@ issue-1995:
|
||||
# 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
|
||||
@@ -272,33 +359,54 @@ module "vpc" {
|
||||
resource "google_network_security_security_profile" "security_profile" {
|
||||
name = "security-profile"
|
||||
type = "THREAT_PREVENTION"
|
||||
parent = "organizations/0123456789"
|
||||
parent = var.organization_id
|
||||
location = "global"
|
||||
}
|
||||
|
||||
resource "google_network_security_security_profile_group" "security_profile_group" {
|
||||
name = "security-profile-group"
|
||||
parent = "organizations/0123456789"
|
||||
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}"
|
||||
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_rules_file_path = "configs/ingress-spg.yaml"
|
||||
ingress_mirroring_rules_file_path = "configs/mirror-spg.yaml"
|
||||
}
|
||||
}
|
||||
# tftest modules=2 resources=9 files=ingress-spg inventory=factory-spg.yaml
|
||||
# tftest modules=2 resources=11 files=ingress-spg,mirror-spg inventory=factory-spg.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
@@ -316,6 +424,21 @@ http:
|
||||
- 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.
|
||||
@@ -386,16 +509,18 @@ The following variable is defined at the top level of the rule (not within the `
|
||||
|
||||
| name | description | type | required | default |
|
||||
|---|---|:---:|:---:|:---:|
|
||||
| [name](variables.tf#L133) | Policy name. | <code>string</code> | ✓ | |
|
||||
| [parent_id](variables.tf#L139) | 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> | ✓ | |
|
||||
| [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(string)</code> | | <code>{}</code> |
|
||||
| [context](variables.tf#L24) | Context-specific interpolations. | <code title="object({ cidr_ranges = optional(map(string), {}) cidr_ranges_sets = optional(map(list(string)), {}) folder_ids = optional(map(string), {}) iam_principals = optional(map(string), {}) locations = optional(map(string), {}) networks = optional(map(string), {}) project_ids = optional(map(string), {}) tag_values = optional(map(string), {}) })">object({…})</code> | | <code>{}</code> |
|
||||
| [description](variables.tf#L40) | Policy description. | <code>string</code> | | <code>null</code> |
|
||||
| [egress_rules](variables.tf#L46) | 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 title="map(object({ priority = number action = optional(string, "deny") description = optional(string) disabled = optional(bool, false) enable_logging = optional(bool) security_profile_group = optional(string) target_resources = optional(list(string)) target_service_accounts = optional(list(string)) target_tags = optional(list(string)) tls_inspect = optional(bool, null) match = object({ address_groups = optional(list(string)) fqdns = optional(list(string)) region_codes = optional(list(string)) threat_intelligences = optional(list(string)) destination_ranges = optional(list(string)) source_ranges = optional(list(string)) source_tags = optional(list(string)) layer4_configs = optional(list(object({ protocol = optional(string, "all") ports = optional(list(string)) })), [{}]) }) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||
| [factories_config](variables.tf#L84) | Paths to folders for the optional factories. | <code title="object({ cidr_file_path = optional(string) egress_rules_file_path = optional(string) ingress_rules_file_path = optional(string) })">object({…})</code> | | <code>{}</code> |
|
||||
| [ingress_rules](variables.tf#L95) | List of ingress rule definitions, action can be 'allow', 'deny', 'goto_next' or 'apply_security_profile_group'. | <code title="map(object({ priority = number action = optional(string, "allow") description = optional(string) disabled = optional(bool, false) enable_logging = optional(bool) security_profile_group = optional(string) target_resources = optional(list(string)) target_service_accounts = optional(list(string)) target_tags = optional(list(string)) tls_inspect = optional(bool, null) match = object({ address_groups = optional(list(string)) fqdns = optional(list(string)) region_codes = optional(list(string)) threat_intelligences = optional(list(string)) destination_ranges = optional(list(string)) source_ranges = optional(list(string)) source_tags = optional(list(string)) layer4_configs = optional(list(object({ protocol = optional(string, "all") ports = optional(list(string)) })), [{}]) }) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||
| [region](variables.tf#L145) | 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#L151) | The optional security groups ids to be referenced in factories. | <code>map(string)</code> | | <code>{}</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 title="map(object({ priority = number action = optional(string, "mirror") description = optional(string) disabled = optional(bool, false) security_profile_group = optional(string) target_tags = optional(list(string)) tls_inspect = optional(bool, null) match = object({ destination_ranges = optional(list(string)) source_ranges = optional(list(string)) source_tags = optional(list(string)) layer4_configs = optional(list(object({ protocol = optional(string, "all") ports = optional(list(string)) })), [{}]) }) }))">map(object({…}))</code> | | <code>{}</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 title="map(object({ priority = number action = optional(string, "deny") description = optional(string) disabled = optional(bool, false) enable_logging = optional(bool) security_profile_group = optional(string) target_resources = optional(list(string)) target_service_accounts = optional(list(string)) target_tags = optional(list(string)) tls_inspect = optional(bool, null) match = object({ address_groups = optional(list(string)) fqdns = optional(list(string)) region_codes = optional(list(string)) threat_intelligences = optional(list(string)) destination_ranges = optional(list(string)) source_ranges = optional(list(string)) source_tags = optional(list(string)) layer4_configs = optional(list(object({ protocol = optional(string, "all") ports = optional(list(string)) })), [{}]) }) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||
| [factories_config](variables.tf#L115) | Paths to folders for the optional factories. | <code title="object({ cidr_file_path = optional(string) egress_rules_file_path = optional(string) ingress_rules_file_path = optional(string) ingress_mirroring_rules_file_path = optional(string) egress_mirroring_rules_file_path = optional(string) })">object({…})</code> | | <code>{}</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 title="map(object({ priority = number action = optional(string, "mirror") description = optional(string) disabled = optional(bool, false) security_profile_group = optional(string) target_tags = optional(list(string)) tls_inspect = optional(bool, null) match = object({ destination_ranges = optional(list(string)) source_ranges = optional(list(string)) source_tags = optional(list(string)) layer4_configs = optional(list(object({ protocol = optional(string, "all") ports = optional(list(string)) })), [{}]) }) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||
| [ingress_rules](variables.tf#L159) | List of ingress rule definitions, action can be 'allow', 'deny', 'goto_next' or 'apply_security_profile_group'. | <code title="map(object({ priority = number action = optional(string, "allow") description = optional(string) disabled = optional(bool, false) enable_logging = optional(bool) security_profile_group = optional(string) target_resources = optional(list(string)) target_service_accounts = optional(list(string)) target_tags = optional(list(string)) tls_inspect = optional(bool, null) match = object({ address_groups = optional(list(string)) fqdns = optional(list(string)) region_codes = optional(list(string)) threat_intelligences = optional(list(string)) destination_ranges = optional(list(string)) source_ranges = optional(list(string)) source_tags = optional(list(string)) layer4_configs = optional(list(object({ protocol = optional(string, "all") ports = optional(list(string)) })), [{}]) }) }))">map(object({…}))</code> | | <code>{}</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(string)</code> | | <code>{}</code> |
|
||||
|
||||
## Outputs
|
||||
|
||||
|
||||
Reference in New Issue
Block a user