From 512430b1982d89834d9c05a8fab1536ead39f3a7 Mon Sep 17 00:00:00 2001
From: Mauro Santos <103214014+mauro-cit@users.noreply.github.com>
Date: Wed, 6 Jul 2022 12:11:43 -0300
Subject: [PATCH] feat!: split network step (#735)
* adding copy of 3-network folder for hub-and-spoke definition
* Removing unnecessary hub-and-spoke setup on 3-networks step
* Adding script to undo the disable_tf_files.sh removal
* adding 3-networks-hub-and-spoke directory to scripts disable/restore
* Adding 3-networks-hub-and-spoke/shared to disable/restore scripts
* Adding hub-and-spoke IT for networks and shared test folders
* Adding conditional for specific netwotk folder based on environment mode
* adjusting 3-networks-hub-and-spoke to only contain this topology
* Removing unnecessary additional test files
* Adjusting projects test to hit the specific networks folder
* Renaming 3-networks to 3-networks-dual-svpc
* Making the scripts sensitive to the TF_VAR_example_foundations_mode env
* Removing hub and spoke references
* Adjusting hub-and-spoke .tf setup
* generate docs
* Updating readme with new folders
* Internal review issues changes
* Cherry pick from "Feature/private service connect module"
* Lint fixes
* Internal PR small issues
* Adding missing tfvars file for environments on new networks folders
* Updating network version of the modules in advance to merge conflict
* Removing unnecessary transitivity module and adjusting some readme details
* "network architecture" description updated on readme
* Removing some unnecessary conditional flow from hub and spoke
* Resolving the conflicts from master
* Corrections after generate docs and lint
* FIxing some more lint issues
* Fixing wrong conditional removes
* Generate docs fix
* putting enable HS transitivity back
---
0-bootstrap/README.md | 11 +-
1-org/README.md | 9 +-
2-environments/README.md | 11 +-
.../.gitignore | 0
.../README.md | 30 +-
.../access_context.auto.example.tfvars | 0
.../common.auto.example.tfvars | 27 ++
.../envs/development/README.md | 46 +++
.../development/access_context.auto.tfvars | 0
.../envs/development/backend.tf | 0
.../envs/development/common.auto.tfvars | 0
3-networks-dual-svpc/envs/development/main.tf | 84 +++++
.../envs/development/outputs.tf | 0
.../envs/development/providers.tf | 0
.../envs/development/variables.tf | 47 +++
.../envs/development/versions.tf | 0
.../envs/non-production/README.md | 46 +++
.../non-production/access_context.auto.tfvars | 0
.../envs/non-production/backend.tf | 0
.../envs/non-production/common.auto.tfvars | 0
.../envs/non-production/main.tf | 83 +++++
.../envs/non-production/outputs.tf | 0
.../envs/non-production/providers.tf | 0
.../envs/non-production/variables.tf | 48 +++
.../envs/non-production/versions.tf | 0
.../envs/production/README.md | 46 +++
.../production/access_context.auto.tfvars | 0
.../envs/production/backend.tf | 0
.../envs/production/common.auto.tfvars | 0
3-networks-dual-svpc/envs/production/main.tf | 83 +++++
.../envs/production/outputs.tf | 0
.../envs/production/providers.tf | 0
.../envs/production/variables.tf | 47 +++
.../envs/production/versions.tf | 0
3-networks-dual-svpc/envs/shared/README.md | 50 +++
.../envs/shared/access_context.auto.tfvars | 0
.../envs/shared/backend.tf | 0
.../envs/shared/common.auto.tfvars | 0
.../envs/shared/dns-hub.tf | 0
.../envs/shared/hierarchical_firewall.tf | 0
.../shared/interconnect.auto.tfvars.example | 0
.../envs/shared/interconnect.tf.example | 0
.../envs/shared/main.tf | 0
.../envs/shared/outputs.tf | 0
.../shared/partner_interconnect.tf.example | 2 -
.../envs/shared/providers.tf | 0
.../envs/shared/shared.auto.tfvars | 0
3-networks-dual-svpc/envs/shared/variables.tf | 178 ++++++++++
.../envs/shared/versions.tf | 0
.../modules/base_env/README.md | 45 +++
.../modules/base_env/interconnect.tf.example | 0
3-networks-dual-svpc/modules/base_env/main.tf | 139 ++++++++
.../modules/base_env/outputs.tf | 0
.../base_env/partner_interconnect.tf.example | 2 -
.../modules/base_env/variables.tf | 103 ++++++
.../modules/base_env/versions.tf | 0
.../modules/base_env/vpn.tf.example | 0
.../modules/base_shared_vpc/README.md | 1 -
.../modules/base_shared_vpc/data.tf | 0
.../modules/base_shared_vpc/dns.tf | 0
.../modules/base_shared_vpc/firewall.tf | 0
.../modules/base_shared_vpc/main.tf | 146 ++++++++
.../modules/base_shared_vpc/nat.tf | 0
.../modules/base_shared_vpc/outputs.tf | 0
.../private_service_connect.tf | 0
.../modules/base_shared_vpc/variables.tf | 144 ++++++++
.../modules/base_shared_vpc/versions.tf | 0
.../modules/dedicated_interconnect/README.md | 2 +-
.../modules/dedicated_interconnect/main.tf | 0
.../modules/dedicated_interconnect/outputs.tf | 0
.../dedicated_interconnect/variables.tf | 0
.../dedicated_interconnect/versions.tf | 0
.../hierarchical_firewall_policy/README.md | 0
.../hierarchical_firewall_policy/main.tf | 0
.../hierarchical_firewall_policy/outputs.tf | 0
.../hierarchical_firewall_policy/variables.tf | 0
.../hierarchical_firewall_policy/versions.tf | 0
.../modules/partner_interconnect/README.md | 5 +-
.../modules/partner_interconnect/main.tf | 4 +-
.../modules/partner_interconnect/outputs.tf | 0
.../modules/partner_interconnect/variables.tf | 7 -
.../modules/partner_interconnect/versions.tf | 0
.../modules/private_service_connect/dns.tf | 0
.../modules/private_service_connect/main.tf | 0
.../private_service_connect/outputs.tf | 0
.../private_service_connect/variables.tf | 0
.../private_service_connect/versions.tf | 0
.../modules/restricted_shared_vpc/README.md | 1 -
.../modules/restricted_shared_vpc/data.tf | 0
.../modules/restricted_shared_vpc/dns.tf | 0
.../modules/restricted_shared_vpc/firewall.tf | 0
.../modules/restricted_shared_vpc/main.tf | 148 ++++++++
.../modules/restricted_shared_vpc/nat.tf | 0
.../modules/restricted_shared_vpc/outputs.tf | 0
.../private_service_connect.tf | 0
.../restricted_shared_vpc/service_control.tf | 57 ++++
.../restricted_shared_vpc/variables.tf | 158 +++++++++
.../modules/restricted_shared_vpc/versions.tf | 0
.../modules/vpn-ha/README.md | 2 +-
.../modules/vpn-ha/main.tf | 0
.../modules/vpn-ha/variables.tf | 0
.../shared.auto.example.tfvars | 0
3-networks-hub-and-spoke/.gitignore | 58 ++++
3-networks-hub-and-spoke/README.md | 315 ++++++++++++++++++
.../access_context.auto.example.tfvars | 17 +
.../common.auto.example.tfvars | 4 +-
.../envs/development/README.md | 7 +-
.../development/access_context.auto.tfvars | 1 +
.../envs/development/backend.tf | 22 ++
.../envs/development/common.auto.tfvars | 1 +
.../envs/development/main.tf | 3 +-
.../envs/development/outputs.tf | 103 ++++++
.../envs/development/providers.tf | 33 ++
.../envs/development/variables.tf | 8 +-
.../envs/development/versions.tf | 29 ++
.../envs/non-production/README.md | 7 +-
.../non-production/access_context.auto.tfvars | 1 +
.../envs/non-production/backend.tf | 22 ++
.../envs/non-production/common.auto.tfvars | 1 +
.../envs/non-production/main.tf | 3 +-
.../envs/non-production/outputs.tf | 103 ++++++
.../envs/non-production/providers.tf | 33 ++
.../envs/non-production/variables.tf | 8 +-
.../envs/non-production/versions.tf | 29 ++
.../envs/production/README.md | 7 +-
.../production/access_context.auto.tfvars | 1 +
.../envs/production/backend.tf | 22 ++
.../envs/production/common.auto.tfvars | 1 +
.../envs/production/main.tf | 3 +-
.../envs/production/outputs.tf | 103 ++++++
.../envs/production/providers.tf | 33 ++
.../envs/production/variables.tf | 8 +-
.../envs/production/versions.tf | 29 ++
.../envs/shared/README.md | 5 +-
.../envs/shared/access_context.auto.tfvars | 1 +
.../envs/shared/backend.tf | 22 ++
.../envs/shared/common.auto.tfvars | 1 +
.../envs/shared/dns-hub.tf | 174 ++++++++++
.../envs/shared/hierarchical_firewall.tf | 104 ++++++
.../shared/interconnect.auto.tfvars.example | 4 +
.../envs/shared/interconnect.tf.example | 57 ++++
3-networks-hub-and-spoke/envs/shared/main.tf | 29 ++
.../envs/shared/net-hubs-transitivity.tf | 6 +-
.../envs/shared/net-hubs.tf | 12 +-
.../envs/shared/outputs.tf | 20 ++
.../shared/partner_interconnect.tf.example | 79 +++++
.../envs/shared/providers.tf | 33 ++
.../envs/shared/shared.auto.tfvars | 1 +
.../envs/shared/variables.tf | 20 +-
.../envs/shared/versions.tf | 29 ++
.../modules/base_env/README.md | 1 -
.../modules/base_env/interconnect.tf.example | 100 ++++++
.../modules/base_env/main.tf | 9 +-
.../modules/base_env/outputs.tf | 103 ++++++
.../base_env/partner_interconnect.tf.example | 76 +++++
.../modules/base_env/variables.tf | 8 +-
.../modules/base_env/versions.tf | 29 ++
.../modules/base_env/vpn.tf.example | 106 ++++++
.../modules/base_shared_vpc/README.md | 45 +++
.../modules/base_shared_vpc/data.tf | 31 ++
.../modules/base_shared_vpc/dns.tf | 69 ++++
.../modules/base_shared_vpc/firewall.tf | 122 +++++++
.../modules/base_shared_vpc/main.tf | 4 +-
.../modules/base_shared_vpc/nat.tf | 90 +++++
.../modules/base_shared_vpc/outputs.tf | 60 ++++
.../private_service_connect.tf | 26 ++
.../modules/base_shared_vpc/variables.tf | 2 +-
.../modules/base_shared_vpc/versions.tf | 37 ++
.../modules/dedicated_interconnect/README.md | 63 ++++
.../modules/dedicated_interconnect/main.tf | 125 +++++++
.../modules/dedicated_interconnect/outputs.tf | 55 +++
.../dedicated_interconnect/variables.tf | 169 ++++++++++
.../dedicated_interconnect/versions.tf | 37 ++
.../hierarchical_firewall_policy/README.md | 17 +
.../hierarchical_firewall_policy/main.tf | 68 ++++
.../hierarchical_firewall_policy/outputs.tf | 19 ++
.../hierarchical_firewall_policy/variables.tf | 46 +++
.../hierarchical_firewall_policy/versions.tf | 40 +++
.../modules/partner_interconnect/README.md | 54 +++
.../modules/partner_interconnect/main.tf | 81 +++++
.../modules/partner_interconnect/outputs.tf | 55 +++
.../modules/partner_interconnect/variables.tf | 111 ++++++
.../modules/partner_interconnect/versions.tf | 37 ++
.../modules/private_service_connect/dns.tf | 114 +++++++
.../modules/private_service_connect/main.tf | 41 +++
.../private_service_connect/outputs.tf | 29 ++
.../private_service_connect/variables.tf | 50 +++
.../private_service_connect/versions.tf | 29 ++
.../modules/restricted_shared_vpc/README.md | 48 +++
.../modules/restricted_shared_vpc/data.tf | 31 ++
.../modules/restricted_shared_vpc/dns.tf | 69 ++++
.../modules/restricted_shared_vpc/firewall.tf | 120 +++++++
.../modules/restricted_shared_vpc/main.tf | 2 +-
.../modules/restricted_shared_vpc/nat.tf | 89 +++++
.../modules/restricted_shared_vpc/outputs.tf | 60 ++++
.../private_service_connect.tf | 26 ++
.../restricted_shared_vpc/service_control.tf | 2 +-
.../restricted_shared_vpc/variables.tf | 2 +-
.../modules/restricted_shared_vpc/versions.tf | 40 +++
.../modules/transitivity/README.md | 0
.../modules/transitivity/assets/gw.yaml | 2 +-
.../modules/transitivity/main.tf | 0
.../modules/transitivity/variables.tf | 0
.../modules/transitivity/versions.tf | 2 +-
.../modules/vpn-ha/README.md | 60 ++++
.../modules/vpn-ha/main.tf | 224 +++++++++++++
.../modules/vpn-ha/variables.tf | 177 ++++++++++
.../shared.auto.example.tfvars | 19 ++
4-projects/README.md | 9 +-
5-app-infra/README.md | 8 +-
README.md | 11 +-
test/disable_tf_files.sh | 41 ++-
test/integration/networks/networks_test.go | 11 +-
test/integration/projects/projects_test.go | 12 +-
test/integration/shared/shared_test.go | 17 +-
test/restore_tf_files.sh | 178 ++++++++++
216 files changed, 6694 insertions(+), 148 deletions(-)
rename {3-networks => 3-networks-dual-svpc}/.gitignore (100%)
rename {3-networks => 3-networks-dual-svpc}/README.md (92%)
rename {3-networks => 3-networks-dual-svpc}/access_context.auto.example.tfvars (100%)
create mode 100644 3-networks-dual-svpc/common.auto.example.tfvars
create mode 100644 3-networks-dual-svpc/envs/development/README.md
rename {3-networks => 3-networks-dual-svpc}/envs/development/access_context.auto.tfvars (100%)
rename {3-networks => 3-networks-dual-svpc}/envs/development/backend.tf (100%)
rename {3-networks => 3-networks-dual-svpc}/envs/development/common.auto.tfvars (100%)
create mode 100644 3-networks-dual-svpc/envs/development/main.tf
rename {3-networks => 3-networks-dual-svpc}/envs/development/outputs.tf (100%)
rename {3-networks => 3-networks-dual-svpc}/envs/development/providers.tf (100%)
create mode 100644 3-networks-dual-svpc/envs/development/variables.tf
rename {3-networks => 3-networks-dual-svpc}/envs/development/versions.tf (100%)
create mode 100644 3-networks-dual-svpc/envs/non-production/README.md
rename {3-networks => 3-networks-dual-svpc}/envs/non-production/access_context.auto.tfvars (100%)
rename {3-networks => 3-networks-dual-svpc}/envs/non-production/backend.tf (100%)
rename {3-networks => 3-networks-dual-svpc}/envs/non-production/common.auto.tfvars (100%)
create mode 100644 3-networks-dual-svpc/envs/non-production/main.tf
rename {3-networks => 3-networks-dual-svpc}/envs/non-production/outputs.tf (100%)
rename {3-networks => 3-networks-dual-svpc}/envs/non-production/providers.tf (100%)
create mode 100644 3-networks-dual-svpc/envs/non-production/variables.tf
rename {3-networks => 3-networks-dual-svpc}/envs/non-production/versions.tf (100%)
create mode 100644 3-networks-dual-svpc/envs/production/README.md
rename {3-networks => 3-networks-dual-svpc}/envs/production/access_context.auto.tfvars (100%)
rename {3-networks => 3-networks-dual-svpc}/envs/production/backend.tf (100%)
rename {3-networks => 3-networks-dual-svpc}/envs/production/common.auto.tfvars (100%)
create mode 100644 3-networks-dual-svpc/envs/production/main.tf
rename {3-networks => 3-networks-dual-svpc}/envs/production/outputs.tf (100%)
rename {3-networks => 3-networks-dual-svpc}/envs/production/providers.tf (100%)
create mode 100644 3-networks-dual-svpc/envs/production/variables.tf
rename {3-networks => 3-networks-dual-svpc}/envs/production/versions.tf (100%)
create mode 100644 3-networks-dual-svpc/envs/shared/README.md
rename {3-networks => 3-networks-dual-svpc}/envs/shared/access_context.auto.tfvars (100%)
rename {3-networks => 3-networks-dual-svpc}/envs/shared/backend.tf (100%)
rename {3-networks => 3-networks-dual-svpc}/envs/shared/common.auto.tfvars (100%)
rename {3-networks => 3-networks-dual-svpc}/envs/shared/dns-hub.tf (100%)
rename {3-networks => 3-networks-dual-svpc}/envs/shared/hierarchical_firewall.tf (100%)
rename {3-networks => 3-networks-dual-svpc}/envs/shared/interconnect.auto.tfvars.example (100%)
rename {3-networks => 3-networks-dual-svpc}/envs/shared/interconnect.tf.example (100%)
rename {3-networks => 3-networks-dual-svpc}/envs/shared/main.tf (100%)
rename {3-networks => 3-networks-dual-svpc}/envs/shared/outputs.tf (100%)
rename {3-networks => 3-networks-dual-svpc}/envs/shared/partner_interconnect.tf.example (96%)
rename {3-networks => 3-networks-dual-svpc}/envs/shared/providers.tf (100%)
rename {3-networks => 3-networks-dual-svpc}/envs/shared/shared.auto.tfvars (100%)
create mode 100644 3-networks-dual-svpc/envs/shared/variables.tf
rename {3-networks => 3-networks-dual-svpc}/envs/shared/versions.tf (100%)
create mode 100644 3-networks-dual-svpc/modules/base_env/README.md
rename {3-networks => 3-networks-dual-svpc}/modules/base_env/interconnect.tf.example (100%)
create mode 100644 3-networks-dual-svpc/modules/base_env/main.tf
rename {3-networks => 3-networks-dual-svpc}/modules/base_env/outputs.tf (100%)
rename {3-networks => 3-networks-dual-svpc}/modules/base_env/partner_interconnect.tf.example (96%)
create mode 100644 3-networks-dual-svpc/modules/base_env/variables.tf
rename {3-networks => 3-networks-dual-svpc}/modules/base_env/versions.tf (100%)
rename {3-networks => 3-networks-dual-svpc}/modules/base_env/vpn.tf.example (100%)
rename {3-networks => 3-networks-dual-svpc}/modules/base_shared_vpc/README.md (95%)
rename {3-networks => 3-networks-dual-svpc}/modules/base_shared_vpc/data.tf (100%)
rename {3-networks => 3-networks-dual-svpc}/modules/base_shared_vpc/dns.tf (100%)
rename {3-networks => 3-networks-dual-svpc}/modules/base_shared_vpc/firewall.tf (100%)
create mode 100644 3-networks-dual-svpc/modules/base_shared_vpc/main.tf
rename {3-networks => 3-networks-dual-svpc}/modules/base_shared_vpc/nat.tf (100%)
rename {3-networks => 3-networks-dual-svpc}/modules/base_shared_vpc/outputs.tf (100%)
rename {3-networks => 3-networks-dual-svpc}/modules/base_shared_vpc/private_service_connect.tf (100%)
create mode 100644 3-networks-dual-svpc/modules/base_shared_vpc/variables.tf
rename {3-networks => 3-networks-dual-svpc}/modules/base_shared_vpc/versions.tf (100%)
rename {3-networks => 3-networks-dual-svpc}/modules/dedicated_interconnect/README.md (99%)
rename {3-networks => 3-networks-dual-svpc}/modules/dedicated_interconnect/main.tf (100%)
rename {3-networks => 3-networks-dual-svpc}/modules/dedicated_interconnect/outputs.tf (100%)
rename {3-networks => 3-networks-dual-svpc}/modules/dedicated_interconnect/variables.tf (100%)
rename {3-networks => 3-networks-dual-svpc}/modules/dedicated_interconnect/versions.tf (100%)
rename {3-networks => 3-networks-dual-svpc}/modules/hierarchical_firewall_policy/README.md (100%)
rename {3-networks => 3-networks-dual-svpc}/modules/hierarchical_firewall_policy/main.tf (100%)
rename {3-networks => 3-networks-dual-svpc}/modules/hierarchical_firewall_policy/outputs.tf (100%)
rename {3-networks => 3-networks-dual-svpc}/modules/hierarchical_firewall_policy/variables.tf (100%)
rename {3-networks => 3-networks-dual-svpc}/modules/hierarchical_firewall_policy/versions.tf (100%)
rename {3-networks => 3-networks-dual-svpc}/modules/partner_interconnect/README.md (95%)
rename {3-networks => 3-networks-dual-svpc}/modules/partner_interconnect/main.tf (94%)
rename {3-networks => 3-networks-dual-svpc}/modules/partner_interconnect/outputs.tf (100%)
rename {3-networks => 3-networks-dual-svpc}/modules/partner_interconnect/variables.tf (96%)
rename {3-networks => 3-networks-dual-svpc}/modules/partner_interconnect/versions.tf (100%)
rename {3-networks => 3-networks-dual-svpc}/modules/private_service_connect/dns.tf (100%)
rename {3-networks => 3-networks-dual-svpc}/modules/private_service_connect/main.tf (100%)
rename {3-networks => 3-networks-dual-svpc}/modules/private_service_connect/outputs.tf (100%)
rename {3-networks => 3-networks-dual-svpc}/modules/private_service_connect/variables.tf (100%)
rename {3-networks => 3-networks-dual-svpc}/modules/private_service_connect/versions.tf (100%)
rename {3-networks => 3-networks-dual-svpc}/modules/restricted_shared_vpc/README.md (96%)
rename {3-networks => 3-networks-dual-svpc}/modules/restricted_shared_vpc/data.tf (100%)
rename {3-networks => 3-networks-dual-svpc}/modules/restricted_shared_vpc/dns.tf (100%)
rename {3-networks => 3-networks-dual-svpc}/modules/restricted_shared_vpc/firewall.tf (100%)
create mode 100644 3-networks-dual-svpc/modules/restricted_shared_vpc/main.tf
rename {3-networks => 3-networks-dual-svpc}/modules/restricted_shared_vpc/nat.tf (100%)
rename {3-networks => 3-networks-dual-svpc}/modules/restricted_shared_vpc/outputs.tf (100%)
rename {3-networks => 3-networks-dual-svpc}/modules/restricted_shared_vpc/private_service_connect.tf (100%)
create mode 100644 3-networks-dual-svpc/modules/restricted_shared_vpc/service_control.tf
create mode 100644 3-networks-dual-svpc/modules/restricted_shared_vpc/variables.tf
rename {3-networks => 3-networks-dual-svpc}/modules/restricted_shared_vpc/versions.tf (100%)
rename {3-networks => 3-networks-dual-svpc}/modules/vpn-ha/README.md (99%)
rename {3-networks => 3-networks-dual-svpc}/modules/vpn-ha/main.tf (100%)
rename {3-networks => 3-networks-dual-svpc}/modules/vpn-ha/variables.tf (100%)
rename {3-networks => 3-networks-dual-svpc}/shared.auto.example.tfvars (100%)
create mode 100644 3-networks-hub-and-spoke/.gitignore
create mode 100644 3-networks-hub-and-spoke/README.md
create mode 100644 3-networks-hub-and-spoke/access_context.auto.example.tfvars
rename {3-networks => 3-networks-hub-and-spoke}/common.auto.example.tfvars (94%)
rename {3-networks => 3-networks-hub-and-spoke}/envs/development/README.md (92%)
create mode 120000 3-networks-hub-and-spoke/envs/development/access_context.auto.tfvars
create mode 100644 3-networks-hub-and-spoke/envs/development/backend.tf
create mode 120000 3-networks-hub-and-spoke/envs/development/common.auto.tfvars
rename {3-networks => 3-networks-hub-and-spoke}/envs/development/main.tf (97%)
create mode 100644 3-networks-hub-and-spoke/envs/development/outputs.tf
create mode 100644 3-networks-hub-and-spoke/envs/development/providers.tf
rename {3-networks => 3-networks-hub-and-spoke}/envs/development/variables.tf (92%)
create mode 100644 3-networks-hub-and-spoke/envs/development/versions.tf
rename {3-networks => 3-networks-hub-and-spoke}/envs/non-production/README.md (92%)
create mode 120000 3-networks-hub-and-spoke/envs/non-production/access_context.auto.tfvars
create mode 100644 3-networks-hub-and-spoke/envs/non-production/backend.tf
create mode 120000 3-networks-hub-and-spoke/envs/non-production/common.auto.tfvars
rename {3-networks => 3-networks-hub-and-spoke}/envs/non-production/main.tf (97%)
create mode 100644 3-networks-hub-and-spoke/envs/non-production/outputs.tf
create mode 100644 3-networks-hub-and-spoke/envs/non-production/providers.tf
rename {3-networks => 3-networks-hub-and-spoke}/envs/non-production/variables.tf (92%)
create mode 100644 3-networks-hub-and-spoke/envs/non-production/versions.tf
rename {3-networks => 3-networks-hub-and-spoke}/envs/production/README.md (92%)
create mode 120000 3-networks-hub-and-spoke/envs/production/access_context.auto.tfvars
create mode 100644 3-networks-hub-and-spoke/envs/production/backend.tf
create mode 120000 3-networks-hub-and-spoke/envs/production/common.auto.tfvars
rename {3-networks => 3-networks-hub-and-spoke}/envs/production/main.tf (97%)
create mode 100644 3-networks-hub-and-spoke/envs/production/outputs.tf
create mode 100644 3-networks-hub-and-spoke/envs/production/providers.tf
rename {3-networks => 3-networks-hub-and-spoke}/envs/production/variables.tf (92%)
create mode 100644 3-networks-hub-and-spoke/envs/production/versions.tf
rename {3-networks => 3-networks-hub-and-spoke}/envs/shared/README.md (94%)
create mode 120000 3-networks-hub-and-spoke/envs/shared/access_context.auto.tfvars
create mode 100644 3-networks-hub-and-spoke/envs/shared/backend.tf
create mode 120000 3-networks-hub-and-spoke/envs/shared/common.auto.tfvars
create mode 100644 3-networks-hub-and-spoke/envs/shared/dns-hub.tf
create mode 100644 3-networks-hub-and-spoke/envs/shared/hierarchical_firewall.tf
create mode 100644 3-networks-hub-and-spoke/envs/shared/interconnect.auto.tfvars.example
create mode 100644 3-networks-hub-and-spoke/envs/shared/interconnect.tf.example
create mode 100644 3-networks-hub-and-spoke/envs/shared/main.tf
rename {3-networks => 3-networks-hub-and-spoke}/envs/shared/net-hubs-transitivity.tf (95%)
rename {3-networks => 3-networks-hub-and-spoke}/envs/shared/net-hubs.tf (91%)
create mode 100644 3-networks-hub-and-spoke/envs/shared/outputs.tf
create mode 100644 3-networks-hub-and-spoke/envs/shared/partner_interconnect.tf.example
create mode 100644 3-networks-hub-and-spoke/envs/shared/providers.tf
create mode 120000 3-networks-hub-and-spoke/envs/shared/shared.auto.tfvars
rename {3-networks => 3-networks-hub-and-spoke}/envs/shared/variables.tf (97%)
create mode 100644 3-networks-hub-and-spoke/envs/shared/versions.tf
rename {3-networks => 3-networks-hub-and-spoke}/modules/base_env/README.md (97%)
create mode 100644 3-networks-hub-and-spoke/modules/base_env/interconnect.tf.example
rename {3-networks => 3-networks-hub-and-spoke}/modules/base_env/main.tf (95%)
create mode 100644 3-networks-hub-and-spoke/modules/base_env/outputs.tf
create mode 100644 3-networks-hub-and-spoke/modules/base_env/partner_interconnect.tf.example
rename {3-networks => 3-networks-hub-and-spoke}/modules/base_env/variables.tf (95%)
create mode 100644 3-networks-hub-and-spoke/modules/base_env/versions.tf
create mode 100644 3-networks-hub-and-spoke/modules/base_env/vpn.tf.example
create mode 100644 3-networks-hub-and-spoke/modules/base_shared_vpc/README.md
create mode 100644 3-networks-hub-and-spoke/modules/base_shared_vpc/data.tf
create mode 100644 3-networks-hub-and-spoke/modules/base_shared_vpc/dns.tf
create mode 100644 3-networks-hub-and-spoke/modules/base_shared_vpc/firewall.tf
rename {3-networks => 3-networks-hub-and-spoke}/modules/base_shared_vpc/main.tf (98%)
create mode 100644 3-networks-hub-and-spoke/modules/base_shared_vpc/nat.tf
create mode 100644 3-networks-hub-and-spoke/modules/base_shared_vpc/outputs.tf
create mode 100644 3-networks-hub-and-spoke/modules/base_shared_vpc/private_service_connect.tf
rename {3-networks => 3-networks-hub-and-spoke}/modules/base_shared_vpc/variables.tf (99%)
create mode 100644 3-networks-hub-and-spoke/modules/base_shared_vpc/versions.tf
create mode 100644 3-networks-hub-and-spoke/modules/dedicated_interconnect/README.md
create mode 100644 3-networks-hub-and-spoke/modules/dedicated_interconnect/main.tf
create mode 100644 3-networks-hub-and-spoke/modules/dedicated_interconnect/outputs.tf
create mode 100644 3-networks-hub-and-spoke/modules/dedicated_interconnect/variables.tf
create mode 100644 3-networks-hub-and-spoke/modules/dedicated_interconnect/versions.tf
create mode 100644 3-networks-hub-and-spoke/modules/hierarchical_firewall_policy/README.md
create mode 100644 3-networks-hub-and-spoke/modules/hierarchical_firewall_policy/main.tf
create mode 100644 3-networks-hub-and-spoke/modules/hierarchical_firewall_policy/outputs.tf
create mode 100644 3-networks-hub-and-spoke/modules/hierarchical_firewall_policy/variables.tf
create mode 100644 3-networks-hub-and-spoke/modules/hierarchical_firewall_policy/versions.tf
create mode 100644 3-networks-hub-and-spoke/modules/partner_interconnect/README.md
create mode 100644 3-networks-hub-and-spoke/modules/partner_interconnect/main.tf
create mode 100644 3-networks-hub-and-spoke/modules/partner_interconnect/outputs.tf
create mode 100644 3-networks-hub-and-spoke/modules/partner_interconnect/variables.tf
create mode 100644 3-networks-hub-and-spoke/modules/partner_interconnect/versions.tf
create mode 100644 3-networks-hub-and-spoke/modules/private_service_connect/dns.tf
create mode 100644 3-networks-hub-and-spoke/modules/private_service_connect/main.tf
create mode 100644 3-networks-hub-and-spoke/modules/private_service_connect/outputs.tf
create mode 100644 3-networks-hub-and-spoke/modules/private_service_connect/variables.tf
create mode 100644 3-networks-hub-and-spoke/modules/private_service_connect/versions.tf
create mode 100644 3-networks-hub-and-spoke/modules/restricted_shared_vpc/README.md
create mode 100644 3-networks-hub-and-spoke/modules/restricted_shared_vpc/data.tf
create mode 100644 3-networks-hub-and-spoke/modules/restricted_shared_vpc/dns.tf
create mode 100644 3-networks-hub-and-spoke/modules/restricted_shared_vpc/firewall.tf
rename {3-networks => 3-networks-hub-and-spoke}/modules/restricted_shared_vpc/main.tf (99%)
create mode 100644 3-networks-hub-and-spoke/modules/restricted_shared_vpc/nat.tf
create mode 100644 3-networks-hub-and-spoke/modules/restricted_shared_vpc/outputs.tf
create mode 100644 3-networks-hub-and-spoke/modules/restricted_shared_vpc/private_service_connect.tf
rename {3-networks => 3-networks-hub-and-spoke}/modules/restricted_shared_vpc/service_control.tf (99%)
rename {3-networks => 3-networks-hub-and-spoke}/modules/restricted_shared_vpc/variables.tf (99%)
create mode 100644 3-networks-hub-and-spoke/modules/restricted_shared_vpc/versions.tf
rename {3-networks => 3-networks-hub-and-spoke}/modules/transitivity/README.md (100%)
rename {3-networks => 3-networks-hub-and-spoke}/modules/transitivity/assets/gw.yaml (96%)
rename {3-networks => 3-networks-hub-and-spoke}/modules/transitivity/main.tf (100%)
rename {3-networks => 3-networks-hub-and-spoke}/modules/transitivity/variables.tf (100%)
rename {3-networks => 3-networks-hub-and-spoke}/modules/transitivity/versions.tf (97%)
create mode 100755 3-networks-hub-and-spoke/modules/vpn-ha/README.md
create mode 100755 3-networks-hub-and-spoke/modules/vpn-ha/main.tf
create mode 100644 3-networks-hub-and-spoke/modules/vpn-ha/variables.tf
create mode 100644 3-networks-hub-and-spoke/shared.auto.example.tfvars
create mode 100644 test/restore_tf_files.sh
diff --git a/0-bootstrap/README.md b/0-bootstrap/README.md
index aeb16463a..b1efc0f8c 100644
--- a/0-bootstrap/README.md
+++ b/0-bootstrap/README.md
@@ -26,13 +26,20 @@ organizational policy.
Google Cloud organization that you've created.
-3-networks |
+3-networks-dual-svpc |
Sets up base and restricted shared VPCs with default DNS, NAT (optional),
Private Service networking, VPC service controls, on-premises Dedicated
-Interconnect, and baseline firewall rules for each environment. Also sets
+Interconnect, and baseline firewall rules for each environment. It also sets
up the global DNS hub. |
+3-networks-hub-and-spoke |
+Sets up base and restricted shared VPCs with all the default configuration
+found on step 3-networks-dual-svpc, but here the architecture will be based on the
+Hub and Spoke network model. It also sets up the global DNS hub |
+
+
+
4-projects |
Set up a folder structure, projects, and application infrastructure pipeline for applications,
which are connected as service projects to the shared VPC created in the previous stage. |
diff --git a/1-org/README.md b/1-org/README.md
index 2465395fa..e3e7ba496 100644
--- a/1-org/README.md
+++ b/1-org/README.md
@@ -26,13 +26,20 @@ organizational policy.
Google Cloud organization that you've created.
-3-networks |
+3-networks-dual-svpc |
Sets up base and restricted shared VPCs with default DNS, NAT (optional),
Private Service networking, VPC service controls, on-premises Dedicated
Interconnect, and baseline firewall rules for each environment. It also sets
up the global DNS hub. |
+3-networks-hub-and-spoke |
+Sets up base and restricted shared VPCs with all the default configuration
+found on step 3-networks-dual-svpc, but here the architecture will be based on the
+Hub and Spoke network model. It also sets up the global DNS hub |
+
+
+
4-projects |
Sets up a folder structure, projects, and application infrastructure pipeline for applications,
which are connected as service projects to the shared VPC created in the previous stage. |
diff --git a/2-environments/README.md b/2-environments/README.md
index 590d93245..11fa6cf36 100644
--- a/2-environments/README.md
+++ b/2-environments/README.md
@@ -26,13 +26,20 @@ organizational policy.
Google Cloud organization that you've created.
-3-networks |
+3-networks-dual-svpc |
Sets up base and restricted shared VPCs with default DNS, NAT (optional),
Private Service networking, VPC service controls, on-premises Dedicated
Interconnect, and baseline firewall rules for each environment. It also sets
up the global DNS hub. |
+3-networks-hub-and-spoke |
+Sets up base and restricted shared VPCs with all the default configuration
+found on step 3-networks-dual-svpc, but here the architecture will be based on the
+Hub and Spoke network model. It also sets up the global DNS hub |
+
+
+
4-projects |
Sets up a folder structure, projects, and application infrastructure pipeline for applications,
which are connected as service projects to the shared VPC created in the previous stage. |
@@ -131,7 +138,7 @@ commands. The `-T` flag is needed for Linux, but causes problems for MacOS.
git push origin production
```
1. Review the apply output in your cloud build project https://console.cloud.google.com/cloud-build/builds?project=YOUR_CLOUD_BUILD_PROJECT_ID
-1. You can now move to the instructions in the step [3-networks](../3-networks/README.md).
+1. You can now move to the instructions in the step go to for the Dual Shared VPC mode [3-networks-dual-svpc](../3-networks-dual-svpc/README.md), or go to [3-networks-hub-and-spoke](../3-networks-hub-and-spoke/README.md) to use the Hub and Spoke network mode.
### Deploying with Jenkins
diff --git a/3-networks/.gitignore b/3-networks-dual-svpc/.gitignore
similarity index 100%
rename from 3-networks/.gitignore
rename to 3-networks-dual-svpc/.gitignore
diff --git a/3-networks/README.md b/3-networks-dual-svpc/README.md
similarity index 92%
rename from 3-networks/README.md
rename to 3-networks-dual-svpc/README.md
index 4272047ae..29472787d 100644
--- a/3-networks/README.md
+++ b/3-networks-dual-svpc/README.md
@@ -1,4 +1,4 @@
-# 3-networks
+# 3-networks-dual-svpc
This repo is part of a multi-part guide that shows how to configure and deploy
the example.com reference architecture described in
@@ -26,13 +26,20 @@ organizational policy.
Google Cloud organization that you've created.
-3-networks (this file) |
+3-networks-dual-svpc (this file) |
Sets up base and restricted shared VPCs with default DNS, NAT (optional),
-Private Service networking, VPC service controls, Dedicated or Partner
+Private Service networking, VPC service controls, on-premises Dedicated
Interconnect, and baseline firewall rules for each environment. It also sets
up the global DNS hub. |
+3-networks-hub-and-spoke |
+Sets up base and restricted shared VPCs with all the default configuration
+found on step 3-networks-dual-svpc, but here the architecture will be based on the
+Hub and Spoke network model. It also sets up the global DNS hub |
+
+
+
4-projects |
Sets up a folder structure, projects, and application infrastructure pipeline for applications,
which are connected as service projects to the shared VPC created in the previous stage. |
@@ -80,13 +87,14 @@ commands. The `-T` flag is needed for Linux, but causes problems for MacOS.
### Networking Architecture
-You need to set variables `enable_hub_and_spoke` and `enable_hub_and_spoke_transitivity` to `true` to be able to use the **Hub-and-Spoke** architecture detailed in the **Networking** section of the [Google cloud security foundations guide](https://services.google.com/fh/files/misc/google-cloud-security-foundations-guide.pdf).
+This step makes use of the **Dual Shared VPC** architecture, and more details can be found described at the **Networking** section of the [Google cloud security foundations guide](https://cloud.google.com/architecture/security-foundations/networking). To see the version that makes use the Hub and Spoce mode, check the step [3-networks-hub-and-spoke](../3-networks-hub-and-spoke).
+
### Using Dedicated Interconnect
If you provisioned the prerequisites listed in the [Dedicated Interconnect README](./modules/dedicated_interconnect/README.md), follow these steps to enable Dedicated Interconnect to access on-premises resources.
-1. Rename `interconnect.tf.example` to `interconnect.tf` in base_env folder in `3-networks/modules/base_env`.
+1. Rename `interconnect.tf.example` to `interconnect.tf` in base_env folder in `3-networks-dual-svpc/modules/base_env`.
1. Update the file `interconnect.tf` with values that are valid for your environment for the interconnects, locations, candidate subnetworks, vlan_tag8021q and peer info.
1. The candidate subnetworks and vlan_tag8021q variables can be set to `null` to allow the interconnect module to auto generate these values.
@@ -94,7 +102,7 @@ If you provisioned the prerequisites listed in the [Dedicated Interconnect READM
If you provisioned the prerequisites listed in the [Partner Interconnect README](./modules/partner_interconnect/README.md) follow this steps to enable Partner Interconnect to access on-premises resources.
-1. Rename `partner_interconnect.tf.example` to `partner_interconnect.tf` in the base-env folder in `3-networks/modules/base_env` .
+1. Rename `partner_interconnect.tf.example` to `partner_interconnect.tf` in the base-env folder in `3-networks-dual-svpc/modules/base_env` .
1. Update the file `partner_interconnect.tf` with values that are valid for your environment for the VLAN attachments, locations, and candidate subnetworks.
1. The candidate subnetworks variable can be set to `null` to allow the interconnect module to auto generate this value.
@@ -102,7 +110,7 @@ If you provisioned the prerequisites listed in the [Partner Interconnect README]
If you are not able to use Dedicated or Partner Interconnect, you can also use an HA Cloud VPN to access on-premises resources.
-1. Rename `vpn.tf.example` to `vpn.tf` in base-env folder in `3-networks/modules/base_env`.
+1. Rename `vpn.tf.example` to `vpn.tf` in base-env folder in `3-networks-dual-svpc/modules/base_env`.
1. Create secret for VPN private preshared key.
```
echo '' | gcloud secrets create --project --replication-policy=automatic --data-file=-
@@ -127,7 +135,7 @@ If you are not able to use Dedicated or Partner Interconnect, you can also use a
```
1. Copy contents of foundation to new repo.
```
- cp -RT ../terraform-example-foundation/3-networks/ .
+ cp -RT ../terraform-example-foundation/3-networks-dual-svpc/ .
```
1. Copy Cloud Build configuration files for Terraform.
```
@@ -204,7 +212,7 @@ If you are not able to use Dedicated or Partner Interconnect, you can also use a
```
1. Copy contents of foundation to new repo.
```
- cp -RT ../terraform-example-foundation/3-networks/ .
+ cp -RT ../terraform-example-foundation/3-networks-dual-svpc/ .
```
1. Copy the Jenkinsfile script to the root of your new repository.
```
@@ -267,7 +275,7 @@ If you are not able to use Dedicated or Partner Interconnect, you can also use a
### Run Terraform locally
-1. Change into the 3-networks folder.
+1. Change into the 3-networks-dual-svpc folder.
1. Run `cp ../build/tf-wrapper.sh .`
1. Run `chmod 755 ./tf-wrapper.sh`.
1. Rename `common.auto.example.tfvars` to `common.auto.tfvars` and update the file with values from your environment and bootstrap. See any of the envs folder [README.md](./envs/production/README.md) files for additional information on the values in the `common.auto.tfvars` file.
@@ -280,7 +288,7 @@ If you are not able to use Dedicated or Partner Interconnect, you can also use a
You can run `terraform output gcs_bucket_tfstate` in the 0-bootstrap folder to obtain the bucket name.
We will now deploy each of our environments(development/production/non-production) using this script.
-When using Cloud Build or Jenkins as your CI/CD tool each environment corresponds to a branch in the repository for 3-networks step
+When using Cloud Build or Jenkins as your CI/CD tool each environment corresponds to a branch in the repository for 3-networks-dual-svpc step
and only the corresponding environment is applied.
To use the `validate` option of the `tf-wrapper.sh` script, please follow the [instructions](https://github.com/GoogleCloudPlatform/terraform-validator/blob/main/docs/install.md) in the **Install Terraform Validator** section and install version `v0.4.0` in your system. You will also need to rename the binary from `terraform-validator-` to `terraform-validator` and the `terraform-validator` binary must be in your `PATH`.
diff --git a/3-networks/access_context.auto.example.tfvars b/3-networks-dual-svpc/access_context.auto.example.tfvars
similarity index 100%
rename from 3-networks/access_context.auto.example.tfvars
rename to 3-networks-dual-svpc/access_context.auto.example.tfvars
diff --git a/3-networks-dual-svpc/common.auto.example.tfvars b/3-networks-dual-svpc/common.auto.example.tfvars
new file mode 100644
index 000000000..dd1729399
--- /dev/null
+++ b/3-networks-dual-svpc/common.auto.example.tfvars
@@ -0,0 +1,27 @@
+/**
+ * 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.
+ */
+
+org_id = "000000000000"
+
+terraform_service_account = "org-terraform@prj-b-seed-2334.iam.gserviceaccount.com"
+
+// The DNS name of peering managed zone. Must end with a period.
+domain = "example.com."
+
+// Optional - for an organization with existing projects or for development/validation.
+// Must be the same value used in previous steps.
+//parent_folder = "000000000000"
+
diff --git a/3-networks-dual-svpc/envs/development/README.md b/3-networks-dual-svpc/envs/development/README.md
new file mode 100644
index 000000000..7fd10b78b
--- /dev/null
+++ b/3-networks-dual-svpc/envs/development/README.md
@@ -0,0 +1,46 @@
+# 3-networks-dual-svpc/development
+
+The purpose of this step is to set up base and restricted shared VPCs with default DNS, NAT (optional), Private Service networking, VPC service controls, onprem Dedicated Interconnect, onprem VPN and baseline firewall rules for environment development.
+
+## Prerequisites
+
+1. 0-bootstrap executed successfully.
+1. 1-org executed successfully.
+1. 2-environments/envs/development executed successfully.
+1. 3-networks-dual-svpc/envs/shared executed successfully.
+1. Obtain the value for the access_context_manager_policy_id variable. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR_ORGANIZATION_ID --format="value(name)"`.
+
+
+## Inputs
+
+| 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 |
+| domain | The DNS name of peering managed zone, for instance 'example.com.'. Must end with a period. | `string` | n/a | yes |
+| folder\_prefix | Name prefix to use for folders created. Should be the same in all steps. | `string` | `"fldr"` | no |
+| org\_id | Organization ID | `string` | n/a | yes |
+| parent\_folder | Optional - for an organization with existing projects or for development/validation. It will place all the example foundation resources under the provided folder instead of the root organization. The value is the numeric folder ID. The folder must already exist. Must be the same value used in previous step. | `string` | `""` | no |
+| terraform\_service\_account | Service account email of the account to impersonate to run Terraform. | `string` | n/a | yes |
+
+## Outputs
+
+| Name | Description |
+|------|-------------|
+| base\_host\_project\_id | The base host project ID |
+| base\_network\_name | The name of the VPC being created |
+| base\_network\_self\_link | The URI of the VPC being created |
+| base\_subnets\_ips | The IPs and CIDRs of the subnets being created |
+| base\_subnets\_names | The names of the subnets being created |
+| base\_subnets\_secondary\_ranges | The secondary ranges associated with these subnets |
+| base\_subnets\_self\_links | The self-links of subnets being created |
+| restricted\_access\_level\_name | Access context manager access level name |
+| restricted\_host\_project\_id | The restricted host project ID |
+| restricted\_network\_name | The name of the VPC being created |
+| restricted\_network\_self\_link | The URI of the VPC being created |
+| restricted\_service\_perimeter\_name | Access context manager service perimeter name |
+| restricted\_subnets\_ips | The IPs and CIDRs of the subnets being created |
+| restricted\_subnets\_names | The names of the subnets being created |
+| restricted\_subnets\_secondary\_ranges | The secondary ranges associated with these subnets |
+| restricted\_subnets\_self\_links | The self-links of subnets being created |
+
+
diff --git a/3-networks/envs/development/access_context.auto.tfvars b/3-networks-dual-svpc/envs/development/access_context.auto.tfvars
similarity index 100%
rename from 3-networks/envs/development/access_context.auto.tfvars
rename to 3-networks-dual-svpc/envs/development/access_context.auto.tfvars
diff --git a/3-networks/envs/development/backend.tf b/3-networks-dual-svpc/envs/development/backend.tf
similarity index 100%
rename from 3-networks/envs/development/backend.tf
rename to 3-networks-dual-svpc/envs/development/backend.tf
diff --git a/3-networks/envs/development/common.auto.tfvars b/3-networks-dual-svpc/envs/development/common.auto.tfvars
similarity index 100%
rename from 3-networks/envs/development/common.auto.tfvars
rename to 3-networks-dual-svpc/envs/development/common.auto.tfvars
diff --git a/3-networks-dual-svpc/envs/development/main.tf b/3-networks-dual-svpc/envs/development/main.tf
new file mode 100644
index 000000000..462695f6d
--- /dev/null
+++ b/3-networks-dual-svpc/envs/development/main.tf
@@ -0,0 +1,84 @@
+/**
+ * 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.
+ */
+
+locals {
+ env = "development"
+ environment_code = substr(local.env, 0, 1)
+ default_region1 = "us-west1"
+ default_region2 = "us-central1"
+ /*
+ * Base network ranges
+ */
+ base_private_service_cidr = "10.16.64.0/21"
+ base_subnet_primary_ranges = {
+ (local.default_region1) = "10.0.64.0/21"
+ (local.default_region2) = "10.1.64.0/21"
+ }
+ base_subnet_secondary_ranges = {
+ (local.default_region1) = [
+ {
+ range_name = "rn-${local.environment_code}-shared-base-${local.default_region1}-gke-pod"
+ ip_cidr_range = "100.64.64.0/21"
+ },
+ {
+ range_name = "rn-${local.environment_code}-shared-base-${local.default_region1}-gke-svc"
+ ip_cidr_range = "100.64.72.0/21"
+ }
+ ]
+ }
+ /*
+ * Restricted network ranges
+ */
+ restricted_private_service_cidr = "10.24.64.0/21"
+ restricted_subnet_primary_ranges = {
+ (local.default_region1) = "10.8.64.0/21"
+ (local.default_region2) = "10.9.64.0/21"
+ }
+ restricted_subnet_secondary_ranges = {
+ (local.default_region1) = [
+ {
+ range_name = "rn-${local.environment_code}-shared-restricted-${local.default_region1}-gke-pod"
+ ip_cidr_range = "100.72.64.0/21"
+ },
+ {
+ range_name = "rn-${local.environment_code}-shared-restricted-${local.default_region1}-gke-svc"
+ ip_cidr_range = "100.72.72.0/21"
+ }
+ ]
+ }
+}
+
+module "base_env" {
+ source = "../../modules/base_env"
+
+ env = local.env
+ environment_code = local.environment_code
+ org_id = var.org_id
+ access_context_manager_policy_id = var.access_context_manager_policy_id
+ terraform_service_account = var.terraform_service_account
+ default_region1 = local.default_region1
+ default_region2 = local.default_region2
+ domain = var.domain
+ parent_folder = var.parent_folder
+ enable_partner_interconnect = false
+ base_private_service_cidr = local.base_private_service_cidr
+ base_subnet_primary_ranges = local.base_subnet_primary_ranges
+ base_subnet_secondary_ranges = local.base_subnet_secondary_ranges
+ restricted_private_service_cidr = local.restricted_private_service_cidr
+ restricted_subnet_primary_ranges = local.restricted_subnet_primary_ranges
+ restricted_subnet_secondary_ranges = local.restricted_subnet_secondary_ranges
+
+}
diff --git a/3-networks/envs/development/outputs.tf b/3-networks-dual-svpc/envs/development/outputs.tf
similarity index 100%
rename from 3-networks/envs/development/outputs.tf
rename to 3-networks-dual-svpc/envs/development/outputs.tf
diff --git a/3-networks/envs/development/providers.tf b/3-networks-dual-svpc/envs/development/providers.tf
similarity index 100%
rename from 3-networks/envs/development/providers.tf
rename to 3-networks-dual-svpc/envs/development/providers.tf
diff --git a/3-networks-dual-svpc/envs/development/variables.tf b/3-networks-dual-svpc/envs/development/variables.tf
new file mode 100644
index 000000000..a4c3d07d4
--- /dev/null
+++ b/3-networks-dual-svpc/envs/development/variables.tf
@@ -0,0 +1,47 @@
+/**
+ * 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.
+ */
+
+variable "org_id" {
+ type = string
+ description = "Organization ID"
+}
+
+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 "terraform_service_account" {
+ type = string
+ description = "Service account email of the account to impersonate to run Terraform."
+}
+
+variable "domain" {
+ type = string
+ description = "The DNS name of peering managed zone, for instance 'example.com.'. Must end with a period."
+}
+
+variable "parent_folder" {
+ description = "Optional - for an organization with existing projects or for development/validation. It will place all the example foundation resources under the provided folder instead of the root organization. The value is the numeric folder ID. The folder must already exist. Must be the same value used in previous step."
+ type = string
+ default = ""
+}
+
+variable "folder_prefix" {
+ description = "Name prefix to use for folders created. Should be the same in all steps."
+ type = string
+ default = "fldr"
+}
diff --git a/3-networks/envs/development/versions.tf b/3-networks-dual-svpc/envs/development/versions.tf
similarity index 100%
rename from 3-networks/envs/development/versions.tf
rename to 3-networks-dual-svpc/envs/development/versions.tf
diff --git a/3-networks-dual-svpc/envs/non-production/README.md b/3-networks-dual-svpc/envs/non-production/README.md
new file mode 100644
index 000000000..5246bef37
--- /dev/null
+++ b/3-networks-dual-svpc/envs/non-production/README.md
@@ -0,0 +1,46 @@
+# 3-networks-dual-svpc/non-production
+
+The purpose of this step is to set up base and restricted shared VPCs with default DNS, NAT (optional), Private Service networking, VPC service controls, onprem Dedicated Interconnect, onprem VPN and baseline firewall rules for environment non-production.
+
+## Prerequisites
+
+1. 0-bootstrap executed successfully.
+1. 1-org executed successfully.
+1. 2-environments/envs/non-production executed successfully.
+1. 3-networks-dual-svpc/envs/shared executed successfully.
+1. Obtain the value for the access_context_manager_policy_id variable. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR_ORGANIZATION_ID --format="value(name)"`.
+
+
+## Inputs
+
+| 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 |
+| domain | The DNS name of peering managed zone, for instance 'example.com.'. Must end with a period. | `string` | n/a | yes |
+| folder\_prefix | Name prefix to use for folders created. Should be the same in all steps. | `string` | `"fldr"` | no |
+| org\_id | Organization ID | `string` | n/a | yes |
+| parent\_folder | Optional - for an organization with existing projects or for development/validation. It will place all the example foundation resources under the provided folder instead of the root organization. The value is the numeric folder ID. The folder must already exist. Must be the same value used in previous step. | `string` | `""` | no |
+| terraform\_service\_account | Service account email of the account to impersonate to run Terraform. | `string` | n/a | yes |
+
+## Outputs
+
+| Name | Description |
+|------|-------------|
+| base\_host\_project\_id | The base host project ID |
+| base\_network\_name | The name of the VPC being created |
+| base\_network\_self\_link | The URI of the VPC being created |
+| base\_subnets\_ips | The IPs and CIDRs of the subnets being created |
+| base\_subnets\_names | The names of the subnets being created |
+| base\_subnets\_secondary\_ranges | The secondary ranges associated with these subnets |
+| base\_subnets\_self\_links | The self-links of subnets being created |
+| restricted\_access\_level\_name | Access context manager access level name |
+| restricted\_host\_project\_id | The restricted host project ID |
+| restricted\_network\_name | The name of the VPC being created |
+| restricted\_network\_self\_link | The URI of the VPC being created |
+| restricted\_service\_perimeter\_name | Access context manager service perimeter name |
+| restricted\_subnets\_ips | The IPs and CIDRs of the subnets being created |
+| restricted\_subnets\_names | The names of the subnets being created |
+| restricted\_subnets\_secondary\_ranges | The secondary ranges associated with these subnets |
+| restricted\_subnets\_self\_links | The self-links of subnets being created |
+
+
diff --git a/3-networks/envs/non-production/access_context.auto.tfvars b/3-networks-dual-svpc/envs/non-production/access_context.auto.tfvars
similarity index 100%
rename from 3-networks/envs/non-production/access_context.auto.tfvars
rename to 3-networks-dual-svpc/envs/non-production/access_context.auto.tfvars
diff --git a/3-networks/envs/non-production/backend.tf b/3-networks-dual-svpc/envs/non-production/backend.tf
similarity index 100%
rename from 3-networks/envs/non-production/backend.tf
rename to 3-networks-dual-svpc/envs/non-production/backend.tf
diff --git a/3-networks/envs/non-production/common.auto.tfvars b/3-networks-dual-svpc/envs/non-production/common.auto.tfvars
similarity index 100%
rename from 3-networks/envs/non-production/common.auto.tfvars
rename to 3-networks-dual-svpc/envs/non-production/common.auto.tfvars
diff --git a/3-networks-dual-svpc/envs/non-production/main.tf b/3-networks-dual-svpc/envs/non-production/main.tf
new file mode 100644
index 000000000..5aeb6286f
--- /dev/null
+++ b/3-networks-dual-svpc/envs/non-production/main.tf
@@ -0,0 +1,83 @@
+/**
+ * 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.
+ */
+
+locals {
+ env = "non-production"
+ environment_code = substr(local.env, 0, 1)
+ default_region1 = "us-west1"
+ default_region2 = "us-central1"
+ /*
+ * Base network ranges
+ */
+ base_private_service_cidr = "10.16.128.0/21"
+ base_subnet_primary_ranges = {
+ (local.default_region1) = "10.0.128.0/21"
+ (local.default_region2) = "10.1.128.0/21"
+ }
+ base_subnet_secondary_ranges = {
+ (local.default_region1) = [
+ {
+ range_name = "rn-${local.environment_code}-shared-base-${local.default_region1}-gke-pod"
+ ip_cidr_range = "100.64.128.0/21"
+ },
+ {
+ range_name = "rn-${local.environment_code}-shared-base-${local.default_region1}-gke-svc"
+ ip_cidr_range = "100.64.136.0/21"
+ }
+ ]
+ }
+ /*
+ * Restricted network ranges
+ */
+ restricted_private_service_cidr = "10.24.128.0/21"
+ restricted_subnet_primary_ranges = {
+ (local.default_region1) = "10.8.128.0/21"
+ (local.default_region2) = "10.9.128.0/21"
+ }
+ restricted_subnet_secondary_ranges = {
+ (local.default_region1) = [
+ {
+ range_name = "rn-${local.environment_code}-shared-restricted-${local.default_region1}-gke-pod"
+ ip_cidr_range = "100.72.128.0/21"
+ },
+ {
+ range_name = "rn-${local.environment_code}-shared-restricted-${local.default_region1}-gke-svc"
+ ip_cidr_range = "100.72.136.0/21"
+ }
+ ]
+ }
+}
+
+module "base_env" {
+ source = "../../modules/base_env"
+
+ env = local.env
+ environment_code = local.environment_code
+ org_id = var.org_id
+ access_context_manager_policy_id = var.access_context_manager_policy_id
+ terraform_service_account = var.terraform_service_account
+ default_region1 = local.default_region1
+ default_region2 = local.default_region2
+ domain = var.domain
+ parent_folder = var.parent_folder
+ enable_partner_interconnect = false
+ base_private_service_cidr = local.base_private_service_cidr
+ base_subnet_primary_ranges = local.base_subnet_primary_ranges
+ base_subnet_secondary_ranges = local.base_subnet_secondary_ranges
+ restricted_private_service_cidr = local.restricted_private_service_cidr
+ restricted_subnet_primary_ranges = local.restricted_subnet_primary_ranges
+ restricted_subnet_secondary_ranges = local.restricted_subnet_secondary_ranges
+}
diff --git a/3-networks/envs/non-production/outputs.tf b/3-networks-dual-svpc/envs/non-production/outputs.tf
similarity index 100%
rename from 3-networks/envs/non-production/outputs.tf
rename to 3-networks-dual-svpc/envs/non-production/outputs.tf
diff --git a/3-networks/envs/non-production/providers.tf b/3-networks-dual-svpc/envs/non-production/providers.tf
similarity index 100%
rename from 3-networks/envs/non-production/providers.tf
rename to 3-networks-dual-svpc/envs/non-production/providers.tf
diff --git a/3-networks-dual-svpc/envs/non-production/variables.tf b/3-networks-dual-svpc/envs/non-production/variables.tf
new file mode 100644
index 000000000..82e3d849a
--- /dev/null
+++ b/3-networks-dual-svpc/envs/non-production/variables.tf
@@ -0,0 +1,48 @@
+/**
+ * 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.
+ */
+
+variable "org_id" {
+ type = string
+ description = "Organization ID"
+}
+
+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 "terraform_service_account" {
+ type = string
+ description = "Service account email of the account to impersonate to run Terraform."
+}
+
+variable "domain" {
+ type = string
+ description = "The DNS name of peering managed zone, for instance 'example.com.'. Must end with a period."
+}
+
+variable "parent_folder" {
+ description = "Optional - for an organization with existing projects or for development/validation. It will place all the example foundation resources under the provided folder instead of the root organization. The value is the numeric folder ID. The folder must already exist. Must be the same value used in previous step."
+ type = string
+ default = ""
+}
+
+variable "folder_prefix" {
+ description = "Name prefix to use for folders created. Should be the same in all steps."
+ type = string
+ default = "fldr"
+}
+
diff --git a/3-networks/envs/non-production/versions.tf b/3-networks-dual-svpc/envs/non-production/versions.tf
similarity index 100%
rename from 3-networks/envs/non-production/versions.tf
rename to 3-networks-dual-svpc/envs/non-production/versions.tf
diff --git a/3-networks-dual-svpc/envs/production/README.md b/3-networks-dual-svpc/envs/production/README.md
new file mode 100644
index 000000000..f79ef4dbe
--- /dev/null
+++ b/3-networks-dual-svpc/envs/production/README.md
@@ -0,0 +1,46 @@
+# 3-networks-dual-svpc/production
+
+The purpose of this step is to set up base and restricted shared VPCs with default DNS, NAT (optional), Private Service networking, VPC service controls, onprem Dedicated Interconnect, onprem VPN and baseline firewall rules for environment production.
+
+## Prerequisites
+
+1. 0-bootstrap executed successfully.
+1. 1-org executed successfully.
+1. 2-environments/envs/production executed successfully.
+1. 3-networks-dual-svpc/envs/shared executed successfully.
+1. Obtain the value for the access_context_manager_policy_id variable. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR_ORGANIZATION_ID --format="value(name)"`.
+
+
+## Inputs
+
+| 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 |
+| domain | The DNS name of peering managed zone, for instance 'example.com.'. Must end with a period. | `string` | n/a | yes |
+| folder\_prefix | Name prefix to use for folders created. Should be the same in all steps. | `string` | `"fldr"` | no |
+| org\_id | Organization ID | `string` | n/a | yes |
+| parent\_folder | Optional - for an organization with existing projects or for development/validation. It will place all the example foundation resources under the provided folder instead of the root organization. The value is the numeric folder ID. The folder must already exist. Must be the same value used in previous step. | `string` | `""` | no |
+| terraform\_service\_account | Service account email of the account to impersonate to run Terraform. | `string` | n/a | yes |
+
+## Outputs
+
+| Name | Description |
+|------|-------------|
+| base\_host\_project\_id | The base host project ID |
+| base\_network\_name | The name of the VPC being created |
+| base\_network\_self\_link | The URI of the VPC being created |
+| base\_subnets\_ips | The IPs and CIDRs of the subnets being created |
+| base\_subnets\_names | The names of the subnets being created |
+| base\_subnets\_secondary\_ranges | The secondary ranges associated with these subnets |
+| base\_subnets\_self\_links | The self-links of subnets being created |
+| restricted\_access\_level\_name | Access context manager access level name |
+| restricted\_host\_project\_id | The restricted host project ID |
+| restricted\_network\_name | The name of the VPC being created |
+| restricted\_network\_self\_link | The URI of the VPC being created |
+| restricted\_service\_perimeter\_name | Access context manager service perimeter name |
+| restricted\_subnets\_ips | The IPs and CIDRs of the subnets being created |
+| restricted\_subnets\_names | The names of the subnets being created |
+| restricted\_subnets\_secondary\_ranges | The secondary ranges associated with these subnets |
+| restricted\_subnets\_self\_links | The self-links of subnets being created |
+
+
diff --git a/3-networks/envs/production/access_context.auto.tfvars b/3-networks-dual-svpc/envs/production/access_context.auto.tfvars
similarity index 100%
rename from 3-networks/envs/production/access_context.auto.tfvars
rename to 3-networks-dual-svpc/envs/production/access_context.auto.tfvars
diff --git a/3-networks/envs/production/backend.tf b/3-networks-dual-svpc/envs/production/backend.tf
similarity index 100%
rename from 3-networks/envs/production/backend.tf
rename to 3-networks-dual-svpc/envs/production/backend.tf
diff --git a/3-networks/envs/production/common.auto.tfvars b/3-networks-dual-svpc/envs/production/common.auto.tfvars
similarity index 100%
rename from 3-networks/envs/production/common.auto.tfvars
rename to 3-networks-dual-svpc/envs/production/common.auto.tfvars
diff --git a/3-networks-dual-svpc/envs/production/main.tf b/3-networks-dual-svpc/envs/production/main.tf
new file mode 100644
index 000000000..660f35234
--- /dev/null
+++ b/3-networks-dual-svpc/envs/production/main.tf
@@ -0,0 +1,83 @@
+/**
+ * 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.
+ */
+
+locals {
+ env = "production"
+ environment_code = substr(local.env, 0, 1)
+ default_region1 = "us-west1"
+ default_region2 = "us-central1"
+ /*
+ * Base network ranges
+ */
+ base_private_service_cidr = "10.16.192.0/21"
+ base_subnet_primary_ranges = {
+ (local.default_region1) = "10.0.192.0/21"
+ (local.default_region2) = "10.1.192.0/21"
+ }
+ base_subnet_secondary_ranges = {
+ (local.default_region1) = [
+ {
+ range_name = "rn-${local.environment_code}-shared-base-${local.default_region1}-gke-pod"
+ ip_cidr_range = "100.64.192.0/21"
+ },
+ {
+ range_name = "rn-${local.environment_code}-shared-base-${local.default_region1}-gke-svc"
+ ip_cidr_range = "100.64.200.0/21"
+ }
+ ]
+ }
+ /*
+ * Restricted network ranges
+ */
+ restricted_private_service_cidr = "10.24.192.0/21"
+ restricted_subnet_primary_ranges = {
+ (local.default_region1) = "10.8.192.0/21"
+ (local.default_region2) = "10.9.192.0/21"
+ }
+ restricted_subnet_secondary_ranges = {
+ (local.default_region1) = [
+ {
+ range_name = "rn-${local.environment_code}-shared-restricted-${local.default_region1}-gke-pod"
+ ip_cidr_range = "100.72.192.0/21"
+ },
+ {
+ range_name = "rn-${local.environment_code}-shared-restricted-${local.default_region1}-gke-svc"
+ ip_cidr_range = "100.72.200.0/21"
+ }
+ ]
+ }
+}
+
+module "base_env" {
+ source = "../../modules/base_env"
+
+ env = local.env
+ environment_code = local.environment_code
+ org_id = var.org_id
+ access_context_manager_policy_id = var.access_context_manager_policy_id
+ terraform_service_account = var.terraform_service_account
+ default_region1 = local.default_region1
+ default_region2 = local.default_region2
+ domain = var.domain
+ parent_folder = var.parent_folder
+ enable_partner_interconnect = false
+ base_private_service_cidr = local.base_private_service_cidr
+ base_subnet_primary_ranges = local.base_subnet_primary_ranges
+ base_subnet_secondary_ranges = local.base_subnet_secondary_ranges
+ restricted_private_service_cidr = local.restricted_private_service_cidr
+ restricted_subnet_primary_ranges = local.restricted_subnet_primary_ranges
+ restricted_subnet_secondary_ranges = local.restricted_subnet_secondary_ranges
+}
diff --git a/3-networks/envs/production/outputs.tf b/3-networks-dual-svpc/envs/production/outputs.tf
similarity index 100%
rename from 3-networks/envs/production/outputs.tf
rename to 3-networks-dual-svpc/envs/production/outputs.tf
diff --git a/3-networks/envs/production/providers.tf b/3-networks-dual-svpc/envs/production/providers.tf
similarity index 100%
rename from 3-networks/envs/production/providers.tf
rename to 3-networks-dual-svpc/envs/production/providers.tf
diff --git a/3-networks-dual-svpc/envs/production/variables.tf b/3-networks-dual-svpc/envs/production/variables.tf
new file mode 100644
index 000000000..a4c3d07d4
--- /dev/null
+++ b/3-networks-dual-svpc/envs/production/variables.tf
@@ -0,0 +1,47 @@
+/**
+ * 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.
+ */
+
+variable "org_id" {
+ type = string
+ description = "Organization ID"
+}
+
+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 "terraform_service_account" {
+ type = string
+ description = "Service account email of the account to impersonate to run Terraform."
+}
+
+variable "domain" {
+ type = string
+ description = "The DNS name of peering managed zone, for instance 'example.com.'. Must end with a period."
+}
+
+variable "parent_folder" {
+ description = "Optional - for an organization with existing projects or for development/validation. It will place all the example foundation resources under the provided folder instead of the root organization. The value is the numeric folder ID. The folder must already exist. Must be the same value used in previous step."
+ type = string
+ default = ""
+}
+
+variable "folder_prefix" {
+ description = "Name prefix to use for folders created. Should be the same in all steps."
+ type = string
+ default = "fldr"
+}
diff --git a/3-networks/envs/production/versions.tf b/3-networks-dual-svpc/envs/production/versions.tf
similarity index 100%
rename from 3-networks/envs/production/versions.tf
rename to 3-networks-dual-svpc/envs/production/versions.tf
diff --git a/3-networks-dual-svpc/envs/shared/README.md b/3-networks-dual-svpc/envs/shared/README.md
new file mode 100644
index 000000000..60111ac4a
--- /dev/null
+++ b/3-networks-dual-svpc/envs/shared/README.md
@@ -0,0 +1,50 @@
+# 3-networks-dual-svpc/shared
+
+The purpose of this step is to set up the global [DNS Hub](https://cloud.google.com/blog/products/networking/cloud-forwarding-peering-and-zones) that will be used by all environments.
+
+## Prerequisites
+
+1. 0-bootstrap executed successfully.
+1. 1-org executed successfully.
+
+
+## Inputs
+
+| 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 |
+| bgp\_asn\_dns | BGP Autonomous System Number (ASN). | `number` | `64667` | no |
+| dns\_enable\_logging | Toggle DNS logging for VPC DNS. | `bool` | `true` | no |
+| domain | The DNS name of forwarding managed zone, for instance 'example.com'. Must end with a period. | `string` | n/a | yes |
+| enable\_partner\_interconnect | Enable Partner Interconnect in the environment. | `bool` | `false` | no |
+| firewall\_policies\_enable\_logging | Toggle hierarchical firewall logging. | `bool` | `true` | no |
+| folder\_prefix | Name prefix to use for folders created. Should be the same in all steps. | `string` | `"fldr"` | no |
+| org\_id | Organization ID | `string` | n/a | yes |
+| parent\_folder | Optional - for an organization with existing projects or for development/validation. It will place all the example foundation resources under the provided folder instead of the root organization. The value is the numeric folder ID. The folder must already exist. Must be the same value used in previous step. | `string` | `""` | no |
+| preactivate\_partner\_interconnect | Preactivate Partner Interconnect VLAN attachment in the environment. | `bool` | `false` | 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\_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 Subnetworks. | `bool` | `true` | no |
+| target\_name\_server\_addresses | List of IPv4 address of target name servers for the forwarding zone configuration. See https://cloud.google.com/dns/docs/overview#dns-forwarding-zones for details on target name servers in the context of Cloud DNS forwarding zones. | `list(string)` | n/a | yes |
+| terraform\_service\_account | Service account email of the account to impersonate to run Terraform. | `string` | n/a | yes |
+
+## Outputs
+
+| Name | Description |
+|------|-------------|
+| dns\_hub\_project\_id | The DNS hub project ID |
+
+
diff --git a/3-networks/envs/shared/access_context.auto.tfvars b/3-networks-dual-svpc/envs/shared/access_context.auto.tfvars
similarity index 100%
rename from 3-networks/envs/shared/access_context.auto.tfvars
rename to 3-networks-dual-svpc/envs/shared/access_context.auto.tfvars
diff --git a/3-networks/envs/shared/backend.tf b/3-networks-dual-svpc/envs/shared/backend.tf
similarity index 100%
rename from 3-networks/envs/shared/backend.tf
rename to 3-networks-dual-svpc/envs/shared/backend.tf
diff --git a/3-networks/envs/shared/common.auto.tfvars b/3-networks-dual-svpc/envs/shared/common.auto.tfvars
similarity index 100%
rename from 3-networks/envs/shared/common.auto.tfvars
rename to 3-networks-dual-svpc/envs/shared/common.auto.tfvars
diff --git a/3-networks/envs/shared/dns-hub.tf b/3-networks-dual-svpc/envs/shared/dns-hub.tf
similarity index 100%
rename from 3-networks/envs/shared/dns-hub.tf
rename to 3-networks-dual-svpc/envs/shared/dns-hub.tf
diff --git a/3-networks/envs/shared/hierarchical_firewall.tf b/3-networks-dual-svpc/envs/shared/hierarchical_firewall.tf
similarity index 100%
rename from 3-networks/envs/shared/hierarchical_firewall.tf
rename to 3-networks-dual-svpc/envs/shared/hierarchical_firewall.tf
diff --git a/3-networks/envs/shared/interconnect.auto.tfvars.example b/3-networks-dual-svpc/envs/shared/interconnect.auto.tfvars.example
similarity index 100%
rename from 3-networks/envs/shared/interconnect.auto.tfvars.example
rename to 3-networks-dual-svpc/envs/shared/interconnect.auto.tfvars.example
diff --git a/3-networks/envs/shared/interconnect.tf.example b/3-networks-dual-svpc/envs/shared/interconnect.tf.example
similarity index 100%
rename from 3-networks/envs/shared/interconnect.tf.example
rename to 3-networks-dual-svpc/envs/shared/interconnect.tf.example
diff --git a/3-networks/envs/shared/main.tf b/3-networks-dual-svpc/envs/shared/main.tf
similarity index 100%
rename from 3-networks/envs/shared/main.tf
rename to 3-networks-dual-svpc/envs/shared/main.tf
diff --git a/3-networks/envs/shared/outputs.tf b/3-networks-dual-svpc/envs/shared/outputs.tf
similarity index 100%
rename from 3-networks/envs/shared/outputs.tf
rename to 3-networks-dual-svpc/envs/shared/outputs.tf
diff --git a/3-networks/envs/shared/partner_interconnect.tf.example b/3-networks-dual-svpc/envs/shared/partner_interconnect.tf.example
similarity index 96%
rename from 3-networks/envs/shared/partner_interconnect.tf.example
rename to 3-networks-dual-svpc/envs/shared/partner_interconnect.tf.example
index 3568cc744..49edebb0d 100644
--- a/3-networks/envs/shared/partner_interconnect.tf.example
+++ b/3-networks-dual-svpc/envs/shared/partner_interconnect.tf.example
@@ -21,7 +21,6 @@ module "shared_restricted_interconnect" {
parent_folder = var.parent_folder
vpc_name = "${local.environment_code}-shared-restricted"
environment = local.env
- enable_hub_and_spoke = var.enable_hub_and_spoke
vpc_type = "restricted"
preactivate = var.preactivate_partner_interconnect
@@ -54,7 +53,6 @@ module "shared_base_interconnect" {
parent_folder = var.parent_folder
vpc_name = "${local.environment_code}-shared-base"
environment = local.env
- enable_hub_and_spoke = var.enable_hub_and_spoke
vpc_type = "base"
preactivate = var.preactivate_partner_interconnect
diff --git a/3-networks/envs/shared/providers.tf b/3-networks-dual-svpc/envs/shared/providers.tf
similarity index 100%
rename from 3-networks/envs/shared/providers.tf
rename to 3-networks-dual-svpc/envs/shared/providers.tf
diff --git a/3-networks/envs/shared/shared.auto.tfvars b/3-networks-dual-svpc/envs/shared/shared.auto.tfvars
similarity index 100%
rename from 3-networks/envs/shared/shared.auto.tfvars
rename to 3-networks-dual-svpc/envs/shared/shared.auto.tfvars
diff --git a/3-networks-dual-svpc/envs/shared/variables.tf b/3-networks-dual-svpc/envs/shared/variables.tf
new file mode 100644
index 000000000..c0f61370b
--- /dev/null
+++ b/3-networks-dual-svpc/envs/shared/variables.tf
@@ -0,0 +1,178 @@
+/**
+ * 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.
+ */
+
+variable "org_id" {
+ type = string
+ description = "Organization ID"
+}
+
+variable "terraform_service_account" {
+ type = string
+ description = "Service account email of the account to impersonate to run Terraform."
+}
+
+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 "dns_enable_logging" {
+ type = bool
+ description = "Toggle DNS logging for VPC DNS."
+ default = true
+}
+
+variable "subnetworks_enable_logging" {
+ type = bool
+ description = "Toggle subnetworks flow logging for VPC Subnetworks."
+ default = true
+}
+
+variable "domain" {
+ type = string
+ description = "The DNS name of forwarding managed zone, for instance 'example.com'. Must end with a period."
+}
+
+variable "bgp_asn_dns" {
+ type = number
+ description = "BGP Autonomous System Number (ASN)."
+ default = 64667
+}
+
+variable "target_name_server_addresses" {
+ description = "List of IPv4 address of target name servers for the forwarding zone configuration. See https://cloud.google.com/dns/docs/overview#dns-forwarding-zones for details on target name servers in the context of Cloud DNS forwarding zones."
+ type = list(string)
+}
+
+variable "parent_folder" {
+ description = "Optional - for an organization with existing projects or for development/validation. It will place all the example foundation resources under the provided folder instead of the root organization. The value is the numeric folder ID. The folder must already exist. Must be the same value used in previous step."
+ type = string
+ default = ""
+}
+
+variable "folder_prefix" {
+ description = "Name prefix to use for folders created. Should be the same in all steps."
+ type = string
+ default = "fldr"
+}
+
+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_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
+}
+
+variable "firewall_policies_enable_logging" {
+ type = bool
+ description = "Toggle hierarchical firewall logging."
+ default = true
+}
+
+variable "enable_partner_interconnect" {
+ description = "Enable Partner Interconnect in the environment."
+ type = bool
+ default = false
+}
+
+variable "preactivate_partner_interconnect" {
+ description = "Preactivate Partner Interconnect VLAN attachment in the environment."
+ type = bool
+ default = false
+}
diff --git a/3-networks/envs/shared/versions.tf b/3-networks-dual-svpc/envs/shared/versions.tf
similarity index 100%
rename from 3-networks/envs/shared/versions.tf
rename to 3-networks-dual-svpc/envs/shared/versions.tf
diff --git a/3-networks-dual-svpc/modules/base_env/README.md b/3-networks-dual-svpc/modules/base_env/README.md
new file mode 100644
index 000000000..95f0ad4d7
--- /dev/null
+++ b/3-networks-dual-svpc/modules/base_env/README.md
@@ -0,0 +1,45 @@
+
+## Inputs
+
+| 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\_private\_service\_cidr | CIDR range for private service networking. Used for Cloud SQL and other managed services in the Base Shared Vpc. | `string` | n/a | yes |
+| base\_subnet\_primary\_ranges | The base subnet primary IPTs ranges to the Base Shared Vpc. | `map(string)` | n/a | yes |
+| base\_subnet\_secondary\_ranges | The base subnet secondary IPTs ranges to the Base Shared Vpc. | `map(list(map(string)))` | n/a | yes |
+| default\_region1 | First subnet region. The shared vpc modules only configures two regions. | `string` | n/a | yes |
+| default\_region2 | Second subnet region. The shared vpc modules only configures two regions. | `string` | n/a | yes |
+| domain | The DNS name of peering managed zone, for instance 'example.com.'. Must end with a period. | `string` | n/a | yes |
+| enable\_partner\_interconnect | Enable Partner Interconnect in the environment. | `bool` | `false` | no |
+| env | The environment to prepare (ex. development) | `string` | n/a | yes |
+| environment\_code | A short form of the folder level resources (environment) within the Google Cloud organization (ex. d). | `string` | n/a | yes |
+| folder\_prefix | Name prefix to use for folders created. Should be the same in all steps. | `string` | `"fldr"` | no |
+| org\_id | Organization ID | `string` | n/a | yes |
+| parent\_folder | Optional - for an organization with existing projects or for development/validation. It will place all the example foundation resources under the provided folder instead of the root organization. The value is the numeric folder ID. The folder must already exist. Must be the same value used in previous step. | `string` | `""` | no |
+| restricted\_private\_service\_cidr | CIDR range for private service networking. Used for Cloud SQL and other managed services in the Restricted Shared Vpc. | `string` | n/a | yes |
+| restricted\_subnet\_primary\_ranges | The base subnet primary IPTs ranges to the Restricted Shared Vpc. | `map(string)` | n/a | yes |
+| restricted\_subnet\_secondary\_ranges | The base subnet secondary IPTs ranges to the Restricted Shared Vpc | `map(list(map(string)))` | n/a | yes |
+| terraform\_service\_account | Service account email of the account to impersonate to run Terraform. | `string` | n/a | yes |
+
+## Outputs
+
+| Name | Description |
+|------|-------------|
+| base\_host\_project\_id | The base host project ID |
+| base\_network\_name | The name of the VPC being created |
+| base\_network\_self\_link | The URI of the VPC being created |
+| base\_subnets\_ips | The IPs and CIDRs of the subnets being created |
+| base\_subnets\_names | The names of the subnets being created |
+| base\_subnets\_secondary\_ranges | The secondary ranges associated with these subnets |
+| base\_subnets\_self\_links | The self-links of subnets being created |
+| restricted\_access\_level\_name | Access context manager access level name |
+| restricted\_host\_project\_id | The restricted host project ID |
+| restricted\_network\_name | The name of the VPC being created |
+| restricted\_network\_self\_link | The URI of the VPC being created |
+| restricted\_service\_perimeter\_name | Access context manager service perimeter name |
+| restricted\_subnets\_ips | The IPs and CIDRs of the subnets being created |
+| restricted\_subnets\_names | The names of the subnets being created |
+| restricted\_subnets\_secondary\_ranges | The secondary ranges associated with these subnets |
+| restricted\_subnets\_self\_links | The self-links of subnets being created |
+
+
diff --git a/3-networks/modules/base_env/interconnect.tf.example b/3-networks-dual-svpc/modules/base_env/interconnect.tf.example
similarity index 100%
rename from 3-networks/modules/base_env/interconnect.tf.example
rename to 3-networks-dual-svpc/modules/base_env/interconnect.tf.example
diff --git a/3-networks-dual-svpc/modules/base_env/main.tf b/3-networks-dual-svpc/modules/base_env/main.tf
new file mode 100644
index 000000000..dba48e392
--- /dev/null
+++ b/3-networks-dual-svpc/modules/base_env/main.tf
@@ -0,0 +1,139 @@
+/**
+ * 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.
+ */
+
+locals {
+ restricted_project_id = data.google_projects.restricted_host_project.projects[0].project_id
+ 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}"
+ bgp_asn_number = var.enable_partner_interconnect ? "16550" : "64514"
+ /*
+ * Base network ranges
+ */
+ base_subnet_aggregates = ["10.0.0.0/16", "10.1.0.0/16", "100.64.0.0/16", "100.65.0.0/16"]
+ base_hub_subnet_ranges = ["10.0.0.0/24", "10.1.0.0/24"]
+ /*
+ * Restricted network ranges
+ */
+ restricted_subnet_aggregates = ["10.8.0.0/16", "10.9.0.0/16", "100.72.0.0/16", "100.73.0.0/16"]
+ restricted_hub_subnet_ranges = ["10.8.0.0/24", "10.9.0.0/24"]
+}
+
+data "google_active_folder" "env" {
+ display_name = "${var.folder_prefix}-${var.env}"
+ parent = local.parent_id
+}
+
+/******************************************
+ VPC Host Projects
+*****************************************/
+
+data "google_projects" "restricted_host_project" {
+ filter = "parent.id:${split("/", data.google_active_folder.env.name)[1]} labels.application_name=restricted-shared-vpc-host labels.environment=${var.env} lifecycleState=ACTIVE"
+}
+
+data "google_project" "restricted_host_project" {
+ project_id = data.google_projects.restricted_host_project.projects[0].project_id
+}
+
+data "google_projects" "base_host_project" {
+ filter = "parent.id:${split("/", data.google_active_folder.env.name)[1]} labels.application_name=base-shared-vpc-host labels.environment=${var.env} lifecycleState=ACTIVE"
+}
+
+/******************************************
+ Restricted shared VPC
+*****************************************/
+module "restricted_shared_vpc" {
+ source = "../restricted_shared_vpc"
+ project_id = local.restricted_project_id
+ project_number = local.restricted_project_number
+ environment_code = var.environment_code
+ 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}"]
+ private_service_cidr = var.restricted_private_service_cidr
+ org_id = var.org_id
+ parent_folder = var.parent_folder
+ bgp_asn_subnet = local.bgp_asn_number
+ default_region1 = var.default_region1
+ default_region2 = var.default_region2
+ domain = var.domain
+
+ subnets = [
+ {
+ subnet_name = "sb-${var.environment_code}-shared-restricted-${var.default_region1}"
+ subnet_ip = var.restricted_subnet_primary_ranges[var.default_region1]
+ subnet_region = var.default_region1
+ subnet_private_access = "true"
+ subnet_flow_logs = true
+ description = "First ${var.env} subnet example."
+ },
+ {
+ subnet_name = "sb-${var.environment_code}-shared-restricted-${var.default_region2}"
+ subnet_ip = var.restricted_subnet_primary_ranges[var.default_region2]
+ subnet_region = var.default_region2
+ subnet_private_access = "true"
+ subnet_flow_logs = true
+ description = "Second ${var.env} subnet example."
+ }
+ ]
+ secondary_ranges = {
+ "sb-${var.environment_code}-shared-restricted-${var.default_region1}" = var.restricted_subnet_secondary_ranges[var.default_region1]
+ }
+ allow_all_ingress_ranges = null
+ allow_all_egress_ranges = null
+}
+
+/******************************************
+ Base shared VPC
+*****************************************/
+
+module "base_shared_vpc" {
+ source = "../base_shared_vpc"
+ project_id = local.base_project_id
+ environment_code = var.environment_code
+ private_service_cidr = var.base_private_service_cidr
+ org_id = var.org_id
+ parent_folder = var.parent_folder
+ default_region1 = var.default_region1
+ default_region2 = var.default_region2
+ domain = var.domain
+ bgp_asn_subnet = local.bgp_asn_number
+
+ subnets = [
+ {
+ subnet_name = "sb-${var.environment_code}-shared-base-${var.default_region1}"
+ subnet_ip = var.base_subnet_primary_ranges[var.default_region1]
+ subnet_region = var.default_region1
+ subnet_private_access = "true"
+ subnet_flow_logs = true
+ description = "First ${var.env} subnet example."
+ },
+ {
+ subnet_name = "sb-${var.environment_code}-shared-base-${var.default_region2}"
+ subnet_ip = var.base_subnet_primary_ranges[var.default_region2]
+ subnet_region = var.default_region2
+ subnet_private_access = "true"
+ subnet_flow_logs = true
+ description = "Second ${var.env} subnet example."
+ }
+ ]
+ secondary_ranges = {
+ "sb-${var.environment_code}-shared-base-${var.default_region1}" = var.base_subnet_secondary_ranges[var.default_region1]
+ }
+ allow_all_ingress_ranges = null
+ allow_all_egress_ranges = null
+}
diff --git a/3-networks/modules/base_env/outputs.tf b/3-networks-dual-svpc/modules/base_env/outputs.tf
similarity index 100%
rename from 3-networks/modules/base_env/outputs.tf
rename to 3-networks-dual-svpc/modules/base_env/outputs.tf
diff --git a/3-networks/modules/base_env/partner_interconnect.tf.example b/3-networks-dual-svpc/modules/base_env/partner_interconnect.tf.example
similarity index 96%
rename from 3-networks/modules/base_env/partner_interconnect.tf.example
rename to 3-networks-dual-svpc/modules/base_env/partner_interconnect.tf.example
index d517ed7d6..4db0be5ea 100644
--- a/3-networks/modules/base_env/partner_interconnect.tf.example
+++ b/3-networks-dual-svpc/modules/base_env/partner_interconnect.tf.example
@@ -21,7 +21,6 @@ module "shared_restricted_interconnect" {
parent_folder = var.parent_folder
vpc_name = "${var.environment_code}-shared-restricted"
environment = var.env
- enable_hub_and_spoke = var.enable_hub_and_spoke
vpc_type = "restricted"
preactivate = true
@@ -52,7 +51,6 @@ module "shared_base_interconnect" {
parent_folder = var.parent_folder
vpc_name = "${var.environment_code}-shared-base"
environment = var.env
- enable_hub_and_spoke = var.enable_hub_and_spoke
vpc_type = "base"
preactivate = true
diff --git a/3-networks-dual-svpc/modules/base_env/variables.tf b/3-networks-dual-svpc/modules/base_env/variables.tf
new file mode 100644
index 000000000..0db9d2880
--- /dev/null
+++ b/3-networks-dual-svpc/modules/base_env/variables.tf
@@ -0,0 +1,103 @@
+/**
+ * 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.
+ */
+
+variable "env" {
+ description = "The environment to prepare (ex. development)"
+ type = string
+}
+
+variable "environment_code" {
+ type = string
+ description = "A short form of the folder level resources (environment) within the Google Cloud organization (ex. d)."
+}
+
+variable "org_id" {
+ type = string
+ description = "Organization ID"
+}
+
+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 "terraform_service_account" {
+ type = string
+ description = "Service account email of the account to impersonate to run Terraform."
+}
+
+variable "default_region1" {
+ type = string
+ description = "First subnet region. The shared vpc modules only configures two regions."
+}
+
+variable "default_region2" {
+ type = string
+ description = "Second subnet region. The shared vpc modules only configures two regions."
+}
+
+variable "domain" {
+ type = string
+ description = "The DNS name of peering managed zone, for instance 'example.com.'. Must end with a period."
+}
+
+variable "parent_folder" {
+ description = "Optional - for an organization with existing projects or for development/validation. It will place all the example foundation resources under the provided folder instead of the root organization. The value is the numeric folder ID. The folder must already exist. Must be the same value used in previous step."
+ type = string
+ default = ""
+}
+
+variable "folder_prefix" {
+ description = "Name prefix to use for folders created. Should be the same in all steps."
+ type = string
+ default = "fldr"
+}
+
+variable "enable_partner_interconnect" {
+ description = "Enable Partner Interconnect in the environment."
+ type = bool
+ default = false
+}
+
+variable "base_private_service_cidr" {
+ type = string
+ description = "CIDR range for private service networking. Used for Cloud SQL and other managed services in the Base Shared Vpc."
+}
+
+variable "base_subnet_primary_ranges" {
+ type = map(string)
+ description = "The base subnet primary IPTs ranges to the Base Shared Vpc."
+}
+
+variable "base_subnet_secondary_ranges" {
+ type = map(list(map(string)))
+ description = "The base subnet secondary IPTs ranges to the Base Shared Vpc."
+}
+
+variable "restricted_private_service_cidr" {
+ type = string
+ description = "CIDR range for private service networking. Used for Cloud SQL and other managed services in the Restricted Shared Vpc."
+}
+
+variable "restricted_subnet_primary_ranges" {
+ type = map(string)
+ description = "The base subnet primary IPTs ranges to the Restricted Shared Vpc."
+}
+
+variable "restricted_subnet_secondary_ranges" {
+ type = map(list(map(string)))
+ description = "The base subnet secondary IPTs ranges to the Restricted Shared Vpc"
+}
diff --git a/3-networks/modules/base_env/versions.tf b/3-networks-dual-svpc/modules/base_env/versions.tf
similarity index 100%
rename from 3-networks/modules/base_env/versions.tf
rename to 3-networks-dual-svpc/modules/base_env/versions.tf
diff --git a/3-networks/modules/base_env/vpn.tf.example b/3-networks-dual-svpc/modules/base_env/vpn.tf.example
similarity index 100%
rename from 3-networks/modules/base_env/vpn.tf.example
rename to 3-networks-dual-svpc/modules/base_env/vpn.tf.example
diff --git a/3-networks/modules/base_shared_vpc/README.md b/3-networks-dual-svpc/modules/base_shared_vpc/README.md
similarity index 95%
rename from 3-networks/modules/base_shared_vpc/README.md
rename to 3-networks-dual-svpc/modules/base_shared_vpc/README.md
index ba7ba2359..e8c207265 100644
--- a/3-networks/modules/base_shared_vpc/README.md
+++ b/3-networks-dual-svpc/modules/base_shared_vpc/README.md
@@ -14,7 +14,6 @@
| 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 chosen, keep as `null` otherwise. | `string` | `null` | no |
| nat\_bgp\_asn | BGP ASN for first NAT cloud routes. | `number` | `64514` | 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 |
diff --git a/3-networks/modules/base_shared_vpc/data.tf b/3-networks-dual-svpc/modules/base_shared_vpc/data.tf
similarity index 100%
rename from 3-networks/modules/base_shared_vpc/data.tf
rename to 3-networks-dual-svpc/modules/base_shared_vpc/data.tf
diff --git a/3-networks/modules/base_shared_vpc/dns.tf b/3-networks-dual-svpc/modules/base_shared_vpc/dns.tf
similarity index 100%
rename from 3-networks/modules/base_shared_vpc/dns.tf
rename to 3-networks-dual-svpc/modules/base_shared_vpc/dns.tf
diff --git a/3-networks/modules/base_shared_vpc/firewall.tf b/3-networks-dual-svpc/modules/base_shared_vpc/firewall.tf
similarity index 100%
rename from 3-networks/modules/base_shared_vpc/firewall.tf
rename to 3-networks-dual-svpc/modules/base_shared_vpc/firewall.tf
diff --git a/3-networks-dual-svpc/modules/base_shared_vpc/main.tf b/3-networks-dual-svpc/modules/base_shared_vpc/main.tf
new file mode 100644
index 000000000..96f204bd6
--- /dev/null
+++ b/3-networks-dual-svpc/modules/base_shared_vpc/main.tf
@@ -0,0 +1,146 @@
+/**
+ * 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.
+ */
+
+locals {
+ vpc_name = "${var.environment_code}-shared-base"
+ network_name = "vpc-${local.vpc_name}"
+ private_googleapis_cidr = module.private_service_connect.private_service_connect_ip
+}
+
+/******************************************
+ Shared VPC configuration
+ *****************************************/
+
+module "main" {
+ source = "terraform-google-modules/network/google"
+ version = "~> 5.1"
+ project_id = var.project_id
+ network_name = local.network_name
+ shared_vpc_host = "true"
+ delete_default_internet_gateway_routes = "true"
+
+ subnets = var.subnets
+ secondary_ranges = var.secondary_ranges
+
+ routes = concat(
+ var.nat_enabled ?
+ [
+ {
+ name = "rt-${local.vpc_name}-1000-egress-internet-default"
+ description = "Tag based route through IGW to access internet"
+ destination_range = "0.0.0.0/0"
+ tags = "egress-internet"
+ next_hop_internet = "true"
+ priority = "1000"
+ }
+ ]
+ : [],
+ var.windows_activation_enabled ?
+ [{
+ name = "rt-${local.vpc_name}-1000-all-default-windows-kms"
+ description = "Route through IGW to allow Windows KMS activation for GCP."
+ destination_range = "35.190.247.13/32"
+ next_hop_internet = "true"
+ priority = "1000"
+ }
+ ]
+ : []
+ )
+}
+
+/***************************************************************
+ 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"
+ address_type = "INTERNAL"
+ address = element(split("/", var.private_service_cidr), 0)
+ prefix_length = element(split("/", var.private_service_cidr), 1)
+ network = module.main.network_self_link
+
+}
+
+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[0].name]
+}
+
+/************************************
+ Router to advertise shared VPC
+ subnetworks and Google Private API
+************************************/
+
+module "region1_router1" {
+ source = "terraform-google-modules/cloud-router/google"
+ version = "~> 2.0.0"
+ name = "cr-${local.vpc_name}-${var.default_region1}-cr1"
+ project = var.project_id
+ network = module.main.network_name
+ region = var.default_region1
+ bgp = {
+ asn = var.bgp_asn_subnet
+ advertised_groups = ["ALL_SUBNETS"]
+ advertised_ip_ranges = [{ range = local.private_googleapis_cidr }]
+ }
+}
+
+module "region1_router2" {
+ source = "terraform-google-modules/cloud-router/google"
+ version = "~> 0.4.0"
+ name = "cr-${local.vpc_name}-${var.default_region1}-cr2"
+ project = var.project_id
+ network = module.main.network_name
+ region = var.default_region1
+ bgp = {
+ asn = var.bgp_asn_subnet
+ advertised_groups = ["ALL_SUBNETS"]
+ advertised_ip_ranges = [{ range = local.private_googleapis_cidr }]
+ }
+}
+
+module "region2_router1" {
+ source = "terraform-google-modules/cloud-router/google"
+ version = "~> 0.4.0"
+ name = "cr-${local.vpc_name}-${var.default_region2}-cr3"
+ project = var.project_id
+ network = module.main.network_name
+ region = var.default_region2
+ bgp = {
+ asn = var.bgp_asn_subnet
+ advertised_groups = ["ALL_SUBNETS"]
+ advertised_ip_ranges = [{ range = local.private_googleapis_cidr }]
+ }
+}
+
+module "region2_router2" {
+ source = "terraform-google-modules/cloud-router/google"
+ version = "~> 0.4.0"
+ name = "cr-${local.vpc_name}-${var.default_region2}-cr4"
+ project = var.project_id
+ network = module.main.network_name
+ region = var.default_region2
+ bgp = {
+ asn = var.bgp_asn_subnet
+ advertised_groups = ["ALL_SUBNETS"]
+ advertised_ip_ranges = [{ range = local.private_googleapis_cidr }]
+ }
+}
diff --git a/3-networks/modules/base_shared_vpc/nat.tf b/3-networks-dual-svpc/modules/base_shared_vpc/nat.tf
similarity index 100%
rename from 3-networks/modules/base_shared_vpc/nat.tf
rename to 3-networks-dual-svpc/modules/base_shared_vpc/nat.tf
diff --git a/3-networks/modules/base_shared_vpc/outputs.tf b/3-networks-dual-svpc/modules/base_shared_vpc/outputs.tf
similarity index 100%
rename from 3-networks/modules/base_shared_vpc/outputs.tf
rename to 3-networks-dual-svpc/modules/base_shared_vpc/outputs.tf
diff --git a/3-networks/modules/base_shared_vpc/private_service_connect.tf b/3-networks-dual-svpc/modules/base_shared_vpc/private_service_connect.tf
similarity index 100%
rename from 3-networks/modules/base_shared_vpc/private_service_connect.tf
rename to 3-networks-dual-svpc/modules/base_shared_vpc/private_service_connect.tf
diff --git a/3-networks-dual-svpc/modules/base_shared_vpc/variables.tf b/3-networks-dual-svpc/modules/base_shared_vpc/variables.tf
new file mode 100644
index 000000000..ba675a184
--- /dev/null
+++ b/3-networks-dual-svpc/modules/base_shared_vpc/variables.tf
@@ -0,0 +1,144 @@
+/**
+ * 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.
+ */
+
+variable "org_id" {
+ type = string
+ description = "Organization ID"
+}
+
+variable "project_id" {
+ type = string
+ description = "Project ID for Private Shared VPC."
+}
+
+variable "environment_code" {
+ type = string
+ description = "A short form of the folder level resources (environment) within the Google Cloud organization."
+}
+
+variable "default_region1" {
+ type = string
+ description = "Default region 1 for subnets and Cloud Routers"
+}
+
+variable "default_region2" {
+ type = string
+ description = "Default region 2 for subnets and Cloud Routers"
+}
+
+variable "nat_enabled" {
+ type = bool
+ description = "Toggle creation of NAT cloud router."
+ default = false
+}
+
+variable "nat_bgp_asn" {
+ type = number
+ description = "BGP ASN for first NAT cloud routes."
+ default = 64514
+}
+
+variable "nat_num_addresses_region1" {
+ type = number
+ description = "Number of external IPs to reserve for first Cloud NAT."
+ default = 2
+}
+
+variable "nat_num_addresses_region2" {
+ type = number
+ description = "Number of external IPs to reserve for second Cloud NAT."
+ default = 2
+}
+
+variable "bgp_asn_subnet" {
+ type = number
+ description = "BGP ASN for Subnets cloud routers."
+}
+
+variable "subnets" {
+ type = list(map(string))
+ description = "The list of subnets being created"
+ default = []
+}
+
+variable "secondary_ranges" {
+ type = map(list(object({ range_name = string, ip_cidr_range = string })))
+ description = "Secondary ranges that will be used in some of the subnets"
+ default = {}
+}
+
+variable "dns_enable_inbound_forwarding" {
+ type = bool
+ description = "Toggle inbound query forwarding for VPC DNS."
+ default = true
+}
+
+variable "dns_enable_logging" {
+ type = bool
+ description = "Toggle DNS logging for VPC DNS."
+ default = true
+}
+
+variable "firewall_enable_logging" {
+ type = bool
+ description = "Toggle firewall logging for VPC Firewalls."
+ default = true
+}
+
+variable "domain" {
+ type = string
+ description = "The DNS name of peering managed zone, for instance 'example.com.'"
+}
+
+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" {
+ type = bool
+ description = "Enable Windows license activation for Windows workloads."
+ default = false
+}
+
+variable "nat_num_addresses" {
+ type = number
+ description = "Number of external IPs to reserve for Cloud NAT."
+ default = 2
+}
+
+variable "parent_folder" {
+ description = "Optional - if using a folder for testing."
+ type = string
+ default = ""
+}
+
+variable "folder_prefix" {
+ description = "Name prefix to use for folders created."
+ type = string
+ default = "fldr"
+}
+
+variable "allow_all_egress_ranges" {
+ description = "List of network ranges to which all egress traffic will be allowed"
+ default = null
+}
+
+variable "allow_all_ingress_ranges" {
+ description = "List of network ranges from which all ingress traffic will be allowed"
+ default = null
+}
diff --git a/3-networks/modules/base_shared_vpc/versions.tf b/3-networks-dual-svpc/modules/base_shared_vpc/versions.tf
similarity index 100%
rename from 3-networks/modules/base_shared_vpc/versions.tf
rename to 3-networks-dual-svpc/modules/base_shared_vpc/versions.tf
diff --git a/3-networks/modules/dedicated_interconnect/README.md b/3-networks-dual-svpc/modules/dedicated_interconnect/README.md
similarity index 99%
rename from 3-networks/modules/dedicated_interconnect/README.md
rename to 3-networks-dual-svpc/modules/dedicated_interconnect/README.md
index 89ec7c14b..f4924c200 100644
--- a/3-networks/modules/dedicated_interconnect/README.md
+++ b/3-networks-dual-svpc/modules/dedicated_interconnect/README.md
@@ -8,7 +8,7 @@ This module implements the recommendation proposed in [Establishing 99.99% Avail
## Usage
-1. Rename `interconnect.tf.example` to `interconnect.tf` in the environment folder in `3-networks/envs/`
+1. Rename `interconnect.tf.example` to `interconnect.tf` in the environment folder in `3-networks-dual-svpc/envs/`
1. Update the file `interconnect.tf` with values that are valid for your environment for the interconnects, locations, candidate subnetworks, vlan_tag8021q and peer info.
1. The candidate subnetworks and vlan_tag8021q variables can be set to `null` to allow the interconnect module to auto generate these values.
diff --git a/3-networks/modules/dedicated_interconnect/main.tf b/3-networks-dual-svpc/modules/dedicated_interconnect/main.tf
similarity index 100%
rename from 3-networks/modules/dedicated_interconnect/main.tf
rename to 3-networks-dual-svpc/modules/dedicated_interconnect/main.tf
diff --git a/3-networks/modules/dedicated_interconnect/outputs.tf b/3-networks-dual-svpc/modules/dedicated_interconnect/outputs.tf
similarity index 100%
rename from 3-networks/modules/dedicated_interconnect/outputs.tf
rename to 3-networks-dual-svpc/modules/dedicated_interconnect/outputs.tf
diff --git a/3-networks/modules/dedicated_interconnect/variables.tf b/3-networks-dual-svpc/modules/dedicated_interconnect/variables.tf
similarity index 100%
rename from 3-networks/modules/dedicated_interconnect/variables.tf
rename to 3-networks-dual-svpc/modules/dedicated_interconnect/variables.tf
diff --git a/3-networks/modules/dedicated_interconnect/versions.tf b/3-networks-dual-svpc/modules/dedicated_interconnect/versions.tf
similarity index 100%
rename from 3-networks/modules/dedicated_interconnect/versions.tf
rename to 3-networks-dual-svpc/modules/dedicated_interconnect/versions.tf
diff --git a/3-networks/modules/hierarchical_firewall_policy/README.md b/3-networks-dual-svpc/modules/hierarchical_firewall_policy/README.md
similarity index 100%
rename from 3-networks/modules/hierarchical_firewall_policy/README.md
rename to 3-networks-dual-svpc/modules/hierarchical_firewall_policy/README.md
diff --git a/3-networks/modules/hierarchical_firewall_policy/main.tf b/3-networks-dual-svpc/modules/hierarchical_firewall_policy/main.tf
similarity index 100%
rename from 3-networks/modules/hierarchical_firewall_policy/main.tf
rename to 3-networks-dual-svpc/modules/hierarchical_firewall_policy/main.tf
diff --git a/3-networks/modules/hierarchical_firewall_policy/outputs.tf b/3-networks-dual-svpc/modules/hierarchical_firewall_policy/outputs.tf
similarity index 100%
rename from 3-networks/modules/hierarchical_firewall_policy/outputs.tf
rename to 3-networks-dual-svpc/modules/hierarchical_firewall_policy/outputs.tf
diff --git a/3-networks/modules/hierarchical_firewall_policy/variables.tf b/3-networks-dual-svpc/modules/hierarchical_firewall_policy/variables.tf
similarity index 100%
rename from 3-networks/modules/hierarchical_firewall_policy/variables.tf
rename to 3-networks-dual-svpc/modules/hierarchical_firewall_policy/variables.tf
diff --git a/3-networks/modules/hierarchical_firewall_policy/versions.tf b/3-networks-dual-svpc/modules/hierarchical_firewall_policy/versions.tf
similarity index 100%
rename from 3-networks/modules/hierarchical_firewall_policy/versions.tf
rename to 3-networks-dual-svpc/modules/hierarchical_firewall_policy/versions.tf
diff --git a/3-networks/modules/partner_interconnect/README.md b/3-networks-dual-svpc/modules/partner_interconnect/README.md
similarity index 95%
rename from 3-networks/modules/partner_interconnect/README.md
rename to 3-networks-dual-svpc/modules/partner_interconnect/README.md
index d2ff99f00..e3e6583a4 100644
--- a/3-networks/modules/partner_interconnect/README.md
+++ b/3-networks-dual-svpc/modules/partner_interconnect/README.md
@@ -10,8 +10,8 @@ Without Hub and Spoke enabled VLAN attachments will be created in `prj-{p|n|d}-s
## Usage
-1. Rename `partner_interconnect.tf.example` to `partner_interconnect.tf` in the environment folder in `3-networks/modules/base_env` .
-1. Update the `enable_partner_interconnect` to `true` in each `main.tf` file in the environment folder in `3-networks/envs/` .
+1. Rename `partner_interconnect.tf.example` to `partner_interconnect.tf` in the environment folder in `3-networks-dual-svpc/modules/base_env` .
+1. Update the `enable_partner_interconnect` to `true` in each `main.tf` file in the environment folder in `3-networks-dual-svpc/envs/` .
1. Update the file `partner_interconnect.tf` with values that are valid for your environment for the VLAN attachments, locations.
@@ -20,7 +20,6 @@ Without Hub and Spoke enabled VLAN attachments will be created in `prj-{p|n|d}-s
| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| cloud\_router\_labels | A map of suffixes for labelling vlans with four entries like "vlan\_1" => "suffix1" with keys from `vlan_1` to `vlan_4`. | `map(string)` | `{}` | no |
-| enable\_hub\_and\_spoke | Support hub and spoke architecture | `string` | `false` | no |
| environment | Environment in which to deploy the Partner Interconnect, must be 'common' if enable\_hub\_and\_spoke=true | `string` | `null` | no |
| folder\_prefix | Name prefix to use for folders created. | `string` | `"fldr"` | no |
| org\_id | Organization ID | `string` | n/a | yes |
diff --git a/3-networks/modules/partner_interconnect/main.tf b/3-networks-dual-svpc/modules/partner_interconnect/main.tf
similarity index 94%
rename from 3-networks/modules/partner_interconnect/main.tf
rename to 3-networks-dual-svpc/modules/partner_interconnect/main.tf
index 2086a85ee..e7b81a908 100644
--- a/3-networks/modules/partner_interconnect/main.tf
+++ b/3-networks-dual-svpc/modules/partner_interconnect/main.tf
@@ -23,8 +23,8 @@ locals {
attachment_project_id = data.google_projects.attachment_project.projects[0].project_id
- app_label = var.enable_hub_and_spoke ? "org-${var.vpc_type}-net-hub" : "${var.vpc_type}-shared-vpc-host"
- environment_label = var.enable_hub_and_spoke ? "production" : var.environment
+ app_label = "${var.vpc_type}-shared-vpc-host"
+ environment_label = var.environment
}
data "google_active_folder" "environment" {
diff --git a/3-networks/modules/partner_interconnect/outputs.tf b/3-networks-dual-svpc/modules/partner_interconnect/outputs.tf
similarity index 100%
rename from 3-networks/modules/partner_interconnect/outputs.tf
rename to 3-networks-dual-svpc/modules/partner_interconnect/outputs.tf
diff --git a/3-networks/modules/partner_interconnect/variables.tf b/3-networks-dual-svpc/modules/partner_interconnect/variables.tf
similarity index 96%
rename from 3-networks/modules/partner_interconnect/variables.tf
rename to 3-networks-dual-svpc/modules/partner_interconnect/variables.tf
index d1d4e8ec6..de0cc447f 100644
--- a/3-networks/modules/partner_interconnect/variables.tf
+++ b/3-networks-dual-svpc/modules/partner_interconnect/variables.tf
@@ -109,10 +109,3 @@ variable "vpc_type" {
type = string
default = null
}
-
-variable "enable_hub_and_spoke" {
- description = "Support hub and spoke architecture"
- type = string
- default = false
-}
-
diff --git a/3-networks/modules/partner_interconnect/versions.tf b/3-networks-dual-svpc/modules/partner_interconnect/versions.tf
similarity index 100%
rename from 3-networks/modules/partner_interconnect/versions.tf
rename to 3-networks-dual-svpc/modules/partner_interconnect/versions.tf
diff --git a/3-networks/modules/private_service_connect/dns.tf b/3-networks-dual-svpc/modules/private_service_connect/dns.tf
similarity index 100%
rename from 3-networks/modules/private_service_connect/dns.tf
rename to 3-networks-dual-svpc/modules/private_service_connect/dns.tf
diff --git a/3-networks/modules/private_service_connect/main.tf b/3-networks-dual-svpc/modules/private_service_connect/main.tf
similarity index 100%
rename from 3-networks/modules/private_service_connect/main.tf
rename to 3-networks-dual-svpc/modules/private_service_connect/main.tf
diff --git a/3-networks/modules/private_service_connect/outputs.tf b/3-networks-dual-svpc/modules/private_service_connect/outputs.tf
similarity index 100%
rename from 3-networks/modules/private_service_connect/outputs.tf
rename to 3-networks-dual-svpc/modules/private_service_connect/outputs.tf
diff --git a/3-networks/modules/private_service_connect/variables.tf b/3-networks-dual-svpc/modules/private_service_connect/variables.tf
similarity index 100%
rename from 3-networks/modules/private_service_connect/variables.tf
rename to 3-networks-dual-svpc/modules/private_service_connect/variables.tf
diff --git a/3-networks/modules/private_service_connect/versions.tf b/3-networks-dual-svpc/modules/private_service_connect/versions.tf
similarity index 100%
rename from 3-networks/modules/private_service_connect/versions.tf
rename to 3-networks-dual-svpc/modules/private_service_connect/versions.tf
diff --git a/3-networks/modules/restricted_shared_vpc/README.md b/3-networks-dual-svpc/modules/restricted_shared_vpc/README.md
similarity index 96%
rename from 3-networks/modules/restricted_shared_vpc/README.md
rename to 3-networks-dual-svpc/modules/restricted_shared_vpc/README.md
index 69f9f6a5f..8d51f09e9 100644
--- a/3-networks/modules/restricted_shared_vpc/README.md
+++ b/3-networks-dual-svpc/modules/restricted_shared_vpc/README.md
@@ -16,7 +16,6 @@
| 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 chosen, 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 |
diff --git a/3-networks/modules/restricted_shared_vpc/data.tf b/3-networks-dual-svpc/modules/restricted_shared_vpc/data.tf
similarity index 100%
rename from 3-networks/modules/restricted_shared_vpc/data.tf
rename to 3-networks-dual-svpc/modules/restricted_shared_vpc/data.tf
diff --git a/3-networks/modules/restricted_shared_vpc/dns.tf b/3-networks-dual-svpc/modules/restricted_shared_vpc/dns.tf
similarity index 100%
rename from 3-networks/modules/restricted_shared_vpc/dns.tf
rename to 3-networks-dual-svpc/modules/restricted_shared_vpc/dns.tf
diff --git a/3-networks/modules/restricted_shared_vpc/firewall.tf b/3-networks-dual-svpc/modules/restricted_shared_vpc/firewall.tf
similarity index 100%
rename from 3-networks/modules/restricted_shared_vpc/firewall.tf
rename to 3-networks-dual-svpc/modules/restricted_shared_vpc/firewall.tf
diff --git a/3-networks-dual-svpc/modules/restricted_shared_vpc/main.tf b/3-networks-dual-svpc/modules/restricted_shared_vpc/main.tf
new file mode 100644
index 000000000..5689de0ab
--- /dev/null
+++ b/3-networks-dual-svpc/modules/restricted_shared_vpc/main.tf
@@ -0,0 +1,148 @@
+/**
+ * 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.
+ */
+
+locals {
+ vpc_name = "${var.environment_code}-shared-restricted"
+ network_name = "vpc-${local.vpc_name}"
+ restricted_googleapis_cidr = module.private_service_connect.private_service_connect_ip
+}
+
+/******************************************
+ Shared VPC configuration
+ *****************************************/
+
+module "main" {
+ source = "terraform-google-modules/network/google"
+ version = "~> 5.1"
+ project_id = var.project_id
+ network_name = local.network_name
+ shared_vpc_host = "true"
+ delete_default_internet_gateway_routes = "true"
+
+ subnets = var.subnets
+ secondary_ranges = var.secondary_ranges
+
+ routes = concat(
+ var.nat_enabled ?
+ [
+ {
+ name = "rt-${local.vpc_name}-1000-egress-internet-default"
+ description = "Tag based route through IGW to access internet"
+ destination_range = "0.0.0.0/0"
+ tags = "egress-internet"
+ next_hop_internet = "true"
+ priority = "1000"
+ }
+ ]
+ : [],
+ var.windows_activation_enabled ?
+ [
+ {
+ name = "rt-${local.vpc_name}-1000-all-default-windows-kms"
+ description = "Route through IGW to allow Windows KMS activation for GCP."
+ destination_range = "35.190.247.13/32"
+ next_hop_internet = "true"
+ priority = "1000"
+ }
+ ]
+ : []
+ )
+}
+
+/***************************************************************
+ 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"
+ address_type = "INTERNAL"
+ address = element(split("/", var.private_service_cidr), 0)
+ prefix_length = element(split("/", var.private_service_cidr), 1)
+ network = module.main.network_self_link
+
+}
+
+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[0].name]
+
+}
+
+/************************************
+ Router to advertise shared VPC
+ subnetworks and Google Restricted API
+************************************/
+
+module "region1_router1" {
+ source = "terraform-google-modules/cloud-router/google"
+ version = "~> 2.0.0"
+ name = "cr-${local.vpc_name}-${var.default_region1}-cr5"
+ project = var.project_id
+ network = module.main.network_name
+ region = var.default_region1
+ bgp = {
+ asn = var.bgp_asn_subnet
+ advertised_groups = ["ALL_SUBNETS"]
+ advertised_ip_ranges = [{ range = local.restricted_googleapis_cidr }]
+ }
+}
+
+module "region1_router2" {
+ source = "terraform-google-modules/cloud-router/google"
+ version = "~> 0.4.0"
+ name = "cr-${local.vpc_name}-${var.default_region1}-cr6"
+ project = var.project_id
+ network = module.main.network_name
+ region = var.default_region1
+ bgp = {
+ asn = var.bgp_asn_subnet
+ advertised_groups = ["ALL_SUBNETS"]
+ advertised_ip_ranges = [{ range = local.restricted_googleapis_cidr }]
+ }
+}
+
+module "region2_router1" {
+ source = "terraform-google-modules/cloud-router/google"
+ version = "~> 0.4.0"
+ name = "cr-${local.vpc_name}-${var.default_region2}-cr7"
+ project = var.project_id
+ network = module.main.network_name
+ region = var.default_region2
+ bgp = {
+ asn = var.bgp_asn_subnet
+ advertised_groups = ["ALL_SUBNETS"]
+ advertised_ip_ranges = [{ range = local.restricted_googleapis_cidr }]
+ }
+}
+
+module "region2_router2" {
+ source = "terraform-google-modules/cloud-router/google"
+ version = "~> 0.4.0"
+ name = "cr-${local.vpc_name}-${var.default_region2}-cr8"
+ project = var.project_id
+ network = module.main.network_name
+ region = var.default_region2
+ bgp = {
+ asn = var.bgp_asn_subnet
+ advertised_groups = ["ALL_SUBNETS"]
+ advertised_ip_ranges = [{ range = local.restricted_googleapis_cidr }]
+ }
+}
diff --git a/3-networks/modules/restricted_shared_vpc/nat.tf b/3-networks-dual-svpc/modules/restricted_shared_vpc/nat.tf
similarity index 100%
rename from 3-networks/modules/restricted_shared_vpc/nat.tf
rename to 3-networks-dual-svpc/modules/restricted_shared_vpc/nat.tf
diff --git a/3-networks/modules/restricted_shared_vpc/outputs.tf b/3-networks-dual-svpc/modules/restricted_shared_vpc/outputs.tf
similarity index 100%
rename from 3-networks/modules/restricted_shared_vpc/outputs.tf
rename to 3-networks-dual-svpc/modules/restricted_shared_vpc/outputs.tf
diff --git a/3-networks/modules/restricted_shared_vpc/private_service_connect.tf b/3-networks-dual-svpc/modules/restricted_shared_vpc/private_service_connect.tf
similarity index 100%
rename from 3-networks/modules/restricted_shared_vpc/private_service_connect.tf
rename to 3-networks-dual-svpc/modules/restricted_shared_vpc/private_service_connect.tf
diff --git a/3-networks-dual-svpc/modules/restricted_shared_vpc/service_control.tf b/3-networks-dual-svpc/modules/restricted_shared_vpc/service_control.tf
new file mode 100644
index 000000000..b29614ab4
--- /dev/null
+++ b/3-networks-dual-svpc/modules/restricted_shared_vpc/service_control.tf
@@ -0,0 +1,57 @@
+/**
+ * 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.
+ */
+
+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}"
+}
+
+resource "random_id" "random_access_level_suffix" {
+ byte_length = 2
+}
+
+module "access_level_members" {
+ source = "terraform-google-modules/vpc-service-controls/google//modules/access_level"
+ version = "~> 2.0.0"
+ description = "${local.prefix} Access Level"
+ policy = var.access_context_manager_policy_id
+ name = local.access_level_name
+ members = var.members
+}
+
+resource "google_access_context_manager_service_perimeter" "regular_service_perimeter" {
+ parent = "accessPolicies/${var.access_context_manager_policy_id}"
+ perimeter_type = "PERIMETER_TYPE_REGULAR"
+ name = "accessPolicies/${var.access_context_manager_policy_id}/servicePerimeters/${local.perimeter_name}"
+ title = local.perimeter_name
+ description = "Default VPC Service Controls perimeter"
+
+ status {
+ restricted_services = var.restricted_services
+ resources = formatlist("projects/%s", [var.project_number])
+
+ access_levels = formatlist(
+ "accessPolicies/${var.access_context_manager_policy_id}/accessLevels/%s",
+ [module.access_level_members.name]
+ )
+ }
+
+ lifecycle {
+ ignore_changes = [status[0].resources]
+ }
+}
diff --git a/3-networks-dual-svpc/modules/restricted_shared_vpc/variables.tf b/3-networks-dual-svpc/modules/restricted_shared_vpc/variables.tf
new file mode 100644
index 000000000..734359236
--- /dev/null
+++ b/3-networks-dual-svpc/modules/restricted_shared_vpc/variables.tf
@@ -0,0 +1,158 @@
+/**
+ * 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.
+ */
+
+variable "org_id" {
+ type = string
+ description = "Organization ID"
+}
+
+variable "access_context_manager_policy_id" {
+ type = number
+ description = "The id of the default Access Context Manager policy. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR_ORGANIZATION_ID --format=\"value(name)\"`."
+}
+
+variable "project_id" {
+ type = string
+ description = "Project ID for Restricted Shared VPC."
+}
+
+variable "project_number" {
+ type = number
+ description = "Project number for Restricted Shared VPC. It is the project INSIDE the regular service perimeter."
+}
+
+variable "environment_code" {
+ type = string
+ description = "A short form of the folder level resources (environment) within the Google Cloud organization."
+}
+
+variable "nat_enabled" {
+ type = bool
+ description = "Toggle creation of NAT cloud router."
+ default = false
+}
+
+variable "nat_bgp_asn" {
+ type = number
+ description = "BGP ASN for NAT cloud routes. If NAT is enabled this variable value must be a value in ranges [64512..65534] or [4200000000..4294967294]."
+ default = 64512
+}
+
+variable "nat_num_addresses_region1" {
+ type = number
+ description = "Number of external IPs to reserve for region 1 Cloud NAT."
+ default = 2
+}
+
+variable "nat_num_addresses_region2" {
+ type = number
+ description = "Number of external IPs to reserve for region 2 Cloud NAT."
+ default = 2
+}
+
+variable "bgp_asn_subnet" {
+ type = number
+ description = "BGP ASN for Subnets cloud routers."
+}
+
+variable "default_region1" {
+ type = string
+ description = "First subnet region. The shared vpc modules only configures two regions."
+}
+
+variable "default_region2" {
+ type = string
+ description = "Second subnet region. The shared vpc modules only configures two regions."
+}
+
+variable "subnets" {
+ type = list(map(string))
+ description = "The list of subnets being created"
+ default = []
+}
+
+variable "secondary_ranges" {
+ type = map(list(object({ range_name = string, ip_cidr_range = string })))
+ description = "Secondary ranges that will be used in some of the subnets"
+ default = {}
+}
+
+variable "dns_enable_inbound_forwarding" {
+ type = bool
+ description = "Toggle inbound query forwarding for VPC DNS."
+ default = true
+}
+
+variable "dns_enable_logging" {
+ type = bool
+ description = "Toggle DNS logging for VPC DNS."
+ default = true
+}
+
+variable "firewall_enable_logging" {
+ type = bool
+ description = "Toggle firewall logging for VPC Firewalls."
+ default = true
+}
+
+variable "domain" {
+ type = string
+ description = "The DNS name of peering managed zone, for instance 'example.com.'"
+}
+
+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" {
+ type = bool
+ description = "Enable Windows license activation for Windows workloads."
+ default = false
+}
+
+variable "members" {
+ type = list(string)
+ description = "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}"
+}
+
+variable "restricted_services" {
+ type = list(string)
+ description = "List of services to restrict."
+}
+
+variable "parent_folder" {
+ description = "Optional - if using a folder for testing."
+ type = string
+ default = ""
+}
+
+variable "folder_prefix" {
+ description = "Name prefix to use for folders created."
+ type = string
+ default = "fldr"
+}
+
+variable "allow_all_egress_ranges" {
+ description = "List of network ranges to which all egress traffic will be allowed"
+ default = null
+}
+
+variable "allow_all_ingress_ranges" {
+ description = "List of network ranges from which all ingress traffic will be allowed"
+ default = null
+}
diff --git a/3-networks/modules/restricted_shared_vpc/versions.tf b/3-networks-dual-svpc/modules/restricted_shared_vpc/versions.tf
similarity index 100%
rename from 3-networks/modules/restricted_shared_vpc/versions.tf
rename to 3-networks-dual-svpc/modules/restricted_shared_vpc/versions.tf
diff --git a/3-networks/modules/vpn-ha/README.md b/3-networks-dual-svpc/modules/vpn-ha/README.md
similarity index 99%
rename from 3-networks/modules/vpn-ha/README.md
rename to 3-networks-dual-svpc/modules/vpn-ha/README.md
index 86702189d..311b772aa 100755
--- a/3-networks/modules/vpn-ha/README.md
+++ b/3-networks-dual-svpc/modules/vpn-ha/README.md
@@ -7,7 +7,7 @@ If you are not able to use Dedicated Interconnect or Partner Interconnect you ca
## Usage
-1. Rename `vpn.tf.example` to `vpn.tf` in the environment folder in `3-networks/envs/`
+1. Rename `vpn.tf.example` to `vpn.tf` in the environment folder in `3-networks-dual-svpc/envs/`
1. Create secret for VPN preshared key `echo 'MY_PSK' | gcloud secrets create VPN_PSK_SECRET_NAME --project ENV_SECRETS_PROJECT --replication-policy=automatic --data-file=-`
1. Update in the file the values for `environment`, `vpn_psk_secret_name`, `on_prem_router_ip_address1`, `on_prem_router_ip_address2` and `bgp_peer_asn`.
1. Verify other default values are valid for your environment.
diff --git a/3-networks/modules/vpn-ha/main.tf b/3-networks-dual-svpc/modules/vpn-ha/main.tf
similarity index 100%
rename from 3-networks/modules/vpn-ha/main.tf
rename to 3-networks-dual-svpc/modules/vpn-ha/main.tf
diff --git a/3-networks/modules/vpn-ha/variables.tf b/3-networks-dual-svpc/modules/vpn-ha/variables.tf
similarity index 100%
rename from 3-networks/modules/vpn-ha/variables.tf
rename to 3-networks-dual-svpc/modules/vpn-ha/variables.tf
diff --git a/3-networks/shared.auto.example.tfvars b/3-networks-dual-svpc/shared.auto.example.tfvars
similarity index 100%
rename from 3-networks/shared.auto.example.tfvars
rename to 3-networks-dual-svpc/shared.auto.example.tfvars
diff --git a/3-networks-hub-and-spoke/.gitignore b/3-networks-hub-and-spoke/.gitignore
new file mode 100644
index 000000000..fe232a046
--- /dev/null
+++ b/3-networks-hub-and-spoke/.gitignore
@@ -0,0 +1,58 @@
+# OSX leaves these everywhere on SMB shares
+._*
+
+# OSX trash
+.DS_Store
+
+# Python
+*.pyc
+
+# Emacs save files
+*~
+\#*\#
+.\#*
+
+# Vim-related files
+[._]*.s[a-w][a-z]
+[._]s[a-w][a-z]
+*.un~
+Session.vim
+.netrwhist
+
+### https://raw.github.com/github/gitignore/90f149de451a5433aebd94d02d11b0e28843a1af/Terraform.gitignore
+
+# Local .terraform directories
+**/.terraform/*
+
+# .tfstate files
+*.tfstate
+*.tfstate.*
+
+# Crash log files
+crash.log
+
+# Ignore any .tfvars files that are generated automatically for each Terraform run. Most
+# .tfvars files are managed as part of configuration and so should be included in
+# version control.
+#
+# example.tfvars
+
+# Ignore override files as they are usually used to override resources locally and so
+# are not checked in
+override.tf
+override.tf.json
+*_override.tf
+*_override.tf.json
+.idea/
+.vscode/
+# Kitchen files
+**/inspec.lock
+**.gem
+**/.kitchen
+**/.kitchen.local.yml
+**/Gemfile.lock
+
+credentials.json
+
+# File to populate env vars used by Docker test runs
+.envrc
diff --git a/3-networks-hub-and-spoke/README.md b/3-networks-hub-and-spoke/README.md
new file mode 100644
index 000000000..520398a40
--- /dev/null
+++ b/3-networks-hub-and-spoke/README.md
@@ -0,0 +1,315 @@
+# 3-networks-hub-and-spoke
+
+This repo is part of a multi-part guide that shows how to configure and deploy
+the example.com reference architecture described in
+[Google Cloud security foundations guide](https://services.google.com/fh/files/misc/google-cloud-security-foundations-guide.pdf)
+(PDF). The following table lists the parts of the guide.
+
+
+
+
+0-bootstrap |
+Bootstraps a Google Cloud organization, creating all the required resources
+and permissions to start using the Cloud Foundation Toolkit (CFT). This
+step also configures a CI/CD pipeline for foundations code in subsequent
+stages. |
+
+
+1-org |
+Sets up top level shared folders, monitoring and networking projects, and
+organization-level logging, and sets baseline security settings through
+organizational policy. |
+
+
+2-environments |
+Sets up development, non-production, and production environments within the
+Google Cloud organization that you've created. |
+
+
+3-networks-dual-svpc |
+Sets up base and restricted shared VPCs with default DNS, NAT (optional),
+Private Service networking, VPC service controls, on-premises Dedicated
+Interconnect, and baseline firewall rules for each environment. It also sets
+up the global DNS hub. |
+
+
+3-networks-hub-and-spoke (this file) |
+Sets up base and restricted shared VPCs with all the default configuration
+found on step 3-networks-dual-svpc, but here the architecture will be based on the
+Hub and Spoke network model. It also sets up the global DNS hub |
+
+
+
+4-projects |
+Sets up a folder structure, projects, and application infrastructure pipeline for applications,
+ which are connected as service projects to the shared VPC created in the previous stage. |
+
+
+5-app-infra |
+Deploy a simple Compute Engine instance in one of the business unit projects using the infra pipeline set up in 4-projects. |
+
+
+
+
+For an overview of the architecture and the parts, see the
+[terraform-example-foundation README](https://github.com/terraform-google-modules/terraform-example-foundation).
+
+## Purpose
+
+The purpose of this step is to:
+
+- Set up the global [DNS Hub](https://cloud.google.com/blog/products/networking/cloud-forwarding-peering-and-zones).
+- Set up base and restricted Hubs and it corresponding Spokes. With default DNS, NAT (optional), Private Service networking, VPC service controls, on-premises Dedicated or Partner Interconnect, and baseline firewall rules for each environment.
+
+## Prerequisites
+
+1. 0-bootstrap executed successfully.
+1. 1-org executed successfully.
+1. 2-environments executed successfully.
+1. Obtain the value for the access_context_manager_policy_id variable. Can be obtained by running
+
+ ```bash
+ gcloud access-context-manager policies list --organization YOUR_ORGANIZATION_ID --format="value(name)"
+ ```
+
+1. For the manual step described in this document, you need [Terraform](https://www.terraform.io/downloads.html) version 0.13.7 to be installed.
+
+ **Note:** Make sure that you use the same version of Terraform throughout this series. Otherwise, you might experience Terraform state snapshot lock errors.
+
+### Troubleshooting
+
+Please refer to [troubleshooting](../docs/TROUBLESHOOTING.md) if you run into issues during this step.
+
+## Usage
+
+**Note:** If you are using MacOS, replace `cp -RT` with `cp -R` in the relevant
+commands. The `-T` flag is needed for Linux, but causes problems for MacOS.
+
+### Networking Architecture
+
+This step uses the **Hub and Spoke** architecture mode.
+More details can be found at the **Networking** section of the [Google cloud security foundations guide](https://cloud.google.com/architecture/security-foundations/networking#hub-and-spoke).
+To enabled **Hub and Spoke** [transitivity](https://cloud.google.com/architecture/security-foundations/networking#hub-and-spoke_transitivity) set the variable `enable_hub_and_spoke_transitivity ` to `true`.
+To see the version that makes use of the **Dual Shared VPC** architecture mode check the step [3-networks-dual-svpc](../3-networks-dual-svpc).
+
+### Using Dedicated Interconnect
+
+If you provisioned the prerequisites listed in the [Dedicated Interconnect README](./modules/dedicated_interconnect/README.md), follow these steps to enable Dedicated Interconnect to access on-premises resources.
+
+1. Rename `interconnect.tf.example` to `interconnect.tf` in base_env folder in `3-networks-hub-and-spoke/modules/base_env`.
+1. Update the file `interconnect.tf` with values that are valid for your environment for the interconnects, locations, candidate subnetworks, vlan_tag8021q and peer info.
+1. The candidate subnetworks and vlan_tag8021q variables can be set to `null` to allow the interconnect module to auto generate these values.
+
+### Using Partner Interconnect
+
+If you provisioned the prerequisites listed in the [Partner Interconnect README](./modules/partner_interconnect/README.md) follow this steps to enable Partner Interconnect to access on-premises resources.
+
+1. Rename `partner_interconnect.tf.example` to `partner_interconnect.tf` in the base-env folder in `3-networks-hub-and-spoke/modules/base_env` .
+1. Update the file `partner_interconnect.tf` with values that are valid for your environment for the VLAN attachments, locations, and candidate subnetworks.
+1. The candidate subnetworks variable can be set to `null` to allow the interconnect module to auto generate this value.
+
+### OPTIONAL - Using High Availability VPN
+
+If you are not able to use Dedicated or Partner Interconnect, you can also use an HA Cloud VPN to access on-premises resources.
+
+1. Rename `vpn.tf.example` to `vpn.tf` in base-env folder in `3-networks-hub-and-spoke/modules/base_env`.
+1. Create secret for VPN private preshared key.
+ ```
+ echo '' | gcloud secrets create --project --replication-policy=automatic --data-file=-
+ ```
+1. Create secret for VPN restricted preshared key.
+ ```
+ echo '' | gcloud secrets create --project --replication-policy=automatic --data-file=-
+ ```
+1. In the file `vpn.tf`, update the values for `environment`, `vpn_psk_secret_name`, `on_prem_router_ip_address1`, `on_prem_router_ip_address2` and `bgp_peer_asn`.
+1. Verify other default values are valid for your environment.
+
+### Deploying with Cloud Build
+
+1. Clone repo.
+ ```
+ gcloud source repos clone gcp-networks --project=YOUR_CLOUD_BUILD_PROJECT_ID
+ ```
+1. Change to the freshly cloned repo and change to non-main branch.
+ ```
+ cd gcp-networks/
+ git checkout -b plan
+ ```
+1. Copy contents of foundation to new repo.
+ ```
+ cp -RT ../terraform-example-foundation/3-networks-hub-and-spoke/ .
+ ```
+1. Copy Cloud Build configuration files for Terraform.
+ ```
+ cp ../terraform-example-foundation/build/cloudbuild-tf-* .
+ ```
+1. Copy Terraform wrapper script to the root of your new repository.
+ ```
+ cp ../terraform-example-foundation/build/tf-wrapper.sh .
+ ```
+1. Ensure wrapper script can be executed.
+ ```
+ chmod 755 ./tf-wrapper.sh
+ ```
+1. Rename `common.auto.example.tfvars` to `common.auto.tfvars` and update the file with values from your environment and bootstrap. See any of the envs folder [README.md](./envs/production/README.md) files for additional information on the values in the `common.auto.tfvars` file.
+1. Rename `shared.auto.example.tfvars` to `shared.auto.tfvars` and update the file with the `target_name_server_addresses` (the list of target name servers for the DNS forwarding zone in the DNS Hub).
+1. Rename `access_context.auto.example.tfvars` to `access_context.auto.tfvars` and update the file with the `access_context_manager_policy_id`.
+1. Commit changes
+ ```
+ git add .
+ git commit -m 'Your message'
+ ```
+1. You must manually plan and apply the `shared` environment (only once) since the `development`, `non-production` and `production` environments depend on it.
+ 1. Run `cd ./envs/shared/`.
+ 1. Update `backend.tf` with your bucket name from the bootstrap step.
+ 1. Run `terraform init`.
+ 1. Run `terraform plan` and review output.
+ 1. Run `terraform apply`.
+ 1. If you would like the bucket to be replaced by Cloud Build at run time, change the bucket name back to `UPDATE_ME`.
+1. Push your plan branch to trigger a plan for all environments. Because the
+ _plan_ branch is not a [named environment branch](./docs/FAQ.md), pushing your _plan_
+ branch triggers _terraform plan_ but not _terraform apply_.
+ ```
+ cd ../../
+ git push --set-upstream origin plan
+ ```
+1. Review the plan output in your Cloud Build project https://console.cloud.google.com/cloud-build/builds?project=YOUR_CLOUD_BUILD_PROJECT_ID
+1. Merge changes to production. Because this is a [named environment branch](./docs/FAQ.md#what-is-a-named-branch),
+ pushing to this branch triggers both _terraform plan_ and _terraform apply_.
+ ```
+ git checkout -b production
+ git push origin production
+ ```
+1. Review the apply output in your Cloud Build project https://console.cloud.google.com/cloud-build/builds?project=YOUR_CLOUD_BUILD_PROJECT_ID
+1. After production has been applied, apply development.
+1. Merge changes to development. Because this is a [named environment branch](./docs/FAQ.md#what-is-a-named-branch),
+ pushing to this branch triggers both _terraform plan_ and _terraform apply_.
+ ```
+ git checkout -b development
+ git push origin development
+ ```
+1. Review the apply output in your Cloud Build project https://console.cloud.google.com/cloud-build/builds?project=YOUR_CLOUD_BUILD_PROJECT_ID
+1. After development has been applied, apply non-production.
+1. Merge changes to non-production. Because this is a [named environment branch](./docs/FAQ.md#what-is-a-named-branch),
+ pushing to this branch triggers both _terraform plan_ and _terraform apply_.
+ ```
+ git checkout -b non-production
+ git push origin non-production
+ ```
+1. Review the apply output in your Cloud Build project https://console.cloud.google.com/cloud-build/builds?project=YOUR_CLOUD_BUILD_PROJECT_ID
+1. You can now move to the instructions in the step [4-projects](../4-projects/README.md).
+
+### Deploying with Jenkins
+
+1. Clone the repo you created manually in 0-bootstrap.
+ ```
+ git clone
+ ```
+1. Navigate into the repo and change to a non-production branch. All subsequent
+ steps assume you are running them from the gcp-environments directory. If
+ you run them from another directory, adjust your copy paths accordingly.
+ ```
+ cd YOUR_NEW_REPO_CLONE-3-networks
+ git checkout -b plan
+ ```
+1. Copy contents of foundation to new repo.
+ ```
+ cp -RT ../terraform-example-foundation/3-networks-hub-and-spoke/ .
+ ```
+1. Copy the Jenkinsfile script to the root of your new repository.
+ ```
+ cp ../terraform-example-foundation/build/Jenkinsfile .
+ ```
+1. Update the variables located in the `environment {}` section of the `Jenkinsfile` with values from your environment:
+ ```
+ _TF_SA_EMAIL
+ _STATE_BUCKET_NAME
+ _PROJECT_ID (the cicd project id)
+ ```
+1. Copy Terraform wrapper script to the root of your new repository.
+ ```
+ cp ../terraform-example-foundation/build/tf-wrapper.sh .
+ ```
+1. Ensure wrapper script can be executed.
+ ```
+ chmod 755 ./tf-wrapper.sh
+ ```
+1. Rename `common.auto.example.tfvars` to `common.auto.tfvars` and update the file with values from your environment and bootstrap. See any of the envs folder [README.md](./envs/production/README.md) files for additional information on the values in the `common.auto.tfvars` file.
+1. Rename `shared.auto.example.tfvars` to `shared.auto.tfvars` and update the file with the `target_name_server_addresses`.
+1. Rename `access_context.auto.example.tfvars` to `access_context.auto.tfvars` and update the file with the `access_context_manager_policy_id`.
+1. Commit changes.
+ ```
+ git add .
+ git commit -m 'Your message'
+ ```
+1. You must manually plan and apply the `shared` environment (only once) since the `development`, `non-production` and `production` environments depend on it.
+ 1. Run `cd ./envs/shared/`.
+ 1. Update `backend.tf` with your bucket name from the bootstrap step.
+ 1. Run `terraform init`.
+ 1. Run `terraform plan` and review output.
+ 1. Run `terraform apply`.
+ 1. If you would like the bucket to be replaced by Cloud Build at run time, change the bucket name back to `UPDATE_ME`.
+1. Push your plan branch.
+ ```
+ git push --set-upstream origin plan
+ ```
+ - Assuming you configured an automatic trigger in your Jenkins Master (see [Jenkins sub-module README](../0-bootstrap/modules/jenkins-agent)), this will trigger a plan. You can also trigger a Jenkins job manually. Given the many options to do this in Jenkins, it is out of the scope of this document see [Jenkins website](http://www.jenkins.io) for more details.
+1. Review the plan output in your Master's web UI.
+1. Merge changes to production branch.
+ ```
+ git checkout -b production
+ git push origin production
+ ```
+1. Review the apply output in your Master's web UI (you might want to use the option to "Scan Multibranch Pipeline Now" in your Jenkins Master UI).
+1. After production has been applied, apply development and non-production.
+1. Merge changes to development
+ ```
+ git checkout -b development
+ git push origin development
+ ```
+1. Review the apply output in your Master's web UI (you might want to use the option to "Scan Multibranch Pipeline Now" in your Jenkins Master UI).
+1. Merge changes to non-production.
+ ```
+ git checkout -b non-production
+ git push origin non-production
+ ```
+1. Review the apply output in your Master's web UI (you might want to use the option to "Scan Multibranch Pipeline Now" in your Jenkins Master UI).
+
+### Run Terraform locally
+
+1. Change into the 3-networks-hub-and-spoke folder.
+1. Run `cp ../build/tf-wrapper.sh .`
+1. Run `chmod 755 ./tf-wrapper.sh`.
+1. Rename `common.auto.example.tfvars` to `common.auto.tfvars` and update the file with values from your environment and bootstrap. See any of the envs folder [README.md](./envs/production/README.md) files for additional information on the values in the `common.auto.tfvars` file.
+1. Rename `shared.auto.example.tfvars` to `shared.auto.tfvars` and update the file with the `target_name_server_addresses`.
+1. Rename `access_context.auto.example.tfvars` to `access_context.auto.tfvars` and update the file with the `access_context_manager_policy_id`.
+1. Update `backend.tf` with your bucket name from the bootstrap step.
+ ```
+ for i in `find -name 'backend.tf'`; do sed -i 's/UPDATE_ME//' $i; done
+ ```
+ You can run `terraform output gcs_bucket_tfstate` in the 0-bootstrap folder to obtain the bucket name.
+
+We will now deploy each of our environments(development/production/non-production) using this script.
+When using Cloud Build or Jenkins as your CI/CD tool each environment corresponds to a branch in the repository for 3-networks-hub-and-spoke step
+and only the corresponding environment is applied.
+
+To use the `validate` option of the `tf-wrapper.sh` script, please follow the [instructions](https://github.com/GoogleCloudPlatform/terraform-validator/blob/main/docs/install.md) in the **Install Terraform Validator** section and install version `v0.4.0` in your system. You will also need to rename the binary from `terraform-validator-` to `terraform-validator` and the `terraform-validator` binary must be in your `PATH`.
+
+1. Run `./tf-wrapper.sh init shared`.
+1. Run `./tf-wrapper.sh plan shared` and review output.
+1. Run `./tf-wrapper.sh validate shared $(pwd)/../policy-library ` and check for violations.
+1. Run `./tf-wrapper.sh apply shared`.
+1. Run `./tf-wrapper.sh init production`.
+1. Run `./tf-wrapper.sh plan production` and review output.
+1. Run `./tf-wrapper.sh validate production $(pwd)/../policy-library ` and check for violations.
+1. Run `./tf-wrapper.sh apply production`.
+1. Run `./tf-wrapper.sh init non-production`.
+1. Run `./tf-wrapper.sh plan non-production` and review output.
+1. Run `./tf-wrapper.sh validate non-production $(pwd)/../policy-library ` and check for violations.
+1. Run `./tf-wrapper.sh apply non-production`.
+1. Run `./tf-wrapper.sh init development`.
+1. Run `./tf-wrapper.sh plan development` and review output.
+1. Run `./tf-wrapper.sh validate development $(pwd)/../policy-library ` and check for violations.
+1. Run `./tf-wrapper.sh apply development`.
+
+If you received any errors or made any changes to the Terraform config or any `.tfvars`you must re-run `./tf-wrapper.sh plan ` before run `./tf-wrapper.sh apply `.
diff --git a/3-networks-hub-and-spoke/access_context.auto.example.tfvars b/3-networks-hub-and-spoke/access_context.auto.example.tfvars
new file mode 100644
index 000000000..d82ecf07c
--- /dev/null
+++ b/3-networks-hub-and-spoke/access_context.auto.example.tfvars
@@ -0,0 +1,17 @@
+/**
+ * Copyright 2022 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.
+ */
+
+access_context_manager_policy_id = 000000000000
diff --git a/3-networks/common.auto.example.tfvars b/3-networks-hub-and-spoke/common.auto.example.tfvars
similarity index 94%
rename from 3-networks/common.auto.example.tfvars
rename to 3-networks-hub-and-spoke/common.auto.example.tfvars
index 7f04f3706..7ae89273f 100644
--- a/3-networks/common.auto.example.tfvars
+++ b/3-networks-hub-and-spoke/common.auto.example.tfvars
@@ -1,5 +1,5 @@
/**
- * Copyright 2021 Google LLC
+ * Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,6 +25,4 @@ domain = "example.com."
// Must be the same value used in previous steps.
//parent_folder = "000000000000"
-//enable_hub_and_spoke = true
-
//enable_hub_and_spoke_transitivity = true
diff --git a/3-networks/envs/development/README.md b/3-networks-hub-and-spoke/envs/development/README.md
similarity index 92%
rename from 3-networks/envs/development/README.md
rename to 3-networks-hub-and-spoke/envs/development/README.md
index 283060501..c69da5279 100644
--- a/3-networks/envs/development/README.md
+++ b/3-networks-hub-and-spoke/envs/development/README.md
@@ -1,13 +1,13 @@
-# 3-networks/development
+# 3-networks-hub-and-spoke/development
-The purpose of this step is to set up base and restricted shared VPCs with default DNS, NAT (optional), Private Service networking, VPC service controls, onprem Dedicated Interconnect, onprem VPN and baseline firewall rules for environment development.
+The purpose of this step is to set up base and restricted shared VPCs with default DNS, NAT (optional), Private Service networking, VPC service controls, onprem Dedicated Interconnect, onprem VPN and baseline firewall rules for environment non-production. This version of the Network step will makes usage of the Hub and Spoke network architecture.
## Prerequisites
1. 0-bootstrap executed successfully.
1. 1-org executed successfully.
1. 2-environments/envs/development executed successfully.
-1. 3-networks/envs/shared executed successfully.
+1. 3-networks-hub-and-spoke/envs/shared executed successfully.
1. Obtain the value for the access_context_manager_policy_id variable. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR_ORGANIZATION_ID --format="value(name)"`.
@@ -17,7 +17,6 @@ The purpose of this step is to set up base and restricted shared VPCs with defau
|------|-------------|------|---------|:--------:|
| 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 |
| domain | The DNS name of peering managed zone, for instance 'example.com.'. Must end with a period. | `string` | n/a | yes |
-| enable\_hub\_and\_spoke | Enable Hub-and-Spoke architecture. | `bool` | `false` | no |
| enable\_hub\_and\_spoke\_transitivity | Enable transitivity via gateway VMs on Hub-and-Spoke architecture. | `bool` | `false` | no |
| folder\_prefix | Name prefix to use for folders created. Should be the same in all steps. | `string` | `"fldr"` | no |
| org\_id | Organization ID | `string` | n/a | yes |
diff --git a/3-networks-hub-and-spoke/envs/development/access_context.auto.tfvars b/3-networks-hub-and-spoke/envs/development/access_context.auto.tfvars
new file mode 120000
index 000000000..b0cccce77
--- /dev/null
+++ b/3-networks-hub-and-spoke/envs/development/access_context.auto.tfvars
@@ -0,0 +1 @@
+../../access_context.auto.tfvars
\ No newline at end of file
diff --git a/3-networks-hub-and-spoke/envs/development/backend.tf b/3-networks-hub-and-spoke/envs/development/backend.tf
new file mode 100644
index 000000000..3dac4ea1b
--- /dev/null
+++ b/3-networks-hub-and-spoke/envs/development/backend.tf
@@ -0,0 +1,22 @@
+/**
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+terraform {
+ backend "gcs" {
+ bucket = "UPDATE_ME"
+ prefix = "terraform/networks/development"
+ }
+}
diff --git a/3-networks-hub-and-spoke/envs/development/common.auto.tfvars b/3-networks-hub-and-spoke/envs/development/common.auto.tfvars
new file mode 120000
index 000000000..39aaa4621
--- /dev/null
+++ b/3-networks-hub-and-spoke/envs/development/common.auto.tfvars
@@ -0,0 +1 @@
+../../common.auto.tfvars
\ No newline at end of file
diff --git a/3-networks/envs/development/main.tf b/3-networks-hub-and-spoke/envs/development/main.tf
similarity index 97%
rename from 3-networks/envs/development/main.tf
rename to 3-networks-hub-and-spoke/envs/development/main.tf
index 71cae3824..bcbe2b8e8 100644
--- a/3-networks/envs/development/main.tf
+++ b/3-networks-hub-and-spoke/envs/development/main.tf
@@ -1,5 +1,5 @@
/**
- * Copyright 2021 Google LLC
+ * Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -73,7 +73,6 @@ module "base_env" {
default_region2 = local.default_region2
domain = var.domain
parent_folder = var.parent_folder
- enable_hub_and_spoke = var.enable_hub_and_spoke
enable_partner_interconnect = false
enable_hub_and_spoke_transitivity = var.enable_hub_and_spoke_transitivity
base_private_service_cidr = local.base_private_service_cidr
diff --git a/3-networks-hub-and-spoke/envs/development/outputs.tf b/3-networks-hub-and-spoke/envs/development/outputs.tf
new file mode 100644
index 000000000..673db1adf
--- /dev/null
+++ b/3-networks-hub-and-spoke/envs/development/outputs.tf
@@ -0,0 +1,103 @@
+/**
+ * Copyright 2022 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.
+ */
+
+/*********************
+ Restricted Outputs
+*********************/
+
+output "restricted_host_project_id" {
+ value = module.base_env.restricted_host_project_id
+ description = "The restricted host project ID"
+}
+
+output "restricted_network_name" {
+ value = module.base_env.restricted_network_name
+ description = "The name of the VPC being created"
+}
+
+output "restricted_network_self_link" {
+ value = module.base_env.restricted_network_self_link
+ description = "The URI of the VPC being created"
+}
+
+output "restricted_subnets_names" {
+ value = module.base_env.restricted_subnets_names
+ description = "The names of the subnets being created"
+}
+
+output "restricted_subnets_ips" {
+ value = module.base_env.restricted_subnets_ips
+ description = "The IPs and CIDRs of the subnets being created"
+}
+
+output "restricted_subnets_self_links" {
+ value = module.base_env.restricted_subnets_self_links
+ description = "The self-links of subnets being created"
+}
+
+output "restricted_subnets_secondary_ranges" {
+ value = module.base_env.restricted_subnets_secondary_ranges
+ description = "The secondary ranges associated with these subnets"
+}
+
+output "restricted_access_level_name" {
+ value = module.base_env.restricted_access_level_name
+ description = "Access context manager access level name"
+}
+
+output "restricted_service_perimeter_name" {
+ value = module.base_env.restricted_service_perimeter_name
+ description = "Access context manager service perimeter name"
+}
+
+/******************************************
+ Private Outputs
+*****************************************/
+
+output "base_host_project_id" {
+ value = module.base_env.base_host_project_id
+ description = "The base host project ID"
+}
+
+output "base_network_name" {
+ value = module.base_env.base_network_name
+ description = "The name of the VPC being created"
+}
+
+output "base_network_self_link" {
+ value = module.base_env.base_network_self_link
+ description = "The URI of the VPC being created"
+}
+
+output "base_subnets_names" {
+ value = module.base_env.base_subnets_names
+ description = "The names of the subnets being created"
+}
+
+output "base_subnets_ips" {
+ value = module.base_env.base_subnets_ips
+ description = "The IPs and CIDRs of the subnets being created"
+}
+
+output "base_subnets_self_links" {
+ value = module.base_env.base_subnets_self_links
+ description = "The self-links of subnets being created"
+}
+
+output "base_subnets_secondary_ranges" {
+ value = module.base_env.base_subnets_secondary_ranges
+ description = "The secondary ranges associated with these subnets"
+}
diff --git a/3-networks-hub-and-spoke/envs/development/providers.tf b/3-networks-hub-and-spoke/envs/development/providers.tf
new file mode 100644
index 000000000..0d58ec1d2
--- /dev/null
+++ b/3-networks-hub-and-spoke/envs/development/providers.tf
@@ -0,0 +1,33 @@
+/**
+ * Copyright 2022 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 {
+ tf_sa = var.terraform_service_account
+}
+
+
+/******************************************
+ Provider credential configuration
+ *****************************************/
+provider "google" {
+ impersonate_service_account = local.tf_sa
+ request_timeout = "120s"
+}
+
+provider "google-beta" {
+ impersonate_service_account = local.tf_sa
+ request_timeout = "120s"
+}
diff --git a/3-networks/envs/development/variables.tf b/3-networks-hub-and-spoke/envs/development/variables.tf
similarity index 92%
rename from 3-networks/envs/development/variables.tf
rename to 3-networks-hub-and-spoke/envs/development/variables.tf
index 33635473d..54db4c2b8 100644
--- a/3-networks/envs/development/variables.tf
+++ b/3-networks-hub-and-spoke/envs/development/variables.tf
@@ -1,5 +1,5 @@
/**
- * Copyright 2021 Google LLC
+ * Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -46,12 +46,6 @@ variable "folder_prefix" {
default = "fldr"
}
-variable "enable_hub_and_spoke" {
- description = "Enable Hub-and-Spoke architecture."
- type = bool
- default = false
-}
-
variable "enable_hub_and_spoke_transitivity" {
description = "Enable transitivity via gateway VMs on Hub-and-Spoke architecture."
type = bool
diff --git a/3-networks-hub-and-spoke/envs/development/versions.tf b/3-networks-hub-and-spoke/envs/development/versions.tf
new file mode 100644
index 000000000..6256afb3a
--- /dev/null
+++ b/3-networks-hub-and-spoke/envs/development/versions.tf
@@ -0,0 +1,29 @@
+/**
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+terraform {
+ required_version = ">= 0.13"
+ required_providers {
+ google = {
+ source = "hashicorp/google"
+ version = ">= 3.50"
+ }
+ google-beta = {
+ source = "hashicorp/google-beta"
+ version = ">= 3.50"
+ }
+ }
+}
diff --git a/3-networks/envs/non-production/README.md b/3-networks-hub-and-spoke/envs/non-production/README.md
similarity index 92%
rename from 3-networks/envs/non-production/README.md
rename to 3-networks-hub-and-spoke/envs/non-production/README.md
index 504837071..4d4ba7002 100644
--- a/3-networks/envs/non-production/README.md
+++ b/3-networks-hub-and-spoke/envs/non-production/README.md
@@ -1,13 +1,13 @@
-# 3-networks/non-production
+# 3-networks-hub-and-spoke/non-production
-The purpose of this step is to set up base and restricted shared VPCs with default DNS, NAT (optional), Private Service networking, VPC service controls, onprem Dedicated Interconnect, onprem VPN and baseline firewall rules for environment non-production.
+The purpose of this step is to set up base and restricted shared VPCs with default DNS, NAT (optional), Private Service networking, VPC service controls, onprem Dedicated Interconnect, onprem VPN and baseline firewall rules for environment non-production. This version of the Network step will makes usage of the Hub and Spoke network architecture.
## Prerequisites
1. 0-bootstrap executed successfully.
1. 1-org executed successfully.
1. 2-environments/envs/non-production executed successfully.
-1. 3-networks/envs/shared executed successfully.
+1. 3-networks-hub-and-spoke/envs/shared executed successfully.
1. Obtain the value for the access_context_manager_policy_id variable. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR_ORGANIZATION_ID --format="value(name)"`.
@@ -17,7 +17,6 @@ The purpose of this step is to set up base and restricted shared VPCs with defau
|------|-------------|------|---------|:--------:|
| 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 |
| domain | The DNS name of peering managed zone, for instance 'example.com.'. Must end with a period. | `string` | n/a | yes |
-| enable\_hub\_and\_spoke | Enable Hub-and-Spoke architecture. | `bool` | `false` | no |
| enable\_hub\_and\_spoke\_transitivity | Enable transitivity via gateway VMs on Hub-and-Spoke architecture. | `bool` | `false` | no |
| folder\_prefix | Name prefix to use for folders created. Should be the same in all steps. | `string` | `"fldr"` | no |
| org\_id | Organization ID | `string` | n/a | yes |
diff --git a/3-networks-hub-and-spoke/envs/non-production/access_context.auto.tfvars b/3-networks-hub-and-spoke/envs/non-production/access_context.auto.tfvars
new file mode 120000
index 000000000..b0cccce77
--- /dev/null
+++ b/3-networks-hub-and-spoke/envs/non-production/access_context.auto.tfvars
@@ -0,0 +1 @@
+../../access_context.auto.tfvars
\ No newline at end of file
diff --git a/3-networks-hub-and-spoke/envs/non-production/backend.tf b/3-networks-hub-and-spoke/envs/non-production/backend.tf
new file mode 100644
index 000000000..a9cc89401
--- /dev/null
+++ b/3-networks-hub-and-spoke/envs/non-production/backend.tf
@@ -0,0 +1,22 @@
+/**
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+terraform {
+ backend "gcs" {
+ bucket = "UPDATE_ME"
+ prefix = "terraform/networks/non-production"
+ }
+}
diff --git a/3-networks-hub-and-spoke/envs/non-production/common.auto.tfvars b/3-networks-hub-and-spoke/envs/non-production/common.auto.tfvars
new file mode 120000
index 000000000..39aaa4621
--- /dev/null
+++ b/3-networks-hub-and-spoke/envs/non-production/common.auto.tfvars
@@ -0,0 +1 @@
+../../common.auto.tfvars
\ No newline at end of file
diff --git a/3-networks/envs/non-production/main.tf b/3-networks-hub-and-spoke/envs/non-production/main.tf
similarity index 97%
rename from 3-networks/envs/non-production/main.tf
rename to 3-networks-hub-and-spoke/envs/non-production/main.tf
index 8c15ab937..c66ec87f0 100644
--- a/3-networks/envs/non-production/main.tf
+++ b/3-networks-hub-and-spoke/envs/non-production/main.tf
@@ -1,5 +1,5 @@
/**
- * Copyright 2021 Google LLC
+ * Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -73,7 +73,6 @@ module "base_env" {
default_region2 = local.default_region2
domain = var.domain
parent_folder = var.parent_folder
- enable_hub_and_spoke = var.enable_hub_and_spoke
enable_partner_interconnect = false
enable_hub_and_spoke_transitivity = var.enable_hub_and_spoke_transitivity
base_private_service_cidr = local.base_private_service_cidr
diff --git a/3-networks-hub-and-spoke/envs/non-production/outputs.tf b/3-networks-hub-and-spoke/envs/non-production/outputs.tf
new file mode 100644
index 000000000..673db1adf
--- /dev/null
+++ b/3-networks-hub-and-spoke/envs/non-production/outputs.tf
@@ -0,0 +1,103 @@
+/**
+ * Copyright 2022 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.
+ */
+
+/*********************
+ Restricted Outputs
+*********************/
+
+output "restricted_host_project_id" {
+ value = module.base_env.restricted_host_project_id
+ description = "The restricted host project ID"
+}
+
+output "restricted_network_name" {
+ value = module.base_env.restricted_network_name
+ description = "The name of the VPC being created"
+}
+
+output "restricted_network_self_link" {
+ value = module.base_env.restricted_network_self_link
+ description = "The URI of the VPC being created"
+}
+
+output "restricted_subnets_names" {
+ value = module.base_env.restricted_subnets_names
+ description = "The names of the subnets being created"
+}
+
+output "restricted_subnets_ips" {
+ value = module.base_env.restricted_subnets_ips
+ description = "The IPs and CIDRs of the subnets being created"
+}
+
+output "restricted_subnets_self_links" {
+ value = module.base_env.restricted_subnets_self_links
+ description = "The self-links of subnets being created"
+}
+
+output "restricted_subnets_secondary_ranges" {
+ value = module.base_env.restricted_subnets_secondary_ranges
+ description = "The secondary ranges associated with these subnets"
+}
+
+output "restricted_access_level_name" {
+ value = module.base_env.restricted_access_level_name
+ description = "Access context manager access level name"
+}
+
+output "restricted_service_perimeter_name" {
+ value = module.base_env.restricted_service_perimeter_name
+ description = "Access context manager service perimeter name"
+}
+
+/******************************************
+ Private Outputs
+*****************************************/
+
+output "base_host_project_id" {
+ value = module.base_env.base_host_project_id
+ description = "The base host project ID"
+}
+
+output "base_network_name" {
+ value = module.base_env.base_network_name
+ description = "The name of the VPC being created"
+}
+
+output "base_network_self_link" {
+ value = module.base_env.base_network_self_link
+ description = "The URI of the VPC being created"
+}
+
+output "base_subnets_names" {
+ value = module.base_env.base_subnets_names
+ description = "The names of the subnets being created"
+}
+
+output "base_subnets_ips" {
+ value = module.base_env.base_subnets_ips
+ description = "The IPs and CIDRs of the subnets being created"
+}
+
+output "base_subnets_self_links" {
+ value = module.base_env.base_subnets_self_links
+ description = "The self-links of subnets being created"
+}
+
+output "base_subnets_secondary_ranges" {
+ value = module.base_env.base_subnets_secondary_ranges
+ description = "The secondary ranges associated with these subnets"
+}
diff --git a/3-networks-hub-and-spoke/envs/non-production/providers.tf b/3-networks-hub-and-spoke/envs/non-production/providers.tf
new file mode 100644
index 000000000..0d58ec1d2
--- /dev/null
+++ b/3-networks-hub-and-spoke/envs/non-production/providers.tf
@@ -0,0 +1,33 @@
+/**
+ * Copyright 2022 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 {
+ tf_sa = var.terraform_service_account
+}
+
+
+/******************************************
+ Provider credential configuration
+ *****************************************/
+provider "google" {
+ impersonate_service_account = local.tf_sa
+ request_timeout = "120s"
+}
+
+provider "google-beta" {
+ impersonate_service_account = local.tf_sa
+ request_timeout = "120s"
+}
diff --git a/3-networks/envs/non-production/variables.tf b/3-networks-hub-and-spoke/envs/non-production/variables.tf
similarity index 92%
rename from 3-networks/envs/non-production/variables.tf
rename to 3-networks-hub-and-spoke/envs/non-production/variables.tf
index 33635473d..54db4c2b8 100644
--- a/3-networks/envs/non-production/variables.tf
+++ b/3-networks-hub-and-spoke/envs/non-production/variables.tf
@@ -1,5 +1,5 @@
/**
- * Copyright 2021 Google LLC
+ * Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -46,12 +46,6 @@ variable "folder_prefix" {
default = "fldr"
}
-variable "enable_hub_and_spoke" {
- description = "Enable Hub-and-Spoke architecture."
- type = bool
- default = false
-}
-
variable "enable_hub_and_spoke_transitivity" {
description = "Enable transitivity via gateway VMs on Hub-and-Spoke architecture."
type = bool
diff --git a/3-networks-hub-and-spoke/envs/non-production/versions.tf b/3-networks-hub-and-spoke/envs/non-production/versions.tf
new file mode 100644
index 000000000..6256afb3a
--- /dev/null
+++ b/3-networks-hub-and-spoke/envs/non-production/versions.tf
@@ -0,0 +1,29 @@
+/**
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+terraform {
+ required_version = ">= 0.13"
+ required_providers {
+ google = {
+ source = "hashicorp/google"
+ version = ">= 3.50"
+ }
+ google-beta = {
+ source = "hashicorp/google-beta"
+ version = ">= 3.50"
+ }
+ }
+}
diff --git a/3-networks/envs/production/README.md b/3-networks-hub-and-spoke/envs/production/README.md
similarity index 92%
rename from 3-networks/envs/production/README.md
rename to 3-networks-hub-and-spoke/envs/production/README.md
index 0b29099ce..8c462d3a8 100644
--- a/3-networks/envs/production/README.md
+++ b/3-networks-hub-and-spoke/envs/production/README.md
@@ -1,13 +1,13 @@
-# 3-networks/production
+# 3-networks-hub-and-spoke/production
-The purpose of this step is to set up base and restricted shared VPCs with default DNS, NAT (optional), Private Service networking, VPC service controls, onprem Dedicated Interconnect, onprem VPN and baseline firewall rules for environment production.
+The purpose of this step is to set up base and restricted shared VPCs with default DNS, NAT (optional), Private Service networking, VPC service controls, onprem Dedicated Interconnect, onprem VPN and baseline firewall rules for environment non-production. This version of the Network step will makes usage of the Hub and Spoke network architecture.
## Prerequisites
1. 0-bootstrap executed successfully.
1. 1-org executed successfully.
1. 2-environments/envs/production executed successfully.
-1. 3-networks/envs/shared executed successfully.
+1. 3-networks-hub-and-spoke/envs/shared executed successfully.
1. Obtain the value for the access_context_manager_policy_id variable. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR_ORGANIZATION_ID --format="value(name)"`.
@@ -17,7 +17,6 @@ The purpose of this step is to set up base and restricted shared VPCs with defau
|------|-------------|------|---------|:--------:|
| 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 |
| domain | The DNS name of peering managed zone, for instance 'example.com.'. Must end with a period. | `string` | n/a | yes |
-| enable\_hub\_and\_spoke | Enable Hub-and-Spoke architecture. | `bool` | `false` | no |
| enable\_hub\_and\_spoke\_transitivity | Enable transitivity via gateway VMs on Hub-and-Spoke architecture. | `bool` | `false` | no |
| folder\_prefix | Name prefix to use for folders created. Should be the same in all steps. | `string` | `"fldr"` | no |
| org\_id | Organization ID | `string` | n/a | yes |
diff --git a/3-networks-hub-and-spoke/envs/production/access_context.auto.tfvars b/3-networks-hub-and-spoke/envs/production/access_context.auto.tfvars
new file mode 120000
index 000000000..b0cccce77
--- /dev/null
+++ b/3-networks-hub-and-spoke/envs/production/access_context.auto.tfvars
@@ -0,0 +1 @@
+../../access_context.auto.tfvars
\ No newline at end of file
diff --git a/3-networks-hub-and-spoke/envs/production/backend.tf b/3-networks-hub-and-spoke/envs/production/backend.tf
new file mode 100644
index 000000000..2d4799c72
--- /dev/null
+++ b/3-networks-hub-and-spoke/envs/production/backend.tf
@@ -0,0 +1,22 @@
+/**
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+terraform {
+ backend "gcs" {
+ bucket = "UPDATE_ME"
+ prefix = "terraform/networks/production"
+ }
+}
diff --git a/3-networks-hub-and-spoke/envs/production/common.auto.tfvars b/3-networks-hub-and-spoke/envs/production/common.auto.tfvars
new file mode 120000
index 000000000..39aaa4621
--- /dev/null
+++ b/3-networks-hub-and-spoke/envs/production/common.auto.tfvars
@@ -0,0 +1 @@
+../../common.auto.tfvars
\ No newline at end of file
diff --git a/3-networks/envs/production/main.tf b/3-networks-hub-and-spoke/envs/production/main.tf
similarity index 97%
rename from 3-networks/envs/production/main.tf
rename to 3-networks-hub-and-spoke/envs/production/main.tf
index 617104d9c..0cb2acc2e 100644
--- a/3-networks/envs/production/main.tf
+++ b/3-networks-hub-and-spoke/envs/production/main.tf
@@ -1,5 +1,5 @@
/**
- * Copyright 2021 Google LLC
+ * Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -73,7 +73,6 @@ module "base_env" {
default_region2 = local.default_region2
domain = var.domain
parent_folder = var.parent_folder
- enable_hub_and_spoke = var.enable_hub_and_spoke
enable_partner_interconnect = false
enable_hub_and_spoke_transitivity = var.enable_hub_and_spoke_transitivity
base_private_service_cidr = local.base_private_service_cidr
diff --git a/3-networks-hub-and-spoke/envs/production/outputs.tf b/3-networks-hub-and-spoke/envs/production/outputs.tf
new file mode 100644
index 000000000..673db1adf
--- /dev/null
+++ b/3-networks-hub-and-spoke/envs/production/outputs.tf
@@ -0,0 +1,103 @@
+/**
+ * Copyright 2022 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.
+ */
+
+/*********************
+ Restricted Outputs
+*********************/
+
+output "restricted_host_project_id" {
+ value = module.base_env.restricted_host_project_id
+ description = "The restricted host project ID"
+}
+
+output "restricted_network_name" {
+ value = module.base_env.restricted_network_name
+ description = "The name of the VPC being created"
+}
+
+output "restricted_network_self_link" {
+ value = module.base_env.restricted_network_self_link
+ description = "The URI of the VPC being created"
+}
+
+output "restricted_subnets_names" {
+ value = module.base_env.restricted_subnets_names
+ description = "The names of the subnets being created"
+}
+
+output "restricted_subnets_ips" {
+ value = module.base_env.restricted_subnets_ips
+ description = "The IPs and CIDRs of the subnets being created"
+}
+
+output "restricted_subnets_self_links" {
+ value = module.base_env.restricted_subnets_self_links
+ description = "The self-links of subnets being created"
+}
+
+output "restricted_subnets_secondary_ranges" {
+ value = module.base_env.restricted_subnets_secondary_ranges
+ description = "The secondary ranges associated with these subnets"
+}
+
+output "restricted_access_level_name" {
+ value = module.base_env.restricted_access_level_name
+ description = "Access context manager access level name"
+}
+
+output "restricted_service_perimeter_name" {
+ value = module.base_env.restricted_service_perimeter_name
+ description = "Access context manager service perimeter name"
+}
+
+/******************************************
+ Private Outputs
+*****************************************/
+
+output "base_host_project_id" {
+ value = module.base_env.base_host_project_id
+ description = "The base host project ID"
+}
+
+output "base_network_name" {
+ value = module.base_env.base_network_name
+ description = "The name of the VPC being created"
+}
+
+output "base_network_self_link" {
+ value = module.base_env.base_network_self_link
+ description = "The URI of the VPC being created"
+}
+
+output "base_subnets_names" {
+ value = module.base_env.base_subnets_names
+ description = "The names of the subnets being created"
+}
+
+output "base_subnets_ips" {
+ value = module.base_env.base_subnets_ips
+ description = "The IPs and CIDRs of the subnets being created"
+}
+
+output "base_subnets_self_links" {
+ value = module.base_env.base_subnets_self_links
+ description = "The self-links of subnets being created"
+}
+
+output "base_subnets_secondary_ranges" {
+ value = module.base_env.base_subnets_secondary_ranges
+ description = "The secondary ranges associated with these subnets"
+}
diff --git a/3-networks-hub-and-spoke/envs/production/providers.tf b/3-networks-hub-and-spoke/envs/production/providers.tf
new file mode 100644
index 000000000..0d58ec1d2
--- /dev/null
+++ b/3-networks-hub-and-spoke/envs/production/providers.tf
@@ -0,0 +1,33 @@
+/**
+ * Copyright 2022 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 {
+ tf_sa = var.terraform_service_account
+}
+
+
+/******************************************
+ Provider credential configuration
+ *****************************************/
+provider "google" {
+ impersonate_service_account = local.tf_sa
+ request_timeout = "120s"
+}
+
+provider "google-beta" {
+ impersonate_service_account = local.tf_sa
+ request_timeout = "120s"
+}
diff --git a/3-networks/envs/production/variables.tf b/3-networks-hub-and-spoke/envs/production/variables.tf
similarity index 92%
rename from 3-networks/envs/production/variables.tf
rename to 3-networks-hub-and-spoke/envs/production/variables.tf
index 33635473d..54db4c2b8 100644
--- a/3-networks/envs/production/variables.tf
+++ b/3-networks-hub-and-spoke/envs/production/variables.tf
@@ -1,5 +1,5 @@
/**
- * Copyright 2021 Google LLC
+ * Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -46,12 +46,6 @@ variable "folder_prefix" {
default = "fldr"
}
-variable "enable_hub_and_spoke" {
- description = "Enable Hub-and-Spoke architecture."
- type = bool
- default = false
-}
-
variable "enable_hub_and_spoke_transitivity" {
description = "Enable transitivity via gateway VMs on Hub-and-Spoke architecture."
type = bool
diff --git a/3-networks-hub-and-spoke/envs/production/versions.tf b/3-networks-hub-and-spoke/envs/production/versions.tf
new file mode 100644
index 000000000..6256afb3a
--- /dev/null
+++ b/3-networks-hub-and-spoke/envs/production/versions.tf
@@ -0,0 +1,29 @@
+/**
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+terraform {
+ required_version = ">= 0.13"
+ required_providers {
+ google = {
+ source = "hashicorp/google"
+ version = ">= 3.50"
+ }
+ google-beta = {
+ source = "hashicorp/google-beta"
+ version = ">= 3.50"
+ }
+ }
+}
diff --git a/3-networks/envs/shared/README.md b/3-networks-hub-and-spoke/envs/shared/README.md
similarity index 94%
rename from 3-networks/envs/shared/README.md
rename to 3-networks-hub-and-spoke/envs/shared/README.md
index 887b5e361..af1760d1d 100644
--- a/3-networks/envs/shared/README.md
+++ b/3-networks-hub-and-spoke/envs/shared/README.md
@@ -1,6 +1,6 @@
-# 3-networks/shared
+# 3-networks-hub-and-spoke/shared
-The purpose of this step is to set up the global [DNS Hub](https://cloud.google.com/blog/products/networking/cloud-forwarding-peering-and-zones) that will be used by all environments.
+The purpose of this step is to set up the global [DNS Hub](https://cloud.google.com/blog/products/networking/cloud-forwarding-peering-and-zones) that will be used by all environments. This step will also create the Network Hubs that are part of the [Hub and Spoke](https://cloud.google.com/architecture/security-foundations/networking#hub-and-spoke) setup.
## Prerequisites
@@ -24,7 +24,6 @@ The purpose of this step is to set up the global [DNS Hub](https://cloud.google.
| bgp\_asn\_dns | BGP Autonomous System Number (ASN). | `number` | `64667` | no |
| dns\_enable\_logging | Toggle DNS logging for VPC DNS. | `bool` | `true` | no |
| domain | The DNS name of forwarding managed zone, for instance 'example.com'. Must end with a period. | `string` | n/a | yes |
-| enable\_hub\_and\_spoke | Enable Hub-and-Spoke architecture. | `bool` | `false` | no |
| enable\_hub\_and\_spoke\_transitivity | Enable transitivity via gateway VMs on Hub-and-Spoke architecture. | `bool` | `false` | no |
| enable\_partner\_interconnect | Enable Partner Interconnect in the environment. | `bool` | `false` | no |
| firewall\_policies\_enable\_logging | Toggle hierarchical firewall logging. | `bool` | `true` | no |
diff --git a/3-networks-hub-and-spoke/envs/shared/access_context.auto.tfvars b/3-networks-hub-and-spoke/envs/shared/access_context.auto.tfvars
new file mode 120000
index 000000000..b0cccce77
--- /dev/null
+++ b/3-networks-hub-and-spoke/envs/shared/access_context.auto.tfvars
@@ -0,0 +1 @@
+../../access_context.auto.tfvars
\ No newline at end of file
diff --git a/3-networks-hub-and-spoke/envs/shared/backend.tf b/3-networks-hub-and-spoke/envs/shared/backend.tf
new file mode 100644
index 000000000..43a5655da
--- /dev/null
+++ b/3-networks-hub-and-spoke/envs/shared/backend.tf
@@ -0,0 +1,22 @@
+/**
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+terraform {
+ backend "gcs" {
+ bucket = "UPDATE_ME"
+ prefix = "terraform/networks/envs/shared"
+ }
+}
diff --git a/3-networks-hub-and-spoke/envs/shared/common.auto.tfvars b/3-networks-hub-and-spoke/envs/shared/common.auto.tfvars
new file mode 120000
index 000000000..39aaa4621
--- /dev/null
+++ b/3-networks-hub-and-spoke/envs/shared/common.auto.tfvars
@@ -0,0 +1 @@
+../../common.auto.tfvars
\ No newline at end of file
diff --git a/3-networks-hub-and-spoke/envs/shared/dns-hub.tf b/3-networks-hub-and-spoke/envs/shared/dns-hub.tf
new file mode 100644
index 000000000..848cfab11
--- /dev/null
+++ b/3-networks-hub-and-spoke/envs/shared/dns-hub.tf
@@ -0,0 +1,174 @@
+/**
+ * Copyright 2022 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 {
+ dns_hub_project_id = data.google_projects.dns_hub.projects[0].project_id
+}
+
+data "google_active_folder" "bootstrap" {
+ display_name = "${var.folder_prefix}-bootstrap"
+ parent = local.parent_id
+}
+
+data "google_active_folder" "development" {
+ display_name = "${var.folder_prefix}-development"
+ parent = local.parent_id
+}
+
+data "google_active_folder" "production" {
+ display_name = "${var.folder_prefix}-production"
+ parent = local.parent_id
+}
+
+data "google_active_folder" "non-production" {
+ display_name = "${var.folder_prefix}-non-production"
+ parent = local.parent_id
+}
+
+/******************************************
+ DNS Hub Project
+*****************************************/
+
+data "google_projects" "dns_hub" {
+ filter = "parent.id:${split("/", data.google_active_folder.common.name)[1]} labels.application_name=org-dns-hub lifecycleState=ACTIVE"
+}
+
+
+/******************************************
+ DNS Hub VPC
+*****************************************/
+
+module "dns_hub_vpc" {
+ source = "terraform-google-modules/network/google"
+ version = "~> 5.1"
+ project_id = local.dns_hub_project_id
+ network_name = "vpc-c-dns-hub"
+ shared_vpc_host = "false"
+ delete_default_internet_gateway_routes = "true"
+
+ subnets = [{
+ subnet_name = "sb-c-dns-hub-${local.default_region1}"
+ subnet_ip = "172.16.0.0/25"
+ subnet_region = local.default_region1
+ subnet_private_access = "true"
+ subnet_flow_logs = var.subnetworks_enable_logging
+ description = "DNS hub subnet for region 1."
+ }, {
+ subnet_name = "sb-c-dns-hub-${local.default_region2}"
+ subnet_ip = "172.16.0.128/25"
+ subnet_region = local.default_region2
+ subnet_private_access = "true"
+ subnet_flow_logs = var.subnetworks_enable_logging
+ description = "DNS hub subnet for region 2."
+ }]
+
+ routes = [{
+ name = "rt-c-dns-hub-1000-all-default-private-api"
+ description = "Route through IGW to allow private google api access."
+ destination_range = "199.36.153.8/30"
+ next_hop_internet = "true"
+ priority = "1000"
+ }]
+}
+
+/******************************************
+ Default DNS Policy
+ *****************************************/
+
+resource "google_dns_policy" "default_policy" {
+ project = local.dns_hub_project_id
+ name = "dp-dns-hub-default-policy"
+ enable_inbound_forwarding = true
+ enable_logging = var.dns_enable_logging
+ networks {
+ network_url = module.dns_hub_vpc.network_self_link
+ }
+}
+
+/******************************************
+ DNS Forwarding
+*****************************************/
+
+module "dns-forwarding-zone" {
+ source = "terraform-google-modules/cloud-dns/google"
+ version = "3.0.2"
+
+ project_id = local.dns_hub_project_id
+ type = "forwarding"
+ name = "fz-dns-hub"
+ domain = var.domain
+
+ private_visibility_config_networks = [
+ module.dns_hub_vpc.network_self_link
+ ]
+ target_name_server_addresses = var.target_name_server_addresses
+}
+
+/*********************************************************
+ Routers to advertise DNS proxy range "35.199.192.0/19"
+*********************************************************/
+
+module "dns_hub_region1_router1" {
+ source = "terraform-google-modules/cloud-router/google"
+ version = "~> 2.0"
+ name = "cr-c-dns-hub-${local.default_region1}-cr1"
+ project = local.dns_hub_project_id
+ network = module.dns_hub_vpc.network_name
+ region = local.default_region1
+ bgp = {
+ asn = var.bgp_asn_dns
+ advertised_ip_ranges = [{ range = "35.199.192.0/19" }]
+ }
+}
+
+module "dns_hub_region1_router2" {
+ source = "terraform-google-modules/cloud-router/google"
+ version = "~> 2.0"
+ name = "cr-c-dns-hub-${local.default_region1}-cr2"
+ project = local.dns_hub_project_id
+ network = module.dns_hub_vpc.network_name
+ region = local.default_region1
+ bgp = {
+ asn = var.bgp_asn_dns
+ advertised_ip_ranges = [{ range = "35.199.192.0/19" }]
+ }
+}
+
+module "dns_hub_region2_router1" {
+ source = "terraform-google-modules/cloud-router/google"
+ version = "~> 2.0"
+ name = "cr-c-dns-hub-${local.default_region2}-cr3"
+ project = local.dns_hub_project_id
+ network = module.dns_hub_vpc.network_name
+ region = local.default_region2
+ bgp = {
+ asn = var.bgp_asn_dns
+ advertised_ip_ranges = [{ range = "35.199.192.0/19" }]
+ }
+}
+
+module "dns_hub_region2_router2" {
+ source = "terraform-google-modules/cloud-router/google"
+ version = "~> 2.0"
+ name = "cr-c-dns-hub-${local.default_region2}-cr4"
+ project = local.dns_hub_project_id
+ network = module.dns_hub_vpc.network_name
+ region = local.default_region2
+ bgp = {
+ asn = var.bgp_asn_dns
+ advertised_ip_ranges = [{ range = "35.199.192.0/19" }]
+ }
+}
diff --git a/3-networks-hub-and-spoke/envs/shared/hierarchical_firewall.tf b/3-networks-hub-and-spoke/envs/shared/hierarchical_firewall.tf
new file mode 100644
index 000000000..db9202fb8
--- /dev/null
+++ b/3-networks-hub-and-spoke/envs/shared/hierarchical_firewall.tf
@@ -0,0 +1,104 @@
+/**
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+module "hierarchical_firewall_policy" {
+ source = "../../modules/hierarchical_firewall_policy/"
+ parent = data.google_active_folder.common.name
+ name = "common-firewall-rules"
+ associations = [
+ data.google_active_folder.common.name,
+ data.google_active_folder.bootstrap.name,
+ data.google_active_folder.development.name,
+ data.google_active_folder.production.name,
+ data.google_active_folder.non-production.name,
+ ]
+ rules = {
+ delegate-rfc1918-ingress = {
+ description = "Delegate RFC1918 ingress"
+ direction = "INGRESS"
+ action = "goto_next"
+ priority = 500
+ ranges = [
+ "192.168.0.0/16",
+ "10.0.0.0/8",
+ "172.16.0.0/12"
+ ]
+ ports = { "all" = [] }
+ target_service_accounts = null
+ target_resources = null
+ logging = false
+ }
+ delegate-rfc1918-egress = {
+ description = "Delegate RFC1918 egress"
+ direction = "EGRESS"
+ action = "goto_next"
+ priority = 510
+ ranges = [
+ "192.168.0.0/16",
+ "10.0.0.0/8",
+ "172.16.0.0/12"
+ ]
+ ports = { "all" = [] }
+ target_service_accounts = null
+ target_resources = null
+ logging = false
+ }
+ allow-iap-ssh-rdp = {
+ description = "Always allow SSH and RDP from IAP"
+ direction = "INGRESS"
+ action = "allow"
+ priority = 5000
+ ranges = ["35.235.240.0/20"]
+ ports = {
+ tcp = ["22", "3389"]
+ }
+ target_service_accounts = null
+ target_resources = null
+ logging = var.firewall_policies_enable_logging
+ }
+ allow-windows-activation = {
+ description = "Always outgoing Windows KMS traffic (required to validate Windows licenses)"
+ direction = "EGRESS"
+ action = "allow"
+ priority = 5100
+ ranges = ["35.190.247.13/32"]
+ ports = {
+ tcp = ["1688"]
+ }
+ target_service_accounts = null
+ target_resources = null
+ logging = var.firewall_policies_enable_logging
+ }
+ allow-google-hbs-and-hcs = {
+ description = "Always allow connections from Google load balancer and health check ranges"
+ direction = "INGRESS"
+ action = "allow"
+ priority = 5200
+ ranges = [
+ "35.191.0.0/16",
+ "130.211.0.0/22",
+ "209.85.152.0/22",
+ "209.85.204.0/22"
+ ]
+ ports = {
+ tcp = ["80", "443"]
+ }
+ target_service_accounts = null
+ target_resources = null
+ logging = var.firewall_policies_enable_logging
+ }
+ }
+}
diff --git a/3-networks-hub-and-spoke/envs/shared/interconnect.auto.tfvars.example b/3-networks-hub-and-spoke/envs/shared/interconnect.auto.tfvars.example
new file mode 100644
index 000000000..d7386135a
--- /dev/null
+++ b/3-networks-hub-and-spoke/envs/shared/interconnect.auto.tfvars.example
@@ -0,0 +1,4 @@
+
+enable_partner_interconnect = true
+preactivate_partner_interconnect = true
+
diff --git a/3-networks-hub-and-spoke/envs/shared/interconnect.tf.example b/3-networks-hub-and-spoke/envs/shared/interconnect.tf.example
new file mode 100644
index 000000000..c412743a9
--- /dev/null
+++ b/3-networks-hub-and-spoke/envs/shared/interconnect.tf.example
@@ -0,0 +1,57 @@
+/**
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+module "dns_hub_interconnect" {
+ source = "../../modules/dedicated_interconnect"
+
+ org_id = var.org_id
+ parent_folder = var.parent_folder
+ vpc_name = "c-dns-hub"
+
+ region1 = local.default_region1
+ region1_router1_name = module.dns_hub_region1_router1.router.name
+ region1_interconnect1_candidate_subnets = ["169.254.0.0/29"]
+ region1_interconnect1_vlan_tag8021q = "3931"
+ region1_interconnect1 = "https://www.googleapis.com/compute/v1/projects/example-interconnect-project/global/interconnects/example-interconnect-1"
+ region1_interconnect1_location = "las-zone1-770"
+ region1_router2_name = module.dns_hub_region1_router2.router.name
+ region1_interconnect2_candidate_subnets = ["169.254.0.8/29"]
+ region1_interconnect2_vlan_tag8021q = "3932"
+ region1_interconnect2 = "https://www.googleapis.com/compute/v1/projects/example-interconnect-project/global/interconnects/example-interconnect-2"
+ region1_interconnect2_location = "las-zone1-770"
+
+ region2 = local.default_region2
+ region2_router1_name = module.dns_hub_region2_router1.router.name
+ region2_interconnect1_candidate_subnets = ["169.254.0.16/29"]
+ region2_interconnect1_vlan_tag8021q = "3933"
+ region2_interconnect1 = "https://www.googleapis.com/compute/v1/projects/example-interconnect-project/global/interconnects/example-interconnect-3"
+ region2_interconnect1_location = "lax-zone2-19"
+ region2_router2_name = module.dns_hub_region2_router2.router.name
+ region2_interconnect2_candidate_subnets = ["169.254.0.24/29"]
+ region2_interconnect2_vlan_tag8021q = "3934"
+ region2_interconnect2 = "https://www.googleapis.com/compute/v1/projects/example-interconnect-project/global/interconnects/example-interconnect-4"
+ region2_interconnect2_location = "lax-zone1-403"
+
+ peer_asn = "64515"
+ peer_name = "interconnect-peer"
+
+ cloud_router_labels = {
+ vlan_1 = "cr1",
+ vlan_2 = "cr2",
+ vlan_3 = "cr3",
+ vlan_4 = "cr4"
+ }
+}
diff --git a/3-networks-hub-and-spoke/envs/shared/main.tf b/3-networks-hub-and-spoke/envs/shared/main.tf
new file mode 100644
index 000000000..7636dc61d
--- /dev/null
+++ b/3-networks-hub-and-spoke/envs/shared/main.tf
@@ -0,0 +1,29 @@
+/**
+ * Copyright 2022 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 {
+ parent_id = var.parent_folder != "" ? "folders/${var.parent_folder}" : "organizations/${var.org_id}"
+ env = "common"
+ environment_code = "c"
+ bgp_asn_number = var.enable_partner_interconnect ? "16550" : "64514"
+ default_region1 = "us-west1"
+ default_region2 = "us-central1"
+}
+
+data "google_active_folder" "common" {
+ display_name = "${var.folder_prefix}-${local.env}"
+ parent = local.parent_id
+}
diff --git a/3-networks/envs/shared/net-hubs-transitivity.tf b/3-networks-hub-and-spoke/envs/shared/net-hubs-transitivity.tf
similarity index 95%
rename from 3-networks/envs/shared/net-hubs-transitivity.tf
rename to 3-networks-hub-and-spoke/envs/shared/net-hubs-transitivity.tf
index 220ac171e..08a9ffeed 100644
--- a/3-networks/envs/shared/net-hubs-transitivity.tf
+++ b/3-networks-hub-and-spoke/envs/shared/net-hubs-transitivity.tf
@@ -15,7 +15,7 @@
*/
locals {
- enable_transitivity = var.enable_hub_and_spoke && var.enable_hub_and_spoke_transitivity
+ enable_transitivity = var.enable_hub_and_spoke_transitivity
base_regional_aggregates = {
(local.default_region1) = [
"10.0.0.0/16",
@@ -47,7 +47,7 @@ module "base_transitivity" {
source = "../../modules/transitivity"
project_id = local.base_net_hub_project_id
regions = keys(local.base_subnet_primary_ranges)
- vpc_name = module.base_shared_vpc[0].network_name
+ vpc_name = module.base_shared_vpc.network_name
gw_subnets = { for region in keys(local.base_subnet_primary_ranges) : region => "sb-c-shared-base-hub-${region}" }
regional_aggregates = local.base_regional_aggregates
commands = [
@@ -80,7 +80,7 @@ module "restricted_transitivity" {
source = "../../modules/transitivity"
project_id = local.restricted_net_hub_project_id
regions = keys(local.restricted_subnet_primary_ranges)
- vpc_name = module.restricted_shared_vpc[0].network_name
+ vpc_name = module.restricted_shared_vpc.network_name
gw_subnets = { for region in keys(local.restricted_subnet_primary_ranges) : region => "sb-c-shared-restricted-hub-${region}" }
regional_aggregates = local.restricted_regional_aggregates
commands = [
diff --git a/3-networks/envs/shared/net-hubs.tf b/3-networks-hub-and-spoke/envs/shared/net-hubs.tf
similarity index 91%
rename from 3-networks/envs/shared/net-hubs.tf
rename to 3-networks-hub-and-spoke/envs/shared/net-hubs.tf
index 28ceb4e75..7e730cfb3 100644
--- a/3-networks/envs/shared/net-hubs.tf
+++ b/3-networks-hub-and-spoke/envs/shared/net-hubs.tf
@@ -1,5 +1,5 @@
/**
- * Copyright 2021 Google LLC
+ * Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,9 +15,9 @@
*/
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_net_hub_project_id = data.google_projects.base_net_hub.projects[0].project_id
+ restricted_net_hub_project_id = data.google_projects.restricted_net_hub.projects[0].project_id
+ restricted_net_hub_project_number = data.google_projects.restricted_net_hub.projects[0].number
/*
* Base network ranges
*/
@@ -39,7 +39,6 @@ locals {
*****************************************/
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"
}
@@ -48,7 +47,6 @@ data "google_projects" "base_net_hub" {
*****************************************/
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"
}
@@ -58,7 +56,6 @@ data "google_projects" "restricted_net_hub" {
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 = local.environment_code
org_id = var.org_id
@@ -107,7 +104,6 @@ module "base_shared_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 = local.environment_code
diff --git a/3-networks-hub-and-spoke/envs/shared/outputs.tf b/3-networks-hub-and-spoke/envs/shared/outputs.tf
new file mode 100644
index 000000000..06f9b0702
--- /dev/null
+++ b/3-networks-hub-and-spoke/envs/shared/outputs.tf
@@ -0,0 +1,20 @@
+/**
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+output "dns_hub_project_id" {
+ value = local.dns_hub_project_id
+ description = "The DNS hub project ID"
+}
diff --git a/3-networks-hub-and-spoke/envs/shared/partner_interconnect.tf.example b/3-networks-hub-and-spoke/envs/shared/partner_interconnect.tf.example
new file mode 100644
index 000000000..2b4a07a20
--- /dev/null
+++ b/3-networks-hub-and-spoke/envs/shared/partner_interconnect.tf.example
@@ -0,0 +1,79 @@
+/**
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+module "shared_restricted_interconnect" {
+ source = "../../modules/partner_interconnect"
+
+ org_id = var.org_id
+ parent_folder = var.parent_folder
+ vpc_name = "${local.environment_code}-shared-restricted"
+ environment = local.env
+ vpc_type = "restricted"
+ preactivate = var.preactivate_partner_interconnect
+
+ region1 = local.default_region1
+ region1_router1_name = module.restricted_shared_vpc[0].region1_router1.router.name
+ region1_interconnect1_location = "las-zone1-770"
+ region1_router2_name = module.restricted_shared_vpc[0].region1_router2.router.name
+ region1_interconnect2_location = "las-zone1-770"
+
+ region2 = local.default_region2
+ region2_router1_name = module.restricted_shared_vpc[0].region2_router1.router.name
+ region2_interconnect1_location = "lax-zone2-19"
+ region2_router2_name = module.restricted_shared_vpc[0].region2_router2.router.name
+ region2_interconnect2_location = "lax-zone1-403"
+
+ folder_prefix = var.folder_prefix
+
+ cloud_router_labels = {
+ vlan_1 = "cr5",
+ vlan_2 = "cr6",
+ vlan_3 = "cr7",
+ vlan_4 = "cr8"
+ }
+}
+
+module "shared_base_interconnect" {
+ source = "../../modules/partner_interconnect"
+
+ org_id = var.org_id
+ parent_folder = var.parent_folder
+ vpc_name = "${local.environment_code}-shared-base"
+ environment = local.env
+ vpc_type = "base"
+ preactivate = var.preactivate_partner_interconnect
+
+ region1 = local.default_region1
+ region1_router1_name = module.base_shared_vpc[0].region1_router1.router.name
+ region1_interconnect1_location = "las-zone1-770"
+ region1_router2_name = module.base_shared_vpc[0].region1_router2.router.name
+ region1_interconnect2_location = "las-zone1-770"
+
+ region2 = local.default_region2
+ region2_router1_name = module.base_shared_vpc[0].region2_router1.router.name
+ region2_interconnect1_location = "lax-zone2-19"
+ region2_router2_name = module.base_shared_vpc[0].region2_router2.router.name
+ region2_interconnect2_location = "lax-zone1-403"
+
+ folder_prefix = var.folder_prefix
+
+ cloud_router_labels = {
+ vlan_1 = "cr1",
+ vlan_2 = "cr2",
+ vlan_3 = "cr3",
+ vlan_4 = "cr4"
+ }
+}
diff --git a/3-networks-hub-and-spoke/envs/shared/providers.tf b/3-networks-hub-and-spoke/envs/shared/providers.tf
new file mode 100644
index 000000000..0d58ec1d2
--- /dev/null
+++ b/3-networks-hub-and-spoke/envs/shared/providers.tf
@@ -0,0 +1,33 @@
+/**
+ * Copyright 2022 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 {
+ tf_sa = var.terraform_service_account
+}
+
+
+/******************************************
+ Provider credential configuration
+ *****************************************/
+provider "google" {
+ impersonate_service_account = local.tf_sa
+ request_timeout = "120s"
+}
+
+provider "google-beta" {
+ impersonate_service_account = local.tf_sa
+ request_timeout = "120s"
+}
diff --git a/3-networks-hub-and-spoke/envs/shared/shared.auto.tfvars b/3-networks-hub-and-spoke/envs/shared/shared.auto.tfvars
new file mode 120000
index 000000000..b7f8387a8
--- /dev/null
+++ b/3-networks-hub-and-spoke/envs/shared/shared.auto.tfvars
@@ -0,0 +1 @@
+../../shared.auto.tfvars
\ No newline at end of file
diff --git a/3-networks/envs/shared/variables.tf b/3-networks-hub-and-spoke/envs/shared/variables.tf
similarity index 97%
rename from 3-networks/envs/shared/variables.tf
rename to 3-networks-hub-and-spoke/envs/shared/variables.tf
index c77f08ecd..6d4009666 100644
--- a/3-networks/envs/shared/variables.tf
+++ b/3-networks-hub-and-spoke/envs/shared/variables.tf
@@ -1,5 +1,5 @@
/**
- * Copyright 2021 Google LLC
+ * Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,18 +24,6 @@ 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 "enable_hub_and_spoke_transitivity" {
- description = "Enable transitivity via gateway VMs on 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)\"`."
@@ -194,3 +182,9 @@ variable "preactivate_partner_interconnect" {
type = bool
default = false
}
+
+variable "enable_hub_and_spoke_transitivity" {
+ description = "Enable transitivity via gateway VMs on Hub-and-Spoke architecture."
+ type = bool
+ default = false
+}
diff --git a/3-networks-hub-and-spoke/envs/shared/versions.tf b/3-networks-hub-and-spoke/envs/shared/versions.tf
new file mode 100644
index 000000000..6256afb3a
--- /dev/null
+++ b/3-networks-hub-and-spoke/envs/shared/versions.tf
@@ -0,0 +1,29 @@
+/**
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+terraform {
+ required_version = ">= 0.13"
+ required_providers {
+ google = {
+ source = "hashicorp/google"
+ version = ">= 3.50"
+ }
+ google-beta = {
+ source = "hashicorp/google-beta"
+ version = ">= 3.50"
+ }
+ }
+}
diff --git a/3-networks/modules/base_env/README.md b/3-networks-hub-and-spoke/modules/base_env/README.md
similarity index 97%
rename from 3-networks/modules/base_env/README.md
rename to 3-networks-hub-and-spoke/modules/base_env/README.md
index 5044f3b6e..e95a982d9 100644
--- a/3-networks/modules/base_env/README.md
+++ b/3-networks-hub-and-spoke/modules/base_env/README.md
@@ -10,7 +10,6 @@
| default\_region1 | First subnet region. The shared vpc modules only configures two regions. | `string` | n/a | yes |
| default\_region2 | Second subnet region. The shared vpc modules only configures two regions. | `string` | n/a | yes |
| domain | The DNS name of peering managed zone, for instance 'example.com.'. Must end with a period. | `string` | n/a | yes |
-| enable\_hub\_and\_spoke | Enable Hub-and-Spoke architecture. | `bool` | `false` | no |
| enable\_hub\_and\_spoke\_transitivity | Enable transitivity via gateway VMs on Hub-and-Spoke architecture. | `bool` | `false` | no |
| enable\_partner\_interconnect | Enable Partner Interconnect in the environment. | `bool` | `false` | no |
| env | The environment to prepare (ex. development) | `string` | n/a | yes |
diff --git a/3-networks-hub-and-spoke/modules/base_env/interconnect.tf.example b/3-networks-hub-and-spoke/modules/base_env/interconnect.tf.example
new file mode 100644
index 000000000..9c59be696
--- /dev/null
+++ b/3-networks-hub-and-spoke/modules/base_env/interconnect.tf.example
@@ -0,0 +1,100 @@
+/**
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+module "shared_restricted_interconnect" {
+ source = "../dedicated_interconnect"
+
+ org_id = var.org_id
+ parent_folder = var.parent_folder
+ vpc_name = "${var.environment_code}-shared-restricted"
+
+ region1 = var.default_region1
+ region1_router1_name = module.restricted_shared_vpc.region1_router1.router.name
+ region1_interconnect1_candidate_subnets = ["169.254.0.160/29"]
+ region1_interconnect1_vlan_tag8021q = "3901"
+ region1_interconnect1 = "https://www.googleapis.com/compute/v1/projects/example-interconnect-project/global/interconnects/example-interconnect-1"
+ region1_interconnect1_location = "las-zone1-770"
+ region1_router2_name = module.restricted_shared_vpc.region1_router2.router.name
+ region1_interconnect2_candidate_subnets = ["169.254.0.168/29"]
+ region1_interconnect2_vlan_tag8021q = "3902"
+ region1_interconnect2 = "https://www.googleapis.com/compute/v1/projects/example-interconnect-project/global/interconnects/example-interconnect-2"
+ region1_interconnect2_location = "las-zone1-770"
+
+ region2 = var.default_region2
+ region2_router1_name = module.restricted_shared_vpc.region2_router1.router.name
+ region2_interconnect1_candidate_subnets = ["169.254.0.176/29"]
+ region2_interconnect1_vlan_tag8021q = "3903"
+ region2_interconnect1 = "https://www.googleapis.com/compute/v1/projects/example-interconnect-project/global/interconnects/example-interconnect-3"
+ region2_interconnect1_location = "lax-zone2-19"
+ region2_router2_name = module.restricted_shared_vpc.region2_router2.router.name
+ region2_interconnect2_candidate_subnets = ["169.254.0.184/29"]
+ region2_interconnect2_vlan_tag8021q = "3904"
+ region2_interconnect2 = "https://www.googleapis.com/compute/v1/projects/example-interconnect-project/global/interconnects/example-interconnect-4"
+ region2_interconnect2_location = "lax-zone1-403"
+
+ peer_asn = "64515"
+ peer_name = "interconnect-peer"
+
+ cloud_router_labels = {
+ vlan_1 = "cr5",
+ vlan_2 = "cr6",
+ vlan_3 = "cr7",
+ vlan_4 = "cr8"
+ }
+}
+
+module "shared_base_interconnect" {
+ source = "../dedicated_interconnect"
+
+ org_id = var.org_id
+ parent_folder = var.parent_folder
+ vpc_name = "${var.environment_code}-shared-base"
+
+ region1 = var.default_region1
+ region1_router1_name = module.base_shared_vpc.region1_router1.router.name
+ region1_interconnect1_candidate_subnets = ["169.254.0.192/29"]
+ region1_interconnect1_vlan_tag8021q = "3905"
+ region1_interconnect1 = "https://www.googleapis.com/compute/v1/projects/example-interconnect-project/global/interconnects/example-interconnect-1"
+ region1_interconnect1_location = "las-zone1-770"
+ region1_router2_name = module.base_shared_vpc.region1_router2.router.name
+ region1_interconnect2_candidate_subnets = ["169.254.0.200/29"]
+ region1_interconnect2_vlan_tag8021q = "3906"
+ region1_interconnect2 = "https://www.googleapis.com/compute/v1/projects/example-interconnect-project/global/interconnects/example-interconnect-2"
+ region1_interconnect2_location = "las-zone1-770"
+
+ region2 = var.default_region2
+ region2_router1_name = module.base_shared_vpc.region2_router1.router.name
+ region2_interconnect1_candidate_subnets = ["169.254.0.208/29"]
+ region2_interconnect1_vlan_tag8021q = "3907"
+ region2_interconnect1 = "https://www.googleapis.com/compute/v1/projects/example-interconnect-project/global/interconnects/example-interconnect-3"
+ region2_interconnect1_location = "lax-zone2-19"
+ region2_router2_name = module.base_shared_vpc.region2_router2.router.name
+ region2_interconnect2_candidate_subnets = ["169.254.0.216/29"]
+ region2_interconnect2_vlan_tag8021q = "3908"
+ region2_interconnect2 = "https://www.googleapis.com/compute/v1/projects/example-interconnect-project/global/interconnects/example-interconnect-4"
+ region2_interconnect2_location = "lax-zone1-403"
+
+
+ peer_asn = "64515"
+ peer_name = "interconnect-peer"
+
+ cloud_router_labels = {
+ vlan_1 = "cr1",
+ vlan_2 = "cr2",
+ vlan_3 = "cr3",
+ vlan_4 = "cr4"
+ }
+}
diff --git a/3-networks/modules/base_env/main.tf b/3-networks-hub-and-spoke/modules/base_env/main.tf
similarity index 95%
rename from 3-networks/modules/base_env/main.tf
rename to 3-networks-hub-and-spoke/modules/base_env/main.tf
index d9cd6995d..91aa9d60b 100644
--- a/3-networks/modules/base_env/main.tf
+++ b/3-networks-hub-and-spoke/modules/base_env/main.tf
@@ -1,5 +1,5 @@
/**
- * Copyright 2021 Google LLC
+ * Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,9 +19,8 @@ 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
bgp_asn_number = var.enable_partner_interconnect ? "16550" : "64514"
- enable_transitivity = var.enable_hub_and_spoke && var.enable_hub_and_spoke_transitivity
+ enable_transitivity = var.enable_hub_and_spoke_transitivity
/*
* Base network ranges
*/
@@ -73,7 +72,7 @@ module "restricted_shared_vpc" {
default_region1 = var.default_region1
default_region2 = var.default_region2
domain = var.domain
- mode = local.mode
+ mode = "spoke"
subnets = [
{
@@ -115,7 +114,7 @@ module "base_shared_vpc" {
default_region2 = var.default_region2
domain = var.domain
bgp_asn_subnet = local.bgp_asn_number
- mode = local.mode
+ mode = "spoke"
subnets = [
{
diff --git a/3-networks-hub-and-spoke/modules/base_env/outputs.tf b/3-networks-hub-and-spoke/modules/base_env/outputs.tf
new file mode 100644
index 000000000..88acc19f8
--- /dev/null
+++ b/3-networks-hub-and-spoke/modules/base_env/outputs.tf
@@ -0,0 +1,103 @@
+/**
+ * Copyright 2022 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.
+ */
+
+/*********************
+ Restricted Outputs
+*********************/
+
+output "restricted_host_project_id" {
+ value = local.restricted_project_id
+ description = "The restricted host project ID"
+}
+
+output "restricted_network_name" {
+ value = module.restricted_shared_vpc.network_name
+ description = "The name of the VPC being created"
+}
+
+output "restricted_network_self_link" {
+ value = module.restricted_shared_vpc.network_self_link
+ description = "The URI of the VPC being created"
+}
+
+output "restricted_subnets_names" {
+ value = module.restricted_shared_vpc.subnets_names
+ description = "The names of the subnets being created"
+}
+
+output "restricted_subnets_ips" {
+ value = module.restricted_shared_vpc.subnets_ips
+ description = "The IPs and CIDRs of the subnets being created"
+}
+
+output "restricted_subnets_self_links" {
+ value = module.restricted_shared_vpc.subnets_self_links
+ description = "The self-links of subnets being created"
+}
+
+output "restricted_subnets_secondary_ranges" {
+ value = module.restricted_shared_vpc.subnets_secondary_ranges
+ description = "The secondary ranges associated with these subnets"
+}
+
+output "restricted_access_level_name" {
+ value = module.restricted_shared_vpc.access_level_name
+ description = "Access context manager access level name"
+}
+
+output "restricted_service_perimeter_name" {
+ value = module.restricted_shared_vpc.service_perimeter_name
+ description = "Access context manager service perimeter name"
+}
+
+/******************************************
+ Private Outputs
+*****************************************/
+
+output "base_host_project_id" {
+ value = local.base_project_id
+ description = "The base host project ID"
+}
+
+output "base_network_name" {
+ value = module.base_shared_vpc.network_name
+ description = "The name of the VPC being created"
+}
+
+output "base_network_self_link" {
+ value = module.base_shared_vpc.network_self_link
+ description = "The URI of the VPC being created"
+}
+
+output "base_subnets_names" {
+ value = module.base_shared_vpc.subnets_names
+ description = "The names of the subnets being created"
+}
+
+output "base_subnets_ips" {
+ value = module.base_shared_vpc.subnets_ips
+ description = "The IPs and CIDRs of the subnets being created"
+}
+
+output "base_subnets_self_links" {
+ value = module.base_shared_vpc.subnets_self_links
+ description = "The self-links of subnets being created"
+}
+
+output "base_subnets_secondary_ranges" {
+ value = module.base_shared_vpc.subnets_secondary_ranges
+ description = "The secondary ranges associated with these subnets"
+}
diff --git a/3-networks-hub-and-spoke/modules/base_env/partner_interconnect.tf.example b/3-networks-hub-and-spoke/modules/base_env/partner_interconnect.tf.example
new file mode 100644
index 000000000..2d531cbee
--- /dev/null
+++ b/3-networks-hub-and-spoke/modules/base_env/partner_interconnect.tf.example
@@ -0,0 +1,76 @@
+/**
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+module "shared_restricted_interconnect" {
+ source = "../partner_interconnect"
+
+ org_id = var.org_id
+ parent_folder = var.parent_folder
+ vpc_name = "${var.environment_code}-shared-restricted"
+ environment = var.env
+ vpc_type = "restricted"
+ preactivate = true
+
+ region1 = var.default_region1
+ region1_router1_name = module.restricted_shared_vpc.region1_router1.router.name
+ region1_interconnect1_location = "las-zone1-770"
+ region1_router2_name = module.restricted_shared_vpc.region1_router2.router.name
+ region1_interconnect2_location = "las-zone1-770"
+
+ region2 = var.default_region2
+ region2_router1_name = module.restricted_shared_vpc.region2_router1.router.name
+ region2_interconnect1_location = "lax-zone2-19"
+ region2_router2_name = module.restricted_shared_vpc.region2_router2.router.name
+ region2_interconnect2_location = "lax-zone1-403"
+
+ cloud_router_labels = {
+ vlan_1 = "cr5",
+ vlan_2 = "cr6",
+ vlan_3 = "cr7",
+ vlan_4 = "cr8"
+ }
+}
+
+module "shared_base_interconnect" {
+ source = "../partner_interconnect"
+
+ org_id = var.org_id
+ parent_folder = var.parent_folder
+ vpc_name = "${var.environment_code}-shared-base"
+ environment = var.env
+ vpc_type = "base"
+ preactivate = true
+
+ region1 = var.default_region1
+ region1_router1_name = module.base_shared_vpc.region1_router1.router.name
+ region1_interconnect1_location = "las-zone1-770"
+ region1_router2_name = module.base_shared_vpc.region1_router2.router.name
+ region1_interconnect2_location = "las-zone1-770"
+
+ region2 = var.default_region2
+ region2_router1_name = module.base_shared_vpc.region2_router1.router.name
+ region2_interconnect1_location = "lax-zone2-19"
+ region2_router2_name = module.base_shared_vpc.region2_router2.router.name
+ region2_interconnect2_location = "lax-zone1-403"
+
+
+ cloud_router_labels = {
+ vlan_1 = "cr1",
+ vlan_2 = "cr2",
+ vlan_3 = "cr3",
+ vlan_4 = "cr4"
+ }
+}
diff --git a/3-networks/modules/base_env/variables.tf b/3-networks-hub-and-spoke/modules/base_env/variables.tf
similarity index 95%
rename from 3-networks/modules/base_env/variables.tf
rename to 3-networks-hub-and-spoke/modules/base_env/variables.tf
index 3bec6a4b2..ec81d484b 100644
--- a/3-networks/modules/base_env/variables.tf
+++ b/3-networks-hub-and-spoke/modules/base_env/variables.tf
@@ -1,5 +1,5 @@
/**
- * Copyright 2021 Google LLC
+ * Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -66,12 +66,6 @@ variable "folder_prefix" {
default = "fldr"
}
-variable "enable_hub_and_spoke" {
- description = "Enable Hub-and-Spoke architecture."
- type = bool
- default = false
-}
-
variable "enable_partner_interconnect" {
description = "Enable Partner Interconnect in the environment."
type = bool
diff --git a/3-networks-hub-and-spoke/modules/base_env/versions.tf b/3-networks-hub-and-spoke/modules/base_env/versions.tf
new file mode 100644
index 000000000..6256afb3a
--- /dev/null
+++ b/3-networks-hub-and-spoke/modules/base_env/versions.tf
@@ -0,0 +1,29 @@
+/**
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+terraform {
+ required_version = ">= 0.13"
+ required_providers {
+ google = {
+ source = "hashicorp/google"
+ version = ">= 3.50"
+ }
+ google-beta = {
+ source = "hashicorp/google-beta"
+ version = ">= 3.50"
+ }
+ }
+}
diff --git a/3-networks-hub-and-spoke/modules/base_env/vpn.tf.example b/3-networks-hub-and-spoke/modules/base_env/vpn.tf.example
new file mode 100644
index 000000000..f04d89f4f
--- /dev/null
+++ b/3-networks-hub-and-spoke/modules/base_env/vpn.tf.example
@@ -0,0 +1,106 @@
+/**
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+module "shared_base_vpn" {
+ source = "../vpn-ha"
+
+ project_id = local.base_project_id
+ default_region1 = var.default_region1
+ default_region2 = var.default_region2
+ vpc_name = "${var.environment_code}-shared-base"
+ region1_router1_name = module.base_shared_vpc.region1_router1.router.name
+ region1_router2_name = module.base_shared_vpc.region1_router2.router.name
+ region2_router1_name = module.base_shared_vpc.region2_router1.router.name
+ region2_router2_name = module.base_shared_vpc.region2_router2.router.name
+ environment = var.env
+ parent_folder = var.parent_folder
+ org_id = var.org_id
+ vpn_psk_secret_name = ""
+ folder_prefix = var.folder_prefix
+
+ on_prem_router_ip_address1 = "<8.8.8.8>" # on-prem router ip address 1
+ on_prem_router_ip_address2 = "<8.8.8.8>" # on-prem router ip address 2
+ bgp_peer_asn = "64515"
+
+ region1_router1_tunnel0_bgp_peer_address = "169.254.1.1"
+ region1_router1_tunnel0_bgp_peer_range = "169.254.1.2/30"
+
+ region1_router1_tunnel1_bgp_peer_address = "169.254.2.1"
+ region1_router1_tunnel1_bgp_peer_range = "169.254.2.2/30"
+
+ region1_router2_tunnel0_bgp_peer_address = "169.254.4.1"
+ region1_router2_tunnel0_bgp_peer_range = "169.254.4.2/30"
+
+ region1_router2_tunnel1_bgp_peer_address = "169.254.6.1"
+ region1_router2_tunnel1_bgp_peer_range = "169.254.6.2/30"
+
+ region2_router1_tunnel0_bgp_peer_address = "169.254.8.1"
+ region2_router1_tunnel0_bgp_peer_range = "169.254.8.2/30"
+
+ region2_router1_tunnel1_bgp_peer_address = "169.254.10.1"
+ region2_router1_tunnel1_bgp_peer_range = "169.254.10.2/30"
+
+ region2_router2_tunnel0_bgp_peer_address = "169.254.12.1"
+ region2_router2_tunnel0_bgp_peer_range = "169.254.12.2/30"
+
+ region2_router2_tunnel1_bgp_peer_address = "169.254.14.1"
+ region2_router2_tunnel1_bgp_peer_range = "169.254.14.2/30"
+}
+
+module "shared_restricted_vpn" {
+ source = "../vpn-ha"
+
+ project_id = local.restricted_project_id
+ default_region1 = var.default_region1
+ default_region2 = var.default_region2
+ vpc_name = "${var.environment_code}-shared-restricted"
+ region1_router1_name = module.restricted_shared_vpc.region1_router1.router.name
+ region1_router2_name = module.restricted_shared_vpc.region1_router2.router.name
+ region2_router1_name = module.restricted_shared_vpc.region2_router1.router.name
+ region2_router2_name = module.restricted_shared_vpc.region2_router2.router.name
+ environment = var.env
+ parent_folder = var.parent_folder
+ org_id = var.org_id
+ vpn_psk_secret_name = ""
+
+ on_prem_router_ip_address1 = "<8.8.8.8>" # on-prem router ip address 1
+ on_prem_router_ip_address2 = "<8.8.8.8>" # on-prem router ip address 2
+ bgp_peer_asn = "64515"
+
+ region1_router1_tunnel0_bgp_peer_address = "169.254.1.1"
+ region1_router1_tunnel0_bgp_peer_range = "169.254.1.2/30"
+
+ region1_router1_tunnel1_bgp_peer_address = "169.254.2.1"
+ region1_router1_tunnel1_bgp_peer_range = "169.254.2.2/30"
+
+ region1_router2_tunnel0_bgp_peer_address = "169.254.4.1"
+ region1_router2_tunnel0_bgp_peer_range = "169.254.4.2/30"
+
+ region1_router2_tunnel1_bgp_peer_address = "169.254.6.1"
+ region1_router2_tunnel1_bgp_peer_range = "169.254.6.2/30"
+
+ region2_router1_tunnel0_bgp_peer_address = "169.254.8.1"
+ region2_router1_tunnel0_bgp_peer_range = "169.254.8.2/30"
+
+ region2_router1_tunnel1_bgp_peer_address = "169.254.10.1"
+ region2_router1_tunnel1_bgp_peer_range = "169.254.10.2/30"
+
+ region2_router2_tunnel0_bgp_peer_address = "169.254.12.1"
+ region2_router2_tunnel0_bgp_peer_range = "169.254.12.2/30"
+
+ region2_router2_tunnel1_bgp_peer_address = "169.254.14.1"
+ region2_router2_tunnel1_bgp_peer_range = "169.254.14.2/30"
+}
diff --git a/3-networks-hub-and-spoke/modules/base_shared_vpc/README.md b/3-networks-hub-and-spoke/modules/base_shared_vpc/README.md
new file mode 100644
index 000000000..14155fb65
--- /dev/null
+++ b/3-networks-hub-and-spoke/modules/base_shared_vpc/README.md
@@ -0,0 +1,45 @@
+
+## Inputs
+
+| Name | Description | Type | Default | Required |
+|------|-------------|------|---------|:--------:|
+| allow\_all\_egress\_ranges | List of network ranges to which all egress traffic will be allowed | `any` | `null` | no |
+| allow\_all\_ingress\_ranges | List of network ranges from which all ingress traffic will be allowed | `any` | `null` | no |
+| bgp\_asn\_subnet | BGP ASN for Subnets cloud routers. | `number` | n/a | yes |
+| default\_region1 | Default region 1 for subnets and Cloud Routers | `string` | n/a | yes |
+| default\_region2 | Default region 2 for subnets and Cloud Routers | `string` | n/a | yes |
+| 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 |
+| 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 chosen, keep as `null` otherwise. | `string` | `null` | no |
+| nat\_bgp\_asn | BGP ASN for first NAT cloud routes. | `number` | `64514` | 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 |
+| nat\_num\_addresses\_region1 | Number of external IPs to reserve for first Cloud NAT. | `number` | `2` | no |
+| nat\_num\_addresses\_region2 | Number of external IPs to reserve for second Cloud NAT. | `number` | `2` | 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` | `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 |
+| windows\_activation\_enabled | Enable Windows license activation for Windows workloads. | `bool` | `false` | no |
+
+## Outputs
+
+| Name | Description |
+|------|-------------|
+| network\_name | The name of the VPC being created |
+| network\_self\_link | The URI of the VPC being created |
+| subnets\_flow\_logs | Whether the subnets have VPC flow logs enabled |
+| subnets\_ips | The IPs and CIDRs of the subnets being created |
+| subnets\_names | The names of the subnets being created |
+| subnets\_private\_access | Whether the subnets have access to Google API's without a public IP |
+| subnets\_regions | The region where the subnets will be created |
+| subnets\_secondary\_ranges | The secondary ranges associated with these subnets |
+| subnets\_self\_links | The self-links of subnets being created |
+
+
diff --git a/3-networks-hub-and-spoke/modules/base_shared_vpc/data.tf b/3-networks-hub-and-spoke/modules/base_shared_vpc/data.tf
new file mode 100644
index 000000000..db6163d95
--- /dev/null
+++ b/3-networks-hub-and-spoke/modules/base_shared_vpc/data.tf
@@ -0,0 +1,31 @@
+/**
+ * Copyright 2022 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.
+ */
+
+/******************************************
+ Ranges for default firewall rules.
+ *****************************************/
+
+data "google_netblock_ip_ranges" "legacy_health_checkers" {
+ range_type = "legacy-health-checkers"
+}
+
+data "google_netblock_ip_ranges" "health_checkers" {
+ range_type = "health-checkers"
+}
+
+data "google_netblock_ip_ranges" "iap_forwarders" {
+ range_type = "iap-forwarders"
+}
diff --git a/3-networks-hub-and-spoke/modules/base_shared_vpc/dns.tf b/3-networks-hub-and-spoke/modules/base_shared_vpc/dns.tf
new file mode 100644
index 000000000..63689fe60
--- /dev/null
+++ b/3-networks-hub-and-spoke/modules/base_shared_vpc/dns.tf
@@ -0,0 +1,69 @@
+/**
+ * Copyright 2022 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 {
+ parent_id = var.parent_folder != "" ? "folders/${var.parent_folder}" : "organizations/${var.org_id}"
+}
+
+data "google_active_folder" "common" {
+ display_name = "${var.folder_prefix}-common"
+ parent = local.parent_id
+}
+
+/******************************************
+ DNS Hub Project
+*****************************************/
+
+data "google_projects" "dns_hub" {
+ filter = "parent.id:${split("/", data.google_active_folder.common.name)[1]} labels.application_name=org-dns-hub lifecycleState=ACTIVE"
+}
+
+data "google_compute_network" "vpc_dns_hub" {
+ name = "vpc-c-dns-hub"
+ project = data.google_projects.dns_hub.projects[0].project_id
+}
+
+/******************************************
+ Default DNS Policy
+ *****************************************/
+
+resource "google_dns_policy" "default_policy" {
+ project = var.project_id
+ name = "dp-${var.environment_code}-shared-base-default-policy"
+ enable_inbound_forwarding = var.dns_enable_inbound_forwarding
+ enable_logging = var.dns_enable_logging
+ networks {
+ network_url = module.main.network_self_link
+ }
+}
+
+/******************************************
+ Creates DNS Peering to DNS HUB
+*****************************************/
+module "peering_zone" {
+ source = "terraform-google-modules/cloud-dns/google"
+ version = "~> 3.1"
+ project_id = var.project_id
+ type = "peering"
+ name = "dz-${var.environment_code}-shared-base-to-dns-hub"
+ domain = var.domain
+ description = "Private DNS peering zone."
+
+ private_visibility_config_networks = [
+ module.main.network_self_link
+ ]
+ target_network = data.google_compute_network.vpc_dns_hub.self_link
+}
diff --git a/3-networks-hub-and-spoke/modules/base_shared_vpc/firewall.tf b/3-networks-hub-and-spoke/modules/base_shared_vpc/firewall.tf
new file mode 100644
index 000000000..8c5230f4c
--- /dev/null
+++ b/3-networks-hub-and-spoke/modules/base_shared_vpc/firewall.tf
@@ -0,0 +1,122 @@
+/**
+ * Copyright 2022 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.
+ */
+
+/******************************************
+ Mandatory firewall rules
+ *****************************************/
+
+resource "google_compute_firewall" "deny_all_egress" {
+ name = "fw-${var.environment_code}-shared-base-65535-e-d-all-all-all"
+ network = module.main.network_name
+ project = var.project_id
+ direction = "EGRESS"
+ priority = 65535
+
+ dynamic "log_config" {
+ for_each = var.firewall_enable_logging == true ? [{
+ metadata = "INCLUDE_ALL_METADATA"
+ }] : []
+
+ content {
+ metadata = log_config.value.metadata
+ }
+ }
+
+ deny {
+ protocol = "all"
+ }
+
+ destination_ranges = ["0.0.0.0/0"]
+}
+
+
+resource "google_compute_firewall" "allow_private_api_egress" {
+ name = "fw-${var.environment_code}-shared-base-65534-e-a-allow-google-apis-all-tcp-443"
+ network = module.main.network_name
+ project = var.project_id
+ direction = "EGRESS"
+ priority = 65534
+
+ dynamic "log_config" {
+ for_each = var.firewall_enable_logging == true ? [{
+ metadata = "INCLUDE_ALL_METADATA"
+ }] : []
+
+ content {
+ metadata = log_config.value.metadata
+ }
+ }
+
+ allow {
+ protocol = "tcp"
+ ports = ["443"]
+ }
+
+ destination_ranges = [local.private_googleapis_cidr]
+
+ target_tags = ["allow-google-apis"]
+}
+
+
+resource "google_compute_firewall" "allow_all_egress" {
+ count = var.allow_all_egress_ranges != null ? 1 : 0
+ name = "fw-${var.environment_code}-shared-base-1000-e-a-all"
+ network = module.main.network_name
+ project = var.project_id
+ direction = "EGRESS"
+ priority = 1000
+
+ dynamic "log_config" {
+ for_each = var.firewall_enable_logging == true ? [{
+ metadata = "INCLUDE_ALL_METADATA"
+ }] : []
+
+ content {
+ metadata = log_config.value.metadata
+ }
+ }
+
+ allow {
+ protocol = "all"
+ }
+
+ destination_ranges = var.allow_all_egress_ranges
+}
+
+resource "google_compute_firewall" "allow_all_ingress" {
+ count = var.allow_all_ingress_ranges != null ? 1 : 0
+ name = "fw-${var.environment_code}-shared-base-1000-i-a-all"
+ network = module.main.network_name
+ project = var.project_id
+ direction = "INGRESS"
+ priority = 1000
+
+ dynamic "log_config" {
+ for_each = var.firewall_enable_logging == true ? [{
+ metadata = "INCLUDE_ALL_METADATA"
+ }] : []
+
+ content {
+ metadata = log_config.value.metadata
+ }
+ }
+
+ allow {
+ protocol = "all"
+ }
+
+ source_ranges = var.allow_all_ingress_ranges
+}
diff --git a/3-networks/modules/base_shared_vpc/main.tf b/3-networks-hub-and-spoke/modules/base_shared_vpc/main.tf
similarity index 98%
rename from 3-networks/modules/base_shared_vpc/main.tf
rename to 3-networks-hub-and-spoke/modules/base_shared_vpc/main.tf
index f36e55552..0130f5530 100644
--- a/3-networks/modules/base_shared_vpc/main.tf
+++ b/3-networks-hub-and-spoke/modules/base_shared_vpc/main.tf
@@ -1,5 +1,5 @@
/**
- * Copyright 2021 Google LLC
+ * Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,7 +15,7 @@
*/
locals {
- mode = var.mode == null ? "" : var.mode == "hub" ? "-hub" : "-spoke"
+ mode = var.mode == "hub" ? "-hub" : "-spoke"
vpc_name = "${var.environment_code}-shared-base${local.mode}"
network_name = "vpc-${local.vpc_name}"
private_googleapis_cidr = module.private_service_connect.private_service_connect_ip
diff --git a/3-networks-hub-and-spoke/modules/base_shared_vpc/nat.tf b/3-networks-hub-and-spoke/modules/base_shared_vpc/nat.tf
new file mode 100644
index 000000000..b4872e0a9
--- /dev/null
+++ b/3-networks-hub-and-spoke/modules/base_shared_vpc/nat.tf
@@ -0,0 +1,90 @@
+/**
+ * Copyright 2022 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.
+ */
+
+
+/******************************************
+ NAT Cloud Router & NAT config
+ *****************************************/
+
+resource "google_compute_router" "nat_router_region1" {
+ count = var.nat_enabled ? 1 : 0
+ name = "cr-${local.vpc_name}-${var.default_region1}-nat-router"
+ project = var.project_id
+ region = var.default_region1
+ network = module.main.network_self_link
+
+ bgp {
+ asn = var.nat_bgp_asn
+ }
+}
+
+resource "google_compute_address" "nat_external_addresses_region1" {
+ count = var.nat_enabled ? var.nat_num_addresses_region1 : 0
+ project = var.project_id
+ name = "ca-${local.vpc_name}-${var.default_region1}-${count.index}"
+ region = var.default_region1
+}
+
+resource "google_compute_router_nat" "egress_nat_region1" {
+ count = var.nat_enabled ? 1 : 0
+ name = "rn-${local.vpc_name}-${var.default_region1}-egress"
+ project = var.project_id
+ router = google_compute_router.nat_router_region1.0.name
+ region = var.default_region1
+ nat_ip_allocate_option = "MANUAL_ONLY"
+ nat_ips = google_compute_address.nat_external_addresses_region1.*.self_link
+ source_subnetwork_ip_ranges_to_nat = "ALL_SUBNETWORKS_ALL_IP_RANGES"
+
+ log_config {
+ filter = "TRANSLATIONS_ONLY"
+ enable = true
+ }
+}
+
+resource "google_compute_router" "nat_router_region2" {
+ count = var.nat_enabled ? 1 : 0
+ name = "cr-${local.vpc_name}-${var.default_region2}-nat-router"
+ project = var.project_id
+ region = var.default_region2
+ network = module.main.network_self_link
+
+ bgp {
+ asn = var.nat_bgp_asn
+ }
+}
+
+resource "google_compute_address" "nat_external_addresses_region2" {
+ count = var.nat_enabled ? var.nat_num_addresses_region2 : 0
+ project = var.project_id
+ name = "ca-${local.vpc_name}-${var.default_region2}-${count.index}"
+ region = var.default_region2
+}
+
+resource "google_compute_router_nat" "egress_nat2" {
+ count = var.nat_enabled ? 1 : 0
+ name = "rn-${local.vpc_name}-${var.default_region2}-egress"
+ project = var.project_id
+ router = google_compute_router.nat_router_region2.0.name
+ region = var.default_region2
+ nat_ip_allocate_option = "MANUAL_ONLY"
+ nat_ips = google_compute_address.nat_external_addresses_region2.*.self_link
+ source_subnetwork_ip_ranges_to_nat = "ALL_SUBNETWORKS_ALL_IP_RANGES"
+
+ log_config {
+ filter = "TRANSLATIONS_ONLY"
+ enable = true
+ }
+}
diff --git a/3-networks-hub-and-spoke/modules/base_shared_vpc/outputs.tf b/3-networks-hub-and-spoke/modules/base_shared_vpc/outputs.tf
new file mode 100644
index 000000000..ff2ae8430
--- /dev/null
+++ b/3-networks-hub-and-spoke/modules/base_shared_vpc/outputs.tf
@@ -0,0 +1,60 @@
+/**
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+output "network_name" {
+ value = module.main.network_name
+ description = "The name of the VPC being created"
+}
+
+output "network_self_link" {
+ value = module.main.network_self_link
+ description = "The URI of the VPC being created"
+}
+
+output "subnets_names" {
+ value = module.main.subnets_names
+ description = "The names of the subnets being created"
+}
+
+output "subnets_ips" {
+ value = module.main.subnets_ips
+ description = "The IPs and CIDRs of the subnets being created"
+}
+
+output "subnets_self_links" {
+ value = module.main.subnets_self_links
+ description = "The self-links of subnets being created"
+}
+
+output "subnets_regions" {
+ value = module.main.subnets_regions
+ description = "The region where the subnets will be created"
+}
+
+output "subnets_private_access" {
+ value = module.main.subnets_private_access
+ description = "Whether the subnets have access to Google API's without a public IP"
+}
+
+output "subnets_flow_logs" {
+ value = module.main.subnets_flow_logs
+ description = "Whether the subnets have VPC flow logs enabled"
+}
+
+output "subnets_secondary_ranges" {
+ value = module.main.subnets_secondary_ranges
+ description = "The secondary ranges associated with these subnets"
+}
diff --git a/3-networks-hub-and-spoke/modules/base_shared_vpc/private_service_connect.tf b/3-networks-hub-and-spoke/modules/base_shared_vpc/private_service_connect.tf
new file mode 100644
index 000000000..e16cbdecf
--- /dev/null
+++ b/3-networks-hub-and-spoke/modules/base_shared_vpc/private_service_connect.tf
@@ -0,0 +1,26 @@
+/**
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+module "private_service_connect" {
+ source = "../private_service_connect"
+ project_id = var.project_id
+ network_id = module.main.network_self_link
+ environment_code = var.environment_code
+ network_self_link = module.main.network_self_link
+ private_service_connect_ip = "10.3.0.5"
+ forwarding_rule_target = "all-apis"
+}
diff --git a/3-networks/modules/base_shared_vpc/variables.tf b/3-networks-hub-and-spoke/modules/base_shared_vpc/variables.tf
similarity index 99%
rename from 3-networks/modules/base_shared_vpc/variables.tf
rename to 3-networks-hub-and-spoke/modules/base_shared_vpc/variables.tf
index 6cae02c97..ab7d2c075 100644
--- a/3-networks/modules/base_shared_vpc/variables.tf
+++ b/3-networks-hub-and-spoke/modules/base_shared_vpc/variables.tf
@@ -1,5 +1,5 @@
/**
- * Copyright 2021 Google LLC
+ * Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/3-networks-hub-and-spoke/modules/base_shared_vpc/versions.tf b/3-networks-hub-and-spoke/modules/base_shared_vpc/versions.tf
new file mode 100644
index 000000000..7e65c7ef3
--- /dev/null
+++ b/3-networks-hub-and-spoke/modules/base_shared_vpc/versions.tf
@@ -0,0 +1,37 @@
+/**
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+terraform {
+ required_version = ">= 0.13"
+ required_providers {
+ google = {
+ source = "hashicorp/google"
+ version = ">= 3.50"
+ }
+ google-beta = {
+ source = "hashicorp/google-beta"
+ version = ">= 3.50"
+ }
+ }
+
+ provider_meta "google" {
+ module_name = "blueprints/terraform/terraform-example-foundation:base_shared_vpc/v2.3.1"
+ }
+
+ provider_meta "google-beta" {
+ module_name = "blueprints/terraform/terraform-example-foundation:base_shared_vpc/v2.3.1"
+ }
+}
diff --git a/3-networks-hub-and-spoke/modules/dedicated_interconnect/README.md b/3-networks-hub-and-spoke/modules/dedicated_interconnect/README.md
new file mode 100644
index 000000000..746335121
--- /dev/null
+++ b/3-networks-hub-and-spoke/modules/dedicated_interconnect/README.md
@@ -0,0 +1,63 @@
+# Dedicated Interconnect module
+
+This module implements the recommendation proposed in [Establishing 99.99% Availability for Dedicated Interconnect](https://cloud.google.com/network-connectivity/docs/interconnect/tutorials/dedicated-creating-9999-availability).
+
+## Prerequisites
+
+1. Provisioning of four [Dedicated Interconnect connections](https://cloud.google.com/network-connectivity/docs/interconnect/concepts/dedicated-overview) in the `prj-interconnect` project created in step `1-org` under folder `fldr-common`.
+
+## Usage
+
+1. Rename `interconnect.tf.example` to `interconnect.tf` in the environment folder in `3-networks-hub-and-spoke/envs/`
+1. Update the file `interconnect.tf` with values that are valid for your environment for the interconnects, locations, candidate subnetworks, vlan_tag8021q and peer info.
+1. The candidate subnetworks and vlan_tag8021q variables can be set to `null` to allow the interconnect module to auto generate these values.
+
+
+## Inputs
+
+| Name | Description | Type | Default | Required |
+|------|-------------|------|---------|:--------:|
+| cloud\_router\_labels | A map of suffixes for labelling vlans with four entries like "vlan\_1" => "suffix1" with keys from `vlan_1` to `vlan_4`. | `map(string)` | `{}` | 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 |
+| peer\_asn | Peer BGP Autonomous System Number (ASN). | `number` | n/a | yes |
+| peer\_name | Name of this BGP peer. The name must be 1-63 characters long, and comply with RFC1035. Specifically, the name must be 1-63 characters long and match the regular expression [a-z]([-a-z0-9]\*[a-z0-9])? | `string` | n/a | yes |
+| region1 | First subnet region. The Dedicated Interconnect module only configures two regions. | `string` | n/a | yes |
+| region1\_interconnect1 | URL of the underlying Interconnect object that this attachment's traffic will traverse through. | `string` | n/a | yes |
+| region1\_interconnect1\_candidate\_subnets | Up to 16 candidate prefixes that can be used to restrict the allocation of cloudRouterIpAddress and customerRouterIpAddress for this attachment. All prefixes must be within link-local address space (169.254.0.0/16) and must be /29 or shorter (/28, /27, etc). | `list(string)` | `null` | no |
+| region1\_interconnect1\_location | Name of the interconnect location used in the creation of the Interconnect for the first location of region1 | `string` | n/a | yes |
+| region1\_interconnect1\_vlan\_tag8021q | The IEEE 802.1Q VLAN tag for this attachment, in the range 2-4094. | `string` | `null` | no |
+| region1\_interconnect2 | URL of the underlying Interconnect object that this attachment's traffic will traverse through. | `string` | n/a | yes |
+| region1\_interconnect2\_candidate\_subnets | Up to 16 candidate prefixes that can be used to restrict the allocation of cloudRouterIpAddress and customerRouterIpAddress for this attachment. All prefixes must be within link-local address space (169.254.0.0/16) and must be /29 or shorter (/28, /27, etc). | `list(string)` | `null` | no |
+| region1\_interconnect2\_location | Name of the interconnect location used in the creation of the Interconnect for the second location of region1 | `string` | n/a | yes |
+| region1\_interconnect2\_vlan\_tag8021q | The IEEE 802.1Q VLAN tag for this attachment, in the range 2-4094. | `string` | `null` | no |
+| region1\_router1\_name | Name of the Router 1 for Region 1 where the attachment resides. | `string` | n/a | yes |
+| region1\_router2\_name | Name of the Router 2 for Region 1 where the attachment resides. | `string` | n/a | yes |
+| region2 | Second subnet region. The Dedicated Interconnect module only configures two regions. | `string` | n/a | yes |
+| region2\_interconnect1 | URL of the underlying Interconnect object that this attachment's traffic will traverse through. | `string` | n/a | yes |
+| region2\_interconnect1\_candidate\_subnets | Up to 16 candidate prefixes that can be used to restrict the allocation of cloudRouterIpAddress and customerRouterIpAddress for this attachment. All prefixes must be within link-local address space (169.254.0.0/16) and must be /29 or shorter (/28, /27, etc). | `list(string)` | `null` | no |
+| region2\_interconnect1\_location | Name of the interconnect location used in the creation of the Interconnect for the first location of region2 | `string` | n/a | yes |
+| region2\_interconnect1\_vlan\_tag8021q | The IEEE 802.1Q VLAN tag for this attachment, in the range 2-4094. | `string` | `null` | no |
+| region2\_interconnect2 | URL of the underlying Interconnect object that this attachment's traffic will traverse through. | `string` | n/a | yes |
+| region2\_interconnect2\_candidate\_subnets | Up to 16 candidate prefixes that can be used to restrict the allocation of cloudRouterIpAddress and customerRouterIpAddress for this attachment. All prefixes must be within link-local address space (169.254.0.0/16) and must be /29 or shorter (/28, /27, etc). | `list(string)` | `null` | no |
+| region2\_interconnect2\_location | Name of the interconnect location used in the creation of the Interconnect for the second location of region2 | `string` | n/a | yes |
+| region2\_interconnect2\_vlan\_tag8021q | The IEEE 802.1Q VLAN tag for this attachment, in the range 2-4094. | `string` | `null` | no |
+| region2\_router1\_name | Name of the Router 1 for Region 2 where the attachment resides. | `string` | n/a | yes |
+| region2\_router2\_name | Name of the Router 2 for Region 2 where the attachment resides | `string` | n/a | yes |
+| vpc\_name | Label to identify the VPC associated with shared VPC that will use the Interconnect. | `string` | n/a | yes |
+
+## Outputs
+
+| Name | Description |
+|------|-------------|
+| interconnect\_attachment1\_region1 | The interconnect attachment 1 for region 1 |
+| interconnect\_attachment1\_region1\_customer\_router\_ip\_address | IPv4 address + prefix length to be configured on the customer router subinterface for this interconnect attachment. |
+| interconnect\_attachment1\_region2 | The interconnect attachment 1 for region 2 |
+| interconnect\_attachment1\_region2\_customer\_router\_ip\_address | IPv4 address + prefix length to be configured on the customer router subinterface for this interconnect attachment. |
+| interconnect\_attachment2\_region1 | The interconnect attachment 2 for region 1 |
+| interconnect\_attachment2\_region1\_customer\_router\_ip\_address | IPv4 address + prefix length to be configured on the customer router subinterface for this interconnect attachment. |
+| interconnect\_attachment2\_region2 | The interconnect attachment 2 for region 2 |
+| interconnect\_attachment2\_region2\_customer\_router\_ip\_address | IPv4 address + prefix length to be configured on the customer router subinterface for this interconnect attachment. |
+
+
diff --git a/3-networks-hub-and-spoke/modules/dedicated_interconnect/main.tf b/3-networks-hub-and-spoke/modules/dedicated_interconnect/main.tf
new file mode 100644
index 000000000..0380a69ac
--- /dev/null
+++ b/3-networks-hub-and-spoke/modules/dedicated_interconnect/main.tf
@@ -0,0 +1,125 @@
+/**
+ * Copyright 2022 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 {
+ parent_id = var.parent_folder != "" ? "folders/${var.parent_folder}" : "organizations/${var.org_id}"
+ interconnect_project_id = data.google_projects.interconnect_project.projects[0].project_id
+ suffix1 = lookup(var.cloud_router_labels, "vlan_1", "cr1")
+ suffix2 = lookup(var.cloud_router_labels, "vlan_2", "cr2")
+ suffix3 = lookup(var.cloud_router_labels, "vlan_3", "cr3")
+ suffix4 = lookup(var.cloud_router_labels, "vlan_4", "cr4")
+}
+
+data "google_active_folder" "common" {
+ display_name = "${var.folder_prefix}-common"
+ parent = local.parent_id
+}
+
+data "google_projects" "interconnect_project" {
+ filter = "parent.id:${split("/", data.google_active_folder.common.name)[1]} labels.application_name=org-interconnect lifecycleState=ACTIVE"
+}
+
+module "interconnect_attachment1_region1" {
+ source = "terraform-google-modules/cloud-router/google//modules/interconnect_attachment"
+ version = "~> 2.0.0"
+
+ name = "vl-${var.region1_interconnect1_location}-${var.vpc_name}-${var.region1}-${local.suffix1}"
+ project = local.interconnect_project_id
+ region = var.region1
+ router = var.region1_router1_name
+
+ interconnect = var.region1_interconnect1
+ candidate_subnets = var.region1_interconnect1_candidate_subnets
+ vlan_tag8021q = var.region1_interconnect1_vlan_tag8021q
+
+ interface = {
+ name = "if-${var.region1_interconnect1_location}-${var.vpc_name}-${var.region1}-${local.suffix1}"
+ }
+
+ peer = {
+ name = var.peer_name
+ peer_asn = var.peer_asn
+ }
+}
+
+module "interconnect_attachment2_region1" {
+ source = "terraform-google-modules/cloud-router/google//modules/interconnect_attachment"
+ version = "~> 0.4.0"
+
+ name = "vl-${var.region1_interconnect2_location}-${var.vpc_name}-${var.region1}-${local.suffix2}"
+ project = local.interconnect_project_id
+ region = var.region1
+ router = var.region1_router2_name
+
+ interconnect = var.region1_interconnect2
+ candidate_subnets = var.region1_interconnect2_candidate_subnets
+ vlan_tag8021q = var.region1_interconnect2_vlan_tag8021q
+
+ interface = {
+ name = "if-${var.region1_interconnect2_location}-${var.vpc_name}-${var.region1}-${local.suffix2}"
+ }
+
+ peer = {
+ name = var.peer_name
+ peer_asn = var.peer_asn
+ }
+}
+
+module "interconnect_attachment1_region2" {
+ source = "terraform-google-modules/cloud-router/google//modules/interconnect_attachment"
+ version = "~> 0.4.0"
+
+ name = "vl-${var.region2_interconnect1_location}-${var.vpc_name}-${var.region2}-${local.suffix3}"
+ project = local.interconnect_project_id
+ region = var.region2
+ router = var.region2_router1_name
+
+ interconnect = var.region2_interconnect1
+ candidate_subnets = var.region2_interconnect1_candidate_subnets
+ vlan_tag8021q = var.region2_interconnect1_vlan_tag8021q
+
+ interface = {
+ name = "if-${var.region2_interconnect1_location}-${var.vpc_name}-${var.region2}-${local.suffix3}"
+ }
+
+ peer = {
+ name = var.peer_name
+ peer_asn = var.peer_asn
+ }
+}
+
+module "interconnect_attachment2_region2" {
+ source = "terraform-google-modules/cloud-router/google//modules/interconnect_attachment"
+ version = "~> 0.4.0"
+
+ name = "vl-${var.region2_interconnect2_location}-${var.vpc_name}-${var.region2}-${local.suffix4}"
+ project = local.interconnect_project_id
+ region = var.region2
+ router = var.region2_router2_name
+
+ interconnect = var.region2_interconnect2
+ candidate_subnets = var.region2_interconnect2_candidate_subnets
+ vlan_tag8021q = var.region2_interconnect2_vlan_tag8021q
+
+ interface = {
+ name = "if-${var.region2_interconnect2_location}-${var.vpc_name}-${var.region2}-${local.suffix4}"
+ }
+
+ peer = {
+ name = var.peer_name
+ peer_asn = var.peer_asn
+ }
+}
diff --git a/3-networks-hub-and-spoke/modules/dedicated_interconnect/outputs.tf b/3-networks-hub-and-spoke/modules/dedicated_interconnect/outputs.tf
new file mode 100644
index 000000000..8169261c9
--- /dev/null
+++ b/3-networks-hub-and-spoke/modules/dedicated_interconnect/outputs.tf
@@ -0,0 +1,55 @@
+/**
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+output "interconnect_attachment1_region1" {
+ value = module.interconnect_attachment1_region1.attachment
+ description = "The interconnect attachment 1 for region 1"
+}
+
+output "interconnect_attachment1_region1_customer_router_ip_address" {
+ value = module.interconnect_attachment1_region1.attachment.customer_router_ip_address
+ description = "IPv4 address + prefix length to be configured on the customer router subinterface for this interconnect attachment."
+}
+
+output "interconnect_attachment2_region1" {
+ value = module.interconnect_attachment2_region1.attachment
+ description = "The interconnect attachment 2 for region 1"
+}
+
+output "interconnect_attachment2_region1_customer_router_ip_address" {
+ value = module.interconnect_attachment2_region1.attachment.customer_router_ip_address
+ description = "IPv4 address + prefix length to be configured on the customer router subinterface for this interconnect attachment."
+}
+
+output "interconnect_attachment1_region2" {
+ value = module.interconnect_attachment1_region2.attachment
+ description = "The interconnect attachment 1 for region 2"
+}
+
+output "interconnect_attachment1_region2_customer_router_ip_address" {
+ value = module.interconnect_attachment1_region2.attachment.customer_router_ip_address
+ description = "IPv4 address + prefix length to be configured on the customer router subinterface for this interconnect attachment."
+}
+
+output "interconnect_attachment2_region2" {
+ value = module.interconnect_attachment2_region2.attachment
+ description = "The interconnect attachment 2 for region 2"
+}
+
+output "interconnect_attachment2_region2_customer_router_ip_address" {
+ value = module.interconnect_attachment2_region2.attachment.customer_router_ip_address
+ description = "IPv4 address + prefix length to be configured on the customer router subinterface for this interconnect attachment."
+}
diff --git a/3-networks-hub-and-spoke/modules/dedicated_interconnect/variables.tf b/3-networks-hub-and-spoke/modules/dedicated_interconnect/variables.tf
new file mode 100644
index 000000000..3a3f71259
--- /dev/null
+++ b/3-networks-hub-and-spoke/modules/dedicated_interconnect/variables.tf
@@ -0,0 +1,169 @@
+/**
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+variable "org_id" {
+ type = string
+ description = "Organization ID"
+}
+
+variable "parent_folder" {
+ description = "Optional - if using a folder for testing."
+ type = string
+ default = ""
+}
+
+variable "vpc_name" {
+ type = string
+ description = "Label to identify the VPC associated with shared VPC that will use the Interconnect."
+}
+
+variable "region1" {
+ type = string
+ description = "First subnet region. The Dedicated Interconnect module only configures two regions."
+}
+
+variable "region2" {
+ type = string
+ description = "Second subnet region. The Dedicated Interconnect module only configures two regions."
+}
+
+variable "peer_name" {
+ type = string
+ description = "Name of this BGP peer. The name must be 1-63 characters long, and comply with RFC1035. Specifically, the name must be 1-63 characters long and match the regular expression [a-z]([-a-z0-9]*[a-z0-9])?"
+}
+
+variable "peer_asn" {
+ type = number
+ description = "Peer BGP Autonomous System Number (ASN)."
+}
+
+variable "region1_interconnect1_location" {
+ type = string
+ description = "Name of the interconnect location used in the creation of the Interconnect for the first location of region1"
+}
+
+variable "region1_interconnect2_location" {
+ type = string
+ description = "Name of the interconnect location used in the creation of the Interconnect for the second location of region1"
+}
+
+variable "region2_interconnect1_location" {
+ type = string
+ description = "Name of the interconnect location used in the creation of the Interconnect for the first location of region2"
+}
+
+variable "region2_interconnect2_location" {
+ type = string
+ description = "Name of the interconnect location used in the creation of the Interconnect for the second location of region2"
+}
+
+variable "region1_interconnect1" {
+ type = string
+ description = "URL of the underlying Interconnect object that this attachment's traffic will traverse through."
+}
+
+variable "region1_interconnect2" {
+ type = string
+ description = "URL of the underlying Interconnect object that this attachment's traffic will traverse through."
+}
+
+variable "region2_interconnect1" {
+ type = string
+ description = "URL of the underlying Interconnect object that this attachment's traffic will traverse through."
+}
+
+variable "region2_interconnect2" {
+ type = string
+ description = "URL of the underlying Interconnect object that this attachment's traffic will traverse through."
+}
+
+variable "region1_router1_name" {
+ type = string
+ description = "Name of the Router 1 for Region 1 where the attachment resides."
+}
+
+variable "region1_router2_name" {
+ type = string
+ description = "Name of the Router 2 for Region 1 where the attachment resides."
+}
+
+variable "region2_router1_name" {
+ type = string
+ description = "Name of the Router 1 for Region 2 where the attachment resides."
+}
+
+variable "region2_router2_name" {
+ type = string
+ description = "Name of the Router 2 for Region 2 where the attachment resides"
+}
+
+variable "cloud_router_labels" {
+ type = map(string)
+ description = "A map of suffixes for labelling vlans with four entries like \"vlan_1\" => \"suffix1\" with keys from `vlan_1` to `vlan_4`."
+ default = {}
+}
+
+variable "region1_interconnect1_candidate_subnets" {
+ type = list(string)
+ description = "Up to 16 candidate prefixes that can be used to restrict the allocation of cloudRouterIpAddress and customerRouterIpAddress for this attachment. All prefixes must be within link-local address space (169.254.0.0/16) and must be /29 or shorter (/28, /27, etc)."
+ default = null
+}
+
+variable "region1_interconnect2_candidate_subnets" {
+ type = list(string)
+ description = "Up to 16 candidate prefixes that can be used to restrict the allocation of cloudRouterIpAddress and customerRouterIpAddress for this attachment. All prefixes must be within link-local address space (169.254.0.0/16) and must be /29 or shorter (/28, /27, etc)."
+ default = null
+}
+variable "region2_interconnect1_candidate_subnets" {
+ type = list(string)
+ description = "Up to 16 candidate prefixes that can be used to restrict the allocation of cloudRouterIpAddress and customerRouterIpAddress for this attachment. All prefixes must be within link-local address space (169.254.0.0/16) and must be /29 or shorter (/28, /27, etc)."
+ default = null
+}
+variable "region2_interconnect2_candidate_subnets" {
+ type = list(string)
+ description = "Up to 16 candidate prefixes that can be used to restrict the allocation of cloudRouterIpAddress and customerRouterIpAddress for this attachment. All prefixes must be within link-local address space (169.254.0.0/16) and must be /29 or shorter (/28, /27, etc)."
+ default = null
+}
+
+variable "region1_interconnect1_vlan_tag8021q" {
+ type = string
+ description = "The IEEE 802.1Q VLAN tag for this attachment, in the range 2-4094."
+ default = null
+}
+
+variable "region1_interconnect2_vlan_tag8021q" {
+ type = string
+ description = "The IEEE 802.1Q VLAN tag for this attachment, in the range 2-4094."
+ default = null
+}
+
+variable "region2_interconnect1_vlan_tag8021q" {
+ type = string
+ description = "The IEEE 802.1Q VLAN tag for this attachment, in the range 2-4094."
+ default = null
+}
+
+variable "region2_interconnect2_vlan_tag8021q" {
+ type = string
+ description = "The IEEE 802.1Q VLAN tag for this attachment, in the range 2-4094."
+ default = null
+}
+
+variable "folder_prefix" {
+ description = "Name prefix to use for folders created."
+ type = string
+ default = "fldr"
+}
diff --git a/3-networks-hub-and-spoke/modules/dedicated_interconnect/versions.tf b/3-networks-hub-and-spoke/modules/dedicated_interconnect/versions.tf
new file mode 100644
index 000000000..fb19c84e1
--- /dev/null
+++ b/3-networks-hub-and-spoke/modules/dedicated_interconnect/versions.tf
@@ -0,0 +1,37 @@
+/**
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+terraform {
+ required_version = ">= 0.13"
+ required_providers {
+ google = {
+ source = "hashicorp/google"
+ version = ">= 3.50"
+ }
+ google-beta = {
+ source = "hashicorp/google-beta"
+ version = ">= 3.50"
+ }
+ }
+
+ provider_meta "google" {
+ module_name = "blueprints/terraform/terraform-example-foundation:dedicated_interconnect/v2.3.1"
+ }
+
+ provider_meta "google-beta" {
+ module_name = "blueprints/terraform/terraform-example-foundation:dedicated_interconnect/v2.3.1"
+ }
+}
diff --git a/3-networks-hub-and-spoke/modules/hierarchical_firewall_policy/README.md b/3-networks-hub-and-spoke/modules/hierarchical_firewall_policy/README.md
new file mode 100644
index 000000000..e10abeba2
--- /dev/null
+++ b/3-networks-hub-and-spoke/modules/hierarchical_firewall_policy/README.md
@@ -0,0 +1,17 @@
+
+## Inputs
+
+| Name | Description | Type | Default | Required |
+|------|-------------|------|---------|:--------:|
+| associations | Resources to associate the policy to | `list(string)` | n/a | yes |
+| name | Hierarchical policy name | `string` | n/a | yes |
+| parent | Where the firewall policy will be created (can be organizations/{organization\_id} or folders/{folder\_id}) | `string` | n/a | yes |
+| rules | Firewall rules to add to the policy | map(object({
description = string
direction = string
action = string
priority = number
ranges = list(string)
ports = map(list(string))
target_service_accounts = list(string)
target_resources = list(string)
logging = bool
}))
| `{}` | no |
+
+## Outputs
+
+| Name | Description |
+|------|-------------|
+| id | n/a |
+
+
diff --git a/3-networks-hub-and-spoke/modules/hierarchical_firewall_policy/main.tf b/3-networks-hub-and-spoke/modules/hierarchical_firewall_policy/main.tf
new file mode 100644
index 000000000..be13e2f61
--- /dev/null
+++ b/3-networks-hub-and-spoke/modules/hierarchical_firewall_policy/main.tf
@@ -0,0 +1,68 @@
+/**
+ * Copyright 2022 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 {
+ policy_id = google_compute_organization_security_policy.policy.id
+}
+
+resource "random_string" "suffix" {
+ length = 4
+ upper = false
+ special = false
+}
+
+resource "google_compute_organization_security_policy" "policy" {
+ provider = google-beta
+ display_name = "${var.name}-${random_string.suffix.result}"
+ parent = var.parent
+}
+
+resource "google_compute_organization_security_policy_rule" "rule" {
+ provider = google-beta
+ for_each = var.rules
+
+ policy_id = google_compute_organization_security_policy.policy.id
+ action = each.value.action
+ direction = each.value.direction
+ priority = each.value.priority
+ target_resources = each.value.target_resources
+ target_service_accounts = each.value.target_service_accounts
+ enable_logging = each.value.logging
+ # preview = each.value.preview
+ match {
+ # description = each.value.description
+ config {
+ src_ip_ranges = each.value.direction == "INGRESS" ? each.value.ranges : null
+ dest_ip_ranges = each.value.direction == "EGRESS" ? each.value.ranges : null
+ dynamic "layer4_config" {
+ for_each = each.value.ports
+ iterator = port
+ content {
+ ip_protocol = port.key
+ ports = port.value
+ }
+ }
+ }
+ }
+}
+
+resource "google_compute_organization_security_policy_association" "association" {
+ provider = google-beta
+ for_each = toset(var.associations)
+ name = "${local.policy_id}-${each.value}"
+ policy_id = local.policy_id
+ attachment_id = each.value
+}
diff --git a/3-networks-hub-and-spoke/modules/hierarchical_firewall_policy/outputs.tf b/3-networks-hub-and-spoke/modules/hierarchical_firewall_policy/outputs.tf
new file mode 100644
index 000000000..eb6c174be
--- /dev/null
+++ b/3-networks-hub-and-spoke/modules/hierarchical_firewall_policy/outputs.tf
@@ -0,0 +1,19 @@
+/**
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+output "id" {
+ value = google_compute_organization_security_policy.policy.id
+}
diff --git a/3-networks-hub-and-spoke/modules/hierarchical_firewall_policy/variables.tf b/3-networks-hub-and-spoke/modules/hierarchical_firewall_policy/variables.tf
new file mode 100644
index 000000000..7a1eaee49
--- /dev/null
+++ b/3-networks-hub-and-spoke/modules/hierarchical_firewall_policy/variables.tf
@@ -0,0 +1,46 @@
+/**
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+variable "name" {
+ description = "Hierarchical policy name"
+ type = string
+}
+
+variable "parent" {
+ description = "Where the firewall policy will be created (can be organizations/{organization_id} or folders/{folder_id})"
+ type = string
+}
+
+variable "rules" {
+ description = "Firewall rules to add to the policy"
+ type = map(object({
+ description = string
+ direction = string
+ action = string
+ priority = number
+ ranges = list(string)
+ ports = map(list(string))
+ target_service_accounts = list(string)
+ target_resources = list(string)
+ logging = bool
+ }))
+ default = {}
+}
+
+variable "associations" {
+ description = "Resources to associate the policy to"
+ type = list(string)
+}
diff --git a/3-networks-hub-and-spoke/modules/hierarchical_firewall_policy/versions.tf b/3-networks-hub-and-spoke/modules/hierarchical_firewall_policy/versions.tf
new file mode 100644
index 000000000..fa91784e9
--- /dev/null
+++ b/3-networks-hub-and-spoke/modules/hierarchical_firewall_policy/versions.tf
@@ -0,0 +1,40 @@
+/**
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+terraform {
+ required_version = ">= 0.13"
+ required_providers {
+ google = {
+ source = "hashicorp/google"
+ version = ">= 3.50"
+ }
+ google-beta = {
+ source = "hashicorp/google-beta"
+ version = ">= 3.50"
+ }
+ random = {
+ source = "hashicorp/random"
+ }
+ }
+
+ provider_meta "google" {
+ module_name = "blueprints/terraform/terraform-example-foundation:hierarchical_firewall_policy/v2.3.1"
+ }
+
+ provider_meta "google-beta" {
+ module_name = "blueprints/terraform/terraform-example-foundation:hierarchical_firewall_policy/v2.3.1"
+ }
+}
diff --git a/3-networks-hub-and-spoke/modules/partner_interconnect/README.md b/3-networks-hub-and-spoke/modules/partner_interconnect/README.md
new file mode 100644
index 000000000..a89753d97
--- /dev/null
+++ b/3-networks-hub-and-spoke/modules/partner_interconnect/README.md
@@ -0,0 +1,54 @@
+# Partner Interconnect module
+
+This module implements the recommendation proposed in [Establishing 99.99% Availability for Partner Interconnect](https://cloud.google.com/network-connectivity/docs/interconnect/tutorials/partner-creating-9999-availability).
+
+## Prerequisites
+
+1. Provisioning of four [VLAN attachments](https://cloud.google.com/network-connectivity/docs/interconnect/concepts/partner-overview) in the Hub project in the specified environment. That would be the `prj-c-{base|restricted}-net-hub` under the folder `fldr-common` in case of Hub and Spoke architecture.
+
+Without Hub and Spoke enabled VLAN attachments will be created in `prj-{p|n|d}-shared-{base|restricted}` under corresponding environment's folder.
+
+## Usage
+
+1. Rename `partner_interconnect.tf.example` to `partner_interconnect.tf` in the environment folder in `3-networks-hub-and-spoke/modules/base_env` .
+1. Update the `enable_partner_interconnect` to `true` in each `main.tf` file in the environment folder in `3-networks-hub-and-spoke/envs/` .
+1. Update the file `partner_interconnect.tf` with values that are valid for your environment for the VLAN attachments, locations.
+
+
+## Inputs
+
+| Name | Description | Type | Default | Required |
+|------|-------------|------|---------|:--------:|
+| cloud\_router\_labels | A map of suffixes for labelling vlans with four entries like "vlan\_1" => "suffix1" with keys from `vlan_1` to `vlan_4`. | `map(string)` | `{}` | no |
+| environment | Environment in which to deploy the Partner Interconnect, must be 'common' if enable\_hub\_and\_spoke=true | `string` | `null` | 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 |
+| preactivate | Preactivate Partner Interconnect attachments, works only for level3 Partner Interconnect | `string` | `false` | no |
+| region1 | First subnet region. The Partner Interconnect module only configures two regions. | `string` | n/a | yes |
+| region1\_interconnect1\_location | Name of the interconnect location used in the creation of the Interconnect for the first location of region1 | `string` | n/a | yes |
+| region1\_interconnect2\_location | Name of the interconnect location used in the creation of the Interconnect for the second location of region1 | `string` | n/a | yes |
+| region1\_router1\_name | Name of the Router 1 for Region 1 where the attachment resides. | `string` | n/a | yes |
+| region1\_router2\_name | Name of the Router 2 for Region 1 where the attachment resides. | `string` | n/a | yes |
+| region2 | Second subnet region. The Partner Interconnect module only configures two regions. | `string` | n/a | yes |
+| region2\_interconnect1\_location | Name of the interconnect location used in the creation of the Interconnect for the first location of region2 | `string` | n/a | yes |
+| region2\_interconnect2\_location | Name of the interconnect location used in the creation of the Interconnect for the second location of region2 | `string` | n/a | yes |
+| region2\_router1\_name | Name of the Router 1 for Region 2 where the attachment resides. | `string` | n/a | yes |
+| region2\_router2\_name | Name of the Router 2 for Region 2 where the attachment resides | `string` | n/a | yes |
+| vpc\_name | Label to identify the VPC associated with shared VPC that will use the Interconnect. | `string` | n/a | yes |
+| vpc\_type | To which Shared VPC Host attach the Partner Interconnect - base/restricted | `string` | `null` | no |
+
+## Outputs
+
+| Name | Description |
+|------|-------------|
+| interconnect\_attachment1\_region1 | The interconnect attachment 1 for region 1 |
+| interconnect\_attachment1\_region1\_customer\_router\_ip\_address | IPv4 address + prefix length to be configured on the customer router subinterface for this interconnect attachment. |
+| interconnect\_attachment1\_region2 | The interconnect attachment 1 for region 2 |
+| interconnect\_attachment1\_region2\_customer\_router\_ip\_address | IPv4 address + prefix length to be configured on the customer router subinterface for this interconnect attachment. |
+| interconnect\_attachment2\_region1 | The interconnect attachment 2 for region 1 |
+| interconnect\_attachment2\_region1\_customer\_router\_ip\_address | IPv4 address + prefix length to be configured on the customer router subinterface for this interconnect attachment. |
+| interconnect\_attachment2\_region2 | The interconnect attachment 2 for region 2 |
+| interconnect\_attachment2\_region2\_customer\_router\_ip\_address | IPv4 address + prefix length to be configured on the customer router subinterface for this interconnect attachment. |
+
+
diff --git a/3-networks-hub-and-spoke/modules/partner_interconnect/main.tf b/3-networks-hub-and-spoke/modules/partner_interconnect/main.tf
new file mode 100644
index 000000000..f5f53e854
--- /dev/null
+++ b/3-networks-hub-and-spoke/modules/partner_interconnect/main.tf
@@ -0,0 +1,81 @@
+/**
+ * Copyright 2022 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 {
+ parent_id = var.parent_folder != "" ? "folders/${var.parent_folder}" : "organizations/${var.org_id}"
+ suffix1 = lookup(var.cloud_router_labels, "vlan_1", "cr1")
+ suffix2 = lookup(var.cloud_router_labels, "vlan_2", "cr2")
+ suffix3 = lookup(var.cloud_router_labels, "vlan_3", "cr3")
+ suffix4 = lookup(var.cloud_router_labels, "vlan_4", "cr4")
+
+ attachment_project_id = data.google_projects.attachment_project.projects[0].project_id
+
+ app_label = "org-${var.vpc_type}-net-hub"
+ environment_label = "production"
+}
+
+data "google_active_folder" "environment" {
+ display_name = "${var.folder_prefix}-${var.environment}"
+ parent = local.parent_id
+}
+
+data "google_projects" "attachment_project" {
+ filter = "parent.id:${split("/", data.google_active_folder.environment.name)[1]} labels.application_name=${local.app_label} labels.environment=${local.environment_label} lifecycleState=ACTIVE"
+}
+
+resource "google_compute_interconnect_attachment" "interconnect_attachment1_region1" {
+ name = "vl-${var.region1_interconnect1_location}-${var.vpc_name}-${var.region1}-${local.suffix1}"
+ project = local.attachment_project_id
+ region = var.region1
+ router = var.region1_router1_name
+
+ admin_enabled = var.preactivate
+ edge_availability_domain = "AVAILABILITY_DOMAIN_1"
+ type = "PARTNER"
+}
+
+resource "google_compute_interconnect_attachment" "interconnect_attachment2_region1" {
+ name = "vl-${var.region1_interconnect2_location}-${var.vpc_name}-${var.region1}-${local.suffix2}"
+ project = local.attachment_project_id
+ region = var.region1
+ router = var.region1_router2_name
+
+ admin_enabled = var.preactivate
+ edge_availability_domain = "AVAILABILITY_DOMAIN_2"
+ type = "PARTNER"
+}
+
+resource "google_compute_interconnect_attachment" "interconnect_attachment1_region2" {
+ name = "vl-${var.region2_interconnect1_location}-${var.vpc_name}-${var.region2}-${local.suffix1}"
+ project = local.attachment_project_id
+ region = var.region2
+ router = var.region2_router1_name
+
+ admin_enabled = var.preactivate
+ edge_availability_domain = "AVAILABILITY_DOMAIN_1"
+ type = "PARTNER"
+}
+
+resource "google_compute_interconnect_attachment" "interconnect_attachment2_region2" {
+ name = "vl-${var.region2_interconnect2_location}-${var.vpc_name}-${var.region2}-${local.suffix2}"
+ project = local.attachment_project_id
+ region = var.region2
+ router = var.region2_router2_name
+
+ admin_enabled = var.preactivate
+ edge_availability_domain = "AVAILABILITY_DOMAIN_2"
+ type = "PARTNER"
+}
diff --git a/3-networks-hub-and-spoke/modules/partner_interconnect/outputs.tf b/3-networks-hub-and-spoke/modules/partner_interconnect/outputs.tf
new file mode 100644
index 000000000..6c3116484
--- /dev/null
+++ b/3-networks-hub-and-spoke/modules/partner_interconnect/outputs.tf
@@ -0,0 +1,55 @@
+/**
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+output "interconnect_attachment1_region1" {
+ value = google_compute_interconnect_attachment.interconnect_attachment1_region1
+ description = "The interconnect attachment 1 for region 1"
+}
+
+output "interconnect_attachment1_region1_customer_router_ip_address" {
+ value = google_compute_interconnect_attachment.interconnect_attachment1_region1.customer_router_ip_address
+ description = "IPv4 address + prefix length to be configured on the customer router subinterface for this interconnect attachment."
+}
+
+output "interconnect_attachment2_region1" {
+ value = google_compute_interconnect_attachment.interconnect_attachment2_region1
+ description = "The interconnect attachment 2 for region 1"
+}
+
+output "interconnect_attachment2_region1_customer_router_ip_address" {
+ value = google_compute_interconnect_attachment.interconnect_attachment2_region1.customer_router_ip_address
+ description = "IPv4 address + prefix length to be configured on the customer router subinterface for this interconnect attachment."
+}
+
+output "interconnect_attachment1_region2" {
+ value = google_compute_interconnect_attachment.interconnect_attachment1_region2
+ description = "The interconnect attachment 1 for region 2"
+}
+
+output "interconnect_attachment1_region2_customer_router_ip_address" {
+ value = google_compute_interconnect_attachment.interconnect_attachment1_region2.customer_router_ip_address
+ description = "IPv4 address + prefix length to be configured on the customer router subinterface for this interconnect attachment."
+}
+
+output "interconnect_attachment2_region2" {
+ value = google_compute_interconnect_attachment.interconnect_attachment2_region2
+ description = "The interconnect attachment 2 for region 2"
+}
+
+output "interconnect_attachment2_region2_customer_router_ip_address" {
+ value = google_compute_interconnect_attachment.interconnect_attachment2_region2.customer_router_ip_address
+ description = "IPv4 address + prefix length to be configured on the customer router subinterface for this interconnect attachment."
+}
diff --git a/3-networks-hub-and-spoke/modules/partner_interconnect/variables.tf b/3-networks-hub-and-spoke/modules/partner_interconnect/variables.tf
new file mode 100644
index 000000000..cfadab154
--- /dev/null
+++ b/3-networks-hub-and-spoke/modules/partner_interconnect/variables.tf
@@ -0,0 +1,111 @@
+/**
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+variable "org_id" {
+ type = string
+ description = "Organization ID"
+}
+
+variable "parent_folder" {
+ description = "Optional - if using a folder for testing."
+ type = string
+ default = ""
+}
+
+variable "vpc_name" {
+ type = string
+ description = "Label to identify the VPC associated with shared VPC that will use the Interconnect."
+}
+
+variable "region1" {
+ type = string
+ description = "First subnet region. The Partner Interconnect module only configures two regions."
+}
+
+variable "region2" {
+ type = string
+ description = "Second subnet region. The Partner Interconnect module only configures two regions."
+}
+
+variable "region1_interconnect1_location" {
+ type = string
+ description = "Name of the interconnect location used in the creation of the Interconnect for the first location of region1"
+}
+
+variable "region1_interconnect2_location" {
+ type = string
+ description = "Name of the interconnect location used in the creation of the Interconnect for the second location of region1"
+}
+
+variable "region2_interconnect1_location" {
+ type = string
+ description = "Name of the interconnect location used in the creation of the Interconnect for the first location of region2"
+}
+
+variable "region2_interconnect2_location" {
+ type = string
+ description = "Name of the interconnect location used in the creation of the Interconnect for the second location of region2"
+}
+
+variable "region1_router1_name" {
+ type = string
+ description = "Name of the Router 1 for Region 1 where the attachment resides."
+}
+
+variable "region1_router2_name" {
+ type = string
+ description = "Name of the Router 2 for Region 1 where the attachment resides."
+}
+
+variable "region2_router1_name" {
+ type = string
+ description = "Name of the Router 1 for Region 2 where the attachment resides."
+}
+
+variable "region2_router2_name" {
+ type = string
+ description = "Name of the Router 2 for Region 2 where the attachment resides"
+}
+
+variable "cloud_router_labels" {
+ type = map(string)
+ description = "A map of suffixes for labelling vlans with four entries like \"vlan_1\" => \"suffix1\" with keys from `vlan_1` to `vlan_4`."
+ default = {}
+}
+
+variable "folder_prefix" {
+ description = "Name prefix to use for folders created."
+ type = string
+ default = "fldr"
+}
+
+variable "preactivate" {
+ description = "Preactivate Partner Interconnect attachments, works only for level3 Partner Interconnect"
+ type = string
+ default = false
+}
+
+variable "environment" {
+ description = "Environment in which to deploy the Partner Interconnect, must be 'common' if enable_hub_and_spoke=true"
+ type = string
+ default = null
+}
+
+variable "vpc_type" {
+ description = "To which Shared VPC Host attach the Partner Interconnect - base/restricted"
+ type = string
+ default = null
+}
diff --git a/3-networks-hub-and-spoke/modules/partner_interconnect/versions.tf b/3-networks-hub-and-spoke/modules/partner_interconnect/versions.tf
new file mode 100644
index 000000000..d52b59836
--- /dev/null
+++ b/3-networks-hub-and-spoke/modules/partner_interconnect/versions.tf
@@ -0,0 +1,37 @@
+/**
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+terraform {
+ required_version = ">= 0.13"
+ required_providers {
+ google = {
+ source = "hashicorp/google"
+ version = ">= 3.50"
+ }
+ google-beta = {
+ source = "hashicorp/google-beta"
+ version = ">= 3.50"
+ }
+ }
+
+ provider_meta "google" {
+ module_name = "blueprints/terraform/terraform-example-foundation:partner_interconnect/v2.3.1"
+ }
+
+ provider_meta "google-beta" {
+ module_name = "blueprints/terraform/terraform-example-foundation:partner_interconnect/v2.3.1"
+ }
+}
diff --git a/3-networks-hub-and-spoke/modules/private_service_connect/dns.tf b/3-networks-hub-and-spoke/modules/private_service_connect/dns.tf
new file mode 100644
index 000000000..81cb5d948
--- /dev/null
+++ b/3-networks-hub-and-spoke/modules/private_service_connect/dns.tf
@@ -0,0 +1,114 @@
+/**
+ * Copyright 2022 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.
+ */
+
+/******************************************
+ Private Google APIs DNS Zone & records.
+ *****************************************/
+
+module "googleapis" {
+ source = "terraform-google-modules/cloud-dns/google"
+ version = "~> 4.0"
+ project_id = var.project_id
+ type = "private"
+ name = "dz-${var.environment_code}-shared-${local.vpc_type}-apis"
+ domain = "googleapis.com."
+ description = "Private DNS zone to configure ${local.googleapis_url}"
+
+ private_visibility_config_networks = [
+ var.network_self_link
+ ]
+
+ recordsets = [
+ {
+ name = "*"
+ type = "CNAME"
+ ttl = 300
+ records = [local.googleapis_url]
+ },
+ {
+ name = local.recordsets_name
+ type = "A"
+ ttl = 300
+ records = [var.private_service_connect_ip]
+ },
+ ]
+}
+
+/******************************************
+ GCR DNS Zone & records.
+ *****************************************/
+
+module "gcr" {
+ source = "terraform-google-modules/cloud-dns/google"
+ version = "~> 3.1"
+ project_id = var.project_id
+ type = "private"
+ name = "dz-${var.environment_code}-shared-${local.vpc_type}-gcr"
+ domain = "gcr.io."
+ description = "Private DNS zone to configure gcr.io"
+
+ private_visibility_config_networks = [
+ var.network_self_link
+ ]
+
+ recordsets = [
+ {
+ name = "*"
+ type = "CNAME"
+ ttl = 300
+ records = ["gcr.io."]
+ },
+ {
+ name = ""
+ type = "A"
+ ttl = 300
+ records = [var.private_service_connect_ip]
+ },
+ ]
+}
+
+/***********************************************
+ Artifact Registry DNS Zone & records.
+ ***********************************************/
+
+module "pkg_dev" {
+ source = "terraform-google-modules/cloud-dns/google"
+ version = "~> 3.1"
+ project_id = var.project_id
+ type = "private"
+ name = "dz-${var.environment_code}-shared-${local.vpc_type}-pkg-dev"
+ domain = "pkg.dev."
+ description = "Private DNS zone to configure pkg.dev"
+
+ private_visibility_config_networks = [
+ var.network_self_link
+ ]
+
+ recordsets = [
+ {
+ name = "*"
+ type = "CNAME"
+ ttl = 300
+ records = ["pkg.dev."]
+ },
+ {
+ name = ""
+ type = "A"
+ ttl = 300
+ records = [var.private_service_connect_ip]
+ },
+ ]
+}
diff --git a/3-networks-hub-and-spoke/modules/private_service_connect/main.tf b/3-networks-hub-and-spoke/modules/private_service_connect/main.tf
new file mode 100644
index 000000000..d8104c7a9
--- /dev/null
+++ b/3-networks-hub-and-spoke/modules/private_service_connect/main.tf
@@ -0,0 +1,41 @@
+/**
+ * Copyright 2022 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 {
+ vpc_type = var.forwarding_rule_target == "vpc-sc" ? "restricted" : "base"
+ googleapis_url = var.forwarding_rule_target == "vpc-sc" ? "restricted.googleapis.com." : "private.googleapis.com."
+ recordsets_name = split(".", local.googleapis_url)[0]
+}
+
+resource "google_compute_global_address" "private_service_connect" {
+ provider = google-beta
+ project = var.project_id
+ name = "global-psconnect-ip"
+ address_type = "INTERNAL"
+ purpose = "PRIVATE_SERVICE_CONNECT"
+ network = var.network_id
+ address = var.private_service_connect_ip
+}
+
+resource "google_compute_global_forwarding_rule" "forwarding_rule_private_service_connect" {
+ provider = google-beta
+ project = var.project_id
+ name = "globalrule"
+ target = var.forwarding_rule_target
+ network = var.network_id
+ ip_address = google_compute_global_address.private_service_connect.id
+ load_balancing_scheme = ""
+}
diff --git a/3-networks-hub-and-spoke/modules/private_service_connect/outputs.tf b/3-networks-hub-and-spoke/modules/private_service_connect/outputs.tf
new file mode 100644
index 000000000..2603beacb
--- /dev/null
+++ b/3-networks-hub-and-spoke/modules/private_service_connect/outputs.tf
@@ -0,0 +1,29 @@
+/**
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+output "private_service_connect_ip" {
+ value = var.private_service_connect_ip
+ description = "The private service connect ip"
+
+ depends_on = [
+ google_compute_global_forwarding_rule.forwarding_rule_private_service_connect
+ ]
+}
+
+output "global_address_id" {
+ value = google_compute_global_address.private_service_connect.id
+ description = "An identifier for the global address created for the private service connect with format `projects/{{project}}/global/addresses/{{name}}`"
+}
diff --git a/3-networks-hub-and-spoke/modules/private_service_connect/variables.tf b/3-networks-hub-and-spoke/modules/private_service_connect/variables.tf
new file mode 100644
index 000000000..b1e585328
--- /dev/null
+++ b/3-networks-hub-and-spoke/modules/private_service_connect/variables.tf
@@ -0,0 +1,50 @@
+/**
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+variable "project_id" {
+ description = "Project ID for Private Service Connect."
+ type = string
+}
+
+variable "network_id" {
+ description = "Network ID for Private Service Connect."
+ type = string
+}
+
+variable "network_self_link" {
+ description = "Network self link for Private Service Connect."
+ type = string
+}
+
+variable "environment_code" {
+ description = "A short form of the folder level resources (environment) within the Google Cloud organization."
+ type = string
+}
+
+variable "private_service_connect_ip" {
+ description = "The internal IP to be used for the private service connect."
+ type = string
+}
+
+variable "forwarding_rule_target" {
+ description = "Target resource to receive the matched traffic. Only `all-apis` and `vpc-sc` are valid."
+ type = string
+
+ validation {
+ condition = var.forwarding_rule_target == "all-apis" || var.forwarding_rule_target == "vpc-sc"
+ error_message = "For forwarding_rule_target only `all-apis` and `vpc-sc` are valid."
+ }
+}
diff --git a/3-networks-hub-and-spoke/modules/private_service_connect/versions.tf b/3-networks-hub-and-spoke/modules/private_service_connect/versions.tf
new file mode 100644
index 000000000..6256afb3a
--- /dev/null
+++ b/3-networks-hub-and-spoke/modules/private_service_connect/versions.tf
@@ -0,0 +1,29 @@
+/**
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+terraform {
+ required_version = ">= 0.13"
+ required_providers {
+ google = {
+ source = "hashicorp/google"
+ version = ">= 3.50"
+ }
+ google-beta = {
+ source = "hashicorp/google-beta"
+ version = ">= 3.50"
+ }
+ }
+}
diff --git a/3-networks-hub-and-spoke/modules/restricted_shared_vpc/README.md b/3-networks-hub-and-spoke/modules/restricted_shared_vpc/README.md
new file mode 100644
index 000000000..4e7fb1702
--- /dev/null
+++ b/3-networks-hub-and-spoke/modules/restricted_shared_vpc/README.md
@@ -0,0 +1,48 @@
+
+## Inputs
+
+| Name | Description | Type | Default | Required |
+|------|-------------|------|---------|:--------:|
+| access\_context\_manager\_policy\_id | The id of the default Access Context Manager policy. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR_ORGANIZATION_ID --format="value(name)"`. | `number` | n/a | yes |
+| allow\_all\_egress\_ranges | List of network ranges to which all egress traffic will be allowed | `any` | `null` | no |
+| allow\_all\_ingress\_ranges | List of network ranges from which all ingress traffic will be allowed | `any` | `null` | no |
+| bgp\_asn\_subnet | BGP ASN for Subnets cloud routers. | `number` | n/a | yes |
+| default\_region1 | First subnet region. The shared vpc modules only configures two regions. | `string` | n/a | yes |
+| default\_region2 | Second subnet region. The shared vpc modules only configures two regions. | `string` | n/a | yes |
+| 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 |
+| 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 |
+| 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 chosen, 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 |
+| nat\_num\_addresses\_region2 | Number of external IPs to reserve for region 2 Cloud NAT. | `number` | `2` | 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` | `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 |
+| 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 |
+| windows\_activation\_enabled | Enable Windows license activation for Windows workloads. | `bool` | `false` | no |
+
+## Outputs
+
+| Name | Description |
+|------|-------------|
+| access\_level\_name | Access context manager access level name |
+| network\_name | The name of the VPC being created |
+| network\_self\_link | The URI of the VPC being created |
+| service\_perimeter\_name | Access context manager service perimeter name |
+| subnets\_ips | The IPs and CIDRs of the subnets being created |
+| subnets\_names | The names of the subnets being created |
+| subnets\_regions | The region where the subnets will be created |
+| subnets\_secondary\_ranges | The secondary ranges associated with these subnets |
+| subnets\_self\_links | The self-links of subnets being created |
+
+
diff --git a/3-networks-hub-and-spoke/modules/restricted_shared_vpc/data.tf b/3-networks-hub-and-spoke/modules/restricted_shared_vpc/data.tf
new file mode 100644
index 000000000..db6163d95
--- /dev/null
+++ b/3-networks-hub-and-spoke/modules/restricted_shared_vpc/data.tf
@@ -0,0 +1,31 @@
+/**
+ * Copyright 2022 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.
+ */
+
+/******************************************
+ Ranges for default firewall rules.
+ *****************************************/
+
+data "google_netblock_ip_ranges" "legacy_health_checkers" {
+ range_type = "legacy-health-checkers"
+}
+
+data "google_netblock_ip_ranges" "health_checkers" {
+ range_type = "health-checkers"
+}
+
+data "google_netblock_ip_ranges" "iap_forwarders" {
+ range_type = "iap-forwarders"
+}
diff --git a/3-networks-hub-and-spoke/modules/restricted_shared_vpc/dns.tf b/3-networks-hub-and-spoke/modules/restricted_shared_vpc/dns.tf
new file mode 100644
index 000000000..036237778
--- /dev/null
+++ b/3-networks-hub-and-spoke/modules/restricted_shared_vpc/dns.tf
@@ -0,0 +1,69 @@
+/**
+ * Copyright 2022 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 {
+ parent_id = var.parent_folder != "" ? "folders/${var.parent_folder}" : "organizations/${var.org_id}"
+}
+
+data "google_active_folder" "common" {
+ display_name = "${var.folder_prefix}-common"
+ parent = local.parent_id
+}
+
+/******************************************
+ DNS Hub Project
+*****************************************/
+
+data "google_projects" "dns_hub" {
+ filter = "parent.id:${split("/", data.google_active_folder.common.name)[1]} labels.application_name=org-dns-hub lifecycleState=ACTIVE"
+}
+
+data "google_compute_network" "vpc_dns_hub" {
+ name = "vpc-c-dns-hub"
+ project = data.google_projects.dns_hub.projects[0].project_id
+}
+
+/******************************************
+ Default DNS Policy
+ *****************************************/
+
+resource "google_dns_policy" "default_policy" {
+ project = var.project_id
+ name = "default-policy"
+ enable_inbound_forwarding = var.dns_enable_inbound_forwarding
+ enable_logging = var.dns_enable_logging
+ networks {
+ network_url = module.main.network_self_link
+ }
+}
+
+/******************************************
+ Creates DNS Peering to DNS HUB
+*****************************************/
+module "peering_zone" {
+ source = "terraform-google-modules/cloud-dns/google"
+ version = "~> 3.1"
+ project_id = var.project_id
+ type = "peering"
+ name = "dz-${var.environment_code}-shared-restricted-to-dns-hub"
+ domain = var.domain
+ description = "Private DNS peering zone."
+
+ private_visibility_config_networks = [
+ module.main.network_self_link
+ ]
+ target_network = data.google_compute_network.vpc_dns_hub.self_link
+}
diff --git a/3-networks-hub-and-spoke/modules/restricted_shared_vpc/firewall.tf b/3-networks-hub-and-spoke/modules/restricted_shared_vpc/firewall.tf
new file mode 100644
index 000000000..d992a195b
--- /dev/null
+++ b/3-networks-hub-and-spoke/modules/restricted_shared_vpc/firewall.tf
@@ -0,0 +1,120 @@
+/**
+ * Copyright 2022 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.
+ */
+
+
+/******************************************
+ Mandatory firewall rules
+ *****************************************/
+resource "google_compute_firewall" "deny_all_egress" {
+ name = "fw-${var.environment_code}-shared-restricted-65535-e-d-all-all-all"
+ network = module.main.network_name
+ project = var.project_id
+ direction = "EGRESS"
+ priority = 65535
+
+ dynamic "log_config" {
+ for_each = var.firewall_enable_logging == true ? [{
+ metadata = "INCLUDE_ALL_METADATA"
+ }] : []
+
+ content {
+ metadata = log_config.value.metadata
+ }
+ }
+
+ deny {
+ protocol = "all"
+ }
+
+ destination_ranges = ["0.0.0.0/0"]
+}
+
+resource "google_compute_firewall" "allow_restricted_api_egress" {
+ name = "fw-${var.environment_code}-shared-restricted-65534-e-a-allow-google-apis-all-tcp-443"
+ network = module.main.network_name
+ project = var.project_id
+ direction = "EGRESS"
+ priority = 65534
+
+ dynamic "log_config" {
+ for_each = var.firewall_enable_logging == true ? [{
+ metadata = "INCLUDE_ALL_METADATA"
+ }] : []
+
+ content {
+ metadata = log_config.value.metadata
+ }
+ }
+
+ allow {
+ protocol = "tcp"
+ ports = ["443"]
+ }
+
+ destination_ranges = [local.restricted_googleapis_cidr]
+
+ target_tags = ["allow-google-apis"]
+}
+
+resource "google_compute_firewall" "allow_all_egress" {
+ count = var.allow_all_egress_ranges != null ? 1 : 0
+ name = "fw-${var.environment_code}-shared-base-1000-e-a-all"
+ network = module.main.network_name
+ project = var.project_id
+ direction = "EGRESS"
+ priority = 1000
+
+ dynamic "log_config" {
+ for_each = var.firewall_enable_logging == true ? [{
+ metadata = "INCLUDE_ALL_METADATA"
+ }] : []
+
+ content {
+ metadata = log_config.value.metadata
+ }
+ }
+
+ allow {
+ protocol = "all"
+ }
+
+ destination_ranges = var.allow_all_egress_ranges
+}
+
+resource "google_compute_firewall" "allow_all_ingress" {
+ count = var.allow_all_ingress_ranges != null ? 1 : 0
+ name = "fw-${var.environment_code}-shared-base-1000-i-a-all"
+ network = module.main.network_name
+ project = var.project_id
+ direction = "INGRESS"
+ priority = 1000
+
+ dynamic "log_config" {
+ for_each = var.firewall_enable_logging == true ? [{
+ metadata = "INCLUDE_ALL_METADATA"
+ }] : []
+
+ content {
+ metadata = log_config.value.metadata
+ }
+ }
+
+ allow {
+ protocol = "all"
+ }
+
+ source_ranges = var.allow_all_ingress_ranges
+}
diff --git a/3-networks/modules/restricted_shared_vpc/main.tf b/3-networks-hub-and-spoke/modules/restricted_shared_vpc/main.tf
similarity index 99%
rename from 3-networks/modules/restricted_shared_vpc/main.tf
rename to 3-networks-hub-and-spoke/modules/restricted_shared_vpc/main.tf
index 9bc819be1..717d62926 100644
--- a/3-networks/modules/restricted_shared_vpc/main.tf
+++ b/3-networks-hub-and-spoke/modules/restricted_shared_vpc/main.tf
@@ -1,5 +1,5 @@
/**
- * Copyright 2021 Google LLC
+ * Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/3-networks-hub-and-spoke/modules/restricted_shared_vpc/nat.tf b/3-networks-hub-and-spoke/modules/restricted_shared_vpc/nat.tf
new file mode 100644
index 000000000..a596b0ff5
--- /dev/null
+++ b/3-networks-hub-and-spoke/modules/restricted_shared_vpc/nat.tf
@@ -0,0 +1,89 @@
+/**
+ * Copyright 2022 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.
+ */
+
+/******************************************
+ NAT Cloud Router & NAT config
+ *****************************************/
+
+resource "google_compute_router" "nat_router_region1" {
+ count = var.nat_enabled ? 1 : 0
+ name = "cr-${local.vpc_name}-${var.default_region1}-nat-router"
+ project = var.project_id
+ region = var.default_region1
+ network = module.main.network_self_link
+
+ bgp {
+ asn = var.nat_bgp_asn
+ }
+}
+
+resource "google_compute_address" "nat_external_addresses1" {
+ count = var.nat_enabled ? var.nat_num_addresses_region1 : 0
+ project = var.project_id
+ name = "ca-${local.vpc_name}-${var.default_region1}-${count.index}"
+ region = var.default_region1
+}
+
+resource "google_compute_router_nat" "nat_external_addresses_region1" {
+ count = var.nat_enabled ? 1 : 0
+ name = "rn-${local.vpc_name}-${var.default_region1}-egress"
+ project = var.project_id
+ router = google_compute_router.nat_router_region1.0.name
+ region = var.default_region1
+ nat_ip_allocate_option = "MANUAL_ONLY"
+ nat_ips = google_compute_address.nat_external_addresses1.*.self_link
+ source_subnetwork_ip_ranges_to_nat = "ALL_SUBNETWORKS_ALL_IP_RANGES"
+
+ log_config {
+ filter = "TRANSLATIONS_ONLY"
+ enable = true
+ }
+}
+
+resource "google_compute_router" "nat_router_region2" {
+ count = var.nat_enabled ? 1 : 0
+ name = "cr-${local.vpc_name}-${var.default_region2}-nat-router"
+ project = var.project_id
+ region = var.default_region2
+ network = module.main.network_self_link
+
+ bgp {
+ asn = var.nat_bgp_asn
+ }
+}
+
+resource "google_compute_address" "nat_external_addresses_region2" {
+ count = var.nat_enabled ? var.nat_num_addresses_region2 : 0
+ project = var.project_id
+ name = "ca-${local.vpc_name}-${var.default_region2}-${count.index}"
+ region = var.default_region2
+}
+
+resource "google_compute_router_nat" "egress_nat_region2" {
+ count = var.nat_enabled ? 1 : 0
+ name = "rn-${local.vpc_name}-${var.default_region2}-egress"
+ project = var.project_id
+ router = google_compute_router.nat_router_region2.0.name
+ region = var.default_region2
+ nat_ip_allocate_option = "MANUAL_ONLY"
+ nat_ips = google_compute_address.nat_external_addresses_region2.*.self_link
+ source_subnetwork_ip_ranges_to_nat = "ALL_SUBNETWORKS_ALL_IP_RANGES"
+
+ log_config {
+ filter = "TRANSLATIONS_ONLY"
+ enable = true
+ }
+}
diff --git a/3-networks-hub-and-spoke/modules/restricted_shared_vpc/outputs.tf b/3-networks-hub-and-spoke/modules/restricted_shared_vpc/outputs.tf
new file mode 100644
index 000000000..79ebafec5
--- /dev/null
+++ b/3-networks-hub-and-spoke/modules/restricted_shared_vpc/outputs.tf
@@ -0,0 +1,60 @@
+/**
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+output "network_name" {
+ value = module.main.network_name
+ description = "The name of the VPC being created"
+}
+
+output "network_self_link" {
+ value = module.main.network_self_link
+ description = "The URI of the VPC being created"
+}
+
+output "subnets_names" {
+ value = module.main.subnets_names
+ description = "The names of the subnets being created"
+}
+
+output "subnets_ips" {
+ value = module.main.subnets_ips
+ description = "The IPs and CIDRs of the subnets being created"
+}
+
+output "subnets_self_links" {
+ value = module.main.subnets_self_links
+ description = "The self-links of subnets being created"
+}
+
+output "subnets_regions" {
+ value = module.main.subnets_regions
+ description = "The region where the subnets will be created"
+}
+
+output "subnets_secondary_ranges" {
+ value = module.main.subnets_secondary_ranges
+ description = "The secondary ranges associated with these subnets"
+}
+
+output "access_level_name" {
+ value = local.access_level_name
+ description = "Access context manager access level name "
+}
+
+output "service_perimeter_name" {
+ value = local.perimeter_name
+ description = "Access context manager service perimeter name "
+}
diff --git a/3-networks-hub-and-spoke/modules/restricted_shared_vpc/private_service_connect.tf b/3-networks-hub-and-spoke/modules/restricted_shared_vpc/private_service_connect.tf
new file mode 100644
index 000000000..c5db59f3a
--- /dev/null
+++ b/3-networks-hub-and-spoke/modules/restricted_shared_vpc/private_service_connect.tf
@@ -0,0 +1,26 @@
+/**
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+module "private_service_connect" {
+ source = "../private_service_connect"
+ project_id = var.project_id
+ network_id = module.main.network_self_link
+ environment_code = var.environment_code
+ network_self_link = module.main.network_self_link
+ private_service_connect_ip = "10.3.0.5"
+ forwarding_rule_target = "vpc-sc"
+}
diff --git a/3-networks/modules/restricted_shared_vpc/service_control.tf b/3-networks-hub-and-spoke/modules/restricted_shared_vpc/service_control.tf
similarity index 99%
rename from 3-networks/modules/restricted_shared_vpc/service_control.tf
rename to 3-networks-hub-and-spoke/modules/restricted_shared_vpc/service_control.tf
index d1fc312ff..5009ff3e6 100644
--- a/3-networks/modules/restricted_shared_vpc/service_control.tf
+++ b/3-networks-hub-and-spoke/modules/restricted_shared_vpc/service_control.tf
@@ -1,5 +1,5 @@
/**
- * Copyright 2021 Google LLC
+ * Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/3-networks/modules/restricted_shared_vpc/variables.tf b/3-networks-hub-and-spoke/modules/restricted_shared_vpc/variables.tf
similarity index 99%
rename from 3-networks/modules/restricted_shared_vpc/variables.tf
rename to 3-networks-hub-and-spoke/modules/restricted_shared_vpc/variables.tf
index 53a540fef..0c01ce81c 100644
--- a/3-networks/modules/restricted_shared_vpc/variables.tf
+++ b/3-networks-hub-and-spoke/modules/restricted_shared_vpc/variables.tf
@@ -1,5 +1,5 @@
/**
- * Copyright 2021 Google LLC
+ * Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/3-networks-hub-and-spoke/modules/restricted_shared_vpc/versions.tf b/3-networks-hub-and-spoke/modules/restricted_shared_vpc/versions.tf
new file mode 100644
index 000000000..4cc03a85d
--- /dev/null
+++ b/3-networks-hub-and-spoke/modules/restricted_shared_vpc/versions.tf
@@ -0,0 +1,40 @@
+/**
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+terraform {
+ required_version = ">= 0.13"
+ required_providers {
+ google = {
+ source = "hashicorp/google"
+ version = ">= 3.50"
+ }
+ google-beta = {
+ source = "hashicorp/google-beta"
+ version = ">= 3.50"
+ }
+ random = {
+ source = "hashicorp/random"
+ }
+ }
+
+ provider_meta "google" {
+ module_name = "blueprints/terraform/terraform-example-foundation:restricted_shared_vpc/v2.3.1"
+ }
+
+ provider_meta "google-beta" {
+ module_name = "blueprints/terraform/terraform-example-foundation:restricted_shared_vpc/v2.3.1"
+ }
+}
diff --git a/3-networks/modules/transitivity/README.md b/3-networks-hub-and-spoke/modules/transitivity/README.md
similarity index 100%
rename from 3-networks/modules/transitivity/README.md
rename to 3-networks-hub-and-spoke/modules/transitivity/README.md
diff --git a/3-networks/modules/transitivity/assets/gw.yaml b/3-networks-hub-and-spoke/modules/transitivity/assets/gw.yaml
similarity index 96%
rename from 3-networks/modules/transitivity/assets/gw.yaml
rename to 3-networks-hub-and-spoke/modules/transitivity/assets/gw.yaml
index fcff6673a..55a2e5bae 100644
--- a/3-networks/modules/transitivity/assets/gw.yaml
+++ b/3-networks-hub-and-spoke/modules/transitivity/assets/gw.yaml
@@ -1,6 +1,6 @@
#cloud-config
-# Copyright 2021 Google LLC
+# Copyright 2022 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/3-networks/modules/transitivity/main.tf b/3-networks-hub-and-spoke/modules/transitivity/main.tf
similarity index 100%
rename from 3-networks/modules/transitivity/main.tf
rename to 3-networks-hub-and-spoke/modules/transitivity/main.tf
diff --git a/3-networks/modules/transitivity/variables.tf b/3-networks-hub-and-spoke/modules/transitivity/variables.tf
similarity index 100%
rename from 3-networks/modules/transitivity/variables.tf
rename to 3-networks-hub-and-spoke/modules/transitivity/variables.tf
diff --git a/3-networks/modules/transitivity/versions.tf b/3-networks-hub-and-spoke/modules/transitivity/versions.tf
similarity index 97%
rename from 3-networks/modules/transitivity/versions.tf
rename to 3-networks-hub-and-spoke/modules/transitivity/versions.tf
index ebe2005cf..1f66c0185 100644
--- a/3-networks/modules/transitivity/versions.tf
+++ b/3-networks-hub-and-spoke/modules/transitivity/versions.tf
@@ -1,5 +1,5 @@
/**
- * Copyright 2021 Google LLC
+ * Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/3-networks-hub-and-spoke/modules/vpn-ha/README.md b/3-networks-hub-and-spoke/modules/vpn-ha/README.md
new file mode 100755
index 000000000..0480eef1a
--- /dev/null
+++ b/3-networks-hub-and-spoke/modules/vpn-ha/README.md
@@ -0,0 +1,60 @@
+# High Availability VPN module
+
+This module implements the recommendation proposed in
+[High Availability VPN](https://cloud.google.com/network-connectivity/docs/vpn/concepts/topologies#overview).
+
+If you are not able to use Dedicated Interconnect or Partner Interconnect you can also use an High Availability Cloud VPN to connect the On-Prem to your Google Organization.
+
+## Usage
+
+1. Rename `vpn.tf.example` to `vpn.tf` in the environment folder in `3-networks-hub-and-spoke/envs/`
+1. Create secret for VPN preshared key `echo 'MY_PSK' | gcloud secrets create VPN_PSK_SECRET_NAME --project ENV_SECRETS_PROJECT --replication-policy=automatic --data-file=-`
+1. Update in the file the values for `environment`, `vpn_psk_secret_name`, `on_prem_router_ip_address1`, `on_prem_router_ip_address2` and `bgp_peer_asn`.
+1. Verify other default values are valid for your environment.
+
+**This module only works with two regions.**
+
+
+
+## Inputs
+
+| Name | Description | Type | Default | Required |
+|------|-------------|------|---------|:--------:|
+| bgp\_peer\_asn | BGP ASN for cloud routes. | `number` | n/a | yes |
+| default\_region1 | Default region 1 for Cloud Routers | `string` | n/a | yes |
+| default\_region2 | Default region 2 for Cloud Routers | `string` | n/a | yes |
+| environment | Environment for the VPN configuration. Valid options are development, non-production, production | `string` | n/a | yes |
+| folder\_prefix | Name prefix to use for folders created. | `string` | `"fldr"` | no |
+| on\_prem\_router\_ip\_address1 | On-Prem Router IP address | `string` | n/a | yes |
+| on\_prem\_router\_ip\_address2 | On-Prem Router IP address | `string` | n/a | yes |
+| org\_id | Organization ID | `string` | n/a | yes |
+| parent\_folder | Optional - if using a folder for testing. | `string` | `""` | no |
+| project\_id | VPC Project ID | `string` | n/a | yes |
+| region1\_router1\_name | Name of the Router 1 for Region 1 where the attachment resides. | `string` | n/a | yes |
+| region1\_router1\_tunnel0\_bgp\_peer\_address | BGP session address for router 1 in region 1 tunnel 0 | `string` | n/a | yes |
+| region1\_router1\_tunnel0\_bgp\_peer\_range | BGP session range for router 1 in region 1 tunnel 0 | `string` | n/a | yes |
+| region1\_router1\_tunnel1\_bgp\_peer\_address | BGP session address for router 1 in region 1 tunnel 1 | `string` | n/a | yes |
+| region1\_router1\_tunnel1\_bgp\_peer\_range | BGP session range for router 1 in region 1 tunnel 1 | `string` | n/a | yes |
+| region1\_router2\_name | Name of the Router 2 for Region 1 where the attachment resides. | `string` | n/a | yes |
+| region1\_router2\_tunnel0\_bgp\_peer\_address | BGP session address for router 2 in region 1 tunnel 0 | `string` | n/a | yes |
+| region1\_router2\_tunnel0\_bgp\_peer\_range | BGP session range for router 2 in region 1 tunnel 0 | `string` | n/a | yes |
+| region1\_router2\_tunnel1\_bgp\_peer\_address | BGP session address for router 2 in region 1 tunnel 1 | `string` | n/a | yes |
+| region1\_router2\_tunnel1\_bgp\_peer\_range | BGP session range for router 2 in region 1 tunnel 1 | `string` | n/a | yes |
+| region2\_router1\_name | Name of the Router 1 for Region 2 where the attachment resides. | `string` | n/a | yes |
+| region2\_router1\_tunnel0\_bgp\_peer\_address | BGP session address for router 1 in region 2 tunnel 0 | `string` | n/a | yes |
+| region2\_router1\_tunnel0\_bgp\_peer\_range | BGP session range for router 1 in region 2 tunnel 0 | `string` | n/a | yes |
+| region2\_router1\_tunnel1\_bgp\_peer\_address | BGP session address for router 1 in region 2 tunnel 2 | `string` | n/a | yes |
+| region2\_router1\_tunnel1\_bgp\_peer\_range | BGP session range for router 1 in region 2 tunnel 2 | `string` | n/a | yes |
+| region2\_router2\_name | Name of the Router 2 for Region 2 where the attachment resides | `string` | n/a | yes |
+| region2\_router2\_tunnel0\_bgp\_peer\_address | BGP session address for router 2 in region 2 tunnel 0 | `string` | n/a | yes |
+| region2\_router2\_tunnel0\_bgp\_peer\_range | BGP session range for router 2 in region 2 tunnel 0 | `string` | n/a | yes |
+| region2\_router2\_tunnel1\_bgp\_peer\_address | BGP session address for router 2 in region 1 tunnel 1 | `string` | n/a | yes |
+| region2\_router2\_tunnel1\_bgp\_peer\_range | BGP session range for router 2 in region 1 tunnel 1 | `string` | n/a | yes |
+| vpc\_name | Label to identify the VPC associated with shared VPC that will use the Interconnect. | `string` | n/a | yes |
+| vpn\_psk\_secret\_name | The name of the secret to retrieve from secret manager. This will be retrieved from the environment secrets project. | `string` | n/a | yes |
+
+## Outputs
+
+No output.
+
+
diff --git a/3-networks-hub-and-spoke/modules/vpn-ha/main.tf b/3-networks-hub-and-spoke/modules/vpn-ha/main.tf
new file mode 100755
index 000000000..e10cf1c49
--- /dev/null
+++ b/3-networks-hub-and-spoke/modules/vpn-ha/main.tf
@@ -0,0 +1,224 @@
+/**
+ * Copyright 2022 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.
+ */
+
+/******************************************
+ HA VPN configuration
+ *****************************************/
+
+locals {
+ parent_id = var.parent_folder != "" ? "folders/${var.parent_folder}" : "organizations/${var.org_id}"
+ network_name = "vpc-${var.vpc_name}"
+ env_secret_project_id = data.google_projects.env_secrets.projects[0].project_id
+ psk_secret_data = chomp(data.google_secret_manager_secret_version.psk.secret_data)
+}
+
+data "google_active_folder" "env" {
+ display_name = "${var.folder_prefix}-${var.environment}"
+ parent = local.parent_id
+}
+
+data "google_projects" "env_secrets" {
+ filter = "parent.id:${split("/", data.google_active_folder.env.name)[1]} labels.application_name=env-secrets labels.environment=${var.environment} lifecycleState=ACTIVE"
+}
+
+data "google_secret_manager_secret_version" "psk" {
+ project = local.env_secret_project_id
+ secret = var.vpn_psk_secret_name
+}
+
+module "vpn_ha_region1_router1" {
+ source = "terraform-google-modules/vpn/google//modules/vpn_ha"
+ project_id = var.project_id
+ region = var.default_region1
+ network = local.network_name
+ name = "vpn-${var.vpc_name}-${var.default_region1}-cr1"
+ peer_external_gateway = {
+ redundancy_type = "TWO_IPS_REDUNDANCY"
+ interfaces = [{
+ id = 0
+ ip_address = var.on_prem_router_ip_address1
+ },
+ {
+ id = 1
+ ip_address = var.on_prem_router_ip_address2
+ }]
+ }
+ router_name = var.region1_router1_name
+ tunnels = {
+ remote-0 = {
+ bgp_peer = {
+ address = var.region1_router1_tunnel0_bgp_peer_address
+ asn = var.bgp_peer_asn
+ }
+ bgp_peer_options = null
+ bgp_session_range = var.region1_router1_tunnel0_bgp_peer_range
+ ike_version = 2
+ vpn_gateway_interface = 0
+ peer_external_gateway_interface = 0
+ shared_secret = local.psk_secret_data
+ }
+ remote-1 = {
+ bgp_peer = {
+ address = var.region1_router1_tunnel1_bgp_peer_address
+ asn = var.bgp_peer_asn
+ }
+ bgp_peer_options = null
+ bgp_session_range = var.region1_router1_tunnel1_bgp_peer_range
+ ike_version = 2
+ vpn_gateway_interface = 1
+ peer_external_gateway_interface = 1
+ shared_secret = local.psk_secret_data
+ }
+ }
+}
+
+module "vpn_ha_region1_router2" {
+ source = "terraform-google-modules/vpn/google//modules/vpn_ha"
+ project_id = var.project_id
+ region = var.default_region1
+ network = local.network_name
+ name = "vpn-${var.vpc_name}-${var.default_region1}-cr2"
+ peer_external_gateway = {
+ redundancy_type = "TWO_IPS_REDUNDANCY"
+ interfaces = [{
+ id = 0
+ ip_address = var.on_prem_router_ip_address1
+ },
+ {
+ id = 1
+ ip_address = var.on_prem_router_ip_address2
+ }]
+ }
+ router_name = var.region1_router2_name
+ tunnels = {
+ remote-0 = {
+ bgp_peer = {
+ address = var.region1_router2_tunnel0_bgp_peer_address
+ asn = var.bgp_peer_asn
+ }
+ bgp_peer_options = null
+ bgp_session_range = var.region1_router2_tunnel0_bgp_peer_range
+ ike_version = 2
+ vpn_gateway_interface = 0
+ peer_external_gateway_interface = 0
+ shared_secret = local.psk_secret_data
+ }
+ remote-1 = {
+ bgp_peer = {
+ address = var.region1_router2_tunnel1_bgp_peer_address
+ asn = var.bgp_peer_asn
+ }
+ bgp_peer_options = null
+ bgp_session_range = var.region1_router2_tunnel1_bgp_peer_range
+ ike_version = 2
+ vpn_gateway_interface = 1
+ peer_external_gateway_interface = 1
+ shared_secret = local.psk_secret_data
+ }
+ }
+}
+
+module "vpn_ha_region2_router1" {
+ source = "terraform-google-modules/vpn/google//modules/vpn_ha"
+ project_id = var.project_id
+ region = var.default_region2
+ network = local.network_name
+ name = "vpn-${var.vpc_name}-${var.default_region2}-cr1"
+ peer_external_gateway = {
+ redundancy_type = "TWO_IPS_REDUNDANCY"
+ interfaces = [{
+ id = 0
+ ip_address = var.on_prem_router_ip_address1
+ },
+ {
+ id = 1
+ ip_address = var.on_prem_router_ip_address2
+ }]
+ }
+ router_name = var.region2_router1_name
+ tunnels = {
+ remote-0 = {
+ bgp_peer = {
+ address = var.region2_router1_tunnel0_bgp_peer_address
+ asn = var.bgp_peer_asn
+ }
+ bgp_peer_options = null
+ bgp_session_range = var.region2_router1_tunnel0_bgp_peer_range
+ ike_version = 2
+ vpn_gateway_interface = 0
+ peer_external_gateway_interface = 0
+ shared_secret = local.psk_secret_data
+ }
+ remote-1 = {
+ bgp_peer = {
+ address = var.region2_router1_tunnel1_bgp_peer_address
+ asn = var.bgp_peer_asn
+ }
+ bgp_peer_options = null
+ bgp_session_range = var.region2_router1_tunnel1_bgp_peer_range
+ ike_version = 2
+ vpn_gateway_interface = 1
+ peer_external_gateway_interface = 1
+ shared_secret = local.psk_secret_data
+ }
+ }
+}
+
+module "vpn_ha_region2_router2" {
+ source = "terraform-google-modules/vpn/google//modules/vpn_ha"
+ project_id = var.project_id
+ region = var.default_region2
+ network = local.network_name
+ name = "vpn-${var.vpc_name}-${var.default_region2}-cr2"
+ peer_external_gateway = {
+ redundancy_type = "TWO_IPS_REDUNDANCY"
+ interfaces = [{
+ id = 0
+ ip_address = var.on_prem_router_ip_address1
+ },
+ {
+ id = 1
+ ip_address = var.on_prem_router_ip_address2
+ }]
+ }
+ router_name = var.region2_router2_name
+ tunnels = {
+ remote-0 = {
+ bgp_peer = {
+ address = var.region2_router2_tunnel0_bgp_peer_address
+ asn = var.bgp_peer_asn
+ }
+ bgp_peer_options = null
+ bgp_session_range = var.region2_router2_tunnel0_bgp_peer_range
+ ike_version = 2
+ vpn_gateway_interface = 0
+ peer_external_gateway_interface = 0
+ shared_secret = local.psk_secret_data
+ }
+ remote-1 = {
+ bgp_peer = {
+ address = var.region2_router2_tunnel1_bgp_peer_address
+ asn = var.bgp_peer_asn
+ }
+ bgp_peer_options = null
+ bgp_session_range = var.region2_router2_tunnel1_bgp_peer_range
+ ike_version = 2
+ vpn_gateway_interface = 1
+ peer_external_gateway_interface = 1
+ shared_secret = local.psk_secret_data
+ }
+ }
+}
diff --git a/3-networks-hub-and-spoke/modules/vpn-ha/variables.tf b/3-networks-hub-and-spoke/modules/vpn-ha/variables.tf
new file mode 100644
index 000000000..6b426f129
--- /dev/null
+++ b/3-networks-hub-and-spoke/modules/vpn-ha/variables.tf
@@ -0,0 +1,177 @@
+/**
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+variable "project_id" {
+ type = string
+ description = "VPC Project ID"
+}
+
+variable "default_region1" {
+ type = string
+ description = "Default region 1 for Cloud Routers"
+}
+
+variable "default_region2" {
+ type = string
+ description = "Default region 2 for Cloud Routers"
+}
+
+variable "environment" {
+ type = string
+ description = "Environment for the VPN configuration. Valid options are development, non-production, production"
+}
+
+variable "org_id" {
+ type = string
+ description = "Organization ID"
+}
+
+variable "vpn_psk_secret_name" {
+ type = string
+ description = "The name of the secret to retrieve from secret manager. This will be retrieved from the environment secrets project."
+}
+
+variable "on_prem_router_ip_address1" {
+ type = string
+ description = "On-Prem Router IP address"
+}
+
+variable "on_prem_router_ip_address2" {
+ type = string
+ description = "On-Prem Router IP address"
+}
+
+variable "region1_router1_name" {
+ type = string
+ description = "Name of the Router 1 for Region 1 where the attachment resides."
+}
+
+variable "region1_router2_name" {
+ type = string
+ description = "Name of the Router 2 for Region 1 where the attachment resides."
+}
+
+variable "region2_router1_name" {
+ type = string
+ description = "Name of the Router 1 for Region 2 where the attachment resides."
+}
+
+variable "region2_router2_name" {
+ type = string
+ description = "Name of the Router 2 for Region 2 where the attachment resides"
+}
+
+variable "vpc_name" {
+ type = string
+ description = "Label to identify the VPC associated with shared VPC that will use the Interconnect."
+}
+
+variable "bgp_peer_asn" {
+ type = number
+ description = "BGP ASN for cloud routes."
+}
+
+variable "region1_router1_tunnel0_bgp_peer_address" {
+ type = string
+ description = "BGP session address for router 1 in region 1 tunnel 0"
+}
+
+variable "region1_router1_tunnel0_bgp_peer_range" {
+ type = string
+ description = "BGP session range for router 1 in region 1 tunnel 0"
+}
+
+variable "region1_router1_tunnel1_bgp_peer_address" {
+ type = string
+ description = "BGP session address for router 1 in region 1 tunnel 1"
+}
+
+variable "region1_router1_tunnel1_bgp_peer_range" {
+ type = string
+ description = "BGP session range for router 1 in region 1 tunnel 1"
+}
+
+variable "region1_router2_tunnel0_bgp_peer_address" {
+ type = string
+ description = "BGP session address for router 2 in region 1 tunnel 0"
+}
+
+variable "region1_router2_tunnel0_bgp_peer_range" {
+ type = string
+ description = "BGP session range for router 2 in region 1 tunnel 0"
+}
+
+variable "region1_router2_tunnel1_bgp_peer_address" {
+ type = string
+ description = "BGP session address for router 2 in region 1 tunnel 1"
+}
+
+variable "region1_router2_tunnel1_bgp_peer_range" {
+ type = string
+ description = "BGP session range for router 2 in region 1 tunnel 1"
+}
+
+variable "region2_router1_tunnel0_bgp_peer_address" {
+ type = string
+ description = "BGP session address for router 1 in region 2 tunnel 0"
+}
+
+variable "region2_router1_tunnel0_bgp_peer_range" {
+ type = string
+ description = "BGP session range for router 1 in region 2 tunnel 0"
+}
+
+variable "region2_router1_tunnel1_bgp_peer_address" {
+ type = string
+ description = "BGP session address for router 1 in region 2 tunnel 2"
+}
+
+variable "region2_router1_tunnel1_bgp_peer_range" {
+ type = string
+ description = "BGP session range for router 1 in region 2 tunnel 2"
+}
+
+variable "region2_router2_tunnel0_bgp_peer_address" {
+ type = string
+ description = "BGP session address for router 2 in region 2 tunnel 0"
+}
+
+variable "region2_router2_tunnel0_bgp_peer_range" {
+ type = string
+ description = "BGP session range for router 2 in region 2 tunnel 0"
+}
+
+variable "region2_router2_tunnel1_bgp_peer_address" {
+ type = string
+ description = "BGP session address for router 2 in region 1 tunnel 1"
+}
+
+variable "region2_router2_tunnel1_bgp_peer_range" {
+ type = string
+ description = "BGP session range for router 2 in region 1 tunnel 1"
+}
+
+variable "parent_folder" {
+ description = "Optional - if using a folder for testing."
+ type = string
+ default = ""
+}
+
+variable "folder_prefix" {
+ description = "Name prefix to use for folders created."
+ type = string
+ default = "fldr"
+}
diff --git a/3-networks-hub-and-spoke/shared.auto.example.tfvars b/3-networks-hub-and-spoke/shared.auto.example.tfvars
new file mode 100644
index 000000000..371eb9e00
--- /dev/null
+++ b/3-networks-hub-and-spoke/shared.auto.example.tfvars
@@ -0,0 +1,19 @@
+/**
+ * Copyright 2022 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.
+ */
+
+// List of IPv4 address of target name servers for the forwarding zone configuration.
+// See https://cloud.google.com/dns/docs/overview#dns-forwarding-zones
+target_name_server_addresses = ["192.168.0.1", "192.168.0.2"]
diff --git a/4-projects/README.md b/4-projects/README.md
index f6350520d..43006142e 100644
--- a/4-projects/README.md
+++ b/4-projects/README.md
@@ -26,13 +26,20 @@ organizational policy.
Google Cloud organization that you've created.
-3-networks |
+3-networks-dual-svpc |
Sets up base and restricted shared VPCs with default DNS, NAT (optional),
Private Service networking, VPC service controls, on-premises Dedicated
Interconnect, and baseline firewall rules for each environment. It also sets
up the global DNS hub. |
+3-networks-hub-and-spoke |
+Sets up base and restricted shared VPCs with all the default configuration
+found on step 3-networks-dual-svpc, but here the architecture will be based on the
+Hub and Spoke network model. It also sets up the global DNS hub |
+
+
+
4-projects (this file) |
Sets up a folder structure, projects, and application infrastructure pipeline for applications,
which are connected as service projects to the shared VPC created in the previous stage. |
diff --git a/5-app-infra/README.md b/5-app-infra/README.md
index 9685c9088..23de889a8 100644
--- a/5-app-infra/README.md
+++ b/5-app-infra/README.md
@@ -26,13 +26,19 @@ organizational policies.
Google Cloud organization that you've created.
-3-networks |
+3-networks-dual-svpc |
Sets up base and restricted shared VPCs with default DNS, NAT (optional),
Private Service networking, VPC service controls, on-premises Dedicated
Interconnect, and baseline firewall rules for each environment. It also sets
up the global DNS hub. |
+3-networks-hub-and-spoke |
+Sets up base and restricted shared VPCs with all the default configuration
+found on step 3-networks-dual-svpc, but here the architecture will be based on the
+Hub and Spoke network model. It also sets up the global DNS hub |
+
+
4-projects |
Sets up a folder structure, projects, and an application infrastructure pipeline for applications,
which are connected as service projects to the shared VPC created in the previous stage. |
diff --git a/README.md b/README.md
index 058ef9309..b6114ab2b 100644
--- a/README.md
+++ b/README.md
@@ -138,7 +138,7 @@ Under the environment folder, a project is created per environment (`development
Usage instructions are available for the environments step in the [README](./2-environments/README.md).
-### [3. networks](./3-networks/)
+### [3. networks-dual-svpc](./3-networks-dual-svpc/)
This step focuses on creating a Shared VPC per environment (`development`, `non-production` & `production`) in a standard configuration with a reasonable security baseline. Currently, this includes:
@@ -154,7 +154,14 @@ This step focuses on creating a Shared VPC per environment (`development`, `non-
- Optional - Cloud NAT configured for all subnets with logging and static outbound IPs.
- Default Cloud DNS policy applied, with DNS logging and [inbound query forwarding](https://cloud.google.com/dns/docs/overview#dns-server-policy-in) turned on.
-Usage instructions are available for the networks step in the [README](./3-networks/README.md).
+Usage instructions are available for the networks step in the [README](./3-networks-dual-svpc/README.md).
+
+### [3. networks-hub-and-spoke](./3-networks-hub-and-spoke/)
+
+This step configures the same network resources that the step 3-networks-dual-svpc does, but this time it makes usage of the architeture based on the Hub and Spoke reference network model.
+
+Usage instructions are available for the networks step in the [README](./3-networks-hub-and-spoke/README.md).
+
### [4. projects](./4-projects/)
diff --git a/test/disable_tf_files.sh b/test/disable_tf_files.sh
index 73f9a64f7..e14cece51 100755
--- a/test/disable_tf_files.sh
+++ b/test/disable_tf_files.sh
@@ -29,34 +29,49 @@ function envs(){
}
function networks(){
+
+ # shellcheck disable=SC2154
+ if [ "$TF_VAR_example_foundations_mode" == "HubAndSpoke" ]; then
+ network_dir="3-networks-hub-and-spoke"
+ else
+ network_dir="3-networks-dual-svpc"
+ fi
+
# disable backend configs in main module
- mv 3-networks/envs/development/backend.tf 3-networks/envs/development/backend.tf.disabled
- mv 3-networks/envs/non-production/backend.tf 3-networks/envs/non-production/backend.tf.disabled
- mv 3-networks/envs/production/backend.tf 3-networks/envs/production/backend.tf.disabled
+ mv $network_dir/envs/development/backend.tf $network_dir/envs/development/backend.tf.disabled
+ mv $network_dir/envs/non-production/backend.tf $network_dir/envs/non-production/backend.tf.disabled
+ mv $network_dir/envs/production/backend.tf $network_dir/envs/production/backend.tf.disabled
# disable access_context.auto.tfvars in main module
- mv 3-networks/envs/development/access_context.auto.tfvars 3-networks/envs/development/access_context.auto.tfvars.disabled
- mv 3-networks/envs/non-production/access_context.auto.tfvars 3-networks/envs/non-production/access_context.auto.tfvars.disabled
- mv 3-networks/envs/production/access_context.auto.tfvars 3-networks/envs/production/access_context.auto.tfvars.disabled
+ mv $network_dir/envs/development/access_context.auto.tfvars $network_dir/envs/development/access_context.auto.tfvars.disabled
+ mv $network_dir/envs/non-production/access_context.auto.tfvars $network_dir/envs/non-production/access_context.auto.tfvars.disabled
+ mv $network_dir/envs/production/access_context.auto.tfvars $network_dir/envs/production/access_context.auto.tfvars.disabled
# disable common.auto.tfvars in main module
- mv 3-networks/envs/development/common.auto.tfvars 3-networks/envs/development/common.auto.tfvars.disabled
- mv 3-networks/envs/non-production/common.auto.tfvars 3-networks/envs/non-production/common.auto.tfvars.disabled
- mv 3-networks/envs/production/common.auto.tfvars 3-networks/envs/production/common.auto.tfvars.disabled
+ mv $network_dir/envs/development/common.auto.tfvars $network_dir/envs/development/common.auto.tfvars.disabled
+ mv $network_dir/envs/non-production/common.auto.tfvars $network_dir/envs/non-production/common.auto.tfvars.disabled
+ mv $network_dir/envs/production/common.auto.tfvars $network_dir/envs/production/common.auto.tfvars.disabled
}
function shared(){
+
+ if [ "$TF_VAR_example_foundations_mode" == "HubAndSpoke" ]; then
+ network_dir="3-networks-hub-and-spoke"
+ else
+ network_dir="3-networks-dual-svpc"
+ fi
+
# disable backend configs in main module
- mv 3-networks/envs/shared/backend.tf 3-networks/envs/shared/backend.tf.disabled
+ mv $network_dir/envs/shared/backend.tf $network_dir/envs/shared/backend.tf.disabled
# disable access_context.auto.tfvars in main module
- mv 3-networks/envs/shared/access_context.auto.tfvars 3-networks/envs/shared/access_context.auto.tfvars.disabled
+ mv $network_dir/envs/shared/access_context.auto.tfvars $network_dir/envs/shared/access_context.auto.tfvars.disabled
# disable common.auto.tfvars in main module
- mv 3-networks/envs/shared/common.auto.tfvars 3-networks/envs/shared/common.auto.tfvars.disabled
+ mv $network_dir/envs/shared/common.auto.tfvars $network_dir/envs/shared/common.auto.tfvars.disabled
# disable shared.auto.tfvars in main module
- mv 3-networks/envs/shared/shared.auto.tfvars 3-networks/envs/shared/shared.auto.tfvars.disabled
+ mv $network_dir/envs/shared/shared.auto.tfvars $network_dir/envs/shared/shared.auto.tfvars.disabled
}
function projects(){
diff --git a/test/integration/networks/networks_test.go b/test/integration/networks/networks_test.go
index 1616f2f5d..299d36dea 100644
--- a/test/integration/networks/networks_test.go
+++ b/test/integration/networks/networks_test.go
@@ -119,9 +119,16 @@ func TestNetworks(t *testing.T) {
"access_context_manager_policy_id": policyID,
}
+ var tfdDir string
+ if networkMode == "" {
+ tfdDir = "../../../3-networks-dual-svpc/envs/%s"
+ } else {
+ tfdDir = "../../../3-networks-hub-and-spoke/envs/%s"
+ }
+
envCode := string(envName[0:1])
networks := tft.NewTFBlueprintTest(t,
- tft.WithTFDir(fmt.Sprintf("../../../3-networks/envs/%s", envName)),
+ tft.WithTFDir(fmt.Sprintf(tfdDir, envName)),
tft.WithVars(vars),
)
networks.DefineVerify(
@@ -135,7 +142,7 @@ func TestNetworks(t *testing.T) {
servicePerimeter := gcloud.Runf(t, "access-context-manager perimeters describe %s --policy %s", servicePerimeterLink, policyID)
assert.Equal(servicePerimeterLink, servicePerimeter.Get("name").String(), fmt.Sprintf("service perimeter %s should exist", servicePerimeterLink))
- listLevels := utils.GetResultStrSlice(servicePerimeter.Get("status.accessLevels").Array())
+ listLevels := utils.GetResultStrSlice(servicePerimeter.Get("status.accessLevels").Array())
assert.Contains(listLevels, accessLevel, fmt.Sprintf("service perimeter %s should have access level %s", servicePerimeterLink, accessLevel))
listServices := utils.GetResultStrSlice(servicePerimeter.Get("status.restrictedServices").Array())
assert.Subset(listServices, restrictedServices, fmt.Sprintf("service perimeter %s should restrict 'bigquery.googleapis.com' and 'storage.googleapis.com'", servicePerimeterLink))
diff --git a/test/integration/projects/projects_test.go b/test/integration/projects/projects_test.go
index 819030378..1bde74a97 100644
--- a/test/integration/projects/projects_test.go
+++ b/test/integration/projects/projects_test.go
@@ -22,8 +22,8 @@ import (
"github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/gcloud"
"github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/tft"
"github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/utils"
- "github.com/tidwall/gjson"
"github.com/stretchr/testify/assert"
+ "github.com/tidwall/gjson"
)
func getPolicyID(t *testing.T, orgID string) string {
@@ -174,8 +174,16 @@ func TestProjects(t *testing.T) {
"access_context_manager_policy_id": policyID,
}
// networks created to retrieve output from the network step for this environment
+
+ var networkTFDir string
+ if networkMode == "" {
+ networkTFDir = "../../../3-networks-dual-svpc/envs/%s"
+ } else {
+ networkTFDir = "../../../3-networks-hub-and-spoke/envs/%s"
+ }
+
networks := tft.NewTFBlueprintTest(t,
- tft.WithTFDir(fmt.Sprintf("../../../3-networks/envs/%s", env[1])),
+ tft.WithTFDir(fmt.Sprintf(networkTFDir, env[1])),
tft.WithVars(netVars),
)
perimeterName := networks.GetStringOutput("restricted_service_perimeter_name")
diff --git a/test/integration/shared/shared_test.go b/test/integration/shared/shared_test.go
index 830d3442e..4b8f7b216 100644
--- a/test/integration/shared/shared_test.go
+++ b/test/integration/shared/shared_test.go
@@ -30,6 +30,14 @@ func getPolicyID(t *testing.T, orgID string) string {
return op.String()
}
+func getNetworkMode(t *testing.T) bool {
+ mode := utils.ValFromEnv(t, "TF_VAR_example_foundations_mode")
+ if mode == "HubAndSpoke" {
+ return true
+ }
+ return false
+}
+
func TestShared(t *testing.T) {
orgID := utils.ValFromEnv(t, "TF_VAR_org_id")
@@ -39,8 +47,15 @@ func TestShared(t *testing.T) {
"access_context_manager_policy_id": policyID,
}
+ var tfdDir string
+ if getNetworkMode(t) {
+ tfdDir = "../../../3-networks-hub-and-spoke/envs/shared"
+ } else {
+ tfdDir = "../../../3-networks-dual-svpc/envs/shared"
+ }
+
shared := tft.NewTFBlueprintTest(t,
- tft.WithTFDir("../../../3-networks/envs/shared"),
+ tft.WithTFDir(tfdDir),
tft.WithVars(vars),
)
shared.DefineVerify(
diff --git a/test/restore_tf_files.sh b/test/restore_tf_files.sh
new file mode 100644
index 000000000..d7022b09e
--- /dev/null
+++ b/test/restore_tf_files.sh
@@ -0,0 +1,178 @@
+#!/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 org(){
+ # restore backend configs in main module
+ mv 1-org/envs/shared/backend.tf.disabled 1-org/envs/shared/backend.tf
+}
+
+function envs(){
+ # restore backend configs in main module
+ mv 2-environments/envs/development/backend.tf.disabled 2-environments/envs/development/backend.tf
+ mv 2-environments/envs/non-production/backend.tf.disabled 2-environments/envs/non-production/backend.tf
+ mv 2-environments/envs/production/backend.tf.disabled 2-environments/envs/production/backend.tf
+}
+
+function networks(){
+
+ # shellcheck disable=SC2154
+ if [ "$TF_VAR_example_foundations_mode" == "HubAndSpoke" ]; then
+ network_dir="3-networks-hub-and-spoke"
+ else
+ network_dir="3-networks-dual-svpc"
+ fi
+
+ # restore backend configs in main module
+ mv $network_dir/envs/development/backend.tf.disabled $network_dir/envs/development/backend.tf
+ mv $network_dir/envs/non-production/backend.tf.disabled $network_dir/envs/non-production/backend.tf
+ mv $network_dir/envs/production/backend.tf.disabled $network_dir/envs/production/backend.tf
+
+ # restore access_context.auto.tfvars in main module
+ mv $network_dir/envs/development/access_context.auto.tfvars.disabled $network_dir/envs/development/access_context.auto.tfvars
+ mv $network_dir/envs/non-production/access_context.auto.tfvars.disabled $network_dir/envs/non-production/access_context.auto.tfvars
+ mv $network_dir/envs/production/access_context.auto.tfvars.disabled $network_dir/envs/production/access_context.auto.tfvars
+
+ # restore common.auto.tfvars in main module
+ mv $network_dir/envs/development/common.auto.tfvars.disabled $network_dir/envs/development/common.auto.tfvars
+ mv $network_dir/envs/non-production/common.auto.tfvars.disabled $network_dir/envs/non-production/common.auto.tfvars
+ mv $network_dir/envs/production/common.auto.tfvars.disabled $network_dir/envs/production/common.auto.tfvars
+}
+
+function shared(){
+
+ if [ "$TF_VAR_example_foundations_mode" == "HubAndSpoke" ]; then
+ network_dir="3-networks-hub-and-spoke"
+ else
+ network_dir="3-networks-dual-svpc"
+ fi
+
+ # restore backend configs in main module
+ mv $network_dir/envs/shared/backend.tf.disabled $network_dir/envs/shared/backend.tf
+
+ # restore access_context.auto.tfvars in main module
+ mv $network_dir/envs/shared/access_context.auto.tfvars.disabled $network_dir/envs/shared/access_context.auto.tfvars
+
+ # restore common.auto.tfvars in main module
+ mv $network_dir/envs/shared/common.auto.tfvars.disabled $network_dir/envs/shared/common.auto.tfvars
+
+ # restore shared.auto.tfvars in main module
+ mv $network_dir/envs/shared/shared.auto.tfvars.disabled $network_dir/envs/shared/shared.auto.tfvars
+}
+
+function projects(){
+ # restore backend configs in main module
+ mv 4-projects/business_unit_1/development/backend.tf.disabled 4-projects/business_unit_1/development/backend.tf
+ mv 4-projects/business_unit_1/non-production/backend.tf.disabled 4-projects/business_unit_1/non-production/backend.tf
+ mv 4-projects/business_unit_1/production/backend.tf.disabled 4-projects/business_unit_1/production/backend.tf
+ mv 4-projects/business_unit_1/shared/backend.tf.disabled 4-projects/business_unit_1/shared/backend.tf
+ mv 4-projects/business_unit_2/development/backend.tf.disabled 4-projects/business_unit_2/development/backend.tf
+ mv 4-projects/business_unit_2/non-production/backend.tf.disabled 4-projects/business_unit_2/non-production/backend.tf
+ mv 4-projects/business_unit_2/production/backend.tf.disabled 4-projects/business_unit_2/production/backend.tf
+ mv 4-projects/business_unit_2/shared/backend.tf.disabled 4-projects/business_unit_2/shared/backend.tf
+
+ # restore access_context.auto.tfvars in main module
+ mv 4-projects/business_unit_1/development/access_context.auto.tfvars.disabled 4-projects/business_unit_1/development/access_context.auto.tfvars
+ mv 4-projects/business_unit_1/non-production/access_context.auto.tfvars.disabled 4-projects/business_unit_1/non-production/access_context.auto.tfvars
+ mv 4-projects/business_unit_1/production/access_context.auto.tfvars.disabled 4-projects/business_unit_1/production/access_context.auto.tfvars
+ mv 4-projects/business_unit_2/development/access_context.auto.tfvars.disabled 4-projects/business_unit_2/development/access_context.auto.tfvars
+ mv 4-projects/business_unit_2/non-production/access_context.auto.tfvars.disabled 4-projects/business_unit_2/non-production/access_context.auto.tfvars
+ mv 4-projects/business_unit_2/production/access_context.auto.tfvars.disabled 4-projects/business_unit_2/production/access_context.auto.tfvars
+
+ # restore business_unit_1.auto.tfvars in main module
+ mv 4-projects/business_unit_1/development/business_unit_1.auto.tfvars.disabled 4-projects/business_unit_1/development/business_unit_1.auto.tfvars
+ mv 4-projects/business_unit_1/non-production/business_unit_1.auto.tfvars.disabled 4-projects/business_unit_1/non-production/business_unit_1.auto.tfvars
+ mv 4-projects/business_unit_1/production/business_unit_1.auto.tfvars.disabled 4-projects/business_unit_1/production/business_unit_1.auto.tfvars
+
+ # restore business_unit_2.auto.tfvars in main module
+ mv 4-projects/business_unit_2/development/business_unit_2.auto.tfvars.disabled 4-projects/business_unit_2/development/business_unit_2.auto.tfvars
+ mv 4-projects/business_unit_2/non-production/business_unit_2.auto.tfvars.disabled 4-projects/business_unit_2/non-production/business_unit_2.auto.tfvars
+ mv 4-projects/business_unit_2/production/business_unit_2.auto.tfvars.disabled 4-projects/business_unit_2/production/business_unit_2.auto.tfvars
+
+ # restore ENVS.auto.tfvars in main module
+ mv 4-projects/business_unit_1/development/development.auto.tfvars.disabled 4-projects/business_unit_1/development/development.auto.tfvars
+ mv 4-projects/business_unit_2/development/development.auto.tfvars.disabled 4-projects/business_unit_2/development/development.auto.tfvars
+ mv 4-projects/business_unit_1/non-production/non-production.auto.tfvars.disabled 4-projects/business_unit_1/non-production/non-production.auto.tfvars
+ mv 4-projects/business_unit_2/non-production/non-production.auto.tfvars.disabled 4-projects/business_unit_2/non-production/non-production.auto.tfvars
+ mv 4-projects/business_unit_1/production/production.auto.tfvars.disabled 4-projects/business_unit_1/production/production.auto.tfvars
+ mv 4-projects/business_unit_2/production/production.auto.tfvars.disabled 4-projects/business_unit_2/production/production.auto.tfvars
+ mv 4-projects/business_unit_1/shared/shared.auto.tfvars.disabled 4-projects/business_unit_1/shared/shared.auto.tfvars
+ mv 4-projects/business_unit_2/shared/shared.auto.tfvars.disabled 4-projects/business_unit_2/shared/shared.auto.tfvars
+
+ # restore common.auto.tfvars in main module
+ mv 4-projects/business_unit_1/development/common.auto.tfvars.disabled 4-projects/business_unit_1/development/common.auto.tfvars
+ mv 4-projects/business_unit_1/non-production/common.auto.tfvars.disabled 4-projects/business_unit_1/non-production/common.auto.tfvars
+ mv 4-projects/business_unit_1/production/common.auto.tfvars.disabled 4-projects/business_unit_1/production/common.auto.tfvars
+ mv 4-projects/business_unit_1/shared/common.auto.tfvars.disabled 4-projects/business_unit_1/shared/common.auto.tfvars
+ mv 4-projects/business_unit_2/development/common.auto.tfvars.disabled 4-projects/business_unit_2/development/common.auto.tfvars
+ mv 4-projects/business_unit_2/non-production/common.auto.tfvars.disabled 4-projects/business_unit_2/non-production/common.auto.tfvars
+ mv 4-projects/business_unit_2/production/common.auto.tfvars.disabled 4-projects/business_unit_2/production/common.auto.tfvars
+ mv 4-projects/business_unit_2/shared/common.auto.tfvars.disabled 4-projects/business_unit_2/shared/common.auto.tfvars
+
+}
+
+function appinfra(){
+ # restore backend configs in main module
+ mv 5-app-infra/business_unit_1/development/backend.tf.disabled 5-app-infra/business_unit_1/development/backend.tf
+ mv 5-app-infra/business_unit_1/non-production/backend.tf.disabled 5-app-infra/business_unit_1/non-production/backend.tf
+ mv 5-app-infra/business_unit_1/production/backend.tf.disabled 5-app-infra/business_unit_1/production/backend.tf
+
+ # restore ENVS.auto.tfvars in main module
+ mv 5-app-infra/business_unit_1/development/bu1-development.auto.tfvars.disabled 5-app-infra/business_unit_1/development/bu1-development.auto.tfvars
+ mv 5-app-infra/business_unit_1/non-production/bu1-non-production.auto.tfvars.disabled 5-app-infra/business_unit_1/non-production/bu1-non-production.auto.tfvars
+ mv 5-app-infra/business_unit_1/production/bu1-production.auto.tfvars.disabled 5-app-infra/business_unit_1/production/bu1-production.auto.tfvars
+
+ # restore common.auto.tfvars in main module
+ mv 5-app-infra/business_unit_1/development/common.auto.tfvars.disabled 5-app-infra/business_unit_1/development/common.auto.tfvars
+ mv 5-app-infra/business_unit_1/non-production/common.auto.tfvars.disabled 5-app-infra/business_unit_1/non-production/common.auto.tfvars
+ mv 5-app-infra/business_unit_1/production/common.auto.tfvars.disabled 5-app-infra/business_unit_1/production/common.auto.tfvars
+}
+
+
+# parse args
+for arg in "$@"
+do
+ case $arg in
+ -n|--networks)
+ networks
+ shift
+ ;;
+ -s|--shared)
+ shared
+ shift
+ ;;
+ -o|--org)
+ org
+ shift
+ ;;
+ -e|--envs)
+ envs
+ shift
+ ;;
+ -a|--appinfra)
+ appinfra
+ shift
+ ;;
+ -p|--projects)
+ projects
+ shift
+ ;;
+ *) # end argument parsing
+ shift
+ ;;
+ esac
+done