diff --git a/.kitchen.yml b/.kitchen.yml index 581c284e6..fa2814907 100644 --- a/.kitchen.yml +++ b/.kitchen.yml @@ -71,9 +71,9 @@ suites: - development - non-production - production - - name: dns_hub + - name: shared driver: - root_module_directory: test/fixtures/dns_hub/ + root_module_directory: test/fixtures/shared/ verifier: color: false systems: diff --git a/0-bootstrap/README.md b/0-bootstrap/README.md index fca98ad88..3398467d3 100644 --- a/0-bootstrap/README.md +++ b/0-bootstrap/README.md @@ -66,7 +66,6 @@ Currently, the bucket information is replaced in the state backends as a part of | org\_project\_creators | Additional list of members to have project creator role across the organization. Prefix of group: user: or serviceAccount: is required. | `list(string)` | `[]` | no | | parent\_folder | Optional - if using a folder for testing. | `string` | `""` | no | | project\_prefix | Name prefix to use for projects created. | `string` | `"prj"` | no | -| skip\_gcloud\_download | Whether to skip downloading gcloud (assumes gcloud is already available outside the module) | `bool` | `true` | no | ## Outputs diff --git a/0-bootstrap/main.tf b/0-bootstrap/main.tf index 09c24db27..a35be28a0 100644 --- a/0-bootstrap/main.tf +++ b/0-bootstrap/main.tf @@ -57,7 +57,6 @@ module "seed_bootstrap" { org_project_creators = var.org_project_creators sa_enable_impersonation = true parent_folder = var.parent_folder == "" ? "" : local.parent - skip_gcloud_download = var.skip_gcloud_download org_admins_org_iam_permissions = local.org_admins_org_iam_permissions project_prefix = var.project_prefix @@ -125,7 +124,6 @@ module "cloudbuild_bootstrap" { terraform_sa_name = module.seed_bootstrap.terraform_sa_name terraform_state_bucket = module.seed_bootstrap.gcs_bucket_tfstate sa_enable_impersonation = true - skip_gcloud_download = var.skip_gcloud_download cloudbuild_plan_filename = "cloudbuild-tf-plan.yaml" cloudbuild_apply_filename = "cloudbuild-tf-apply.yaml" project_prefix = var.project_prefix diff --git a/0-bootstrap/modules/jenkins-agent/README.md b/0-bootstrap/modules/jenkins-agent/README.md index 129fa1d81..9ad076558 100644 --- a/0-bootstrap/modules/jenkins-agent/README.md +++ b/0-bootstrap/modules/jenkins-agent/README.md @@ -74,7 +74,6 @@ module "jenkins_bootstrap" { | router\_asn | BGP ASN for cloud routes. | `number` | `"64515"` | no | | sa\_enable\_impersonation | Allow org\_admins group to impersonate service account & enable APIs required. | `bool` | `false` | no | | service\_account\_prefix | Name prefix to use for service accounts. | `string` | `"sa"` | no | -| skip\_gcloud\_download | Whether to skip downloading gcloud (assumes gcloud is already available outside the module) | `bool` | `true` | no | | storage\_bucket\_labels | Labels to apply to the storage bucket. | `map(string)` | `{}` | no | | storage\_bucket\_prefix | Name prefix to use for storage buckets. | `string` | `"bkt"` | no | | terraform\_sa\_email | Email for terraform service account. It must be supplied by the seed project | `string` | n/a | yes | diff --git a/0-bootstrap/modules/jenkins-agent/main.tf b/0-bootstrap/modules/jenkins-agent/main.tf index 1f54ffcd8..b05fafcc2 100644 --- a/0-bootstrap/modules/jenkins-agent/main.tf +++ b/0-bootstrap/modules/jenkins-agent/main.tf @@ -30,7 +30,7 @@ resource "random_id" "suffix" { *******************************************/ module "cicd_project" { source = "terraform-google-modules/project-factory/google" - version = "~> 9.2" + version = "~> 10.0" name = local.cicd_project_name random_project_id = true disable_services_on_destroy = false @@ -39,7 +39,6 @@ module "cicd_project" { billing_account = var.billing_account activate_apis = local.activate_apis labels = var.project_labels - skip_gcloud_download = var.skip_gcloud_download } /****************************************** diff --git a/0-bootstrap/modules/jenkins-agent/variables.tf b/0-bootstrap/modules/jenkins-agent/variables.tf index 50fd575f7..0440ce9a6 100644 --- a/0-bootstrap/modules/jenkins-agent/variables.tf +++ b/0-bootstrap/modules/jenkins-agent/variables.tf @@ -232,9 +232,3 @@ variable "terraform_version_sha256sum" { type = string default = "602d2529aafdaa0f605c06adb7c72cfb585d8aa19b3f4d8d189b42589e27bf11" } - -variable "skip_gcloud_download" { - description = "Whether to skip downloading gcloud (assumes gcloud is already available outside the module)" - type = bool - default = true -} diff --git a/0-bootstrap/variables.tf b/0-bootstrap/variables.tf index 48b8d45c4..0bd7ffef2 100644 --- a/0-bootstrap/variables.tf +++ b/0-bootstrap/variables.tf @@ -58,12 +58,6 @@ variable "org_policy_admin_role" { default = false } -variable "skip_gcloud_download" { - description = "Whether to skip downloading gcloud (assumes gcloud is already available outside the module)" - type = bool - default = true -} - variable "project_prefix" { description = "Name prefix to use for projects created." type = string diff --git a/1-org/envs/shared/README.md b/1-org/envs/shared/README.md index 383cf31eb..072a450a1 100644 --- a/1-org/envs/shared/README.md +++ b/1-org/envs/shared/README.md @@ -18,9 +18,9 @@ | dns\_hub\_project\_alert\_spent\_percents | A list of percentages of the budget to alert on when threshold is exceeded for the DNS hub project. | `list(number)` |
[| no | | dns\_hub\_project\_budget\_amount | The amount to use as the budget for the DNS hub project. | `number` | `1000` | no | | domains\_to\_allow | The list of domains to allow users from in IAM. | `list(string)` | n/a | yes | +| enable\_hub\_and\_spoke | Enable Hub-and-Spoke architecture. | `bool` | `false` | no | | enable\_os\_login\_policy | Enable OS Login policy. | `bool` | `false` | no | | folder\_prefix | Name prefix to use for folders created. | `string` | `"fldr"` | no | -| hub\_and\_spoke | Enable Hub-and-Spoke architecture. | `bool` | `false` | no | | interconnect\_project\_alert\_pubsub\_topic | The name of the Cloud Pub/Sub topic where budget related messages will be published, in the form of `projects/{project_id}/topics/{topic_id}` for the interconnect project. | `string` | `null` | no | | interconnect\_project\_alert\_spent\_percents | A list of percentages of the budget to alert on when threshold is exceeded for the interconnect project. | `list(number)` |
0.5,
0.75,
0.9,
0.95
]
[| no | | interconnect\_project\_budget\_amount | The amount to use as the budget for the interconnect project. | `number` | `1000` | no | diff --git a/1-org/envs/shared/outputs.tf b/1-org/envs/shared/outputs.tf index 69abaf928..ab9905c5f 100644 --- a/1-org/envs/shared/outputs.tf +++ b/1-org/envs/shared/outputs.tf @@ -70,12 +70,12 @@ output "dns_hub_project_id" { } output "base_net_hub_project_id" { - value = try(module.base_network_hub["yes"].project_id, null) + value = try(module.base_network_hub[0].project_id, null) description = "The Base Network hub project ID" } output "restricted_net_hub_project_id" { - value = try(module.restricted_network_hub["yes"].project_id, null) + value = try(module.restricted_network_hub[0].project_id, null) description = "The Restricted Network hub project ID" } diff --git a/1-org/envs/shared/projects.tf b/1-org/envs/shared/projects.tf index 091f8d766..7cf6d54a4 100644 --- a/1-org/envs/shared/projects.tf +++ b/1-org/envs/shared/projects.tf @@ -20,7 +20,7 @@ module "org_audit_logs" { source = "terraform-google-modules/project-factory/google" - version = "~> 9.2" + version = "~> 10.0" random_project_id = "true" impersonate_service_account = var.terraform_service_account default_service_account = "depriviledge" @@ -28,7 +28,6 @@ module "org_audit_logs" { org_id = var.org_id billing_account = var.billing_account folder_id = google_folder.common.id - skip_gcloud_download = var.skip_gcloud_download activate_apis = ["logging.googleapis.com", "bigquery.googleapis.com", "billingbudgets.googleapis.com"] labels = { @@ -47,7 +46,7 @@ module "org_audit_logs" { module "org_billing_logs" { source = "terraform-google-modules/project-factory/google" - version = "~> 9.2" + version = "~> 10.0" random_project_id = "true" impersonate_service_account = var.terraform_service_account default_service_account = "depriviledge" @@ -55,7 +54,6 @@ module "org_billing_logs" { org_id = var.org_id billing_account = var.billing_account folder_id = google_folder.common.id - skip_gcloud_download = var.skip_gcloud_download activate_apis = ["logging.googleapis.com", "bigquery.googleapis.com", "billingbudgets.googleapis.com"] labels = { @@ -78,7 +76,7 @@ module "org_billing_logs" { module "org_secrets" { source = "terraform-google-modules/project-factory/google" - version = "~> 9.2" + version = "~> 10.0" random_project_id = "true" impersonate_service_account = var.terraform_service_account default_service_account = "depriviledge" @@ -86,7 +84,6 @@ module "org_secrets" { org_id = var.org_id billing_account = var.billing_account folder_id = google_folder.common.id - skip_gcloud_download = var.skip_gcloud_download activate_apis = ["logging.googleapis.com", "secretmanager.googleapis.com", "billingbudgets.googleapis.com"] labels = { @@ -109,7 +106,7 @@ module "org_secrets" { module "interconnect" { source = "terraform-google-modules/project-factory/google" - version = "~> 9.2" + version = "~> 10.0" random_project_id = "true" impersonate_service_account = var.terraform_service_account default_service_account = "depriviledge" @@ -117,7 +114,6 @@ module "interconnect" { org_id = var.org_id billing_account = var.billing_account folder_id = google_folder.common.id - skip_gcloud_download = var.skip_gcloud_download activate_apis = ["billingbudgets.googleapis.com", "compute.googleapis.com"] labels = { @@ -140,7 +136,7 @@ module "interconnect" { module "scc_notifications" { source = "terraform-google-modules/project-factory/google" - version = "~> 9.2" + version = "~> 10.0" random_project_id = "true" impersonate_service_account = var.terraform_service_account default_service_account = "depriviledge" @@ -149,7 +145,6 @@ module "scc_notifications" { billing_account = var.billing_account folder_id = google_folder.common.id activate_apis = ["logging.googleapis.com", "pubsub.googleapis.com", "securitycenter.googleapis.com", "billingbudgets.googleapis.com"] - skip_gcloud_download = var.skip_gcloud_download labels = { environment = "production" @@ -171,7 +166,7 @@ module "scc_notifications" { module "dns_hub" { source = "terraform-google-modules/project-factory/google" - version = "~> 9.2" + version = "~> 10.0" random_project_id = "true" impersonate_service_account = var.terraform_service_account default_service_account = "depriviledge" @@ -179,7 +174,6 @@ module "dns_hub" { org_id = var.org_id billing_account = var.billing_account folder_id = google_folder.common.id - skip_gcloud_download = var.skip_gcloud_download activate_apis = [ "compute.googleapis.com", @@ -210,8 +204,8 @@ module "dns_hub" { module "base_network_hub" { source = "terraform-google-modules/project-factory/google" - version = "~> 9.2" - for_each = var.hub_and_spoke ? toset(["yes"]) : toset([]) + version = "~> 10.0" + count = var.enable_hub_and_spoke ? 1 : 0 random_project_id = "true" impersonate_service_account = var.terraform_service_account default_service_account = "depriviledge" @@ -219,10 +213,10 @@ module "base_network_hub" { org_id = var.org_id billing_account = var.billing_account folder_id = google_folder.common.id - skip_gcloud_download = var.skip_gcloud_download activate_apis = [ "compute.googleapis.com", + "dns.googleapis.com", "servicenetworking.googleapis.com", "logging.googleapis.com", "cloudresourcemanager.googleapis.com", @@ -249,8 +243,8 @@ module "base_network_hub" { module "restricted_network_hub" { source = "terraform-google-modules/project-factory/google" - version = "~> 9.2" - for_each = var.hub_and_spoke ? toset(["yes"]) : toset([]) + version = "~> 10.0" + count = var.enable_hub_and_spoke ? 1 : 0 random_project_id = "true" impersonate_service_account = var.terraform_service_account default_service_account = "depriviledge" @@ -258,10 +252,10 @@ module "restricted_network_hub" { org_id = var.org_id billing_account = var.billing_account folder_id = google_folder.common.id - skip_gcloud_download = var.skip_gcloud_download activate_apis = [ "compute.googleapis.com", + "dns.googleapis.com", "servicenetworking.googleapis.com", "logging.googleapis.com", "cloudresourcemanager.googleapis.com", diff --git a/1-org/envs/shared/variables.tf b/1-org/envs/shared/variables.tf index c086f4273..4f5faa857 100644 --- a/1-org/envs/shared/variables.tf +++ b/1-org/envs/shared/variables.tf @@ -34,7 +34,7 @@ variable "default_region" { type = string } -variable "hub_and_spoke" { +variable "enable_hub_and_spoke" { description = "Enable Hub-and-Spoke architecture." type = bool default = false diff --git a/2-environments/envs/production/variables.tf b/2-environments/envs/production/variables.tf index 4009ace5f..9b54d9130 100644 --- a/2-environments/envs/production/variables.tf +++ b/2-environments/envs/production/variables.tf @@ -51,4 +51,3 @@ variable "folder_prefix" { type = string default = "fldr" } - diff --git a/2-environments/modules/env_baseline/README.md b/2-environments/modules/env_baseline/README.md index 2fe8a88f5..e73c2d040 100644 --- a/2-environments/modules/env_baseline/README.md +++ b/2-environments/modules/env_baseline/README.md @@ -23,17 +23,16 @@ | secret\_project\_alert\_pubsub\_topic | The name of the Cloud Pub/Sub topic where budget related messages will be published, in the form of `projects/{project_id}/topics/{topic_id}` for the secrets project. | `string` | `null` | no | | secret\_project\_alert\_spent\_percents | A list of percentages of the budget to alert on when threshold is exceeded for the secrets project. | `list(number)` |
0.5,
0.75,
0.9,
0.95
]
[| no | | secret\_project\_budget\_amount | The amount to use as the budget for the secrets project. | `number` | `1000` | no | -| skip\_gcloud\_download | Whether to skip downloading gcloud (assumes gcloud is already available outside the module) | `bool` | `true` | no | | terraform\_service\_account | Service account email of the account to impersonate to run Terraform. | `string` | n/a | yes | ## Outputs | Name | Description | |------|-------------| -| base\_shared\_vpc\_project\_id | Project for monitoring infra. | +| base\_shared\_vpc\_project\_id | Project for base shared VPC network. | | env\_folder | Environment folder created under parent. | -| env\_secrets\_project\_id | Project for monitoring infra. | +| env\_secrets\_project\_id | Project for environment secrets. | | monitoring\_project\_id | Project for monitoring infra. | -| restricted\_shared\_vpc\_project\_id | Project for monitoring infra. | +| restricted\_shared\_vpc\_project\_id | Project for restricted shared VPC network. | diff --git a/2-environments/modules/env_baseline/monitoring.tf b/2-environments/modules/env_baseline/monitoring.tf index 795ae9c44..6f7dff408 100644 --- a/2-environments/modules/env_baseline/monitoring.tf +++ b/2-environments/modules/env_baseline/monitoring.tf @@ -20,14 +20,13 @@ module "monitoring_project" { source = "terraform-google-modules/project-factory/google" - version = "~> 9.2" + version = "~> 10.0" random_project_id = "true" impersonate_service_account = var.terraform_service_account name = "${var.project_prefix}-${var.environment_code}-monitoring" org_id = var.org_id billing_account = var.billing_account folder_id = google_folder.env.id - skip_gcloud_download = var.skip_gcloud_download disable_services_on_destroy = false activate_apis = [ "logging.googleapis.com", diff --git a/2-environments/modules/env_baseline/networking.tf b/2-environments/modules/env_baseline/networking.tf index ea5fba89b..93047bdc4 100644 --- a/2-environments/modules/env_baseline/networking.tf +++ b/2-environments/modules/env_baseline/networking.tf @@ -20,14 +20,13 @@ module "base_shared_vpc_host_project" { source = "terraform-google-modules/project-factory/google" - version = "~> 9.2" + version = "~> 10.0" random_project_id = "true" impersonate_service_account = var.terraform_service_account - name = "${var.project_prefix}-${var.environment_code}-shared-base" + name = format("%s-%s-shared-base", var.project_prefix, var.environment_code) org_id = var.org_id billing_account = var.billing_account folder_id = google_folder.env.id - skip_gcloud_download = var.skip_gcloud_download disable_services_on_destroy = false activate_apis = [ "compute.googleapis.com", @@ -54,14 +53,13 @@ module "base_shared_vpc_host_project" { module "restricted_shared_vpc_host_project" { source = "terraform-google-modules/project-factory/google" - version = "~> 9.2" + version = "~> 10.0" random_project_id = "true" impersonate_service_account = var.terraform_service_account - name = "${var.project_prefix}-${var.environment_code}-shared-restricted" + name = format("%s-%s-shared-restricted", var.project_prefix, var.environment_code) org_id = var.org_id billing_account = var.billing_account folder_id = google_folder.env.id - skip_gcloud_download = var.skip_gcloud_download disable_services_on_destroy = false activate_apis = [ "compute.googleapis.com", diff --git a/2-environments/modules/env_baseline/outputs.tf b/2-environments/modules/env_baseline/outputs.tf index fe52fd74d..13b1314b0 100644 --- a/2-environments/modules/env_baseline/outputs.tf +++ b/2-environments/modules/env_baseline/outputs.tf @@ -25,16 +25,16 @@ output "monitoring_project_id" { } output "base_shared_vpc_project_id" { - description = "Project for monitoring infra." + description = "Project for base shared VPC network." value = module.base_shared_vpc_host_project.project_id } output "restricted_shared_vpc_project_id" { - description = "Project for monitoring infra." + description = "Project for restricted shared VPC network." value = module.restricted_shared_vpc_host_project.project_id } output "env_secrets_project_id" { - description = "Project for monitoring infra." + description = "Project for environment secrets." value = module.env_secrets.project_id } diff --git a/2-environments/modules/env_baseline/secrets.tf b/2-environments/modules/env_baseline/secrets.tf index dbdf9ee7a..6b7090282 100644 --- a/2-environments/modules/env_baseline/secrets.tf +++ b/2-environments/modules/env_baseline/secrets.tf @@ -21,7 +21,7 @@ module "env_secrets" { source = "terraform-google-modules/project-factory/google" - version = "~> 9.2" + version = "~> 10.0" random_project_id = "true" impersonate_service_account = var.terraform_service_account default_service_account = "depriviledge" @@ -31,7 +31,6 @@ module "env_secrets" { folder_id = google_folder.env.id disable_services_on_destroy = false activate_apis = ["logging.googleapis.com", "secretmanager.googleapis.com"] - skip_gcloud_download = var.skip_gcloud_download labels = { environment = var.env diff --git a/2-environments/modules/env_baseline/variables.tf b/2-environments/modules/env_baseline/variables.tf index 37bd9efbd..aa5ea39c7 100644 --- a/2-environments/modules/env_baseline/variables.tf +++ b/2-environments/modules/env_baseline/variables.tf @@ -49,12 +49,6 @@ variable "monitoring_workspace_users" { type = string } -variable "skip_gcloud_download" { - description = "Whether to skip downloading gcloud (assumes gcloud is already available outside the module)" - type = bool - default = true -} - variable "base_network_project_alert_spent_percents" { description = "A list of percentages of the budget to alert on when threshold is exceeded for the base networks project" type = list(number) diff --git a/3-networks/envs/development/README.md b/3-networks/envs/development/README.md index f8853c4c7..256a13e05 100644 --- a/3-networks/envs/development/README.md +++ b/3-networks/envs/development/README.md @@ -21,6 +21,7 @@ The purpose of this step is to set up base and restricted shared VPCs with defau | dns\_enable\_inbound\_forwarding | Toggle inbound query forwarding for VPC DNS. | `bool` | `true` | no | | dns\_enable\_logging | Toggle DNS logging for VPC DNS. | `bool` | `true` | no | | domain | The DNS name of peering managed zone, for instance 'example.com.' | `string` | n/a | yes | +| enable\_hub\_and\_spoke | Enable Hub-and-Spoke architecture. | `bool` | `false` | no | | firewall\_enable\_logging | Toggle firewall logging for VPC Firewalls. | `bool` | `true` | no | | folder\_prefix | Name prefix to use for folders created. | `string` | `"fldr"` | no | | nat\_bgp\_asn | BGP ASN for first NAT cloud routes. | `number` | `64514` | no | diff --git a/3-networks/envs/development/main.tf b/3-networks/envs/development/main.tf index 03c85fb16..109e47e96 100644 --- a/3-networks/envs/development/main.tf +++ b/3-networks/envs/development/main.tf @@ -21,6 +21,7 @@ locals { restricted_project_number = data.google_project.restricted_host_project.number base_project_id = data.google_projects.base_host_project.projects[0].project_id parent_id = var.parent_folder != "" ? "folders/${var.parent_folder}" : "organizations/${var.org_id}" + mode = var.enable_hub_and_spoke ? "spoke" : null } data "google_active_folder" "env" { @@ -72,6 +73,7 @@ module "restricted_shared_vpc" { nat_num_addresses_region1 = var.nat_num_addresses_region1 nat_num_addresses_region2 = var.nat_num_addresses_region2 folder_prefix = var.folder_prefix + mode = local.mode subnets = [ { @@ -95,11 +97,11 @@ module "restricted_shared_vpc" { "sb-${local.environment_code}-shared-restricted-${var.default_region1}" = [ { range_name = "rn-${local.environment_code}-shared-restricted-${var.default_region1}-gke-pod" - ip_cidr_range = "192.168.0.0/19" + ip_cidr_range = "192.168.0.0/21" }, { range_name = "rn-${local.environment_code}-shared-restricted-${var.default_region1}-gke-svc" - ip_cidr_range = "192.168.32.0/23" + ip_cidr_range = "192.168.8.0/21" } ] } @@ -131,6 +133,7 @@ module "base_shared_vpc" { nat_num_addresses_region2 = var.nat_num_addresses_region2 nat_num_addresses = var.nat_num_addresses folder_prefix = var.folder_prefix + mode = local.mode subnets = [ { @@ -154,11 +157,11 @@ module "base_shared_vpc" { "sb-${local.environment_code}-shared-base-${var.default_region1}" = [ { range_name = "rn-${local.environment_code}-shared-base-${var.default_region1}-gke-pod" - ip_cidr_range = "192.168.96.0/19" + ip_cidr_range = "192.168.16.0/21" }, { range_name = "rn-${local.environment_code}-shared-base-${var.default_region1}-gke-svc" - ip_cidr_range = "192.168.128.0/23" + ip_cidr_range = "192.168.24.0/21" } ] } diff --git a/3-networks/envs/development/variables.tf b/3-networks/envs/development/variables.tf index c8122c4e8..f2e1be3eb 100644 --- a/3-networks/envs/development/variables.tf +++ b/3-networks/envs/development/variables.tf @@ -121,3 +121,9 @@ variable "folder_prefix" { type = string default = "fldr" } + +variable "enable_hub_and_spoke" { + description = "Enable Hub-and-Spoke architecture." + type = bool + default = false +} diff --git a/3-networks/envs/non-production/README.md b/3-networks/envs/non-production/README.md index 4c7177acc..d4cd4e4bd 100644 --- a/3-networks/envs/non-production/README.md +++ b/3-networks/envs/non-production/README.md @@ -21,6 +21,7 @@ The purpose of this step is to set up base and restricted shared VPCs with defau | dns\_enable\_inbound\_forwarding | Toggle inbound query forwarding for VPC DNS. | `bool` | `true` | no | | dns\_enable\_logging | Toggle DNS logging for VPC DNS. | `bool` | `true` | no | | domain | The DNS name of peering managed zone, for instance 'example.com.' | `string` | n/a | yes | +| enable\_hub\_and\_spoke | Enable Hub-and-Spoke architecture. | `bool` | `false` | no | | firewall\_enable\_logging | Toggle firewall logging for VPC Firewalls. | `bool` | `true` | no | | folder\_prefix | Name prefix to use for folders created. | `string` | `"fldr"` | no | | nat\_bgp\_asn | BGP ASN for first NAT cloud routes. | `number` | `64514` | no | diff --git a/3-networks/envs/non-production/main.tf b/3-networks/envs/non-production/main.tf index d7d4dc0ce..4c9579691 100644 --- a/3-networks/envs/non-production/main.tf +++ b/3-networks/envs/non-production/main.tf @@ -21,6 +21,7 @@ locals { restricted_project_number = data.google_project.restricted_host_project.number base_project_id = data.google_projects.base_host_project.projects[0].project_id parent_id = var.parent_folder != "" ? "folders/${var.parent_folder}" : "organizations/${var.org_id}" + mode = var.enable_hub_and_spoke ? "spoke" : null } data "google_active_folder" "env" { @@ -73,6 +74,7 @@ module "restricted_shared_vpc" { nat_num_addresses_region1 = var.nat_num_addresses_region1 nat_num_addresses_region2 = var.nat_num_addresses_region2 folder_prefix = var.folder_prefix + mode = local.mode subnets = [ { @@ -96,11 +98,11 @@ module "restricted_shared_vpc" { "sb-${local.environment_code}-shared-restricted-${var.default_region1}" = [ { range_name = "rn-${local.environment_code}-shared-restricted-${var.default_region1}-gke-pod" - ip_cidr_range = "192.168.0.0/19" + ip_cidr_range = "192.168.32.0/21" }, { range_name = "rn-${local.environment_code}-shared-restricted-${var.default_region1}-gke-svc" - ip_cidr_range = "192.168.32.0/23" + ip_cidr_range = "192.168.40.0/21" } ] } @@ -132,6 +134,7 @@ module "base_shared_vpc" { nat_num_addresses_region2 = var.nat_num_addresses_region2 nat_num_addresses = var.nat_num_addresses folder_prefix = var.folder_prefix + mode = local.mode subnets = [ { @@ -155,11 +158,11 @@ module "base_shared_vpc" { "sb-${local.environment_code}-shared-base-${var.default_region1}" = [ { range_name = "rn-${local.environment_code}-shared-base-${var.default_region1}-gke-pod" - ip_cidr_range = "192.168.0.0/19" + ip_cidr_range = "192.168.48.0/21" }, { range_name = "rn-${local.environment_code}-shared-base-${var.default_region1}-gke-svc" - ip_cidr_range = "192.168.32.0/23" + ip_cidr_range = "192.168.56.0/21" } ] } diff --git a/3-networks/envs/non-production/variables.tf b/3-networks/envs/non-production/variables.tf index c8122c4e8..f2e1be3eb 100644 --- a/3-networks/envs/non-production/variables.tf +++ b/3-networks/envs/non-production/variables.tf @@ -121,3 +121,9 @@ variable "folder_prefix" { type = string default = "fldr" } + +variable "enable_hub_and_spoke" { + description = "Enable Hub-and-Spoke architecture." + type = bool + default = false +} diff --git a/3-networks/envs/production/README.md b/3-networks/envs/production/README.md index a4715d1b9..b606af043 100644 --- a/3-networks/envs/production/README.md +++ b/3-networks/envs/production/README.md @@ -21,6 +21,7 @@ The purpose of this step is to set up base and restricted shared VPCs with defau | dns\_enable\_inbound\_forwarding | Toggle inbound query forwarding for VPC DNS. | `bool` | `true` | no | | dns\_enable\_logging | Toggle DNS logging for VPC DNS. | `bool` | `true` | no | | domain | The DNS name of peering managed zone, for instance 'example.com.' | `string` | n/a | yes | +| enable\_hub\_and\_spoke | Enable Hub-and-Spoke architecture. | `bool` | `false` | no | | firewall\_enable\_logging | Toggle firewall logging for VPC Firewalls. | `bool` | `true` | no | | folder\_prefix | Name prefix to use for folders created. | `string` | `"fldr"` | no | | nat\_bgp\_asn | BGP ASN for first NAT cloud routes. | `number` | `64514` | no | diff --git a/3-networks/envs/production/main.tf b/3-networks/envs/production/main.tf index 59e1d57b2..28078164f 100644 --- a/3-networks/envs/production/main.tf +++ b/3-networks/envs/production/main.tf @@ -21,6 +21,7 @@ locals { restricted_project_number = data.google_project.restricted_host_project.number base_project_id = data.google_projects.base_host_project.projects[0].project_id parent_id = var.parent_folder != "" ? "folders/${var.parent_folder}" : "organizations/${var.org_id}" + mode = var.enable_hub_and_spoke ? "spoke" : null } data "google_active_folder" "env" { @@ -72,6 +73,7 @@ module "restricted_shared_vpc" { nat_num_addresses_region1 = var.nat_num_addresses_region1 nat_num_addresses_region2 = var.nat_num_addresses_region2 folder_prefix = var.folder_prefix + mode = local.mode subnets = [ { @@ -95,11 +97,11 @@ module "restricted_shared_vpc" { "sb-${local.environment_code}-shared-restricted-${var.default_region1}" = [ { range_name = "rn-${local.environment_code}-shared-restricted-${var.default_region1}-gke-pod" - ip_cidr_range = "192.168.0.0/19" + ip_cidr_range = "192.168.64.0/21" }, { range_name = "rn-${local.environment_code}-shared-restricted-${var.default_region1}-gke-svc" - ip_cidr_range = "192.168.32.0/23" + ip_cidr_range = "192.168.72.0/21" } ] } @@ -131,6 +133,7 @@ module "base_shared_vpc" { nat_num_addresses_region2 = var.nat_num_addresses_region2 nat_num_addresses = var.nat_num_addresses folder_prefix = var.folder_prefix + mode = local.mode subnets = [ { @@ -154,11 +157,11 @@ module "base_shared_vpc" { "sb-${local.environment_code}-shared-base-${var.default_region1}" = [ { range_name = "rn-${local.environment_code}-shared-base-${var.default_region1}-gke-pod" - ip_cidr_range = "192.168.96.0/19" + ip_cidr_range = "192.168.80.0/21" }, { range_name = "rn-${local.environment_code}-shared-base-${var.default_region1}-gke-svc" - ip_cidr_range = "192.168.128.0/23" + ip_cidr_range = "192.168.88.0/21" } ] } diff --git a/3-networks/envs/production/variables.tf b/3-networks/envs/production/variables.tf index dbe44beb0..f2e1be3eb 100644 --- a/3-networks/envs/production/variables.tf +++ b/3-networks/envs/production/variables.tf @@ -61,6 +61,7 @@ variable "firewall_enable_logging" { description = "Toggle firewall logging for VPC Firewalls." default = true } + variable "dns_enable_inbound_forwarding" { type = bool description = "Toggle inbound query forwarding for VPC DNS." @@ -120,3 +121,9 @@ variable "folder_prefix" { type = string default = "fldr" } + +variable "enable_hub_and_spoke" { + description = "Enable Hub-and-Spoke architecture." + type = bool + default = false +} diff --git a/3-networks/envs/shared/README.md b/3-networks/envs/shared/README.md index 8cc4788cb..bbd9b8405 100644 --- a/3-networks/envs/shared/README.md +++ b/3-networks/envs/shared/README.md @@ -12,14 +12,34 @@ The purpose of this step is to set up the global [DNS Hub](https://cloud.google. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| +| access\_context\_manager\_policy\_id | The id of the default Access Context Manager policy created in step `1-org`. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR-ORGANIZATION_ID --format="value(name)"`. | `number` | n/a | yes | +| base\_hub\_dns\_enable\_inbound\_forwarding | Toggle inbound query forwarding for Base Hub VPC DNS. | `bool` | `true` | no | +| base\_hub\_dns\_enable\_logging | Toggle DNS logging for Base Hub VPC DNS. | `bool` | `true` | no | +| base\_hub\_firewall\_enable\_logging | Toggle firewall logging for VPC Firewalls in Base Hub VPC. | `bool` | `true` | no | +| base\_hub\_nat\_bgp\_asn | BGP ASN for first NAT cloud routes in Base Hub. | `number` | `64514` | no | +| base\_hub\_nat\_enabled | Toggle creation of NAT cloud router in Base Hub. | `bool` | `false` | no | +| base\_hub\_nat\_num\_addresses\_region1 | Number of external IPs to reserve for first Cloud NAT in Base Hub. | `number` | `2` | no | +| base\_hub\_nat\_num\_addresses\_region2 | Number of external IPs to reserve for second Cloud NAT in Base Hub. | `number` | `2` | no | +| base\_hub\_optional\_fw\_rules\_enabled | Toggle creation of optional firewall rules: IAP SSH, IAP RDP and Internal & Global load balancing health check and load balancing IP ranges in Base Hub VPC. | `bool` | `false` | no | +| base\_hub\_windows\_activation\_enabled | Enable Windows license activation for Windows workloads in Base Hub | `bool` | `false` | no | | bgp\_asn\_dns | BGP Autonomous System Number (ASN). | `number` | `64667` | no | | default\_region1 | First subnet region for DNS Hub network. | `string` | n/a | yes | | default\_region2 | Second subnet region for DNS Hub network. | `string` | n/a | yes | | dns\_enable\_logging | Toggle DNS logging for VPC DNS. | `bool` | `true` | no | | domain | The DNS name of forwarding managed zone, for instance 'example.com' | `string` | n/a | yes | +| enable\_hub\_and\_spoke | Enable Hub-and-Spoke architecture. | `bool` | `false` | no | | folder\_prefix | Name prefix to use for folders created. | `string` | `"fldr"` | no | | org\_id | Organization ID | `string` | n/a | yes | | parent\_folder | Optional - if using a folder for testing. | `string` | `""` | no | +| restricted\_hub\_dns\_enable\_inbound\_forwarding | Toggle inbound query forwarding for Restricted Hub VPC DNS. | `bool` | `true` | no | +| restricted\_hub\_dns\_enable\_logging | Toggle DNS logging for Restricted Hub VPC DNS. | `bool` | `true` | no | +| restricted\_hub\_firewall\_enable\_logging | Toggle firewall logging for VPC Firewalls in Restricted Hub VPC. | `bool` | `true` | no | +| restricted\_hub\_nat\_bgp\_asn | BGP ASN for first NAT cloud routes in Restricted Hub. | `number` | `64514` | no | +| restricted\_hub\_nat\_enabled | Toggle creation of NAT cloud router in Restricted Hub. | `bool` | `false` | no | +| restricted\_hub\_nat\_num\_addresses\_region1 | Number of external IPs to reserve for first Cloud NAT in Restricted Hub. | `number` | `2` | no | +| restricted\_hub\_nat\_num\_addresses\_region2 | Number of external IPs to reserve for second Cloud NAT in Restricted Hub. | `number` | `2` | no | +| restricted\_hub\_optional\_fw\_rules\_enabled | Toggle creation of optional firewall rules: IAP SSH, IAP RDP and Internal & Global load balancing health check and load balancing IP ranges in Restricted Hub VPC. | `bool` | `false` | no | +| restricted\_hub\_windows\_activation\_enabled | Enable Windows license activation for Windows workloads in Restricted Hub. | `bool` | `false` | no | | subnetworks\_enable\_logging | Toggle subnetworks flow logging for VPC Subnetwoks. | `bool` | `true` | no | | target\_name\_server\_addresses | List of target name servers for forwarding zone. | `list(string)` | n/a | yes | | terraform\_service\_account | Service account email of the account to impersonate to run Terraform. | `string` | n/a | yes | diff --git a/3-networks/envs/shared/main.tf b/3-networks/envs/shared/dns-hub.tf similarity index 100% rename from 3-networks/envs/shared/main.tf rename to 3-networks/envs/shared/dns-hub.tf diff --git a/3-networks/envs/shared/net-hubs.tf b/3-networks/envs/shared/net-hubs.tf new file mode 100644 index 000000000..f763f6d6f --- /dev/null +++ b/3-networks/envs/shared/net-hubs.tf @@ -0,0 +1,143 @@ +/** + * Copyright 2020 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 { + base_net_hub_project_id = try(data.google_projects.base_net_hub[0].projects[0].project_id, null) + restricted_net_hub_project_id = try(data.google_projects.restricted_net_hub[0].projects[0].project_id, null) + restricted_net_hub_project_number = try(data.google_projects.restricted_net_hub[0].projects[0].number, null) +} + +/****************************************** + Base Network Hub Project +*****************************************/ + +data "google_projects" "base_net_hub" { + count = var.enable_hub_and_spoke ? 1 : 0 + filter = "parent.id:${split("/", data.google_active_folder.common.name)[1]} labels.application_name=org-base-net-hub lifecycleState=ACTIVE" +} + +/****************************************** + Restricted Network Hub Project +*****************************************/ + +data "google_projects" "restricted_net_hub" { + count = var.enable_hub_and_spoke ? 1 : 0 + filter = "parent.id:${split("/", data.google_active_folder.common.name)[1]} labels.application_name=org-restricted-net-hub lifecycleState=ACTIVE" +} + +/****************************************** + Base Network VPC +*****************************************/ + +module "base_shared_vpc" { + source = "../../modules/base_shared_vpc" + count = var.enable_hub_and_spoke ? 1 : 0 + project_id = local.base_net_hub_project_id + environment_code = "c" + org_id = var.org_id + parent_folder = var.parent_folder + bgp_asn_subnet = "64514" + default_region1 = var.default_region1 + default_region2 = var.default_region2 + domain = var.domain + windows_activation_enabled = var.base_hub_windows_activation_enabled + dns_enable_inbound_forwarding = var.base_hub_dns_enable_inbound_forwarding + dns_enable_logging = var.base_hub_dns_enable_logging + firewall_enable_logging = var.base_hub_firewall_enable_logging + optional_fw_rules_enabled = var.base_hub_optional_fw_rules_enabled + nat_enabled = var.base_hub_nat_enabled + nat_bgp_asn = var.base_hub_nat_bgp_asn + nat_num_addresses_region1 = var.base_hub_nat_num_addresses_region1 + nat_num_addresses_region2 = var.base_hub_nat_num_addresses_region2 + folder_prefix = var.folder_prefix + mode = "hub" + + subnets = [ + { + subnet_name = "sb-c-shared-restricted-hub-${var.default_region1}" + subnet_ip = "172.16.1.0/24" + subnet_region = var.default_region1 + subnet_private_access = "true" + subnet_flow_logs = var.subnetworks_enable_logging + description = "Restricted network hub subnet for region 1." + }, + { + subnet_name = "sb-c-shared-restricted-hub-${var.default_region2}" + subnet_ip = "172.16.2.0/24" + subnet_region = var.default_region2 + subnet_private_access = "true" + subnet_flow_logs = var.subnetworks_enable_logging + description = "Restricted network hub subnet for region 2." + } + ] + secondary_ranges = {} + + depends_on = [module.dns_hub_vpc] +} + +/****************************************** + Restricted Network VPC +*****************************************/ + +module "restricted_shared_vpc" { + source = "../../modules/restricted_shared_vpc" + count = var.enable_hub_and_spoke ? 1 : 0 + project_id = local.restricted_net_hub_project_id + project_number = local.restricted_net_hub_project_number + environment_code = "c" + access_context_manager_policy_id = var.access_context_manager_policy_id + restricted_services = ["bigquery.googleapis.com", "storage.googleapis.com"] + members = ["serviceAccount:${var.terraform_service_account}"] + org_id = var.org_id + parent_folder = var.parent_folder + bgp_asn_subnet = "64514" + default_region1 = var.default_region1 + default_region2 = var.default_region2 + domain = var.domain + windows_activation_enabled = var.restricted_hub_windows_activation_enabled + dns_enable_inbound_forwarding = var.restricted_hub_dns_enable_inbound_forwarding + dns_enable_logging = var.restricted_hub_dns_enable_logging + firewall_enable_logging = var.restricted_hub_firewall_enable_logging + optional_fw_rules_enabled = var.restricted_hub_optional_fw_rules_enabled + nat_enabled = var.restricted_hub_nat_enabled + nat_bgp_asn = var.restricted_hub_nat_bgp_asn + nat_num_addresses_region1 = var.restricted_hub_nat_num_addresses_region1 + nat_num_addresses_region2 = var.restricted_hub_nat_num_addresses_region2 + folder_prefix = var.folder_prefix + mode = "hub" + + subnets = [ + { + subnet_name = "sb-c-shared-restricted-hub-${var.default_region1}" + subnet_ip = "172.16.3.0/24" + subnet_region = var.default_region1 + subnet_private_access = "true" + subnet_flow_logs = var.subnetworks_enable_logging + description = "Restricted network hub subnet for region 1." + }, + { + subnet_name = "sb-c-shared-restricted-hub-${var.default_region2}" + subnet_ip = "172.16.4.0/24" + subnet_region = var.default_region2 + subnet_private_access = "true" + subnet_flow_logs = var.subnetworks_enable_logging + description = "Restricted network hub subnet for region 2." + } + ] + secondary_ranges = {} + + depends_on = [module.dns_hub_vpc] +} diff --git a/3-networks/envs/shared/variables.tf b/3-networks/envs/shared/variables.tf index 27088c07e..c2c4a58f2 100644 --- a/3-networks/envs/shared/variables.tf +++ b/3-networks/envs/shared/variables.tf @@ -24,6 +24,17 @@ variable "terraform_service_account" { description = "Service account email of the account to impersonate to run Terraform." } +variable "enable_hub_and_spoke" { + description = "Enable Hub-and-Spoke architecture." + type = bool + default = false +} + +variable "access_context_manager_policy_id" { + type = number + description = "The id of the default Access Context Manager policy created in step `1-org`. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR-ORGANIZATION_ID --format=\"value(name)\"`." +} + variable "default_region1" { type = string description = "First subnet region for DNS Hub network." @@ -73,3 +84,111 @@ variable "folder_prefix" { type = string default = "fldr" } + +variable "base_hub_windows_activation_enabled" { + type = bool + description = "Enable Windows license activation for Windows workloads in Base Hub" + default = false +} + +variable "restricted_hub_windows_activation_enabled" { + type = bool + description = "Enable Windows license activation for Windows workloads in Restricted Hub." + default = false +} + +variable "base_hub_dns_enable_inbound_forwarding" { + type = bool + description = "Toggle inbound query forwarding for Base Hub VPC DNS." + default = true +} + +variable "restricted_hub_dns_enable_inbound_forwarding" { + type = bool + description = "Toggle inbound query forwarding for Restricted Hub VPC DNS." + default = true +} + +variable "base_hub_dns_enable_logging" { + type = bool + description = "Toggle DNS logging for Base Hub VPC DNS." + default = true +} + +variable "restricted_hub_dns_enable_logging" { + type = bool + description = "Toggle DNS logging for Restricted Hub VPC DNS." + default = true +} + +variable "base_hub_firewall_enable_logging" { + type = bool + description = "Toggle firewall logging for VPC Firewalls in Base Hub VPC." + default = true +} + +variable "restricted_hub_firewall_enable_logging" { + type = bool + description = "Toggle firewall logging for VPC Firewalls in Restricted Hub VPC." + default = true +} + +variable "base_hub_optional_fw_rules_enabled" { + type = bool + description = "Toggle creation of optional firewall rules: IAP SSH, IAP RDP and Internal & Global load balancing health check and load balancing IP ranges in Base Hub VPC." + default = false +} + +variable "restricted_hub_optional_fw_rules_enabled" { + type = bool + description = "Toggle creation of optional firewall rules: IAP SSH, IAP RDP and Internal & Global load balancing health check and load balancing IP ranges in Restricted Hub VPC." + default = false +} + +variable "base_hub_nat_enabled" { + type = bool + description = "Toggle creation of NAT cloud router in Base Hub." + default = false +} + +variable "restricted_hub_nat_enabled" { + type = bool + description = "Toggle creation of NAT cloud router in Restricted Hub." + default = false +} + +variable "base_hub_nat_bgp_asn" { + type = number + description = "BGP ASN for first NAT cloud routes in Base Hub." + default = 64514 +} + +variable "restricted_hub_nat_bgp_asn" { + type = number + description = "BGP ASN for first NAT cloud routes in Restricted Hub." + default = 64514 +} + +variable "base_hub_nat_num_addresses_region1" { + type = number + description = "Number of external IPs to reserve for first Cloud NAT in Base Hub." + default = 2 +} + +variable "restricted_hub_nat_num_addresses_region1" { + type = number + description = "Number of external IPs to reserve for first Cloud NAT in Restricted Hub." + default = 2 +} + +variable "base_hub_nat_num_addresses_region2" { + type = number + description = "Number of external IPs to reserve for second Cloud NAT in Base Hub." + default = 2 +} + +variable "restricted_hub_nat_num_addresses_region2" { + type = number + description = "Number of external IPs to reserve for second Cloud NAT in Restricted Hub." + default = 2 +} diff --git a/3-networks/modules/base_shared_vpc/README.md b/3-networks/modules/base_shared_vpc/README.md index 42fe9ef9e..1f45cae99 100644 --- a/3-networks/modules/base_shared_vpc/README.md +++ b/3-networks/modules/base_shared_vpc/README.md @@ -12,6 +12,7 @@ | environment\_code | A short form of the folder level resources (environment) within the Google Cloud organization. | `string` | n/a | yes | | firewall\_enable\_logging | Toggle firewall logging for VPC Firewalls. | `bool` | `true` | no | | folder\_prefix | Name prefix to use for folders created. | `string` | `"fldr"` | no | +| mode | Network deployment mode, should be set to `hub` or `spoke` when `enable_hub_and_spoke` architecture choosen, keep as `null` otherwise. | `string` | `null` | no | | nat\_bgp\_asn | BGP ASN for first NAT cloud routes. | `number` | `0` | no | | nat\_enabled | Toggle creation of NAT cloud router. | `bool` | `false` | no | | nat\_num\_addresses | Number of external IPs to reserve for Cloud NAT. | `number` | `2` | no | @@ -20,7 +21,7 @@ | optional\_fw\_rules\_enabled | Toggle creation of optional firewall rules: IAP SSH, IAP RDP and Internal & Global load balancing health check and load balancing IP ranges. | `bool` | `false` | no | | org\_id | Organization ID | `string` | n/a | yes | | parent\_folder | Optional - if using a folder for testing. | `string` | `""` | no | -| private\_service\_cidr | CIDR range for private service networking. Used for Cloud SQL and other managed services. | `string` | n/a | yes | +| private\_service\_cidr | CIDR range for private service networking. Used for Cloud SQL and other managed services. | `string` | `null` | no | | project\_id | Project ID for Private Shared VPC. | `string` | n/a | yes | | secondary\_ranges | Secondary ranges that will be used in some of the subnets | `map(list(object({ range_name = string, ip_cidr_range = string })))` | `{}` | no | | subnets | The list of subnets being created | `list(map(string))` | `[]` | no | diff --git a/3-networks/modules/base_shared_vpc/main.tf b/3-networks/modules/base_shared_vpc/main.tf index cf351ab79..36954969d 100644 --- a/3-networks/modules/base_shared_vpc/main.tf +++ b/3-networks/modules/base_shared_vpc/main.tf @@ -14,16 +14,32 @@ * limitations under the License. */ -/****************************************** - Shared VPC configuration - *****************************************/ - locals { - vpc_name = "${var.environment_code}-shared-base" + mode = var.mode == null ? "" : var.mode == "hub" ? "-hub" : "-spoke" + vpc_name = "${var.environment_code}-shared-base${local.mode}" network_name = "vpc-${local.vpc_name}" private_googleapis_cidr = "199.36.153.8/30" } +/****************************************** + Base Network Hub +*****************************************/ + +data "google_projects" "base_net_hub" { + count = var.mode == "spoke" ? 1 : 0 + filter = "parent.id:${split("/", data.google_active_folder.common.name)[1]} labels.application_name=org-base-net-hub lifecycleState=ACTIVE" +} + +data "google_compute_network" "vpc_base_net_hub" { + count = var.mode == "spoke" ? 1 : 0 + name = "vpc-c-shared-base-hub" + project = data.google_projects.base_net_hub[0].projects[0].project_id +} + +/****************************************** + Shared VPC configuration + *****************************************/ + module "main" { source = "terraform-google-modules/network/google" version = "~> 2.0" @@ -68,11 +84,26 @@ module "main" { ) } +/*************************************************************** + VPC Peering Configuration + **************************************************************/ + +module "peering" { + source = "terraform-google-modules/network/google//modules/network-peering" + version = "~> 2.0" + count = var.mode == "spoke" ? 1 : 0 + prefix = "np" + local_network = module.main.network_self_link + peer_network = data.google_compute_network.vpc_base_net_hub[0].self_link + export_peer_custom_routes = true +} + /*************************************************************** Configure Service Networking for Cloud SQL & future services. **************************************************************/ resource "google_compute_global_address" "private_service_access_address" { + count = var.private_service_cidr != null ? 1 : 0 name = "ga-${local.vpc_name}-vpc-peering-internal" project = var.project_id purpose = "VPC_PEERING" @@ -80,12 +111,17 @@ resource "google_compute_global_address" "private_service_access_address" { address = element(split("/", var.private_service_cidr), 0) prefix_length = element(split("/", var.private_service_cidr), 1) network = module.main.network_self_link + + depends_on = [module.peering] } resource "google_service_networking_connection" "private_vpc_connection" { + count = var.private_service_cidr != null ? 1 : 0 network = module.main.network_self_link service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.private_service_access_address.name] + reserved_peering_ranges = [google_compute_global_address.private_service_access_address[0].name] + + depends_on = [module.peering] } /************************************ @@ -96,6 +132,7 @@ resource "google_service_networking_connection" "private_vpc_connection" { module "region1_router1" { source = "terraform-google-modules/cloud-router/google" version = "~> 0.3.0" + count = var.mode != "spoke" ? 1 : 0 name = "cr-${local.vpc_name}-${var.default_region1}-cr1" project = var.project_id network = module.main.network_name @@ -110,6 +147,7 @@ module "region1_router1" { module "region1_router2" { source = "terraform-google-modules/cloud-router/google" version = "~> 0.3.0" + count = var.mode != "spoke" ? 1 : 0 name = "cr-${local.vpc_name}-${var.default_region1}-cr2" project = var.project_id network = module.main.network_name @@ -124,6 +162,7 @@ module "region1_router2" { module "region2_router1" { source = "terraform-google-modules/cloud-router/google" version = "~> 0.3.0" + count = var.mode != "spoke" ? 1 : 0 name = "cr-${local.vpc_name}-${var.default_region2}-cr3" project = var.project_id network = module.main.network_name @@ -138,6 +177,7 @@ module "region2_router1" { module "region2_router2" { source = "terraform-google-modules/cloud-router/google" version = "~> 0.3.0" + count = var.mode != "spoke" ? 1 : 0 name = "cr-${local.vpc_name}-${var.default_region2}-cr4" project = var.project_id network = module.main.network_name diff --git a/3-networks/modules/base_shared_vpc/outputs.tf b/3-networks/modules/base_shared_vpc/outputs.tf index a69cd9c51..86e985d8c 100644 --- a/3-networks/modules/base_shared_vpc/outputs.tf +++ b/3-networks/modules/base_shared_vpc/outputs.tf @@ -60,21 +60,21 @@ output "subnets_secondary_ranges" { } output "region1_router1" { - value = module.region1_router1 + value = try(module.region1_router1[0], null) description = "Router 1 for Region 1" } output "region1_router2" { - value = module.region1_router2 + value = try(module.region1_router2[0], null) description = "Router 2 for Region 1" } output "region2_router1" { - value = module.region2_router1 + value = try(module.region2_router1[0], null) description = "Router 1 for Region 2" } output "region2_router2" { - value = module.region2_router2 + value = try(module.region2_router2[0], null) description = "Router 2 for Region 2" } diff --git a/3-networks/modules/base_shared_vpc/variables.tf b/3-networks/modules/base_shared_vpc/variables.tf index 4672751d2..15f269ed5 100644 --- a/3-networks/modules/base_shared_vpc/variables.tf +++ b/3-networks/modules/base_shared_vpc/variables.tf @@ -24,6 +24,12 @@ variable "project_id" { description = "Project ID for Private Shared VPC." } +variable "mode" { + type = string + description = "Network deployment mode, should be set to `hub` or `spoke` when `enable_hub_and_spoke` architecture choosen, keep as `null` otherwise." + default = null +} + variable "environment_code" { type = string description = "A short form of the folder level resources (environment) within the Google Cloud organization." @@ -106,6 +112,7 @@ variable "domain" { variable "private_service_cidr" { type = string description = "CIDR range for private service networking. Used for Cloud SQL and other managed services." + default = null } variable "windows_activation_enabled" { diff --git a/3-networks/modules/restricted_shared_vpc/README.md b/3-networks/modules/restricted_shared_vpc/README.md index 14e02de0e..dd2d54701 100644 --- a/3-networks/modules/restricted_shared_vpc/README.md +++ b/3-networks/modules/restricted_shared_vpc/README.md @@ -14,6 +14,7 @@ | firewall\_enable\_logging | Toggle firewall logging for VPC Firewalls. | `bool` | `true` | no | | folder\_prefix | Name prefix to use for folders created. | `string` | `"fldr"` | no | | members | An allowed list of members (users, service accounts). The signed-in identity originating the request must be a part of one of the provided members. If not specified, a request may come from any user (logged in/not logged in, etc.). Formats: user:{emailid}, serviceAccount:{emailid} | `list(string)` | n/a | yes | +| mode | Network deployment mode, should be set to `hub` or `spoke` when `enable_hub_and_spoke` architecture choosen, keep as `null` otherwise. | `string` | `null` | no | | nat\_bgp\_asn | BGP ASN for NAT cloud routes. If NAT is enabled this variable value must be a value in ranges [64512..65534] or [4200000000..4294967294]. | `number` | `64512` | no | | nat\_enabled | Toggle creation of NAT cloud router. | `bool` | `false` | no | | nat\_num\_addresses\_region1 | Number of external IPs to reserve for region 1 Cloud NAT. | `number` | `2` | no | @@ -21,7 +22,7 @@ | optional\_fw\_rules\_enabled | Toggle creation of optional firewall rules: IAP SSH, IAP RDP and Internal & Global load balancing health check and load balancing IP ranges. | `bool` | `false` | no | | org\_id | Organization ID | `string` | n/a | yes | | parent\_folder | Optional - if using a folder for testing. | `string` | `""` | no | -| private\_service\_cidr | CIDR range for private service networking. Used for Cloud SQL and other managed services. | `string` | n/a | yes | +| private\_service\_cidr | CIDR range for private service networking. Used for Cloud SQL and other managed services. | `string` | `null` | no | | project\_id | Project ID for Restricted Shared VPC. | `string` | n/a | yes | | project\_number | Project number for Restricted Shared VPC. It is the project INSIDE the regular service perimeter. | `number` | n/a | yes | | restricted\_services | List of services to restrict. | `list(string)` | n/a | yes | diff --git a/3-networks/modules/restricted_shared_vpc/main.tf b/3-networks/modules/restricted_shared_vpc/main.tf index 8b443eeed..754617f39 100644 --- a/3-networks/modules/restricted_shared_vpc/main.tf +++ b/3-networks/modules/restricted_shared_vpc/main.tf @@ -14,16 +14,32 @@ * limitations under the License. */ -/****************************************** - Shared VPC configuration - *****************************************/ - locals { - vpc_name = "${var.environment_code}-shared-restricted" + mode = var.mode == null ? "" : var.mode == "hub" ? "-hub" : "-spoke" + vpc_name = "${var.environment_code}-shared-restricted${local.mode}" network_name = "vpc-${local.vpc_name}" restricted_googleapis_cidr = "199.36.153.4/30" } +/****************************************** + Restricted Network Hub +*****************************************/ + +data "google_projects" "restricted_net_hub" { + count = var.mode == "spoke" ? 1 : 0 + filter = "parent.id:${split("/", data.google_active_folder.common.name)[1]} labels.application_name=org-restricted-net-hub lifecycleState=ACTIVE" +} + +data "google_compute_network" "vpc_restricted_net_hub" { + count = var.mode == "spoke" ? 1 : 0 + name = "vpc-c-shared-restricted-hub" + project = data.google_projects.restricted_net_hub[0].projects[0].project_id +} + +/****************************************** + Shared VPC configuration + *****************************************/ + module "main" { source = "terraform-google-modules/network/google" version = "~> 2.0" @@ -69,12 +85,26 @@ module "main" { ) } +/*************************************************************** + VPC Peering Configuration + **************************************************************/ + +module "peering" { + source = "terraform-google-modules/network/google//modules/network-peering" + version = "~> 2.0" + count = var.mode == "spoke" ? 1 : 0 + prefix = "np" + local_network = module.main.network_self_link + peer_network = data.google_compute_network.vpc_restricted_net_hub[0].self_link + export_peer_custom_routes = true +} + /*************************************************************** Configure Service Networking for Cloud SQL & future services. **************************************************************/ resource "google_compute_global_address" "private_service_access_address" { - + count = var.private_service_cidr != null ? 1 : 0 name = "ga-${local.vpc_name}-vpc-peering-internal" project = var.project_id purpose = "VPC_PEERING" @@ -82,12 +112,17 @@ resource "google_compute_global_address" "private_service_access_address" { address = element(split("/", var.private_service_cidr), 0) prefix_length = element(split("/", var.private_service_cidr), 1) network = module.main.network_self_link + + depends_on = [module.peering] } resource "google_service_networking_connection" "private_vpc_connection" { + count = var.private_service_cidr != null ? 1 : 0 network = module.main.network_self_link service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.private_service_access_address.name] + reserved_peering_ranges = [google_compute_global_address.private_service_access_address[0].name] + + depends_on = [module.peering] } /************************************ @@ -98,6 +133,7 @@ resource "google_service_networking_connection" "private_vpc_connection" { module "region1_router1" { source = "terraform-google-modules/cloud-router/google" version = "~> 0.3.0" + count = var.mode != "spoke" ? 1 : 0 name = "cr-${local.vpc_name}-${var.default_region1}-cr5" project = var.project_id network = module.main.network_name @@ -112,6 +148,7 @@ module "region1_router1" { module "region1_router2" { source = "terraform-google-modules/cloud-router/google" version = "~> 0.3.0" + count = var.mode != "spoke" ? 1 : 0 name = "cr-${local.vpc_name}-${var.default_region1}-cr6" project = var.project_id network = module.main.network_name @@ -126,6 +163,7 @@ module "region1_router2" { module "region2_router1" { source = "terraform-google-modules/cloud-router/google" version = "~> 0.3.0" + count = var.mode != "spoke" ? 1 : 0 name = "cr-${local.vpc_name}-${var.default_region2}-cr7" project = var.project_id network = module.main.network_name @@ -140,6 +178,7 @@ module "region2_router1" { module "region2_router2" { source = "terraform-google-modules/cloud-router/google" version = "~> 0.3.0" + count = var.mode != "spoke" ? 1 : 0 name = "cr-${local.vpc_name}-${var.default_region2}-cr8" project = var.project_id network = module.main.network_name diff --git a/3-networks/modules/restricted_shared_vpc/outputs.tf b/3-networks/modules/restricted_shared_vpc/outputs.tf index a032c55ea..dca2a2157 100644 --- a/3-networks/modules/restricted_shared_vpc/outputs.tf +++ b/3-networks/modules/restricted_shared_vpc/outputs.tf @@ -50,22 +50,22 @@ output "subnets_secondary_ranges" { } output "region1_router1" { - value = module.region1_router1 + value = try(module.region1_router1[0], null) description = "Router 1 for Region 1" } output "region1_router2" { - value = module.region1_router2 + value = try(module.region1_router2[0], null) description = "Router 2 for Region 1" } output "region2_router1" { - value = module.region2_router1 + value = try(module.region2_router1[0], null) description = "Router 1 for Region 2" } output "region2_router2" { - value = module.region2_router2 + value = try(module.region2_router2[0], null) description = "Router 2 for Region 2" } diff --git a/3-networks/modules/restricted_shared_vpc/service_control.tf b/3-networks/modules/restricted_shared_vpc/service_control.tf index c485cbe8a..ec29c62f2 100644 --- a/3-networks/modules/restricted_shared_vpc/service_control.tf +++ b/3-networks/modules/restricted_shared_vpc/service_control.tf @@ -18,6 +18,12 @@ locals { prefix = "${var.environment_code}_shared_restricted" access_level_name = "alp_${local.prefix}_members_${random_id.random_access_level_suffix.hex}" perimeter_name = "sp_${local.prefix}_default_perimeter_${random_id.random_access_level_suffix.hex}" + bridge_name = "spb_c_to_${local.prefix}_bridge_${random_id.random_access_level_suffix.hex}" +} + +data "google_project" "restricted_net_hub" { + count = var.mode == "spoke" ? 1 : 0 + project_id = data.google_projects.restricted_net_hub[0].projects[0].project_id } resource "random_id" "random_access_level_suffix" { @@ -54,3 +60,17 @@ resource "google_access_context_manager_service_perimeter" "regular_service_peri ignore_changes = [status[0].resources] } } + +resource "google_access_context_manager_service_perimeter" "bridge_to_network_hub_perimeter" { + count = var.mode == "spoke" ? 1 : 0 + perimeter_type = "PERIMETER_TYPE_BRIDGE" + parent = "accessPolicies/${var.access_context_manager_policy_id}" + name = "accessPolicies/${var.access_context_manager_policy_id}/servicePerimeters/${local.bridge_name}" + title = local.bridge_name + + status { + resources = formatlist("projects/%s", [var.project_number, data.google_project.restricted_net_hub[0].number]) + } + + depends_on = [google_access_context_manager_service_perimeter.regular_service_perimeter] +} diff --git a/3-networks/modules/restricted_shared_vpc/variables.tf b/3-networks/modules/restricted_shared_vpc/variables.tf index 61428e5e8..d1ca5199f 100644 --- a/3-networks/modules/restricted_shared_vpc/variables.tf +++ b/3-networks/modules/restricted_shared_vpc/variables.tf @@ -34,6 +34,12 @@ variable "project_number" { description = "Project number for Restricted Shared VPC. It is the project INSIDE the regular service perimeter." } +variable "mode" { + type = string + description = "Network deployment mode, should be set to `hub` or `spoke` when `enable_hub_and_spoke` architecture choosen, keep as `null` otherwise." + default = null +} + variable "environment_code" { type = string description = "A short form of the folder level resources (environment) within the Google Cloud organization." @@ -116,6 +122,7 @@ variable "domain" { variable "private_service_cidr" { type = string description = "CIDR range for private service networking. Used for Cloud SQL and other managed services." + default = null } variable "windows_activation_enabled" { diff --git a/4-projects/business_unit_1/development/README.md b/4-projects/business_unit_1/development/README.md index e4249c630..d01e84da1 100644 --- a/4-projects/business_unit_1/development/README.md +++ b/4-projects/business_unit_1/development/README.md @@ -8,6 +8,7 @@ | alert\_spent\_percents | A list of percentages of the budget to alert on when threshold is exceeded | `list(number)` |
0.5,
0.75,
0.9,
0.95
]
[| no | | billing\_account | The ID of the billing account to associated this project with | `string` | n/a | yes | | budget\_amount | The amount to use as the budget | `number` | `1000` | no | +| enable\_hub\_and\_spoke | Enable Hub-and-Spoke architecture. | `bool` | `false` | no | | firewall\_enable\_logging | Toggle firewall logging for VPC Firewalls. | `bool` | `true` | no | | folder\_prefix | Name prefix to use for folders created. | `string` | `"fldr"` | no | | optional\_fw\_rules\_enabled | Toggle creation of optional firewall rules: IAP SSH, IAP RDP and Internal & Global load balancing health check and load balancing IP ranges. | `bool` | `false` | no | @@ -16,7 +17,6 @@ | peering\_module\_depends\_on | List of modules or resources peering module depends on. | `list` | `[]` | no | | perimeter\_name | Access context manager service perimeter name to attach the restricted svpc project. | `string` | n/a | yes | | project\_prefix | Name prefix to use for projects created. | `string` | `"prj"` | no | -| skip\_gcloud\_download | Whether to skip downloading gcloud (assumes gcloud is already available outside the module) | `bool` | `true` | no | | terraform\_service\_account | Service account email of the account to impersonate to run Terraform | `string` | n/a | yes | | windows\_activation\_enabled | Enable Windows license activation for Windows workloads. | `bool` | `false` | no | diff --git a/4-projects/business_unit_1/development/example_base_shared_vpc_project.tf b/4-projects/business_unit_1/development/example_base_shared_vpc_project.tf index 653d28247..c54975c8f 100644 --- a/4-projects/business_unit_1/development/example_base_shared_vpc_project.tf +++ b/4-projects/business_unit_1/development/example_base_shared_vpc_project.tf @@ -20,13 +20,13 @@ module "base_shared_vpc_project" { org_id = var.org_id billing_account = var.billing_account folder_id = data.google_active_folder.env.name - skip_gcloud_download = var.skip_gcloud_download environment = "development" vpc_type = "base" alert_spent_percents = var.alert_spent_percents alert_pubsub_topic = var.alert_pubsub_topic budget_amount = var.budget_amount project_prefix = var.project_prefix + enable_hub_and_spoke = var.enable_hub_and_spoke # Metadata project_suffix = "sample-base" diff --git a/4-projects/business_unit_1/development/example_floating_project.tf b/4-projects/business_unit_1/development/example_floating_project.tf index 2816af886..cf4c980a8 100644 --- a/4-projects/business_unit_1/development/example_floating_project.tf +++ b/4-projects/business_unit_1/development/example_floating_project.tf @@ -20,7 +20,6 @@ module "floating_project" { org_id = var.org_id billing_account = var.billing_account folder_id = data.google_active_folder.env.name - skip_gcloud_download = var.skip_gcloud_download environment = "development" alert_spent_percents = var.alert_spent_percents alert_pubsub_topic = var.alert_pubsub_topic diff --git a/4-projects/business_unit_1/development/example_peering_project.tf b/4-projects/business_unit_1/development/example_peering_project.tf index da7133bb1..59f849a43 100644 --- a/4-projects/business_unit_1/development/example_peering_project.tf +++ b/4-projects/business_unit_1/development/example_peering_project.tf @@ -14,12 +14,16 @@ * limitations under the License. */ +locals { + shared_vpc_mode = var.enable_hub_and_spoke ? "-spoke" : "" +} + data "google_projects" "projects" { filter = "parent.id:${split("/", data.google_active_folder.env.name)[1]} labels.application_name=base-shared-vpc-host labels.environment=development lifecycleState=ACTIVE" } data "google_compute_network" "shared_vpc" { - name = "vpc-d-shared-base" + name = "vpc-d-shared-base${local.shared_vpc_mode}" project = data.google_projects.projects.projects[0].project_id } @@ -41,7 +45,6 @@ module "peering_project" { org_id = var.org_id billing_account = var.billing_account folder_id = data.google_active_folder.env.name - skip_gcloud_download = var.skip_gcloud_download environment = "development" project_prefix = var.project_prefix diff --git a/4-projects/business_unit_1/development/example_restricted_shared_vpc_project.tf b/4-projects/business_unit_1/development/example_restricted_shared_vpc_project.tf index 58a0e7831..0f508e7ff 100644 --- a/4-projects/business_unit_1/development/example_restricted_shared_vpc_project.tf +++ b/4-projects/business_unit_1/development/example_restricted_shared_vpc_project.tf @@ -20,13 +20,13 @@ module "restricted_shared_vpc_project" { org_id = var.org_id billing_account = var.billing_account folder_id = data.google_active_folder.env.name - skip_gcloud_download = var.skip_gcloud_download environment = "development" vpc_type = "restricted" alert_spent_percents = var.alert_spent_percents alert_pubsub_topic = var.alert_pubsub_topic budget_amount = var.budget_amount project_prefix = var.project_prefix + enable_hub_and_spoke = var.enable_hub_and_spoke activate_apis = ["accesscontextmanager.googleapis.com"] vpc_service_control_attach_enabled = "true" diff --git a/4-projects/business_unit_1/development/variables.tf b/4-projects/business_unit_1/development/variables.tf index 23d2d3386..59b05ac13 100644 --- a/4-projects/business_unit_1/development/variables.tf +++ b/4-projects/business_unit_1/development/variables.tf @@ -29,12 +29,6 @@ variable "billing_account" { type = string } -variable "skip_gcloud_download" { - description = "Whether to skip downloading gcloud (assumes gcloud is already available outside the module)" - type = bool - default = true -} - variable "access_context_manager_policy_id" { type = string description = "The ID of the access context manager policy the perimeter lies in. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR-ORGANIZATION_ID --format=\"value(name)\"`." @@ -104,3 +98,9 @@ variable "folder_prefix" { type = string default = "fldr" } + +variable "enable_hub_and_spoke" { + description = "Enable Hub-and-Spoke architecture." + type = bool + default = false +} diff --git a/4-projects/business_unit_1/non-production/README.md b/4-projects/business_unit_1/non-production/README.md index e4249c630..d01e84da1 100644 --- a/4-projects/business_unit_1/non-production/README.md +++ b/4-projects/business_unit_1/non-production/README.md @@ -8,6 +8,7 @@ | alert\_spent\_percents | A list of percentages of the budget to alert on when threshold is exceeded | `list(number)` |
0.5,
0.75,
0.9,
0.95
]
[| no | | billing\_account | The ID of the billing account to associated this project with | `string` | n/a | yes | | budget\_amount | The amount to use as the budget | `number` | `1000` | no | +| enable\_hub\_and\_spoke | Enable Hub-and-Spoke architecture. | `bool` | `false` | no | | firewall\_enable\_logging | Toggle firewall logging for VPC Firewalls. | `bool` | `true` | no | | folder\_prefix | Name prefix to use for folders created. | `string` | `"fldr"` | no | | optional\_fw\_rules\_enabled | Toggle creation of optional firewall rules: IAP SSH, IAP RDP and Internal & Global load balancing health check and load balancing IP ranges. | `bool` | `false` | no | @@ -16,7 +17,6 @@ | peering\_module\_depends\_on | List of modules or resources peering module depends on. | `list` | `[]` | no | | perimeter\_name | Access context manager service perimeter name to attach the restricted svpc project. | `string` | n/a | yes | | project\_prefix | Name prefix to use for projects created. | `string` | `"prj"` | no | -| skip\_gcloud\_download | Whether to skip downloading gcloud (assumes gcloud is already available outside the module) | `bool` | `true` | no | | terraform\_service\_account | Service account email of the account to impersonate to run Terraform | `string` | n/a | yes | | windows\_activation\_enabled | Enable Windows license activation for Windows workloads. | `bool` | `false` | no | diff --git a/4-projects/business_unit_1/non-production/example_base_shared_vpc_project.tf b/4-projects/business_unit_1/non-production/example_base_shared_vpc_project.tf index a551be10e..fdf571d3b 100644 --- a/4-projects/business_unit_1/non-production/example_base_shared_vpc_project.tf +++ b/4-projects/business_unit_1/non-production/example_base_shared_vpc_project.tf @@ -20,13 +20,13 @@ module "base_shared_vpc_project" { org_id = var.org_id billing_account = var.billing_account folder_id = data.google_active_folder.env.name - skip_gcloud_download = var.skip_gcloud_download environment = "non-production" vpc_type = "base" alert_spent_percents = var.alert_spent_percents alert_pubsub_topic = var.alert_pubsub_topic budget_amount = var.budget_amount project_prefix = var.project_prefix + enable_hub_and_spoke = var.enable_hub_and_spoke # Metadata project_suffix = "sample-base" diff --git a/4-projects/business_unit_1/non-production/example_floating_project.tf b/4-projects/business_unit_1/non-production/example_floating_project.tf index d112d8a4e..a06157661 100644 --- a/4-projects/business_unit_1/non-production/example_floating_project.tf +++ b/4-projects/business_unit_1/non-production/example_floating_project.tf @@ -20,7 +20,6 @@ module "floating_project" { org_id = var.org_id billing_account = var.billing_account folder_id = data.google_active_folder.env.name - skip_gcloud_download = var.skip_gcloud_download environment = "non-production" alert_spent_percents = var.alert_spent_percents alert_pubsub_topic = var.alert_pubsub_topic diff --git a/4-projects/business_unit_1/non-production/example_peering_project.tf b/4-projects/business_unit_1/non-production/example_peering_project.tf index d61ffc62b..61db2f462 100644 --- a/4-projects/business_unit_1/non-production/example_peering_project.tf +++ b/4-projects/business_unit_1/non-production/example_peering_project.tf @@ -14,12 +14,16 @@ * limitations under the License. */ +locals { + shared_vpc_mode = var.enable_hub_and_spoke ? "-spoke" : "" +} + data "google_projects" "projects" { filter = "parent.id:${split("/", data.google_active_folder.env.name)[1]} labels.application_name=base-shared-vpc-host labels.environment=non-production lifecycleState=ACTIVE" } data "google_compute_network" "shared_vpc" { - name = "vpc-n-shared-base" + name = "vpc-n-shared-base${local.shared_vpc_mode}" project = data.google_projects.projects.projects[0].project_id } @@ -41,7 +45,6 @@ module "peering_project" { org_id = var.org_id billing_account = var.billing_account folder_id = data.google_active_folder.env.name - skip_gcloud_download = var.skip_gcloud_download environment = "non-production" project_prefix = var.project_prefix diff --git a/4-projects/business_unit_1/non-production/example_restricted_shared_vpc_project.tf b/4-projects/business_unit_1/non-production/example_restricted_shared_vpc_project.tf index 1d171dece..73d8e80dd 100644 --- a/4-projects/business_unit_1/non-production/example_restricted_shared_vpc_project.tf +++ b/4-projects/business_unit_1/non-production/example_restricted_shared_vpc_project.tf @@ -20,13 +20,13 @@ module "restricted_shared_vpc_project" { org_id = var.org_id billing_account = var.billing_account folder_id = data.google_active_folder.env.name - skip_gcloud_download = var.skip_gcloud_download environment = "non-production" vpc_type = "restricted" alert_spent_percents = var.alert_spent_percents alert_pubsub_topic = var.alert_pubsub_topic budget_amount = var.budget_amount project_prefix = var.project_prefix + enable_hub_and_spoke = var.enable_hub_and_spoke activate_apis = ["accesscontextmanager.googleapis.com"] vpc_service_control_attach_enabled = "true" diff --git a/4-projects/business_unit_1/non-production/variables.tf b/4-projects/business_unit_1/non-production/variables.tf index 23d2d3386..59b05ac13 100644 --- a/4-projects/business_unit_1/non-production/variables.tf +++ b/4-projects/business_unit_1/non-production/variables.tf @@ -29,12 +29,6 @@ variable "billing_account" { type = string } -variable "skip_gcloud_download" { - description = "Whether to skip downloading gcloud (assumes gcloud is already available outside the module)" - type = bool - default = true -} - variable "access_context_manager_policy_id" { type = string description = "The ID of the access context manager policy the perimeter lies in. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR-ORGANIZATION_ID --format=\"value(name)\"`." @@ -104,3 +98,9 @@ variable "folder_prefix" { type = string default = "fldr" } + +variable "enable_hub_and_spoke" { + description = "Enable Hub-and-Spoke architecture." + type = bool + default = false +} diff --git a/4-projects/business_unit_1/production/README.md b/4-projects/business_unit_1/production/README.md index f39d22028..4cd1bdb83 100644 --- a/4-projects/business_unit_1/production/README.md +++ b/4-projects/business_unit_1/production/README.md @@ -8,6 +8,7 @@ | alert\_spent\_percents | A list of percentages of the budget to alert on when threshold is exceeded | `list(number)` |
0.5,
0.75,
0.9,
0.95
]
[| no | | billing\_account | The ID of the billing account to associated this project with | `string` | n/a | yes | | budget\_amount | The amount to use as the budget | `number` | `1000` | no | +| enable\_hub\_and\_spoke | Enable Hub-and-Spoke architecture. | `bool` | `false` | no | | env\_code | A short form of the environment field | `string` | `"p"` | no | | firewall\_enable\_logging | Toggle firewall logging for VPC Firewalls. | `bool` | `true` | no | | folder\_prefix | Name prefix to use for folders created. | `string` | `"fldr"` | no | @@ -17,7 +18,6 @@ | peering\_module\_depends\_on | List of modules or resources peering module depends on. | `list` | `[]` | no | | perimeter\_name | Access context manager service perimeter name to attach the restricted svpc project. | `string` | n/a | yes | | project\_prefix | Name prefix to use for projects created. | `string` | `"prj"` | no | -| skip\_gcloud\_download | Whether to skip downloading gcloud (assumes gcloud is already available outside the module) | `bool` | `true` | no | | terraform\_service\_account | Service account email of the account to impersonate to run Terraform | `string` | n/a | yes | | windows\_activation\_enabled | Enable Windows license activation for Windows workloads. | `bool` | `false` | no | diff --git a/4-projects/business_unit_1/production/example_base_shared_vpc_project.tf b/4-projects/business_unit_1/production/example_base_shared_vpc_project.tf index 22c78b023..7bfa8f82c 100644 --- a/4-projects/business_unit_1/production/example_base_shared_vpc_project.tf +++ b/4-projects/business_unit_1/production/example_base_shared_vpc_project.tf @@ -20,13 +20,13 @@ module "base_shared_vpc_project" { org_id = var.org_id billing_account = var.billing_account folder_id = data.google_active_folder.env.name - skip_gcloud_download = var.skip_gcloud_download environment = "production" vpc_type = "base" alert_spent_percents = var.alert_spent_percents alert_pubsub_topic = var.alert_pubsub_topic budget_amount = var.budget_amount project_prefix = var.project_prefix + enable_hub_and_spoke = var.enable_hub_and_spoke # Metadata project_suffix = "sample-base" diff --git a/4-projects/business_unit_1/production/example_floating_project.tf b/4-projects/business_unit_1/production/example_floating_project.tf index 560dd0995..584a8d067 100644 --- a/4-projects/business_unit_1/production/example_floating_project.tf +++ b/4-projects/business_unit_1/production/example_floating_project.tf @@ -20,7 +20,6 @@ module "floating_project" { org_id = var.org_id billing_account = var.billing_account folder_id = data.google_active_folder.env.name - skip_gcloud_download = var.skip_gcloud_download environment = "production" alert_spent_percents = var.alert_spent_percents alert_pubsub_topic = var.alert_pubsub_topic diff --git a/4-projects/business_unit_1/production/example_peering_project.tf b/4-projects/business_unit_1/production/example_peering_project.tf index a88c9538e..d9d2af356 100644 --- a/4-projects/business_unit_1/production/example_peering_project.tf +++ b/4-projects/business_unit_1/production/example_peering_project.tf @@ -14,12 +14,16 @@ * limitations under the License. */ +locals { + shared_vpc_mode = var.enable_hub_and_spoke ? "-spoke" : "" +} + data "google_projects" "projects" { filter = "parent.id:${split("/", data.google_active_folder.env.name)[1]} labels.application_name=base-shared-vpc-host labels.environment=production lifecycleState=ACTIVE" } data "google_compute_network" "shared_vpc" { - name = "vpc-p-shared-base" + name = "vpc-p-shared-base${local.shared_vpc_mode}" project = data.google_projects.projects.projects[0].project_id } @@ -41,7 +45,6 @@ module "peering_project" { org_id = var.org_id billing_account = var.billing_account folder_id = data.google_active_folder.env.name - skip_gcloud_download = var.skip_gcloud_download environment = "production" project_prefix = var.project_prefix diff --git a/4-projects/business_unit_1/production/example_restricted_shared_vpc_project.tf b/4-projects/business_unit_1/production/example_restricted_shared_vpc_project.tf index 83555cb69..2ebbdb76c 100644 --- a/4-projects/business_unit_1/production/example_restricted_shared_vpc_project.tf +++ b/4-projects/business_unit_1/production/example_restricted_shared_vpc_project.tf @@ -20,13 +20,13 @@ module "restricted_shared_vpc_project" { org_id = var.org_id billing_account = var.billing_account folder_id = data.google_active_folder.env.name - skip_gcloud_download = var.skip_gcloud_download environment = "production" vpc_type = "restricted" alert_spent_percents = var.alert_spent_percents alert_pubsub_topic = var.alert_pubsub_topic budget_amount = var.budget_amount project_prefix = var.project_prefix + enable_hub_and_spoke = var.enable_hub_and_spoke activate_apis = ["accesscontextmanager.googleapis.com"] vpc_service_control_attach_enabled = "true" diff --git a/4-projects/business_unit_1/production/variables.tf b/4-projects/business_unit_1/production/variables.tf index 0cedcaaf6..7adc4c3e1 100644 --- a/4-projects/business_unit_1/production/variables.tf +++ b/4-projects/business_unit_1/production/variables.tf @@ -29,12 +29,6 @@ variable "billing_account" { type = string } -variable "skip_gcloud_download" { - description = "Whether to skip downloading gcloud (assumes gcloud is already available outside the module)" - type = bool - default = true -} - variable "env_code" { description = "A short form of the environment field" type = string @@ -110,3 +104,9 @@ variable "folder_prefix" { type = string default = "fldr" } + +variable "enable_hub_and_spoke" { + description = "Enable Hub-and-Spoke architecture." + type = bool + default = false +} diff --git a/4-projects/business_unit_2/development/README.md b/4-projects/business_unit_2/development/README.md index e4249c630..d01e84da1 100644 --- a/4-projects/business_unit_2/development/README.md +++ b/4-projects/business_unit_2/development/README.md @@ -8,6 +8,7 @@ | alert\_spent\_percents | A list of percentages of the budget to alert on when threshold is exceeded | `list(number)` |
0.5,
0.75,
0.9,
0.95
]
[| no | | billing\_account | The ID of the billing account to associated this project with | `string` | n/a | yes | | budget\_amount | The amount to use as the budget | `number` | `1000` | no | +| enable\_hub\_and\_spoke | Enable Hub-and-Spoke architecture. | `bool` | `false` | no | | firewall\_enable\_logging | Toggle firewall logging for VPC Firewalls. | `bool` | `true` | no | | folder\_prefix | Name prefix to use for folders created. | `string` | `"fldr"` | no | | optional\_fw\_rules\_enabled | Toggle creation of optional firewall rules: IAP SSH, IAP RDP and Internal & Global load balancing health check and load balancing IP ranges. | `bool` | `false` | no | @@ -16,7 +17,6 @@ | peering\_module\_depends\_on | List of modules or resources peering module depends on. | `list` | `[]` | no | | perimeter\_name | Access context manager service perimeter name to attach the restricted svpc project. | `string` | n/a | yes | | project\_prefix | Name prefix to use for projects created. | `string` | `"prj"` | no | -| skip\_gcloud\_download | Whether to skip downloading gcloud (assumes gcloud is already available outside the module) | `bool` | `true` | no | | terraform\_service\_account | Service account email of the account to impersonate to run Terraform | `string` | n/a | yes | | windows\_activation\_enabled | Enable Windows license activation for Windows workloads. | `bool` | `false` | no | diff --git a/4-projects/business_unit_2/development/example_base_shared_vpc_project.tf b/4-projects/business_unit_2/development/example_base_shared_vpc_project.tf index 5d0aa4940..2e2678a99 100644 --- a/4-projects/business_unit_2/development/example_base_shared_vpc_project.tf +++ b/4-projects/business_unit_2/development/example_base_shared_vpc_project.tf @@ -20,13 +20,13 @@ module "base_shared_vpc_project" { org_id = var.org_id billing_account = var.billing_account folder_id = data.google_active_folder.env.name - skip_gcloud_download = var.skip_gcloud_download environment = "development" vpc_type = "base" alert_spent_percents = var.alert_spent_percents alert_pubsub_topic = var.alert_pubsub_topic budget_amount = var.budget_amount project_prefix = var.project_prefix + enable_hub_and_spoke = var.enable_hub_and_spoke # Metadata project_suffix = "sample-base" diff --git a/4-projects/business_unit_2/development/example_floating_project.tf b/4-projects/business_unit_2/development/example_floating_project.tf index 212d7b47c..efceb5e4a 100644 --- a/4-projects/business_unit_2/development/example_floating_project.tf +++ b/4-projects/business_unit_2/development/example_floating_project.tf @@ -20,7 +20,6 @@ module "floating_project" { org_id = var.org_id billing_account = var.billing_account folder_id = data.google_active_folder.env.name - skip_gcloud_download = var.skip_gcloud_download environment = "development" alert_spent_percents = var.alert_spent_percents alert_pubsub_topic = var.alert_pubsub_topic diff --git a/4-projects/business_unit_2/development/example_peering_project.tf b/4-projects/business_unit_2/development/example_peering_project.tf index 42181caf0..e3e3d7958 100644 --- a/4-projects/business_unit_2/development/example_peering_project.tf +++ b/4-projects/business_unit_2/development/example_peering_project.tf @@ -14,12 +14,16 @@ * limitations under the License. */ +locals { + shared_vpc_mode = var.enable_hub_and_spoke ? "-spoke" : "" +} + data "google_projects" "projects" { filter = "parent.id:${split("/", data.google_active_folder.env.name)[1]} labels.application_name=base-shared-vpc-host labels.environment=development lifecycleState=ACTIVE" } data "google_compute_network" "shared_vpc" { - name = "vpc-d-shared-base" + name = "vpc-d-shared-base${local.shared_vpc_mode}" project = data.google_projects.projects.projects[0].project_id } @@ -41,7 +45,6 @@ module "peering_project" { org_id = var.org_id billing_account = var.billing_account folder_id = data.google_active_folder.env.name - skip_gcloud_download = var.skip_gcloud_download environment = "development" project_prefix = var.project_prefix diff --git a/4-projects/business_unit_2/development/example_restricted_shared_vpc_project.tf b/4-projects/business_unit_2/development/example_restricted_shared_vpc_project.tf index 755c772f3..2a490f5d1 100644 --- a/4-projects/business_unit_2/development/example_restricted_shared_vpc_project.tf +++ b/4-projects/business_unit_2/development/example_restricted_shared_vpc_project.tf @@ -20,13 +20,13 @@ module "restricted_shared_vpc_project" { org_id = var.org_id billing_account = var.billing_account folder_id = data.google_active_folder.env.name - skip_gcloud_download = var.skip_gcloud_download environment = "development" vpc_type = "restricted" alert_spent_percents = var.alert_spent_percents alert_pubsub_topic = var.alert_pubsub_topic budget_amount = var.budget_amount project_prefix = var.project_prefix + enable_hub_and_spoke = var.enable_hub_and_spoke activate_apis = ["accesscontextmanager.googleapis.com"] vpc_service_control_attach_enabled = "true" diff --git a/4-projects/business_unit_2/development/variables.tf b/4-projects/business_unit_2/development/variables.tf index 23d2d3386..59b05ac13 100644 --- a/4-projects/business_unit_2/development/variables.tf +++ b/4-projects/business_unit_2/development/variables.tf @@ -29,12 +29,6 @@ variable "billing_account" { type = string } -variable "skip_gcloud_download" { - description = "Whether to skip downloading gcloud (assumes gcloud is already available outside the module)" - type = bool - default = true -} - variable "access_context_manager_policy_id" { type = string description = "The ID of the access context manager policy the perimeter lies in. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR-ORGANIZATION_ID --format=\"value(name)\"`." @@ -104,3 +98,9 @@ variable "folder_prefix" { type = string default = "fldr" } + +variable "enable_hub_and_spoke" { + description = "Enable Hub-and-Spoke architecture." + type = bool + default = false +} diff --git a/4-projects/business_unit_2/non-production/README.md b/4-projects/business_unit_2/non-production/README.md index e4249c630..d01e84da1 100644 --- a/4-projects/business_unit_2/non-production/README.md +++ b/4-projects/business_unit_2/non-production/README.md @@ -8,6 +8,7 @@ | alert\_spent\_percents | A list of percentages of the budget to alert on when threshold is exceeded | `list(number)` |
0.5,
0.75,
0.9,
0.95
]
[| no | | billing\_account | The ID of the billing account to associated this project with | `string` | n/a | yes | | budget\_amount | The amount to use as the budget | `number` | `1000` | no | +| enable\_hub\_and\_spoke | Enable Hub-and-Spoke architecture. | `bool` | `false` | no | | firewall\_enable\_logging | Toggle firewall logging for VPC Firewalls. | `bool` | `true` | no | | folder\_prefix | Name prefix to use for folders created. | `string` | `"fldr"` | no | | optional\_fw\_rules\_enabled | Toggle creation of optional firewall rules: IAP SSH, IAP RDP and Internal & Global load balancing health check and load balancing IP ranges. | `bool` | `false` | no | @@ -16,7 +17,6 @@ | peering\_module\_depends\_on | List of modules or resources peering module depends on. | `list` | `[]` | no | | perimeter\_name | Access context manager service perimeter name to attach the restricted svpc project. | `string` | n/a | yes | | project\_prefix | Name prefix to use for projects created. | `string` | `"prj"` | no | -| skip\_gcloud\_download | Whether to skip downloading gcloud (assumes gcloud is already available outside the module) | `bool` | `true` | no | | terraform\_service\_account | Service account email of the account to impersonate to run Terraform | `string` | n/a | yes | | windows\_activation\_enabled | Enable Windows license activation for Windows workloads. | `bool` | `false` | no | diff --git a/4-projects/business_unit_2/non-production/example_base_shared_vpc_project.tf b/4-projects/business_unit_2/non-production/example_base_shared_vpc_project.tf index 576439f81..aeceaf429 100644 --- a/4-projects/business_unit_2/non-production/example_base_shared_vpc_project.tf +++ b/4-projects/business_unit_2/non-production/example_base_shared_vpc_project.tf @@ -20,13 +20,13 @@ module "base_shared_vpc_project" { org_id = var.org_id billing_account = var.billing_account folder_id = data.google_active_folder.env.name - skip_gcloud_download = var.skip_gcloud_download environment = "non-production" vpc_type = "base" alert_spent_percents = var.alert_spent_percents alert_pubsub_topic = var.alert_pubsub_topic budget_amount = var.budget_amount project_prefix = var.project_prefix + enable_hub_and_spoke = var.enable_hub_and_spoke # Metadata project_suffix = "sample-base" diff --git a/4-projects/business_unit_2/non-production/example_floating_project.tf b/4-projects/business_unit_2/non-production/example_floating_project.tf index a88b15c9f..943ca0439 100644 --- a/4-projects/business_unit_2/non-production/example_floating_project.tf +++ b/4-projects/business_unit_2/non-production/example_floating_project.tf @@ -22,7 +22,6 @@ module "floating_project" { org_id = var.org_id billing_account = var.billing_account folder_id = data.google_active_folder.env.name - skip_gcloud_download = var.skip_gcloud_download environment = "non-production" alert_spent_percents = var.alert_spent_percents alert_pubsub_topic = var.alert_pubsub_topic diff --git a/4-projects/business_unit_2/non-production/example_peering_project.tf b/4-projects/business_unit_2/non-production/example_peering_project.tf index 194ceee42..c00a9c842 100644 --- a/4-projects/business_unit_2/non-production/example_peering_project.tf +++ b/4-projects/business_unit_2/non-production/example_peering_project.tf @@ -14,12 +14,16 @@ * limitations under the License. */ +locals { + shared_vpc_mode = var.enable_hub_and_spoke ? "-spoke" : "" +} + data "google_projects" "projects" { filter = "parent.id:${split("/", data.google_active_folder.env.name)[1]} labels.application_name=base-shared-vpc-host labels.environment=non-production lifecycleState=ACTIVE" } data "google_compute_network" "shared_vpc" { - name = "vpc-n-shared-base" + name = "vpc-n-shared-base${local.shared_vpc_mode}" project = data.google_projects.projects.projects[0].project_id } @@ -41,7 +45,6 @@ module "peering_project" { org_id = var.org_id billing_account = var.billing_account folder_id = data.google_active_folder.env.name - skip_gcloud_download = var.skip_gcloud_download environment = "non-production" project_prefix = var.project_prefix diff --git a/4-projects/business_unit_2/non-production/example_restricted_shared_vpc_project.tf b/4-projects/business_unit_2/non-production/example_restricted_shared_vpc_project.tf index 09a5beb03..19362651c 100644 --- a/4-projects/business_unit_2/non-production/example_restricted_shared_vpc_project.tf +++ b/4-projects/business_unit_2/non-production/example_restricted_shared_vpc_project.tf @@ -20,13 +20,13 @@ module "restricted_shared_vpc_project" { org_id = var.org_id billing_account = var.billing_account folder_id = data.google_active_folder.env.name - skip_gcloud_download = var.skip_gcloud_download environment = "non-production" vpc_type = "restricted" alert_spent_percents = var.alert_spent_percents alert_pubsub_topic = var.alert_pubsub_topic budget_amount = var.budget_amount project_prefix = var.project_prefix + enable_hub_and_spoke = var.enable_hub_and_spoke activate_apis = ["accesscontextmanager.googleapis.com"] vpc_service_control_attach_enabled = "true" diff --git a/4-projects/business_unit_2/non-production/variables.tf b/4-projects/business_unit_2/non-production/variables.tf index 23d2d3386..59b05ac13 100644 --- a/4-projects/business_unit_2/non-production/variables.tf +++ b/4-projects/business_unit_2/non-production/variables.tf @@ -29,12 +29,6 @@ variable "billing_account" { type = string } -variable "skip_gcloud_download" { - description = "Whether to skip downloading gcloud (assumes gcloud is already available outside the module)" - type = bool - default = true -} - variable "access_context_manager_policy_id" { type = string description = "The ID of the access context manager policy the perimeter lies in. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR-ORGANIZATION_ID --format=\"value(name)\"`." @@ -104,3 +98,9 @@ variable "folder_prefix" { type = string default = "fldr" } + +variable "enable_hub_and_spoke" { + description = "Enable Hub-and-Spoke architecture." + type = bool + default = false +} diff --git a/4-projects/business_unit_2/production/README.md b/4-projects/business_unit_2/production/README.md index e4249c630..d01e84da1 100644 --- a/4-projects/business_unit_2/production/README.md +++ b/4-projects/business_unit_2/production/README.md @@ -8,6 +8,7 @@ | alert\_spent\_percents | A list of percentages of the budget to alert on when threshold is exceeded | `list(number)` |
0.5,
0.75,
0.9,
0.95
]
[| no | | billing\_account | The ID of the billing account to associated this project with | `string` | n/a | yes | | budget\_amount | The amount to use as the budget | `number` | `1000` | no | +| enable\_hub\_and\_spoke | Enable Hub-and-Spoke architecture. | `bool` | `false` | no | | firewall\_enable\_logging | Toggle firewall logging for VPC Firewalls. | `bool` | `true` | no | | folder\_prefix | Name prefix to use for folders created. | `string` | `"fldr"` | no | | optional\_fw\_rules\_enabled | Toggle creation of optional firewall rules: IAP SSH, IAP RDP and Internal & Global load balancing health check and load balancing IP ranges. | `bool` | `false` | no | @@ -16,7 +17,6 @@ | peering\_module\_depends\_on | List of modules or resources peering module depends on. | `list` | `[]` | no | | perimeter\_name | Access context manager service perimeter name to attach the restricted svpc project. | `string` | n/a | yes | | project\_prefix | Name prefix to use for projects created. | `string` | `"prj"` | no | -| skip\_gcloud\_download | Whether to skip downloading gcloud (assumes gcloud is already available outside the module) | `bool` | `true` | no | | terraform\_service\_account | Service account email of the account to impersonate to run Terraform | `string` | n/a | yes | | windows\_activation\_enabled | Enable Windows license activation for Windows workloads. | `bool` | `false` | no | diff --git a/4-projects/business_unit_2/production/example_base_shared_vpc_project.tf b/4-projects/business_unit_2/production/example_base_shared_vpc_project.tf index 15904e4bb..5f107f554 100644 --- a/4-projects/business_unit_2/production/example_base_shared_vpc_project.tf +++ b/4-projects/business_unit_2/production/example_base_shared_vpc_project.tf @@ -20,13 +20,13 @@ module "base_shared_vpc_project" { org_id = var.org_id billing_account = var.billing_account folder_id = data.google_active_folder.env.name - skip_gcloud_download = var.skip_gcloud_download environment = "production" vpc_type = "base" alert_spent_percents = var.alert_spent_percents alert_pubsub_topic = var.alert_pubsub_topic budget_amount = var.budget_amount project_prefix = var.project_prefix + enable_hub_and_spoke = var.enable_hub_and_spoke # Metadata project_suffix = "sample-base" diff --git a/4-projects/business_unit_2/production/example_floating_project.tf b/4-projects/business_unit_2/production/example_floating_project.tf index 89b5729a4..527b638d9 100644 --- a/4-projects/business_unit_2/production/example_floating_project.tf +++ b/4-projects/business_unit_2/production/example_floating_project.tf @@ -22,7 +22,6 @@ module "floating_project" { org_id = var.org_id billing_account = var.billing_account folder_id = data.google_active_folder.env.name - skip_gcloud_download = var.skip_gcloud_download environment = "production" alert_spent_percents = var.alert_spent_percents alert_pubsub_topic = var.alert_pubsub_topic diff --git a/4-projects/business_unit_2/production/example_peering_project.tf b/4-projects/business_unit_2/production/example_peering_project.tf index 907009424..63a52c321 100644 --- a/4-projects/business_unit_2/production/example_peering_project.tf +++ b/4-projects/business_unit_2/production/example_peering_project.tf @@ -14,12 +14,16 @@ * limitations under the License. */ +locals { + shared_vpc_mode = var.enable_hub_and_spoke ? "-spoke" : "" +} + data "google_projects" "projects" { filter = "parent.id:${split("/", data.google_active_folder.env.name)[1]} labels.application_name=base-shared-vpc-host labels.environment=production lifecycleState=ACTIVE" } data "google_compute_network" "shared_vpc" { - name = "vpc-p-shared-base" + name = "vpc-p-shared-base${local.shared_vpc_mode}" project = data.google_projects.projects.projects[0].project_id } @@ -41,7 +45,6 @@ module "peering_project" { org_id = var.org_id billing_account = var.billing_account folder_id = data.google_active_folder.env.name - skip_gcloud_download = var.skip_gcloud_download environment = "production" project_prefix = var.project_prefix diff --git a/4-projects/business_unit_2/production/example_restricted_shared_vpc_project.tf b/4-projects/business_unit_2/production/example_restricted_shared_vpc_project.tf index f6031a277..e12173cd4 100644 --- a/4-projects/business_unit_2/production/example_restricted_shared_vpc_project.tf +++ b/4-projects/business_unit_2/production/example_restricted_shared_vpc_project.tf @@ -20,13 +20,13 @@ module "restricted_shared_vpc_project" { org_id = var.org_id billing_account = var.billing_account folder_id = data.google_active_folder.env.name - skip_gcloud_download = var.skip_gcloud_download environment = "production" vpc_type = "restricted" alert_spent_percents = var.alert_spent_percents alert_pubsub_topic = var.alert_pubsub_topic budget_amount = var.budget_amount project_prefix = var.project_prefix + enable_hub_and_spoke = var.enable_hub_and_spoke activate_apis = ["accesscontextmanager.googleapis.com"] vpc_service_control_attach_enabled = "true" diff --git a/4-projects/business_unit_2/production/variables.tf b/4-projects/business_unit_2/production/variables.tf index 23d2d3386..59b05ac13 100644 --- a/4-projects/business_unit_2/production/variables.tf +++ b/4-projects/business_unit_2/production/variables.tf @@ -29,12 +29,6 @@ variable "billing_account" { type = string } -variable "skip_gcloud_download" { - description = "Whether to skip downloading gcloud (assumes gcloud is already available outside the module)" - type = bool - default = true -} - variable "access_context_manager_policy_id" { type = string description = "The ID of the access context manager policy the perimeter lies in. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR-ORGANIZATION_ID --format=\"value(name)\"`." @@ -104,3 +98,9 @@ variable "folder_prefix" { type = string default = "fldr" } + +variable "enable_hub_and_spoke" { + description = "Enable Hub-and-Spoke architecture." + type = bool + default = false +} diff --git a/4-projects/modules/single_project/README.md b/4-projects/modules/single_project/README.md index 04f204d63..a1ff51c20 100644 --- a/4-projects/modules/single_project/README.md +++ b/4-projects/modules/single_project/README.md @@ -11,6 +11,7 @@ | billing\_code | The code that's used to provide chargeback information | `string` | n/a | yes | | budget\_amount | The amount to use as the budget | `number` | `1000` | no | | business\_code | The code that describes which business unit owns the project | `string` | `"abcd"` | no | +| enable\_hub\_and\_spoke | Enable Hub-and-Spoke architecture. | `bool` | `false` | no | | environment | The environment the single project belongs to | `string` | n/a | yes | | folder\_id | The folder id where project will be created | `string` | n/a | yes | | impersonate\_service\_account | Service account email of the account to impersonate to run Terraform | `string` | n/a | yes | @@ -19,7 +20,6 @@ | project\_prefix | Name prefix to use for projects created. | `string` | `"prj"` | no | | project\_suffix | The name of the GCP project. Max 16 characters with 3 character business unit code. | `string` | n/a | yes | | secondary\_contact | The secondary email contact for the project | `string` | `""` | no | -| skip\_gcloud\_download | Whether to skip downloading gcloud (assumes gcloud is already available outside the module) | `bool` | `true` | no | | vpc\_service\_control\_attach\_enabled | Whether the project will be attached to a VPC Service Control Perimeter | `bool` | `false` | no | | vpc\_service\_control\_perimeter\_name | The name of a VPC Service Control Perimeter to add the created project to | `string` | `null` | no | | vpc\_type | The type of VPC to attach the project to. Possible options are base or restricted. | `string` | `""` | no | diff --git a/4-projects/modules/single_project/data.tf b/4-projects/modules/single_project/data.tf index d6074512b..18c0b4d86 100644 --- a/4-projects/modules/single_project/data.tf +++ b/4-projects/modules/single_project/data.tf @@ -21,6 +21,6 @@ data "google_projects" "projects" { data "google_compute_network" "shared_vpc" { count = var.vpc_type == "" ? 0 : 1 - name = "vpc-${local.env_code}-shared-${var.vpc_type}" + name = "vpc-${local.env_code}-shared-${var.vpc_type}${local.shared_vpc_mode}" project = data.google_projects.projects[0].projects[0].project_id } diff --git a/4-projects/modules/single_project/main.tf b/4-projects/modules/single_project/main.tf index 8a65c4fbb..0eca50957 100644 --- a/4-projects/modules/single_project/main.tf +++ b/4-projects/modules/single_project/main.tf @@ -15,12 +15,13 @@ */ locals { - env_code = element(split("", var.environment), 0) + env_code = element(split("", var.environment), 0) + shared_vpc_mode = var.enable_hub_and_spoke ? "-spoke" : "" } module "project" { source = "terraform-google-modules/project-factory/google" - version = "~> 9.2" + version = "~> 10.0" random_project_id = "true" impersonate_service_account = var.impersonate_service_account activate_apis = distinct(concat(var.activate_apis, ["billingbudgets.googleapis.com"])) @@ -28,10 +29,9 @@ module "project" { org_id = var.org_id billing_account = var.billing_account folder_id = var.folder_id - skip_gcloud_download = var.skip_gcloud_download - shared_vpc = var.vpc_type == "" ? "" : data.google_compute_network.shared_vpc[0].project - shared_vpc_subnets = var.vpc_type == "" ? [] : data.google_compute_network.shared_vpc[0].subnetworks_self_links # Optional: To enable subnetting, to replace to "module.networking_project.subnetwork_self_link" + svpc_host_project_id = var.vpc_type == "" ? "" : data.google_compute_network.shared_vpc[0].project + shared_vpc_subnets = var.vpc_type == "" ? [] : data.google_compute_network.shared_vpc[0].subnetworks_self_links # Optional: To enable subnetting, to replace to "module.networking_project.subnetwork_self_link" vpc_service_control_attach_enabled = var.vpc_service_control_attach_enabled vpc_service_control_perimeter_name = var.vpc_service_control_perimeter_name diff --git a/4-projects/modules/single_project/variables.tf b/4-projects/modules/single_project/variables.tf index be5a51b19..6c5056e2f 100644 --- a/4-projects/modules/single_project/variables.tf +++ b/4-projects/modules/single_project/variables.tf @@ -83,12 +83,6 @@ variable "vpc_type" { default = "" } -variable "skip_gcloud_download" { - description = "Whether to skip downloading gcloud (assumes gcloud is already available outside the module)" - type = bool - default = true -} - variable "vpc_service_control_attach_enabled" { description = "Whether the project will be attached to a VPC Service Control Perimeter" type = bool @@ -124,3 +118,9 @@ variable "project_prefix" { type = string default = "prj" } + +variable "enable_hub_and_spoke" { + description = "Enable Hub-and-Spoke architecture." + type = bool + default = false +} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8627df7de..be157886a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -36,7 +36,7 @@ Six test-kitchen instances are defined and should be executed in serial order: - `bootstrap` - `org` - `envs` -- `dns-hub` +- `shared` - `networks` - `projects` diff --git a/build/int.cloudbuild.yaml b/build/int.cloudbuild.yaml index af3e451fb..97a4c11c9 100644 --- a/build/int.cloudbuild.yaml +++ b/build/int.cloudbuild.yaml @@ -21,6 +21,9 @@ steps: - 'TF_VAR_folder_id=$_FOLDER_ID' - 'TF_VAR_billing_account=$_BILLING_ACCOUNT' - 'TF_VAR_group_email=test-gcp-org-admins@test.infra.cft.tips' +- id: prepare-network-hub-and-spoke-config + 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 && ./test/network_test_prepare.sh -p'] - id: create 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 && kitchen_do create'] @@ -48,15 +51,15 @@ steps: - id: verify-envs 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 && kitchen_do verify envs-default'] -- id: create-dns-hub +- id: create-shared 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 && kitchen_do create dns-hub-default'] -- id: converge-dns-hub + args: ['/bin/bash', '-c', 'source /usr/local/bin/task_helper_functions.sh && kitchen_do create shared-default'] +- id: converge-shared 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 && kitchen_do converge dns-hub-default'] -- id: verify-dns-hub + args: ['/bin/bash', '-c', 'source /usr/local/bin/task_helper_functions.sh && export TF_VAR_policy_id=$(gcloud access-context-manager policies list --organization="${TF_VAR_org_id:?}" --format="value(name)") && kitchen_do converge shared-default'] +- id: verify-shared 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 && kitchen_do verify dns-hub-default'] + args: ['/bin/bash', '-c', 'source /usr/local/bin/task_helper_functions.sh && kitchen_do verify shared-default'] - id: create-networks 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 && kitchen_do create networks-default'] @@ -81,9 +84,9 @@ steps: - id: destroy-networks 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 && export TF_VAR_policy_id=$(gcloud access-context-manager policies list --organization="${TF_VAR_org_id:?}" --format="value(name)") && kitchen_do destroy networks-default'] -- id: destroy-dns-hub +- id: destroy-shared 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 && kitchen_do destroy dns-hub-default'] + args: ['/bin/bash', '-c', 'source /usr/local/bin/task_helper_functions.sh && export TF_VAR_policy_id=$(gcloud access-context-manager policies list --organization="${TF_VAR_org_id:?}" --format="value(name)") && kitchen_do destroy shared-default'] - id: destroy-envs 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 && kitchen_do destroy envs-default'] diff --git a/test/fixtures/envs/outputs.tf b/test/fixtures/envs/outputs.tf index ff75bc5ee..592d3124d 100644 --- a/test/fixtures/envs/outputs.tf +++ b/test/fixtures/envs/outputs.tf @@ -30,17 +30,17 @@ output "dev_monitoring_project_id" { } output "dev_base_shared_vpc_project_id" { - description = "Development project for monitoring infra." + description = "Development project for base shared VPC." value = module.development.base_shared_vpc_project_id } output "dev_restricted_shared_vpc_project_id" { - description = "Development project for monitoring infra." + description = "Development project for restricted shared VPC." value = module.development.restricted_shared_vpc_project_id } output "dev_env_secrets_project_id" { - description = "Development project for monitoring infra." + description = "Development project for environment secrets." value = module.development.env_secrets_project_id } @@ -55,17 +55,17 @@ output "nonprod_monitoring_project_id" { } output "nonprod_base_shared_vpc_project_id" { - description = "Non-production project for monitoring infra." + description = "Non-production project for base shared VPC." value = module.non-production.base_shared_vpc_project_id } output "nonprod_restricted_shared_vpc_project_id" { - description = "Non-production project for monitoring infra." + description = "Non-production project for restricted shared VPC." value = module.non-production.restricted_shared_vpc_project_id } output "nonprod_env_secrets_project_id" { - description = "Non-production project for monitoring infra." + description = "Non-production project for environment secrets." value = module.non-production.env_secrets_project_id } @@ -80,16 +80,16 @@ output "prod_monitoring_project_id" { } output "prod_base_shared_vpc_project_id" { - description = "Production project for monitoring infra." + description = "Production project for base shared VPC." value = module.production.base_shared_vpc_project_id } output "prod_restricted_shared_vpc_project_id" { - description = "Production project for monitoring infra." + description = "Production project for restricted shared VPC." value = module.production.restricted_shared_vpc_project_id } output "prod_env_secrets_project_id" { - description = "Production project for monitoring infra." + description = "Production project for environment secrets." value = module.production.env_secrets_project_id } diff --git a/test/fixtures/networks/main.tf b/test/fixtures/networks/main.tf index 5dc090705..3f7546b93 100644 --- a/test/fixtures/networks/main.tf +++ b/test/fixtures/networks/main.tf @@ -23,6 +23,7 @@ module "development" { domain = var.domain terraform_service_account = var.terraform_sa_email parent_folder = var.parent_folder + enable_hub_and_spoke = var.enable_hub_and_spoke } module "non-production" { @@ -34,6 +35,8 @@ module "non-production" { domain = var.domain terraform_service_account = var.terraform_sa_email parent_folder = var.parent_folder + enable_hub_and_spoke = var.enable_hub_and_spoke + depends_on = [module.development] } module "production" { @@ -45,4 +48,6 @@ module "production" { domain = var.domain terraform_service_account = var.terraform_sa_email parent_folder = var.parent_folder + enable_hub_and_spoke = var.enable_hub_and_spoke + depends_on = [module.non-production] } diff --git a/test/fixtures/networks/outputs.tf b/test/fixtures/networks/outputs.tf index e698d4f3b..9246367df 100644 --- a/test/fixtures/networks/outputs.tf +++ b/test/fixtures/networks/outputs.tf @@ -19,6 +19,11 @@ output "access_context_manager_policy_id" { value = var.policy_id } +output "enable_hub_and_spoke" { + description = "Hub and Spoke enabled." + value = var.enable_hub_and_spoke +} + /****************************************** Development Outputs *****************************************/ diff --git a/test/fixtures/networks/variables.tf b/test/fixtures/networks/variables.tf index 0f6b6cd79..428b1254a 100644 --- a/test/fixtures/networks/variables.tf +++ b/test/fixtures/networks/variables.tf @@ -22,6 +22,11 @@ variable "terraform_sa_email" { description = "The SA that will be used for creating projects." } +# used by provider configs copied by /test/network_test_prepare.sh +variable "terraform_service_account" { + description = "The SA that will be used for creating projects." +} + variable "policy_id" { type = number description = "The id of the default Access Context Manager policy created in step `1-org`. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR-ORGANIZATION_ID --format=\"value(name)\"`." @@ -37,3 +42,9 @@ variable "parent_folder" { type = string default = "" } + +variable "enable_hub_and_spoke" { + description = "Enable Hub-and-Spoke architecture." + type = bool + default = false +} diff --git a/test/fixtures/org/main.tf b/test/fixtures/org/main.tf index a06d803b3..8b8b31d02 100644 --- a/test/fixtures/org/main.tf +++ b/test/fixtures/org/main.tf @@ -35,5 +35,5 @@ module "test" { log_export_storage_force_destroy = true enable_os_login_policy = true project_prefix = var.project_prefix - hub_and_spoke = var.hub_and_spoke + enable_hub_and_spoke = var.enable_hub_and_spoke } diff --git a/test/fixtures/org/outputs.tf b/test/fixtures/org/outputs.tf index 3c92cb156..895f5ff12 100644 --- a/test/fixtures/org/outputs.tf +++ b/test/fixtures/org/outputs.tf @@ -94,7 +94,7 @@ output "logs_export_storage_bucket_name" { description = "The storage bucket for destination of log exports" } -output "hub_and_spoke" { - value = var.hub_and_spoke +output "enable_hub_and_spoke" { + value = var.enable_hub_and_spoke description = "Hub-and-Spoke architecture enabled" } diff --git a/test/fixtures/org/variables.tf b/test/fixtures/org/variables.tf index 107c6858d..5c11fc086 100644 --- a/test/fixtures/org/variables.tf +++ b/test/fixtures/org/variables.tf @@ -43,7 +43,7 @@ variable "project_prefix" { type = string } -variable "hub_and_spoke" { +variable "enable_hub_and_spoke" { description = "Enable Hub-and-Spoke architecture." type = bool } diff --git a/test/fixtures/projects/main.tf b/test/fixtures/projects/main.tf index 2009337d3..6550829ce 100644 --- a/test/fixtures/projects/main.tf +++ b/test/fixtures/projects/main.tf @@ -15,7 +15,7 @@ */ module "projects_bu1_dev" { - source = "../../../4-projects/business_unit_1//development" + source = "../../../4-projects/business_unit_1/development" terraform_service_account = var.terraform_sa_email org_id = var.org_id billing_account = var.billing_account @@ -23,10 +23,11 @@ module "projects_bu1_dev" { parent_folder = var.parent_folder perimeter_name = var.dev_restricted_service_perimeter_name project_prefix = var.project_prefix + enable_hub_and_spoke = var.enable_hub_and_spoke } module "projects_bu1_nonprod" { - source = "../../../4-projects/business_unit_1//non-production" + source = "../../../4-projects/business_unit_1/non-production" terraform_service_account = var.terraform_sa_email org_id = var.org_id billing_account = var.billing_account @@ -34,6 +35,7 @@ module "projects_bu1_nonprod" { parent_folder = var.parent_folder perimeter_name = var.nonprod_restricted_service_perimeter_name project_prefix = var.project_prefix + enable_hub_and_spoke = var.enable_hub_and_spoke } @@ -46,6 +48,7 @@ module "projects_bu1_prod" { parent_folder = var.parent_folder perimeter_name = var.prod_restricted_service_perimeter_name project_prefix = var.project_prefix + enable_hub_and_spoke = var.enable_hub_and_spoke } module "projects_bu2_dev" { @@ -58,6 +61,7 @@ module "projects_bu2_dev" { perimeter_name = var.dev_restricted_service_perimeter_name peering_module_depends_on = [module.projects_bu1_dev.peering_complete] project_prefix = var.project_prefix + enable_hub_and_spoke = var.enable_hub_and_spoke } module "projects_bu2_nonprod" { @@ -70,6 +74,7 @@ module "projects_bu2_nonprod" { perimeter_name = var.nonprod_restricted_service_perimeter_name peering_module_depends_on = [module.projects_bu1_nonprod.peering_complete] project_prefix = var.project_prefix + enable_hub_and_spoke = var.enable_hub_and_spoke } @@ -83,4 +88,5 @@ module "projects_bu2_prod" { perimeter_name = var.prod_restricted_service_perimeter_name peering_module_depends_on = [module.projects_bu1_prod.peering_complete] project_prefix = var.project_prefix + enable_hub_and_spoke = var.enable_hub_and_spoke } diff --git a/test/fixtures/projects/outputs.tf b/test/fixtures/projects/outputs.tf index 47387bb1a..081fb4070 100644 --- a/test/fixtures/projects/outputs.tf +++ b/test/fixtures/projects/outputs.tf @@ -258,3 +258,8 @@ output "access_context_manager_policy_id" { description = "Access Context Manager Policy ID." value = var.policy_id } + +output "enable_hub_and_spoke" { + description = "Hub and Spoke enabled." + value = var.enable_hub_and_spoke +} diff --git a/test/fixtures/projects/variables.tf b/test/fixtures/projects/variables.tf index 0514b9006..58bdc1fd9 100644 --- a/test/fixtures/projects/variables.tf +++ b/test/fixtures/projects/variables.tf @@ -59,3 +59,9 @@ variable "project_prefix" { description = "Name prefix to use for projects created." type = string } + +variable "enable_hub_and_spoke" { + description = "Enable Hub-and-Spoke architecture." + type = bool + default = false +} diff --git a/test/fixtures/dns_hub/main.tf b/test/fixtures/shared/main.tf similarity index 50% rename from test/fixtures/dns_hub/main.tf rename to test/fixtures/shared/main.tf index 629fc413d..6100512b9 100644 --- a/test/fixtures/dns_hub/main.tf +++ b/test/fixtures/shared/main.tf @@ -14,13 +14,15 @@ * limitations under the License. */ -module "dns_hub" { - source = "../../../3-networks/envs/shared" - default_region1 = "us-central1" - default_region2 = "us-west1" - domain = var.domain - target_name_server_addresses = ["192.168.0.1", "192.168.0.2"] - terraform_service_account = var.terraform_sa_email - parent_folder = var.parent_folder - org_id = var.org_id +module "shared" { + source = "../../../3-networks/envs/shared" + default_region1 = "us-central1" + default_region2 = "us-west1" + domain = var.domain + access_context_manager_policy_id = var.policy_id + target_name_server_addresses = ["192.168.0.1", "192.168.0.2"] + terraform_service_account = var.terraform_sa_email + parent_folder = var.parent_folder + enable_hub_and_spoke = var.enable_hub_and_spoke + org_id = var.org_id } diff --git a/test/fixtures/dns_hub/outputs.tf b/test/fixtures/shared/outputs.tf similarity index 93% rename from test/fixtures/dns_hub/outputs.tf rename to test/fixtures/shared/outputs.tf index 82c52b232..330018690 100644 --- a/test/fixtures/dns_hub/outputs.tf +++ b/test/fixtures/shared/outputs.tf @@ -15,6 +15,6 @@ */ output "dns_hub_project_id" { - value = module.dns_hub.dns_hub_project_id + value = module.shared.dns_hub_project_id description = "The DNS hub project ID" } diff --git a/test/fixtures/dns_hub/variables.tf b/test/fixtures/shared/variables.tf similarity index 71% rename from test/fixtures/dns_hub/variables.tf rename to test/fixtures/shared/variables.tf index 97e982d64..eb294fbf8 100644 --- a/test/fixtures/dns_hub/variables.tf +++ b/test/fixtures/shared/variables.tf @@ -33,3 +33,14 @@ variable "parent_folder" { type = string default = "" } + +variable "policy_id" { + type = number + description = "The id of the default Access Context Manager policy created in step `1-org`. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR-ORGANIZATION_ID --format=\"value(name)\"`." +} + +variable "enable_hub_and_spoke" { + description = "Enable Hub-and-Spoke architecture." + type = bool + default = false +} diff --git a/test/integration/networks/controls/gcloud_networks.rb b/test/integration/networks/controls/gcloud_networks.rb index 22d7a3dc2..b8aae94e6 100644 --- a/test/integration/networks/controls/gcloud_networks.rb +++ b/test/integration/networks/controls/gcloud_networks.rb @@ -14,6 +14,8 @@ acm_policy_name = attribute('access_context_manager_policy_id') +enable_hub_and_spoke = attribute('enable_hub_and_spoke') + dev_restricted_access_level_name = attribute('dev_restricted_access_level_name') nonprod_restricted_access_level_name = attribute('nonprod_restricted_access_level_name') prod_restricted_access_level_name = attribute('prod_restricted_access_level_name') @@ -62,7 +64,7 @@ access_levels = ["accessPolicies/#{acm_policy_name}/accessLevels/#{access_level_names[environment_code]}"] types.each do |type| - vpc_name = "#{environment_code}-shared-#{type}" + vpc_name = enable_hub_and_spoke ? "#{environment_code}-shared-#{type}-spoke" : "#{environment_code}-shared-#{type}" network_name = "vpc-#{vpc_name}" dns_hub_network_url = "https://www.googleapis.com/compute/v1/projects/#{projects_id[environment_code][type]}/global/networks/#{network_name}" diff --git a/test/integration/networks/controls/gcp_networks.rb b/test/integration/networks/controls/gcp_networks.rb index 17aa6570d..47ef2eca5 100644 --- a/test/integration/networks/controls/gcp_networks.rb +++ b/test/integration/networks/controls/gcp_networks.rb @@ -12,6 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +enable_hub_and_spoke = attribute('enable_hub_and_spoke') + restricted_dev_project_id = attribute('dev_restricted_host_project_id') restricted_nonprod_project_id = attribute('nonprod_restricted_host_project_id') restricted_prod_project_id = attribute('prod_restricted_host_project_id') @@ -48,7 +50,7 @@ environment_codes.each do |environment_code| types.each do |type| - vpc_name = "#{environment_code}-shared-#{type}" + vpc_name = enable_hub_and_spoke ? "#{environment_code}-shared-#{type}-spoke" : "#{environment_code}-shared-#{type}" network_name = "vpc-#{vpc_name}" global_address = "ga-#{vpc_name}-vpc-peering-internal" @@ -133,54 +135,6 @@ its('ip_cidr_range') { should eq cidr_ranges[environment_code][type][1] } end - describe google_compute_router( - project: projects_id[environment_code][type], - region: default_region1, - name: region1_router1 - ) do - it { should exist } - its('bgp.asn') { should eq bgp_asn_subnet } - its('bgp.advertised_ip_ranges.first.range') { should eq googleapis_cidr[type] } - its('bgp.advertised_ip_ranges.last.range') { should eq googleapis_cidr[type] } - its('network') { should match(%r{/#{network_name}$}) } - end - - describe google_compute_router( - project: projects_id[environment_code][type], - region: default_region1, - name: region1_router2 - ) do - it { should exist } - its('bgp.asn') { should eq bgp_asn_subnet } - its('bgp.advertised_ip_ranges.first.range') { should eq googleapis_cidr[type] } - its('bgp.advertised_ip_ranges.last.range') { should eq googleapis_cidr[type] } - its('network') { should match(%r{/#{network_name}$}) } - end - - describe google_compute_router( - project: projects_id[environment_code][type], - region: default_region2, - name: region2_router1 - ) do - it { should exist } - its('bgp.asn') { should eq bgp_asn_subnet } - its('bgp.advertised_ip_ranges.first.range') { should eq googleapis_cidr[type] } - its('bgp.advertised_ip_ranges.last.range') { should eq googleapis_cidr[type] } - its('network') { should match(%r{/#{network_name}$}) } - end - - describe google_compute_router( - project: projects_id[environment_code][type], - region: default_region2, - name: region2_router2 - ) do - it { should exist } - its('bgp.asn') { should eq bgp_asn_subnet } - its('bgp.advertised_ip_ranges.first.range') { should eq googleapis_cidr[type] } - its('bgp.advertised_ip_ranges.last.range') { should eq googleapis_cidr[type] } - its('network') { should match(%r{/#{network_name}$}) } - end - describe google_compute_firewall( project: projects_id[environment_code][type], name: fw_deny_all_egress @@ -209,6 +163,56 @@ ) end end + + unless enable_hub_and_spoke + describe google_compute_router( + project: projects_id[environment_code][type], + region: default_region1, + name: region1_router1 + ) do + it { should exist } + its('bgp.asn') { should eq bgp_asn_subnet } + its('bgp.advertised_ip_ranges.first.range') { should eq googleapis_cidr[type] } + its('bgp.advertised_ip_ranges.last.range') { should eq googleapis_cidr[type] } + its('network') { should match(%r{/#{network_name}$}) } + end + + describe google_compute_router( + project: projects_id[environment_code][type], + region: default_region1, + name: region1_router2 + ) do + it { should exist } + its('bgp.asn') { should eq bgp_asn_subnet } + its('bgp.advertised_ip_ranges.first.range') { should eq googleapis_cidr[type] } + its('bgp.advertised_ip_ranges.last.range') { should eq googleapis_cidr[type] } + its('network') { should match(%r{/#{network_name}$}) } + end + + describe google_compute_router( + project: projects_id[environment_code][type], + region: default_region2, + name: region2_router1 + ) do + it { should exist } + its('bgp.asn') { should eq bgp_asn_subnet } + its('bgp.advertised_ip_ranges.first.range') { should eq googleapis_cidr[type] } + its('bgp.advertised_ip_ranges.last.range') { should eq googleapis_cidr[type] } + its('network') { should match(%r{/#{network_name}$}) } + end + + describe google_compute_router( + project: projects_id[environment_code][type], + region: default_region2, + name: region2_router2 + ) do + it { should exist } + its('bgp.asn') { should eq bgp_asn_subnet } + its('bgp.advertised_ip_ranges.first.range') { should eq googleapis_cidr[type] } + its('bgp.advertised_ip_ranges.last.range') { should eq googleapis_cidr[type] } + its('network') { should match(%r{/#{network_name}$}) } + end + end end end end diff --git a/test/integration/networks/inspec.yml b/test/integration/networks/inspec.yml index 2cdc75472..0ec5e3bf0 100644 --- a/test/integration/networks/inspec.yml +++ b/test/integration/networks/inspec.yml @@ -43,3 +43,6 @@ attributes: - name: prod_base_host_project_id required: true type: string + - name: enable_hub_and_spoke + required: true + type: boolean diff --git a/test/integration/org/controls/gcp_projects.rb b/test/integration/org/controls/gcp_projects.rb index e9cd28cce..bdb0a17b8 100644 --- a/test/integration/org/controls/gcp_projects.rb +++ b/test/integration/org/controls/gcp_projects.rb @@ -21,7 +21,7 @@ dns_hub_project_id = attribute('dns_hub_project_id') base_net_hub_project_id = attribute('base_net_hub_project_id') restricted_net_hub_project_id = attribute('restricted_net_hub_project_id') -hub_and_spoke = attribute('hub_and_spoke') +enable_hub_and_spoke = attribute('enable_hub_and_spoke') dns_hub_apis = [ @@ -92,7 +92,7 @@ its('lifecycle_state') { should cmp 'ACTIVE' } end - if hub_and_spoke + if enable_hub_and_spoke describe google_project(project: base_net_hub_project_id) do it { should exist } its('project_id') { should cmp base_net_hub_project_id } diff --git a/test/integration/org/inspec.yml b/test/integration/org/inspec.yml index 894feb19e..ac890be34 100644 --- a/test/integration/org/inspec.yml +++ b/test/integration/org/inspec.yml @@ -38,7 +38,7 @@ attributes: type: string - name: restricted_net_hub_project_id required: true - - name: hub_and_spoke + - name: enable_hub_and_spoke required: true type: boolean - name: parent_resource_id diff --git a/test/integration/projects/controls/gcloud_projects.rb b/test/integration/projects/controls/gcloud_projects.rb index 28b81736a..7e940003f 100644 --- a/test/integration/projects/controls/gcloud_projects.rb +++ b/test/integration/projects/controls/gcloud_projects.rb @@ -12,6 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +enable_hub_and_spoke = attribute('enable_hub_and_spoke') + dev_bu1_project_base = attribute('dev_bu1_project_base') dev_bu1_project_floating = attribute('dev_bu1_project_floating') dev_bu1_project_peering = attribute('dev_bu1_project_peering') @@ -59,6 +61,8 @@ access_context_manager_policy_id = attribute('access_context_manager_policy_id') +shared_vpc_mode = enable_hub_and_spoke ? "-spoke" : "" + environment_codes = %w[d n p] environment_name = { @@ -165,8 +169,8 @@ expect JSON.parse(command("gcloud projects describe #{data['name']} --format=json").stdout)['labels']['environment'].should eq environment_name[environment_code] end - it "is attached to the VPC with name equals to vpc-#{environment_code}-shared-restricted" do - expect JSON.parse(command("gcloud compute networks list --project #{data['name']} --format=json").stdout)[0]['name'].should eq "vpc-#{environment_code}-shared-restricted" + it "is attached to the VPC with name equals to vpc-#{environment_code}-shared-restricted#{shared_vpc_mode}" do + expect JSON.parse(command("gcloud compute networks list --project #{data['name']} --format=json").stdout)[0]['name'].should eq "vpc-#{environment_code}-shared-restricted#{shared_vpc_mode}" end end end @@ -196,8 +200,8 @@ expect JSON.parse(command("gcloud projects describe #{data['name']} --format=json").stdout)['labels']['environment'].should eq environment_name[environment_code] end - it "is attached to the VPC with name equals to vpc-#{environment_code}-shared-base" do - expect JSON.parse(command("gcloud compute networks list --project #{data['name']} --format=json").stdout)[0]['name'].should eq "vpc-#{environment_code}-shared-base" + it "is attached to the VPC with name equals to vpc-#{environment_code}-shared-base#{shared_vpc_mode}" do + expect JSON.parse(command("gcloud compute networks list --project #{data['name']} --format=json").stdout)[0]['name'].should eq "vpc-#{environment_code}-shared-base#{shared_vpc_mode}" end end end diff --git a/test/integration/projects/inspec.yml b/test/integration/projects/inspec.yml index 04d098e6d..dfab6cb69 100644 --- a/test/integration/projects/inspec.yml +++ b/test/integration/projects/inspec.yml @@ -156,3 +156,6 @@ attributes: - name: prod_bu2_restricted_enabled_apis type: array required: true + - name: enable_hub_and_spoke + required: true + type: boolean diff --git a/test/integration/dns_hub/controls/gcloud_dns_hub.rb b/test/integration/shared/controls/gcloud_dns_hub.rb similarity index 100% rename from test/integration/dns_hub/controls/gcloud_dns_hub.rb rename to test/integration/shared/controls/gcloud_dns_hub.rb diff --git a/test/integration/dns_hub/controls/gcp_dns_hub.rb b/test/integration/shared/controls/gcp_dns_hub.rb similarity index 100% rename from test/integration/dns_hub/controls/gcp_dns_hub.rb rename to test/integration/shared/controls/gcp_dns_hub.rb diff --git a/test/integration/dns_hub/inspec.yml b/test/integration/shared/inspec.yml similarity index 100% rename from test/integration/dns_hub/inspec.yml rename to test/integration/shared/inspec.yml diff --git a/test/network_test_prepare.sh b/test/network_test_prepare.sh new file mode 100755 index 000000000..98a42620c --- /dev/null +++ b/test/network_test_prepare.sh @@ -0,0 +1,76 @@ +#!/usr/bin/env bash + +# 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. + +set -e + +function compare(){ +config1=$1 +config2=$2 +if cmp -s "$config1" "$config2"; then + echo "${config1} and ${config2} are the same" +else + echo "${config1} and ${config2} differ" + exit 1 +fi +} + +function prepare(){ + # assert provider.tf in network envs are same + compare 3-networks/envs/development/providers.tf 3-networks/envs/non-production/providers.tf + compare 3-networks/envs/non-production/providers.tf 3-networks/envs/production/providers.tf + + # copy one config to network fixture + cp 3-networks/envs/development/providers.tf test/fixtures/networks/providers.tf + + # disable provider configs in main module + mv 3-networks/envs/development/providers.tf 3-networks/envs/development/providers.tf.disabled + mv 3-networks/envs/non-production/providers.tf 3-networks/envs/non-production/providers.tf.disabled + mv 3-networks/envs/production/providers.tf 3-networks/envs/production/providers.tf.disabled + + # email fix, we need to add `terraform_service_account` as a var within test/fixtures/networks/variables.tf as network provider.tf uses this. + # Using the same value exported by setup + # shellcheck disable=SC2154 + export TF_VAR_terraform_service_account=$TF_VAR_terraform_sa_email +} + +function restore(){ + # remove test provider config + rm -rf test/fixtures/networks/providers.tf + # replace original provider config + # disable provider configs in main module + mv 3-networks/envs/development/providers.tf.disabled 3-networks/envs/development/providers.tf + mv 3-networks/envs/non-production/providers.tf.disabled 3-networks/envs/non-production/providers.tf + mv 3-networks/envs/production/providers.tf.disabled 3-networks/envs/production/providers.tf +} + + +# parse args +for arg in "$@" +do + case $arg in + -p|--prepare) + prepare + shift + ;; + -r|--restore) + restore + shift + ;; + *) # end argument parsing + shift + ;; + esac +done diff --git a/test/setup/main.tf b/test/setup/main.tf index 1313f27ac..6a4aaeb22 100644 --- a/test/setup/main.tf +++ b/test/setup/main.tf @@ -25,14 +25,13 @@ resource "google_folder" "test_folder" { module "project" { source = "terraform-google-modules/project-factory/google" - version = "~> 9.2" + version = "~> 10.0" - name = "ci-foundation" - random_project_id = true - org_id = var.org_id - folder_id = var.folder_id - billing_account = var.billing_account - skip_gcloud_download = true + name = "ci-foundation" + random_project_id = true + org_id = var.org_id + folder_id = var.folder_id + billing_account = var.billing_account activate_apis = [ "cloudresourcemanager.googleapis.com", diff --git a/test/setup/outputs.tf b/test/setup/outputs.tf index 377c1e6ff..c8495c902 100644 --- a/test/setup/outputs.tf +++ b/test/setup/outputs.tf @@ -33,6 +33,10 @@ output "terraform_sa_email" { value = google_service_account.int_test.email } +output "terraform_service_account" { + value = google_service_account.int_test.email +} + output "org_project_creators" { value = ["serviceAccount:${google_service_account.int_test.email}"] } @@ -49,6 +53,6 @@ output "group_email" { value = var.group_email } -output "hub_and_spoke" { +output "enable_hub_and_spoke" { value = var.example_foundations_mode == "HubAndSpoke" ? "true" : "false" }
0.5,
0.75,
0.9,
0.95
]