From bb91faeb4b54ac9ca56694e3d19e6c88bc6f8015 Mon Sep 17 00:00:00 2001 From: Gary Larizza Date: Mon, 4 Feb 2019 14:54:13 -0800 Subject: [PATCH] Provide ability to delete default gateway route This commit introduces the ability to delete the default gateway route that is created for the VPC network (issue #25). If the input variable `var.delete_default_internet_gateway_routes` is set then a null_resource uses the local-exec provisioner to execute a script that filters for all network routes within the `project_id` whose name begins with "default-route" and who contains a next hop of "default-internet-gateway" and then deletes them. This functionality is useful in the event that all egress traffic should be routed through a single device instead of directly to the default internet gateway. Without this change there is no way to automate the deletion of those routes. --- .kitchen.yml | 13 ++++ README.md | 1 + .../delete_default_gateway_routes/README.md | 30 ++++++++++ .../delete_default_gateway_routes/main.tf | 44 ++++++++++++++ .../delete_default_gateway_routes/outputs.tf | 60 +++++++++++++++++++ .../variables.tf | 19 ++++++ examples/multi_vpc/README.md | 2 - main.tf | 18 ++++++ scripts/delete-default-gateway-routes.sh | 46 ++++++++++++++ .../delete_default_gateway_routes/main.tf | 20 +++++++ .../delete_default_gateway_routes/outputs.tf | 25 ++++++++ .../delete_default_gateway_routes/route.tf | 30 ++++++++++ .../variables.tf | 19 ++++++ .../controls/gcloud.rb | 45 ++++++++++++++ .../delete_default_gateway_routes/inspec.yml | 8 +++ variables.tf | 9 ++- 16 files changed, 385 insertions(+), 4 deletions(-) create mode 100644 examples/delete_default_gateway_routes/README.md create mode 100644 examples/delete_default_gateway_routes/main.tf create mode 100644 examples/delete_default_gateway_routes/outputs.tf create mode 100644 examples/delete_default_gateway_routes/variables.tf create mode 100755 scripts/delete-default-gateway-routes.sh create mode 100644 test/fixtures/delete_default_gateway_routes/main.tf create mode 100644 test/fixtures/delete_default_gateway_routes/outputs.tf create mode 100644 test/fixtures/delete_default_gateway_routes/route.tf create mode 100644 test/fixtures/delete_default_gateway_routes/variables.tf create mode 100644 test/integration/delete_default_gateway_routes/controls/gcloud.rb create mode 100644 test/integration/delete_default_gateway_routes/inspec.yml diff --git a/.kitchen.yml b/.kitchen.yml index c17c6a4fd..14815b2af 100644 --- a/.kitchen.yml +++ b/.kitchen.yml @@ -80,3 +80,16 @@ suites: backend: local controls: - gcloud + - name: "delete_default_gateway_routes" + driver: + name: "terraform" + command_timeout: 1800 + root_module_directory: test/fixtures/delete_default_gateway_routes/ + verifier: + name: terraform + color: true + systems: + - name: local + backend: local + controls: + - gcloud diff --git a/README.md b/README.md index 7459544bc..dde313f78 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,7 @@ Then perform the following commands on the root folder: | Name | Description | Type | Default | Required | |------|-------------|:----:|:-----:|:-----:| +| delete_default_internet_gateway_routes | If set, ensure that all routes within the project whose names begin with 'default-route' and with a next hop of 'default-internet-gateway' are deleted | string | `` | no | | network_name | The name of the network being created | string | - | yes | | project_id | The ID of the project where this VPC will be created | string | - | yes | | routes | List of routes being created in this VPC | list | `` | no | diff --git a/examples/delete_default_gateway_routes/README.md b/examples/delete_default_gateway_routes/README.md new file mode 100644 index 000000000..1905ffeca --- /dev/null +++ b/examples/delete_default_gateway_routes/README.md @@ -0,0 +1,30 @@ +# Delete Default Gateway Routes + +This example configures a single simple VPC inside of a project. + +This VPC has a single subnet with no secondary ranges, and ensures the default internet gateway route is deleted. + +[^]: (autogen_docs_start) + + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|:----:|:-----:|:-----:| +| project_id | The project ID to host the network in | string | - | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| network_name | The name of the VPC being created | +| network_self_link | The URI of the VPC being created | +| routes | The routes associated with this VPC | +| subnets_flow_logs | Whether the subnets will have VPC flow logs enabled | +| subnets_ips | The IP and cidrs of the subnets being created | +| subnets_names | The names of the subnets being created | +| subnets_private_access | Whether the subnets will have access to Google API's without a public IP | +| subnets_regions | The region where subnets will be created | +| subnets_secondary_ranges | The secondary ranges associated with these subnets | + +[^]: (autogen_docs_end) diff --git a/examples/delete_default_gateway_routes/main.tf b/examples/delete_default_gateway_routes/main.tf new file mode 100644 index 000000000..3fd6ba490 --- /dev/null +++ b/examples/delete_default_gateway_routes/main.tf @@ -0,0 +1,44 @@ +/** + * Copyright 2018 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. + */ + +locals { + network_name = "test-network-${random_string.random_suffix.result}" +} + +resource "random_string" "random_suffix" { + length = 4 + upper = "false" + special = "false" +} + +module "test-vpc-module" { + source = "../../" + project_id = "${var.project_id}" + network_name = "${local.network_name}" + delete_default_internet_gateway_routes = "true" + + subnets = [ + { + subnet_name = "subnet-41" + subnet_ip = "10.20.30.0/24" + subnet_region = "us-west1" + }, + ] + + secondary_ranges = { + subnet-41 = [] + } +} diff --git a/examples/delete_default_gateway_routes/outputs.tf b/examples/delete_default_gateway_routes/outputs.tf new file mode 100644 index 000000000..b7afd5553 --- /dev/null +++ b/examples/delete_default_gateway_routes/outputs.tf @@ -0,0 +1,60 @@ +/** + * Copyright 2018 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. + */ + +output "network_name" { + value = "${module.test-vpc-module.network_name}" + description = "The name of the VPC being created" +} + +output "network_self_link" { + value = "${module.test-vpc-module.network_self_link}" + description = "The URI of the VPC being created" +} + +output "subnets_names" { + value = "${module.test-vpc-module.subnets_names}" + description = "The names of the subnets being created" +} + +output "subnets_ips" { + value = "${module.test-vpc-module.subnets_ips}" + description = "The IP and cidrs of the subnets being created" +} + +output "subnets_regions" { + value = "${module.test-vpc-module.subnets_regions}" + description = "The region where subnets will be created" +} + +output "subnets_private_access" { + value = "${module.test-vpc-module.subnets_private_access}" + description = "Whether the subnets will have access to Google API's without a public IP" +} + +output "subnets_flow_logs" { + value = "${module.test-vpc-module.subnets_flow_logs}" + description = "Whether the subnets will have VPC flow logs enabled" +} + +output "subnets_secondary_ranges" { + value = "${module.test-vpc-module.subnets_secondary_ranges}" + description = "The secondary ranges associated with these subnets" +} + +output "routes" { + value = "${module.test-vpc-module.routes}" + description = "The routes associated with this VPC" +} diff --git a/examples/delete_default_gateway_routes/variables.tf b/examples/delete_default_gateway_routes/variables.tf new file mode 100644 index 000000000..b69e2b2e4 --- /dev/null +++ b/examples/delete_default_gateway_routes/variables.tf @@ -0,0 +1,19 @@ +/** + * Copyright 2018 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. + */ + +variable "project_id" { + description = "The project ID to host the network in" +} diff --git a/examples/multi_vpc/README.md b/examples/multi_vpc/README.md index 83f460adc..441c17623 100644 --- a/examples/multi_vpc/README.md +++ b/examples/multi_vpc/README.md @@ -16,7 +16,6 @@ This example configures a host network project with two separate networks. | Name | Description | |------|-------------| | network_01_name | The name of the VPC network-01 | -| network_01_route_data | The route data for network 01 that was passed into the network module | | network_01_routes | The routes associated with network-01 | | network_01_self_link | The URI of the VPC network-01 | | network_01_subnets | The names of the subnets being created on network-01 | @@ -26,7 +25,6 @@ This example configures a host network project with two separate networks. | network_01_subnets_regions | The region where the subnets will be created on network-01 | | network_01_subnets_secondary_ranges | The secondary ranges associated with these subnets on network-01 | | network_02_name | The name of the VPC network-02 | -| network_02_route_data | The route data for network 02 that was passed into the network module | | network_02_routes | The routes associated with network-02 | | network_02_self_link | The URI of the VPC network-02 | | network_02_subnets | The names of the subnets being created on network-02 | diff --git a/main.tf b/main.tf index fb1eba5be..44e9b87b3 100644 --- a/main.tf +++ b/main.tf @@ -81,3 +81,21 @@ resource "google_compute_route" "route" { "google_compute_subnetwork.subnetwork", ] } + +resource "null_resource" "delete_default_internet_gateway_routes" { + count = "${var.delete_default_internet_gateway_routes != "" ? 1 : 0}" + + provisioner "local-exec" { + command = "${path.module}/scripts/delete-default-gateway-routes.sh ${var.project_id} ${var.network_name}" + } + + triggers { + number_of_routes = "${length(var.routes)}" + } + + depends_on = [ + "google_compute_network.network", + "google_compute_subnetwork.subnetwork", + "google_compute_route.route", + ] +} diff --git a/scripts/delete-default-gateway-routes.sh b/scripts/delete-default-gateway-routes.sh new file mode 100755 index 000000000..1d18d9344 --- /dev/null +++ b/scripts/delete-default-gateway-routes.sh @@ -0,0 +1,46 @@ +#!/bin/bash +# Copyright 2018 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. + + +set -e + +PROJECT_ID=$1 +NETWORK_ID=$2 +FILTERED_ROUTES=$(gcloud compute routes list \ + --project="${PROJECT_ID}" \ + --format="value(name)" \ + --filter=" \ + nextHopGateway:https://www.googleapis.com/compute/v1/projects/${PROJECT_ID}/global/gateways/default-internet-gateway \ + AND network:https://www.googleapis.com/compute/v1/projects/${PROJECT_ID}/global/networks/${NETWORK_ID} \ + " +) + +function delete_internet_gateway_routes { + local routes="${1}" + echo "${routes}" | while read -r line; do + if [[ "${line}" =~ ^default-route ]]; then + echo "Deleting route ${line}..." + gcloud compute routes delete "${line}" --quiet --project="${PROJECT_ID}" + fi + done +} + + +if [ -n "${FILTERED_ROUTES}" ]; then + delete_internet_gateway_routes "${FILTERED_ROUTES}" +else + echo "Default internet gateway route(s) not found; exiting..." +fi + diff --git a/test/fixtures/delete_default_gateway_routes/main.tf b/test/fixtures/delete_default_gateway_routes/main.tf new file mode 100644 index 000000000..dddd23794 --- /dev/null +++ b/test/fixtures/delete_default_gateway_routes/main.tf @@ -0,0 +1,20 @@ +/** + * Copyright 2018 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. + */ + +module "example" { + source = "../../../examples/delete_default_gateway_routes" + project_id = "${var.project_id}" +} diff --git a/test/fixtures/delete_default_gateway_routes/outputs.tf b/test/fixtures/delete_default_gateway_routes/outputs.tf new file mode 100644 index 000000000..b7322e425 --- /dev/null +++ b/test/fixtures/delete_default_gateway_routes/outputs.tf @@ -0,0 +1,25 @@ +/** + * Copyright 2018 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. + */ + +output "project_id" { + value = "${var.project_id}" + description = "The ID of the project being used" +} + +output "network_name" { + value = "${module.example.network_name}" + description = "The name of the VPC being created" +} diff --git a/test/fixtures/delete_default_gateway_routes/route.tf b/test/fixtures/delete_default_gateway_routes/route.tf new file mode 100644 index 000000000..0ce579c01 --- /dev/null +++ b/test/fixtures/delete_default_gateway_routes/route.tf @@ -0,0 +1,30 @@ +/** + * Copyright 2018 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. + */ + +# This fixture defines a default internet gateway route that DOESN'T start +# with 'default-route' to test the behavior of the script that deletes +# the default internet gateway routes. + +resource "google_compute_route" "alternative_gateway" { + project = "${var.project_id}" + network = "${module.example.network_name}" + + name = "alternative-gateway-route" + description = "Alternative gateway route" + dest_range = "0.0.0.0/0" + tags = ["egress-inet"] + next_hop_gateway = "default-internet-gateway" +} diff --git a/test/fixtures/delete_default_gateway_routes/variables.tf b/test/fixtures/delete_default_gateway_routes/variables.tf new file mode 100644 index 000000000..0029d2bee --- /dev/null +++ b/test/fixtures/delete_default_gateway_routes/variables.tf @@ -0,0 +1,19 @@ +/** + * Copyright 2018 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. + */ + +variable "project_id" { + description = "The GCP project to use for integration tests" +} diff --git a/test/integration/delete_default_gateway_routes/controls/gcloud.rb b/test/integration/delete_default_gateway_routes/controls/gcloud.rb new file mode 100644 index 000000000..f10e7375f --- /dev/null +++ b/test/integration/delete_default_gateway_routes/controls/gcloud.rb @@ -0,0 +1,45 @@ +# Copyright 2018 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. + +project_id = attribute('project_id') +network_name = attribute('network_name') + +control "gcloud" do + title "gcloud configuration" + + # Verify that no routes whose names begin with 'default-route' and whose + # nextHopGateway is the default-internet-gateway exist + describe command("gcloud compute routes list --project=#{project_id} --filter=\"nextHopGateway:https://www.googleapis.com/compute/v1/projects/#{project_id}/global/gateways/default-internet-gateway AND network:https://www.googleapis.com/compute/v1/projects/#{project_id}/global/networks/#{network_name}\" --format=json") do + its(:exit_status) { should eq 0 } + its(:stderr) { should eq '' } + + let(:data) do + if subject.exit_status == 0 + JSON.parse(subject.stdout) + else + {} + end + end + + describe "routes" do + it "should only be one" do + expect(data.length).to eq 1 + end + + it "should not begin with 'default-route'" do + expect(data.first["name"]).not_to match(/^default-route/) + end + end + end +end \ No newline at end of file diff --git a/test/integration/delete_default_gateway_routes/inspec.yml b/test/integration/delete_default_gateway_routes/inspec.yml new file mode 100644 index 000000000..0b5e75e3d --- /dev/null +++ b/test/integration/delete_default_gateway_routes/inspec.yml @@ -0,0 +1,8 @@ +name: delete_default_gateway_routes +attributes: + - name: project_id + required: true + type: string + - name: network_name + required: true + type: string diff --git a/variables.tf b/variables.tf index 2ea5e1e3e..c5609971e 100644 --- a/variables.tf +++ b/variables.tf @@ -23,8 +23,8 @@ variable "network_name" { } variable "routing_mode" { - type = "string" - default = "GLOBAL" + type = "string" + default = "GLOBAL" description = "The network routing mode (default 'GLOBAL')" } @@ -49,3 +49,8 @@ variable "routes" { description = "List of routes being created in this VPC" default = [] } + +variable "delete_default_internet_gateway_routes" { + description = "If set, ensure that all routes within the network specified whose names begin with 'default-route' and with a next hop of 'default-internet-gateway' are deleted" + default = "" +}