Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cloud NAT rules support #1372

Merged
merged 2 commits into from
May 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 55 additions & 13 deletions modules/net-cloudnat/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Simple Cloud NAT management, with optional router creation.

## Example
## Basic Example

```hcl
module "nat" {
Expand All @@ -14,25 +14,67 @@ module "nat" {
}
# tftest modules=1 resources=2
```

# Reserved IPs and custom rules

```hcl
module "addresses" {
source = "./fabric/modules/net-address"
project_id = "my-project"
external_addresses = {
a1 = "europe-west1"
a2 = "europe-west1"
a3 = "europe-west1"
}
}

module "nat" {
source = "./fabric/modules/net-cloudnat"
project_id = "my-project"
region = "europe-west1"
name = "nat"
router_network = "my-vpc"
addresses = [
module.addresses.external_addresses["a1"].self_link,
module.addresses.external_addresses["a3"].self_link
]

config_port_allocation = {
enable_endpoint_independent_mapping = false
}

rules = [
{
description = "rule1"
match = "destination.ip == '8.8.8.8'"
source_ips = [
module.addresses.external_addresses["a2"].self_link
]
}
]
}
# tftest modules=2 resources=5 inventory=rules.yaml
```
<!-- BEGIN TFDOC -->

## Variables

| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [config_port_allocation](variables.tf#L23) | Configuration for how to assign ports to virtual machines. min_ports_per_vm and max_ports_per_vm have no effect unless enable_dynamic_port_allocation is set to 'true'. | <code title="object&#40;&#123;&#10; enable_endpoint_independent_mapping &#61; optional&#40;bool, true&#41;&#10; enable_dynamic_port_allocation &#61; optional&#40;bool, false&#41;&#10; min_ports_per_vm &#61; optional&#40;number, 64&#41;&#10; max_ports_per_vm &#61; optional&#40;number, 65536&#41;&#10;&#125;&#41;&#10;&#10;&#10;default &#61; &#123;&#10; enable_endpoint_independent_mapping &#61; true&#10; enable_dynamic_port_allocation &#61; false&#10; min_ports_per_vm &#61; 64&#10; max_ports_per_vm &#61; 65536&#10;&#125;">object&#40;&#123;&#8230;&#125;</code> | ✓ | |
| [name](variables.tf#L73) | Name of the Cloud NAT resource. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L78) | Project where resources will be created. | <code>string</code> | ✓ | |
| [region](variables.tf#L83) | Region where resources will be created. | <code>string</code> | ✓ | |
| [name](variables.tf#L63) | Name of the Cloud NAT resource. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L68) | Project where resources will be created. | <code>string</code> | ✓ | |
| [region](variables.tf#L73) | Region where resources will be created. | <code>string</code> | ✓ | |
| [addresses](variables.tf#L17) | Optional list of external address self links. | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</code> |
| [config_source_subnets](variables.tf#L45) | Subnetwork configuration (ALL_SUBNETWORKS_ALL_IP_RANGES, ALL_SUBNETWORKS_ALL_PRIMARY_IP_RANGES, LIST_OF_SUBNETWORKS). | <code>string</code> | | <code>&#34;ALL_SUBNETWORKS_ALL_IP_RANGES&#34;</code> |
| [config_timeouts](variables.tf#L51) | Timeout configurations. | <code title="object&#40;&#123;&#10; icmp &#61; number&#10; tcp_established &#61; number&#10; tcp_transitory &#61; number&#10; udp &#61; number&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; icmp &#61; 30&#10; tcp_established &#61; 1200&#10; tcp_transitory &#61; 30&#10; udp &#61; 30&#10;&#125;">&#123;&#8230;&#125;</code> |
| [logging_filter](variables.tf#L67) | Enables logging if not null, value is one of 'ERRORS_ONLY', 'TRANSLATIONS_ONLY', 'ALL'. | <code>string</code> | | <code>null</code> |
| [router_asn](variables.tf#L88) | Router ASN used for auto-created router. | <code>number</code> | | <code>64514</code> |
| [router_create](variables.tf#L94) | Create router. | <code>bool</code> | | <code>true</code> |
| [router_name](variables.tf#L100) | Router name, leave blank if router will be created to use auto generated name. | <code>string</code> | | <code>null</code> |
| [router_network](variables.tf#L106) | Name of the VPC used for auto-created router. | <code>string</code> | | <code>null</code> |
| [subnetworks](variables.tf#L112) | Subnetworks to NAT, only used when config_source_subnets equals LIST_OF_SUBNETWORKS. | <code title="list&#40;object&#40;&#123;&#10; self_link &#61; string,&#10; config_source_ranges &#61; list&#40;string&#41;&#10; secondary_ranges &#61; list&#40;string&#41;&#10;&#125;&#41;&#41;">list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#91;&#93;</code> |
| [config_port_allocation](variables.tf#L23) | Configuration for how to assign ports to virtual machines. min_ports_per_vm and max_ports_per_vm have no effect unless enable_dynamic_port_allocation is set to 'true'. | <code title="object&#40;&#123;&#10; enable_endpoint_independent_mapping &#61; optional&#40;bool, true&#41;&#10; enable_dynamic_port_allocation &#61; optional&#40;bool, false&#41;&#10; min_ports_per_vm &#61; optional&#40;number, 64&#41;&#10; max_ports_per_vm &#61; optional&#40;number, 65536&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [config_source_subnets](variables.tf#L39) | Subnetwork configuration (ALL_SUBNETWORKS_ALL_IP_RANGES, ALL_SUBNETWORKS_ALL_PRIMARY_IP_RANGES, LIST_OF_SUBNETWORKS). | <code>string</code> | | <code>&#34;ALL_SUBNETWORKS_ALL_IP_RANGES&#34;</code> |
| [config_timeouts](variables.tf#L45) | Timeout configurations. | <code title="object&#40;&#123;&#10; icmp &#61; optional&#40;number, 30&#41;&#10; tcp_established &#61; optional&#40;number, 1200&#41;&#10; tcp_transitory &#61; optional&#40;number, 30&#41;&#10; udp &#61; optional&#40;number, 30&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [logging_filter](variables.tf#L57) | Enables logging if not null, value is one of 'ERRORS_ONLY', 'TRANSLATIONS_ONLY', 'ALL'. | <code>string</code> | | <code>null</code> |
| [router_asn](variables.tf#L78) | Router ASN used for auto-created router. | <code>number</code> | | <code>64514</code> |
| [router_create](variables.tf#L84) | Create router. | <code>bool</code> | | <code>true</code> |
| [router_name](variables.tf#L90) | Router name, leave blank if router will be created to use auto generated name. | <code>string</code> | | <code>null</code> |
| [router_network](variables.tf#L96) | Name of the VPC used for auto-created router. | <code>string</code> | | <code>null</code> |
| [rules](variables.tf#L102) | List of rules associated with this NAT. | <code title="list&#40;object&#40;&#123;&#10; description &#61; optional&#40;string&#41;,&#10; match &#61; string&#10; source_ips &#61; list&#40;string&#41;&#10;&#125;&#41;&#41;">list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#91;&#93;</code> |
| [subnetworks](variables.tf#L113) | Subnetworks to NAT, only used when config_source_subnets equals LIST_OF_SUBNETWORKS. | <code title="list&#40;object&#40;&#123;&#10; self_link &#61; string,&#10; config_source_ranges &#61; list&#40;string&#41;&#10; secondary_ranges &#61; list&#40;string&#41;&#10;&#125;&#41;&#41;">list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#91;&#93;</code> |

## Outputs

Expand Down
14 changes: 13 additions & 1 deletion modules/net-cloudnat/main.tf
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright 2022 Google LLC
* Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -63,5 +63,17 @@ resource "google_compute_router_nat" "nat" {
secondary_ip_range_names = subnetwork.value.secondary_ranges
}
}

dynamic "rules" {
for_each = { for i, r in var.rules : i => r }
content {
rule_number = rules.key
description = rules.value.description
match = rules.value.match
action {
source_nat_active_ips = rules.value.source_ips
}
}
}
}

39 changes: 20 additions & 19 deletions modules/net-cloudnat/variables.tf
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright 2022 Google LLC
* Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -28,14 +28,8 @@ variable "config_port_allocation" {
min_ports_per_vm = optional(number, 64)
max_ports_per_vm = optional(number, 65536)
})

default = {
enable_endpoint_independent_mapping = true
enable_dynamic_port_allocation = false
min_ports_per_vm = 64
max_ports_per_vm = 65536
}

default = {}
nullable = false
validation {
condition = var.config_port_allocation.enable_dynamic_port_allocation ? var.config_port_allocation.enable_endpoint_independent_mapping == false : true
error_message = "You must set enable_endpoint_independent_mapping to false to set enable_dynamic_port_allocation to true."
Expand All @@ -51,17 +45,13 @@ variable "config_source_subnets" {
variable "config_timeouts" {
description = "Timeout configurations."
type = object({
icmp = number
tcp_established = number
tcp_transitory = number
udp = number
icmp = optional(number, 30)
tcp_established = optional(number, 1200)
tcp_transitory = optional(number, 30)
udp = optional(number, 30)
})
default = {
icmp = 30
tcp_established = 1200
tcp_transitory = 30
udp = 30
}
default = {}
nullable = false
}

variable "logging_filter" {
Expand Down Expand Up @@ -109,6 +99,17 @@ variable "router_network" {
default = null
}

variable "rules" {
description = "List of rules associated with this NAT."
type = list(object({
description = optional(string),
match = string
source_ips = list(string)
}))
default = []
nullable = false
}

variable "subnetworks" {
description = "Subnetworks to NAT, only used when config_source_subnets equals LIST_OF_SUBNETWORKS."
type = list(object({
Expand Down
55 changes: 55 additions & 0 deletions tests/modules/net_cloudnat/examples/rules.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Copyright 2023 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:
module.addresses.google_compute_address.external["a1"]:
address_type: EXTERNAL
name: a1
project: my-project
region: europe-west1
module.addresses.google_compute_address.external["a2"]:
address_type: EXTERNAL
name: a2
project: my-project
region: europe-west1
module.addresses.google_compute_address.external["a3"]:
address_type: EXTERNAL
name: a3
project: my-project
region: europe-west1
module.nat.google_compute_router.router[0]:
name: nat-nat
network: my-vpc
project: my-project
region: europe-west1
module.nat.google_compute_router_nat.nat:
enable_dynamic_port_allocation: false
enable_endpoint_independent_mapping: false
icmp_idle_timeout_sec: 30
name: nat
nat_ip_allocate_option: MANUAL_ONLY
project: my-project
region: europe-west1
router: nat-nat
rules:
- action:
- source_nat_drain_ips: []
description: rule1
match: destination.ip == '8.8.8.8'
rule_number: 0

counts:
google_compute_address: 3
google_compute_router: 1
google_compute_router_nat: 1