From 1bd3380a3fd214b28a20a81363f6d3f1d158d48c Mon Sep 17 00:00:00 2001 From: Luca Prete Date: Sat, 6 Jul 2024 13:33:09 +0300 Subject: [PATCH] Adds support for external SPGs to net-firewall-policy (#2409) - Added support to reference external SPGs in factories in net-firewall-policy - Added missing tls_inspect argument to hierarchical and global network firewall policies - Fixed regional firewall policy rules, removing security profile groups and ngfw actions (given they're not supported) - Updated copyright --- modules/net-firewall-policy/README.md | 69 +++++++++++- modules/net-firewall-policy/factory.tf | 4 +- modules/net-firewall-policy/hierarchical.tf | 8 +- modules/net-firewall-policy/net-global.tf | 8 +- modules/net-firewall-policy/net-regional.tf | 3 +- modules/net-firewall-policy/variables.tf | 11 +- .../examples/factory-spg.yaml | 105 ++++++++++++++++++ 7 files changed, 194 insertions(+), 14 deletions(-) create mode 100644 tests/modules/net_firewall_policy/examples/factory-spg.yaml diff --git a/modules/net-firewall-policy/README.md b/modules/net-firewall-policy/README.md index 10d395fe..4c1722c4 100644 --- a/modules/net-firewall-policy/README.md +++ b/modules/net-firewall-policy/README.md @@ -253,19 +253,76 @@ issue-1995: - 1-65535 - protocol: icmp ``` + +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 = "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 +``` + +```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 +``` ## Variables | name | description | type | required | default | |---|---|:---:|:---:|:---:| -| [name](variables.tf#L115) | Policy name. | string | ✓ | | -| [parent_id](variables.tf#L121) | Parent node where the policy will be created, `folders/nnn` or `organizations/nnn` for hierarchical policy, project id for a network policy. | string | ✓ | | +| [name](variables.tf#L117) | Policy name. | string | ✓ | | +| [parent_id](variables.tf#L123) | Parent node where the policy will be created, `folders/nnn` or `organizations/nnn` for hierarchical policy, project id for a network policy. | string | ✓ | | | [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. | map(string) | | {} | | [description](variables.tf#L24) | Policy description. | string | | null | -| [egress_rules](variables.tf#L30) | 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](variables.tf#L67) | Paths to folders for the optional factories. | object({…}) | | {} | -| [ingress_rules](variables.tf#L78) | List of ingress rule definitions, action can be 'allow', 'deny', 'goto_next' or 'apply_security_profile_group'. | map(object({…})) | | {} | -| [region](variables.tf#L127) | Policy region. Leave null for hierarchical policy, set to 'global' for a global network policy. | string | | null | +| [egress_rules](variables.tf#L30) | 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](variables.tf#L68) | Paths to folders for the optional factories. | object({…}) | | {} | +| [ingress_rules](variables.tf#L79) | List of ingress rule definitions, action can be 'allow', 'deny', 'goto_next' or 'apply_security_profile_group'. | map(object({…})) | | {} | +| [region](variables.tf#L129) | Policy region. Leave null for hierarchical policy, set to 'global' for a global network policy. | string | | null | +| [security_profile_group_ids](variables.tf#L135) | The optional security groups ids to be referenced in factories. | map(string) | | {} | ## Outputs diff --git a/modules/net-firewall-policy/factory.tf b/modules/net-firewall-policy/factory.tf index 74ef28d7..b36a068b 100644 --- a/modules/net-firewall-policy/factory.tf +++ b/modules/net-firewall-policy/factory.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -39,6 +39,7 @@ locals { target_resources = lookup(v, "target_resources", null) target_service_accounts = lookup(v, "target_service_accounts", null) target_tags = lookup(v, "target_tags", null) + tls_inspect = lookup(v, "tls_inspect", null) match = { address_groups = lookup(v.match, "address_groups", null) fqdns = lookup(v.match, "fqdns", null) @@ -85,6 +86,7 @@ locals { target_resources = lookup(v, "target_resources", null) target_service_accounts = lookup(v, "target_service_accounts", null) target_tags = lookup(v, "target_tags", null) + tls_inspect = lookup(v, "tls_inspect", null) match = { address_groups = lookup(v.match, "address_groups", null) fqdns = lookup(v.match, "fqdns", null) diff --git a/modules/net-firewall-policy/hierarchical.tf b/modules/net-firewall-policy/hierarchical.tf index 48bc9c9e..7969a559 100644 --- a/modules/net-firewall-policy/hierarchical.tf +++ b/modules/net-firewall-policy/hierarchical.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,12 +37,16 @@ resource "google_compute_firewall_policy_rule" "hierarchical" { action = local.rules[each.key].action description = local.rules[each.key].description direction = local.rules[each.key].direction - security_profile_group = local.rules[each.key].security_profile_group disabled = local.rules[each.key].disabled enable_logging = local.rules[each.key].enable_logging priority = local.rules[each.key].priority target_resources = local.rules[each.key].target_resources target_service_accounts = local.rules[each.key].target_service_accounts + tls_inspect = local.rules[each.key].tls_inspect + security_profile_group = try( + var.security_profile_group_ids[local.rules[each.key].security_profile_group], + local.rules[each.key].security_profile_group + ) match { dest_ip_ranges = local.rules[each.key].match.destination_ranges src_ip_ranges = local.rules[each.key].match.source_ranges diff --git a/modules/net-firewall-policy/net-global.tf b/modules/net-firewall-policy/net-global.tf index db15930d..cf837c86 100644 --- a/modules/net-firewall-policy/net-global.tf +++ b/modules/net-firewall-policy/net-global.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -44,11 +44,15 @@ resource "google_compute_network_firewall_policy_rule" "net-global" { action = local.rules[each.key].action description = local.rules[each.key].description direction = local.rules[each.key].direction - security_profile_group = local.rules[each.key].security_profile_group disabled = local.rules[each.key].disabled enable_logging = local.rules[each.key].enable_logging priority = local.rules[each.key].priority target_service_accounts = local.rules[each.key].target_service_accounts + tls_inspect = local.rules[each.key].tls_inspect + security_profile_group = try( + var.security_profile_group_ids[local.rules[each.key].security_profile_group], + local.rules[each.key].security_profile_group + ) match { dest_ip_ranges = local.rules[each.key].match.destination_ranges src_ip_ranges = local.rules[each.key].match.source_ranges diff --git a/modules/net-firewall-policy/net-regional.tf b/modules/net-firewall-policy/net-regional.tf index a3d9f53d..281cbc4f 100644 --- a/modules/net-firewall-policy/net-regional.tf +++ b/modules/net-firewall-policy/net-regional.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -47,7 +47,6 @@ resource "google_compute_region_network_firewall_policy_rule" "net-regional" { action = local.rules[each.key].action description = local.rules[each.key].description direction = local.rules[each.key].direction - security_profile_group = local.rules[each.key].security_profile_group disabled = local.rules[each.key].disabled enable_logging = local.rules[each.key].enable_logging priority = local.rules[each.key].priority diff --git a/modules/net-firewall-policy/variables.tf b/modules/net-firewall-policy/variables.tf index fad6ab90..bab3ee85 100644 --- a/modules/net-firewall-policy/variables.tf +++ b/modules/net-firewall-policy/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -39,6 +39,7 @@ variable "egress_rules" { 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)) @@ -87,6 +88,7 @@ variable "ingress_rules" { 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)) @@ -129,3 +131,10 @@ variable "region" { type = string default = null } + +variable "security_profile_group_ids" { + description = "The optional security groups ids to be referenced in factories." + type = map(string) + nullable = false + default = {} +} diff --git a/tests/modules/net_firewall_policy/examples/factory-spg.yaml b/tests/modules/net_firewall_policy/examples/factory-spg.yaml new file mode 100644 index 00000000..82353b4c --- /dev/null +++ b/tests/modules/net_firewall_policy/examples/factory-spg.yaml @@ -0,0 +1,105 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +values: + google_network_security_security_profile.security_profile: + description: null + labels: null + location: global + name: security-profile + parent: organizations/0123456789 + threat_prevention_profile: [] + type: THREAT_PREVENTION + google_network_security_security_profile_group.security_profile_group: + description: Sample security profile group. + labels: null + location: global + name: security-profile-group + parent: organizations/0123456789 + module.firewall-policy.google_compute_firewall_policy.hierarchical[0]: + description: null + parent: my-project + short_name: fw-policy + module.firewall-policy.google_compute_firewall_policy_association.hierarchical["my-vpc"]: + name: fw-policy-my-vpc + module.firewall-policy.google_compute_firewall_policy_rule.hierarchical["ingress/http"]: + action: apply_security_profile_group + description: null + direction: INGRESS + disabled: false + enable_logging: null + match: + - dest_address_groups: null + dest_fqdns: null + dest_ip_ranges: null + dest_region_codes: null + dest_threat_intelligences: null + layer4_configs: + - ip_protocol: tcp + ports: + - '80' + src_address_groups: null + src_fqdns: null + src_ip_ranges: + - 10.0.0.0/8 + src_region_codes: null + src_threat_intelligences: null + priority: 1000 + target_resources: null + target_service_accounts: null + tls_inspect: null + module.vpc.google_compute_network.network[0]: + auto_create_subnetworks: false + delete_default_routes_on_create: false + description: Terraform-managed. + enable_ula_internal_ipv6: null + name: my-network + network_firewall_policy_enforcement_order: AFTER_CLASSIC_FIREWALL + project: my-project + routing_mode: GLOBAL + module.vpc.google_compute_route.gateway["private-googleapis"]: + description: Terraform-managed. + dest_range: 199.36.153.8/30 + name: my-network-private-googleapis + network: my-network + next_hop_gateway: default-internet-gateway + next_hop_ilb: null + next_hop_instance: null + next_hop_vpn_tunnel: null + priority: 1000 + project: my-project + tags: null + module.vpc.google_compute_route.gateway["restricted-googleapis"]: + description: Terraform-managed. + dest_range: 199.36.153.4/30 + name: my-network-restricted-googleapis + network: my-network + next_hop_gateway: default-internet-gateway + next_hop_ilb: null + next_hop_instance: null + next_hop_vpn_tunnel: null + priority: 1000 + project: my-project + tags: null + +counts: + google_compute_firewall_policy: 1 + google_compute_firewall_policy_association: 1 + google_compute_firewall_policy_rule: 1 + google_compute_network: 1 + google_compute_route: 2 + google_network_security_security_profile: 1 + google_network_security_security_profile_group: 1 + modules: 2 + resources: 8