diff --git a/build/int.cloudbuild.yaml b/build/int.cloudbuild.yaml index 8c80949b..7661274d 100644 --- a/build/int.cloudbuild.yaml +++ b/build/int.cloudbuild.yaml @@ -31,10 +31,25 @@ steps: - prepare name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' args: ['/bin/bash', '-c', 'source /usr/local/bin/task_helper_functions.sh && source_test_env && init_credentials && cd test/integration && RUN_STAGE=init go test -v ./... -p 1 -timeout 0'] -- id: converge simple-project-local +- id: converge service-networking waitFor: - create all name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' + args: ['/bin/bash', '-c', 'cft test run TestServiceNetworking --stage apply --verbose'] +- id: verify service-networking + waitFor: + - converge service-networking + name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' + args: ['/bin/bash', '-c', 'cft test run TestServiceNetworking --stage verify --verbose'] +- id: destroy service-networking + waitFor: + - verify service-networking + name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' + args: ['/bin/bash', '-c', 'cft test run TestServiceNetworking --stage teardown --verbose'] +- id: converge simple-project-local + waitFor: + - destroy service-networking + name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' args: ['/bin/bash', '-c', 'source /usr/local/bin/task_helper_functions.sh && source_test_env && init_credentials && cd test/integration && RUN_STAGE=apply go test -v ./... -p 1 -timeout 0 -run ^TestSimpleProject$'] - id: verify simple-project-local waitFor: diff --git a/examples/service-networking/README.md b/examples/service-networking/README.md new file mode 100644 index 00000000..ded25941 --- /dev/null +++ b/examples/service-networking/README.md @@ -0,0 +1,38 @@ +# Terraform service networking example +This example creates service networking with a global address. + +``` +resource "google_compute_network" "peering_network" { + name = "private-network" + auto_create_subnetworks = "false" + project = var.project_id +} + +module "service_networking" { + source = "terraform-google-modules/network/google//modules/service-networking" + version = "~> 9.0" + + project_id = var.project_id + network_name = google_compute_network.peering_network.name + global_addresses = [{ name : "global-address" }] + service = "servicenetworking.googleapis.com" +} +``` + +In the above terraform, a service networking connection is created. It enables managed services (cloud sql,memorystore) on internal IP addresses (VPC) to service consumers (cloud-run). Service consumers use private services access to privately connect to the service. + + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| project\_id | Project ID | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| peering | Service networking peering output | +| project\_id | Project ID | + + diff --git a/examples/service-networking/main.tf b/examples/service-networking/main.tf new file mode 100644 index 00000000..3a777f8b --- /dev/null +++ b/examples/service-networking/main.tf @@ -0,0 +1,31 @@ +/** + * 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. + */ + +resource "google_compute_network" "peering_network" { + name = "private-network" + auto_create_subnetworks = "false" + project = var.project_id +} + +module "service_networking" { + source = "terraform-google-modules/network/google//modules/service-networking" + version = "~> 9.0" + + project_id = var.project_id + network_name = google_compute_network.peering_network.name + global_addresses = [{ name : "global-address" }] + service = "servicenetworking.googleapis.com" +} diff --git a/examples/service-networking/outputs.tf b/examples/service-networking/outputs.tf new file mode 100644 index 00000000..1ce92dae --- /dev/null +++ b/examples/service-networking/outputs.tf @@ -0,0 +1,25 @@ +/** + * 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. + */ + +output "project_id" { + description = "Project ID" + value = var.project_id +} + +output "peering" { + description = "Service networking peering output" + value = module.service_networking.peering +} diff --git a/examples/service-networking/variables.tf b/examples/service-networking/variables.tf new file mode 100644 index 00000000..4c2ad67f --- /dev/null +++ b/examples/service-networking/variables.tf @@ -0,0 +1,20 @@ +/** + * 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. + */ + +variable "project_id" { + description = "Project ID" + type = string +} diff --git a/modules/service-networking/README.md b/modules/service-networking/README.md new file mode 100644 index 00000000..449cade7 --- /dev/null +++ b/modules/service-networking/README.md @@ -0,0 +1,29 @@ +# Terraform Google service networking + +This module creates global network address and a service networking. The google_service_networking_connection terraform resource allows to establish a private connection between a Google Cloud Platform (GCP) VPC network and a supported Google service, such as Cloud SQL, BigQuery, or a third-party service. + + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| create\_peered\_dns\_domain | Create peered dns domain | `bool` | `false` | no | +| create\_peering\_routes\_config | Create peering route config | `bool` | `false` | no | +| deletion\_policy | Deletion policy for service networking resource | `string` | `null` | no | +| dns\_suffix | Dns suffix | `string` | `null` | no | +| domain\_name | Domain name | `string` | `null` | no | +| export\_custom\_routes | Export custom routes | `bool` | `false` | no | +| global\_addresses | List of global addresses to be created |
list(object({
name : string,
purpose : optional(string, "VPC_PEERING"),
type : optional(string, "INTERNAL"),
address : optional(string, null),
prefix_length : optional(number, 16)
}))
| n/a | yes | +| import\_custom\_routes | Import custom routes to peering rout config | `bool` | `false` | no | +| network\_name | Network name | `string` | n/a | yes | +| project\_id | Project ID | `string` | n/a | yes | +| service | Service to create service networking connection | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| address\_ids | Global address id | +| peering | Service networking connection peering | + + diff --git a/modules/service-networking/main.tf b/modules/service-networking/main.tf new file mode 100644 index 00000000..091650e0 --- /dev/null +++ b/modules/service-networking/main.tf @@ -0,0 +1,51 @@ +/** + * 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. + */ + +resource "google_compute_global_address" "global_addresses" { + for_each = { for address in var.global_addresses : address.name => address } + project = var.project_id + name = each.value.name + purpose = each.value.purpose + address_type = each.value.type + address = each.value.address + prefix_length = each.value.prefix_length + network = "projects/${var.project_id}/global/networks/${var.network_name}" +} + +resource "google_service_networking_connection" "default" { + network = "projects/${var.project_id}/global/networks/${var.network_name}" + service = var.service + reserved_peering_ranges = [for name, _ in google_compute_global_address.global_addresses : name] + deletion_policy = var.deletion_policy +} + +resource "google_compute_network_peering_routes_config" "peering_routes" { + count = var.create_peering_routes_config ? 1 : 0 + project = var.project_id + peering = google_service_networking_connection.default.peering + network = var.network_name + import_custom_routes = var.import_custom_routes + export_custom_routes = var.export_custom_routes +} + +resource "google_service_networking_peered_dns_domain" "default" { + count = var.create_peered_dns_domain ? 1 : 0 + project = var.project_id + name = var.domain_name + network = var.network_name + dns_suffix = var.dns_suffix + service = var.service +} diff --git a/modules/service-networking/metadata.yaml b/modules/service-networking/metadata.yaml new file mode 100644 index 00000000..87e46202 --- /dev/null +++ b/modules/service-networking/metadata.yaml @@ -0,0 +1,167 @@ + # 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. + +apiVersion: blueprints.cloud.google.com/v1alpha1 +kind: BlueprintMetadata +metadata: + name: terraform-google-network-service-networking + annotations: + config.kubernetes.io/local-config: "true" +spec: + info: + title: Terraform Google service networking + source: + repo: https://github.com/terraform-google-modules/terraform-google-network.git + sourceType: git + dir: /modules/service-networking + version: 9.1.0 + actuationTool: + flavor: Terraform + version: ">= 0.13.0" + description: {} + content: + examples: + - name: basic_auto_mode + location: examples/basic_auto_mode + - name: basic_custom_mode + location: examples/basic_custom_mode + - name: basic_firewall_rule + location: examples/basic_firewall_rule + - name: basic_secondary_ranges + location: examples/basic_secondary_ranges + - name: basic_shared_vpc + location: examples/basic_shared_vpc + - name: basic_vpc_peering + location: examples/basic_vpc_peering + - name: bidirectional-firewall-rules + location: examples/bidirectional-firewall-rules + - name: delete_default_gateway_routes + location: examples/delete_default_gateway_routes + - name: firewall_logging + location: examples/firewall_logging + - name: global-network-firewall-policy + location: examples/global-network-firewall-policy + - name: hierarchical-firewall-policy + location: examples/hierarchical-firewall-policy + - name: ilb_routing + location: examples/ilb_routing + - name: multi_vpc + location: examples/multi_vpc + - name: network_service_tiers + location: examples/network_service_tiers + - name: packet_mirroring + location: examples/packet_mirroring + - name: private_service_connect + location: examples/private_service_connect + - name: private_service_connect_google_apis + location: examples/private_service_connect_google_apis + - name: regional-network-firewall-policy + location: examples/regional-network-firewall-policy + - name: routes + location: examples/routes + - name: secondary_ranges + location: examples/secondary_ranges + - name: service-networking + location: examples/service-networking + - name: simple_ipv6_project + location: examples/simple_ipv6_project + - name: simple_project + location: examples/simple_project + - name: simple_project_with_regional_network + location: examples/simple_project_with_regional_network + - name: submodule_firewall + location: examples/submodule_firewall + - name: submodule_network_peering + location: examples/submodule_network_peering + - name: submodule_svpc_access + location: examples/submodule_svpc_access + - name: submodule_vpc_serverless_connector + location: examples/submodule_vpc_serverless_connector + interfaces: + variables: + - name: create_peered_dns_domain + description: Create peered dns domain + varType: bool + defaultValue: false + - name: create_peering_routes_config + description: Create peering route config + varType: bool + defaultValue: false + - name: deletion_policy + description: Deletion policy for service networking resource + varType: string + - name: dns_suffix + description: Dns suffix + varType: string + - name: domain_name + description: Domain name + varType: string + - name: export_custom_routes + description: Export custom routes + varType: bool + defaultValue: false + - name: global_addresses + description: List of global addresses to be created + varType: |- + list(object({ + name : string, + purpose : optional(string, "VPC_PEERING"), + type : optional(string, "INTERNAL"), + address : optional(string, null), + prefix_length : optional(number, 16) + })) + required: true + - name: import_custom_routes + description: Import custom routes to peering rout config + varType: bool + defaultValue: false + - name: network_name + description: Network name + varType: string + required: true + - name: project_id + description: Project ID + varType: string + required: true + - name: service + description: Service to create service networking connection + varType: string + required: true + outputs: + - name: address_ids + description: Global address id + - name: peering + description: Service networking connection peering + requirements: + roles: + - level: Project + roles: + - roles/compute.networkAdmin + - roles/compute.securityAdmin + - roles/iam.serviceAccountUser + - roles/vpcaccess.admin + - roles/serviceusage.serviceUsageAdmin + - roles/dns.admin + - roles/resourcemanager.tagAdmin + - roles/iam.serviceAccountAdmin + - roles/compute.orgFirewallPolicyAdmin + services: + - cloudresourcemanager.googleapis.com + - compute.googleapis.com + - serviceusage.googleapis.com + - vpcaccess.googleapis.com + - dns.googleapis.com + - networksecurity.googleapis.com + - iam.googleapis.com + - servicenetworking.googleapis.com diff --git a/modules/service-networking/outputs.tf b/modules/service-networking/outputs.tf new file mode 100644 index 00000000..25a3b270 --- /dev/null +++ b/modules/service-networking/outputs.tf @@ -0,0 +1,25 @@ +/** + * 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. + */ + +output "address_ids" { + description = "Global address id" + value = [for id, _ in google_compute_global_address.global_addresses : id] +} + +output "peering" { + description = "Service networking connection peering" + value = google_service_networking_connection.default.peering +} diff --git a/modules/service-networking/variables.tf b/modules/service-networking/variables.tf new file mode 100644 index 00000000..50800d12 --- /dev/null +++ b/modules/service-networking/variables.tf @@ -0,0 +1,83 @@ +/** + * 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. + */ + +variable "project_id" { + description = "Project ID" + type = string +} + +variable "global_addresses" { + description = "List of global addresses to be created" + type = list(object({ + name : string, + purpose : optional(string, "VPC_PEERING"), + type : optional(string, "INTERNAL"), + address : optional(string, null), + prefix_length : optional(number, 16) + })) +} + +variable "network_name" { + description = "Network name" + type = string +} + +variable "service" { + description = "Service to create service networking connection" + type = string +} + +variable "deletion_policy" { + description = "Deletion policy for service networking resource" + type = string + default = null +} + +variable "create_peering_routes_config" { + description = "Create peering route config" + type = bool + default = false +} + +variable "import_custom_routes" { + description = "Import custom routes to peering rout config" + type = bool + default = false +} + +variable "export_custom_routes" { + description = "Export custom routes" + type = bool + default = false +} + +variable "create_peered_dns_domain" { + description = "Create peered dns domain" + type = bool + default = false +} + +variable "domain_name" { + description = "Domain name" + type = string + default = null +} + +variable "dns_suffix" { + description = "Dns suffix" + type = string + default = null +} diff --git a/modules/service-networking/versions.tf b/modules/service-networking/versions.tf new file mode 100644 index 00000000..dc20a141 --- /dev/null +++ b/modules/service-networking/versions.tf @@ -0,0 +1,34 @@ +/** + * 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. + */ + +terraform { + required_version = ">= 0.13.0" + + required_providers { + google = { + source = "hashicorp/google" + version = ">= 5.8, < 6" + } + google-beta = { + source = "hashicorp/google-beta" + version = ">= 3.0, < 6" + } + } + + provider_meta "google-beta" { + module_name = "blueprints/terraform/terraform-google-network:service-networking/v9.1.0" + } +} diff --git a/test/integration/service-networking/service_networking_test.go b/test/integration/service-networking/service_networking_test.go new file mode 100644 index 00000000..8b31ac60 --- /dev/null +++ b/test/integration/service-networking/service_networking_test.go @@ -0,0 +1,34 @@ +// Copyright 2021 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. + +package servicenetworking + +import ( + "testing" + + "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/tft" + "github.com/stretchr/testify/assert" +) + +func TestServiceNetworking(t *testing.T) { + net := tft.NewTFBlueprintTest(t) + net.DefineVerify( + func(assert *assert.Assertions) { + net.DefaultVerify(assert) + peering := net.GetStringOutput("peering") + + assert.Contains(peering, "servicenetworking-googleapis-com") + }) + net.Test() +} diff --git a/test/setup/main.tf b/test/setup/main.tf index 79cbb95d..02a94910 100644 --- a/test/setup/main.tf +++ b/test/setup/main.tf @@ -54,5 +54,6 @@ module "project" { "dns.googleapis.com", "networksecurity.googleapis.com", "iam.googleapis.com", + "servicenetworking.googleapis.com", ] }