From 4365eab9ea9ca9d5659337cac9302130a9017b33 Mon Sep 17 00:00:00 2001 From: eeaton Date: Thu, 4 Jul 2024 16:01:26 +0100 Subject: [PATCH] fix(VPCSC): enable dryrun mode (#1210) Co-authored-by: Daniel Andrade --- 1-org/modules/cai-monitoring/main.tf | 5 +- 3-networks-dual-svpc/README.md | 13 ++++- .../envs/development/README.md | 13 +++-- 3-networks-dual-svpc/envs/development/main.tf | 3 ++ .../envs/development/outputs.tf | 15 +++++- .../envs/development/variables.tf | 39 ++++++++++++--- .../envs/nonproduction/README.md | 13 +++-- .../envs/nonproduction/main.tf | 3 ++ .../envs/nonproduction/outputs.tf | 14 +++++- .../envs/nonproduction/variables.tf | 39 ++++++++++++--- .../envs/production/README.md | 13 +++-- 3-networks-dual-svpc/envs/production/main.tf | 3 ++ .../envs/production/outputs.tf | 14 +++++- .../envs/production/variables.tf | 39 ++++++++++++--- .../modules/base_env/README.md | 18 ++++--- 3-networks-dual-svpc/modules/base_env/main.tf | 16 ++++++- .../modules/base_env/outputs.tf | 18 +++++-- .../modules/base_env/variables.tf | 40 ++++++++++++++-- .../modules/restricted_shared_vpc/README.md | 19 +++++--- .../modules/restricted_shared_vpc/outputs.tf | 14 +++++- .../restricted_shared_vpc/service_control.tf | 41 +++++++++++----- .../restricted_shared_vpc/variables.tf | 42 +++++++++++++++-- 3-networks-hub-and-spoke/README.md | 12 ++++- .../envs/development/README.md | 13 +++-- .../envs/development/outputs.tf | 14 +++++- .../envs/development/variables.tf | 39 ++++++++++++--- .../envs/nonproduction/README.md | 13 +++-- .../envs/nonproduction/main.tf | 3 ++ .../envs/nonproduction/outputs.tf | 14 +++++- .../envs/nonproduction/variables.tf | 39 ++++++++++++--- .../envs/production/README.md | 13 +++-- .../envs/production/main.tf | 3 ++ .../envs/production/outputs.tf | 14 +++++- .../envs/production/variables.tf | 39 ++++++++++++--- .../envs/shared/net-hubs.tf | 9 +++- .../modules/base_env/README.md | 19 +++++--- .../modules/base_env/main.tf | 9 +++- .../modules/base_env/outputs.tf | 18 +++++-- .../modules/base_env/variables.tf | 46 ++++++++++++++++-- .../modules/restricted_shared_vpc/README.md | 19 +++++--- .../modules/restricted_shared_vpc/outputs.tf | 30 ++++++++---- .../restricted_shared_vpc/service_control.tf | 47 ++++++++++++++----- .../restricted_shared_vpc/variables.tf | 42 +++++++++++++++-- 4-projects/modules/base_env/README.md | 2 + .../example_restricted_shared_vpc_project.tf | 3 +- 4-projects/modules/base_env/remote.tf | 1 + 4-projects/modules/base_env/variables.tf | 12 +++++ 4-projects/modules/infra_pipelines/README.md | 2 + .../modules/infra_pipelines/variables.tf | 13 +++++ 4-projects/modules/single_project/README.md | 3 +- 4-projects/modules/single_project/main.tf | 1 + .../modules/single_project/variables.tf | 9 +++- test/integration/networks/networks_test.go | 28 ++++------- test/integration/projects/projects_test.go | 6 +-- 54 files changed, 775 insertions(+), 194 deletions(-) diff --git a/1-org/modules/cai-monitoring/main.tf b/1-org/modules/cai-monitoring/main.tf index 1f742a8d9..2b0002cc7 100644 --- a/1-org/modules/cai-monitoring/main.tf +++ b/1-org/modules/cai-monitoring/main.tf @@ -161,8 +161,9 @@ module "cloud_function" { service_config = { service_account_email = google_service_account.cloudfunction.email runtime_env_variables = { - ROLES = join(",", var.roles_to_monitor) - SOURCE_ID = google_scc_source.cai_monitoring.id + ROLES = join(",", var.roles_to_monitor) + SOURCE_ID = google_scc_source.cai_monitoring.id + LOG_EXECUTION_ID = "true" } } diff --git a/3-networks-dual-svpc/README.md b/3-networks-dual-svpc/README.md index 63d5b2261..d6f6f0a1e 100644 --- a/3-networks-dual-svpc/README.md +++ b/3-networks-dual-svpc/README.md @@ -55,10 +55,11 @@ For an overview of the architecture and the parts, see the ## 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 shared VPCs with default DNS, NAT (optional), Private Service networking, VPC service controls, on-premises Dedicated or Partner Interconnect, and baseline firewall rules for each environment. +- Set up base and restricted Hubs and it corresponding Spokes. With default DNS, NAT (optional), Private Service networking, VPC Service Controls (optional), on-premises Dedicated or Partner Interconnect, and baseline firewall rules for each environment. ## Prerequisites @@ -188,7 +189,7 @@ Run `terraform output cloudbuild_project_id` in the `0-bootstrap` folder to get sed -i'' -e "s/REMOTE_STATE_BUCKET/${backend_bucket}/" ./common.auto.tfvars ``` - **Note:** Make sure that you update the `perimeter_additional_members` variable with your e-mail in order to be able to view/access resources in the project protected by the VPC service controls. + **Note:** Make sure that you update the `perimeter_additional_members` variable with your user identity in order to be able to view/access resources in the project protected by the VPC Service Controls. 1. Commit changes @@ -413,3 +414,11 @@ Before executing the next stages, unset the `GOOGLE_IMPERSONATE_SERVICE_ACCOUNT` ```bash unset GOOGLE_IMPERSONATE_SERVICE_ACCOUNT ``` + +### (Optional) Enforce VPC Service Controls + +Because enabling VPC Service Controls can be a disruptive process, this repo configures VPC Service Controls perimeters in dry run mode by default. This configuration will service traffic that crosses the security perimeter (API requests that originate from inside your perimeter communicating with external resources, or API requests from external resources communicating with resources inside your perimeter) but still allow service traffic normally. + +When you are ready to enforce VPC Service Controls, we recommend that you review the guidance at [Best practices for enabling VPC Service Controls](https://cloud.google.com/vpc-service-controls/docs/enable). After you have added the necessary exceptions and are confident that VPC Service Controls will not disrupt your intended operations, set the variable `enforce_vpcsc` under the module `restricted_shared_vpc` to `true` and re-apply this stage. Then re-apply the 4-projects stage, which will inherit the new setting and include those projects inside the enforced perimeter. + +When you need to make changes to an existing enforced perimeter, you can test safely by modifying the configuration of the [dry run perimeter](https://cloud.google.com/vpc-service-controls/docs/dry-run-mode). This will log traffic denied by the dry run perimeter without impacting whether the enforced perimeter allows or denies traffic. diff --git a/3-networks-dual-svpc/envs/development/README.md b/3-networks-dual-svpc/envs/development/README.md index 286fcad6b..e927ba669 100644 --- a/3-networks-dual-svpc/envs/development/README.md +++ b/3-networks-dual-svpc/envs/development/README.md @@ -17,9 +17,12 @@ 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 | -| egress\_policies | A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference), each list object has a `from` and `to` value that describes egress\_from and egress\_to.

Example: `[{ from={ identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | -| ingress\_policies | A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference), each list object has a `from` and `to` value that describes ingress\_from and ingress\_to.

Example: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | -| perimeter\_additional\_members | The list of additional members to be added to the perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`. | `list(string)` | n/a | yes | +| egress\_policies | A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference) to use in an enforced perimeter. Each list object has a `from` and `to` value that describes egress\_from and egress\_to.

Example: `[{ from={ identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | +| egress\_policies\_dry\_run | A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference) to use in a dry-run perimeter. Each list object has a `from` and `to` value that describes egress\_from and egress\_to.

Example: `[{ from={ identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | +| ingress\_policies | A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference) to use in an enforced perimeter. Each list object has a `from` and `to` value that describes ingress\_from and ingress\_to.

Example: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | +| ingress\_policies\_dry\_run | A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference) to use in a dry-run perimeter. Each list object has a `from` and `to` value that describes ingress\_from and ingress\_to.

Example: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | +| perimeter\_additional\_members | The list of additional members to be added to the enforced perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`. | `list(string)` | `[]` | no | +| perimeter\_additional\_members\_dry\_run | The list of additional members to be added to the dry-run perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`. | `list(string)` | `[]` | no | | remote\_state\_bucket | Backend bucket to load Terraform Remote State Data from previous steps. | `string` | n/a | yes | | tfc\_org\_name | Name of the TFC organization | `string` | `""` | no | @@ -28,6 +31,8 @@ The purpose of this step is to set up base and restricted shared VPCs with defau | Name | Description | |------|-------------| | access\_context\_manager\_policy\_id | Access Context Manager Policy ID. | +| access\_level\_name | Access context manager access level name | +| access\_level\_name\_dry\_run | Access context manager access level name for the dry-run perimeter | | 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 | @@ -35,7 +40,7 @@ The purpose of this step is to set up base and restricted shared VPCs with defau | 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 | +| enforce\_vpcsc | Enable the enforced mode for VPC Service Controls. It is not recommended to enable VPC-SC on the first run deploying your foundation. Review [best practices for enabling VPC Service Controls](https://cloud.google.com/vpc-service-controls/docs/enable), then only enforce the perimeter after you have analyzed the access patterns in your dry-run perimeter and created the necessary exceptions for your use cases. | | 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 | diff --git a/3-networks-dual-svpc/envs/development/main.tf b/3-networks-dual-svpc/envs/development/main.tf index b7d394786..202dc8345 100644 --- a/3-networks-dual-svpc/envs/development/main.tf +++ b/3-networks-dual-svpc/envs/development/main.tf @@ -74,11 +74,14 @@ module "base_env" { environment_code = local.environment_code access_context_manager_policy_id = var.access_context_manager_policy_id perimeter_additional_members = var.perimeter_additional_members + perimeter_additional_members_dry_run = var.perimeter_additional_members_dry_run default_region1 = local.default_region1 default_region2 = local.default_region2 domain = var.domain ingress_policies = var.ingress_policies + ingress_policies_dry_run = var.ingress_policies_dry_run egress_policies = var.egress_policies + egress_policies_dry_run = var.egress_policies_dry_run enable_partner_interconnect = false base_private_service_cidr = local.base_private_service_cidr base_subnet_primary_ranges = local.base_subnet_primary_ranges diff --git a/3-networks-dual-svpc/envs/development/outputs.tf b/3-networks-dual-svpc/envs/development/outputs.tf index bcf18cd1d..e71d3027e 100644 --- a/3-networks-dual-svpc/envs/development/outputs.tf +++ b/3-networks-dual-svpc/envs/development/outputs.tf @@ -58,16 +58,27 @@ output "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 +output "access_level_name" { + value = module.base_env.access_level_name description = "Access context manager access level name" } +output "access_level_name_dry_run" { + value = module.base_env.access_level_name_dry_run + description = "Access context manager access level name for the dry-run perimeter" +} + +output "enforce_vpcsc" { + value = module.base_env.enforce_vpcsc + description = "Enable the enforced mode for VPC Service Controls. It is not recommended to enable VPC-SC on the first run deploying your foundation. Review [best practices for enabling VPC Service Controls](https://cloud.google.com/vpc-service-controls/docs/enable), then only enforce the perimeter after you have analyzed the access patterns in your dry-run perimeter and created the necessary exceptions for your use cases." +} + output "restricted_service_perimeter_name" { value = module.base_env.restricted_service_perimeter_name description = "Access context manager service perimeter name" } + /****************************************** Private Outputs *****************************************/ diff --git a/3-networks-dual-svpc/envs/development/variables.tf b/3-networks-dual-svpc/envs/development/variables.tf index 12e551dbd..02448e5a9 100644 --- a/3-networks-dual-svpc/envs/development/variables.tf +++ b/3-networks-dual-svpc/envs/development/variables.tf @@ -24,18 +24,22 @@ variable "access_context_manager_policy_id" { 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 "perimeter_additional_members" { - description = "The list of additional members to be added to the perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`." - type = list(string) -} - variable "domain" { type = string description = "The DNS name of peering managed zone, for instance 'example.com.'. Must end with a period." } variable "egress_policies" { - description = "A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference), each list object has a `from` and `to` value that describes egress_from and egress_to.\n\nExample: `[{ from={ identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" + description = "A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference) to use in an enforced perimeter. Each list object has a `from` and `to` value that describes egress_from and egress_to.\n\nExample: `[{ from={ identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" + type = list(object({ + from = any + to = any + })) + default = [] +} + +variable "egress_policies_dry_run" { + description = "A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference) to use in a dry-run perimeter. Each list object has a `from` and `to` value that describes egress_from and egress_to.\n\nExample: `[{ from={ identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" type = list(object({ from = any to = any @@ -44,7 +48,7 @@ variable "egress_policies" { } variable "ingress_policies" { - description = "A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference), each list object has a `from` and `to` value that describes ingress_from and ingress_to.\n\nExample: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" + description = "A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference) to use in an enforced perimeter. Each list object has a `from` and `to` value that describes ingress_from and ingress_to.\n\nExample: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" type = list(object({ from = any to = any @@ -52,6 +56,27 @@ variable "ingress_policies" { default = [] } +variable "ingress_policies_dry_run" { + description = "A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference) to use in a dry-run perimeter. Each list object has a `from` and `to` value that describes ingress_from and ingress_to.\n\nExample: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" + type = list(object({ + from = any + to = any + })) + default = [] +} + +variable "perimeter_additional_members" { + description = "The list of additional members to be added to the enforced perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`." + type = list(string) + default = [] +} + +variable "perimeter_additional_members_dry_run" { + description = "The list of additional members to be added to the dry-run perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`." + type = list(string) + default = [] +} + variable "tfc_org_name" { description = "Name of the TFC organization" type = string diff --git a/3-networks-dual-svpc/envs/nonproduction/README.md b/3-networks-dual-svpc/envs/nonproduction/README.md index a493c6bdd..bf0ae714f 100644 --- a/3-networks-dual-svpc/envs/nonproduction/README.md +++ b/3-networks-dual-svpc/envs/nonproduction/README.md @@ -17,9 +17,12 @@ 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 | -| egress\_policies | A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference), each list object has a `from` and `to` value that describes egress\_from and egress\_to.

Example: `[{ from={ identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | -| ingress\_policies | A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference), each list object has a `from` and `to` value that describes ingress\_from and ingress\_to.

Example: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | -| perimeter\_additional\_members | The list of additional members to be added to the perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`. | `list(string)` | n/a | yes | +| egress\_policies | A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference) to use in an enforced perimeter. Each list object has a `from` and `to` value that describes egress\_from and egress\_to.

Example: `[{ from={ identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | +| egress\_policies\_dry\_run | A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference) to use in a dry-run perimeter. Each list object has a `from` and `to` value that describes egress\_from and egress\_to.

Example: `[{ from={ identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | +| ingress\_policies | A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference) to use in an enforced perimeter. Each list object has a `from` and `to` value that describes ingress\_from and ingress\_to.

Example: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | +| ingress\_policies\_dry\_run | A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference) to use in a dry-run perimeter. Each list object has a `from` and `to` value that describes ingress\_from and ingress\_to.

Example: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | +| perimeter\_additional\_members | The list of additional members to be added to the enforced perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`. | `list(string)` | `[]` | no | +| perimeter\_additional\_members\_dry\_run | The list of additional members to be added to the dry-run perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`. | `list(string)` | `[]` | no | | remote\_state\_bucket | Backend bucket to load Terraform Remote State Data from previous steps. | `string` | n/a | yes | | tfc\_org\_name | Name of the TFC organization | `string` | `""` | no | @@ -28,6 +31,8 @@ The purpose of this step is to set up base and restricted shared VPCs with defau | Name | Description | |------|-------------| | access\_context\_manager\_policy\_id | Access Context Manager Policy ID. | +| access\_level\_name | Access context manager access level name | +| access\_level\_name\_dry\_run | Access context manager access level name for the dry-run perimeter | | 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 | @@ -35,7 +40,7 @@ The purpose of this step is to set up base and restricted shared VPCs with defau | 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 | +| enforce\_vpcsc | Enable the enforced mode for VPC Service Controls. It is not recommended to enable VPC-SC on the first run deploying your foundation. Review [best practices for enabling VPC Service Controls](https://cloud.google.com/vpc-service-controls/docs/enable), then only enforce the perimeter after you have analyzed the access patterns in your dry-run perimeter and created the necessary exceptions for your use cases. | | 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 | diff --git a/3-networks-dual-svpc/envs/nonproduction/main.tf b/3-networks-dual-svpc/envs/nonproduction/main.tf index 51a32c8c3..6505a4478 100644 --- a/3-networks-dual-svpc/envs/nonproduction/main.tf +++ b/3-networks-dual-svpc/envs/nonproduction/main.tf @@ -74,11 +74,14 @@ module "base_env" { environment_code = local.environment_code access_context_manager_policy_id = var.access_context_manager_policy_id perimeter_additional_members = var.perimeter_additional_members + perimeter_additional_members_dry_run = var.perimeter_additional_members_dry_run default_region1 = local.default_region1 default_region2 = local.default_region2 domain = var.domain ingress_policies = var.ingress_policies + ingress_policies_dry_run = var.ingress_policies_dry_run egress_policies = var.egress_policies + egress_policies_dry_run = var.egress_policies_dry_run enable_partner_interconnect = false base_private_service_cidr = local.base_private_service_cidr base_subnet_primary_ranges = local.base_subnet_primary_ranges diff --git a/3-networks-dual-svpc/envs/nonproduction/outputs.tf b/3-networks-dual-svpc/envs/nonproduction/outputs.tf index bcf18cd1d..ae890e4d2 100644 --- a/3-networks-dual-svpc/envs/nonproduction/outputs.tf +++ b/3-networks-dual-svpc/envs/nonproduction/outputs.tf @@ -58,11 +58,21 @@ output "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 +output "access_level_name" { + value = module.base_env.access_level_name description = "Access context manager access level name" } +output "access_level_name_dry_run" { + value = module.base_env.access_level_name_dry_run + description = "Access context manager access level name for the dry-run perimeter" +} + +output "enforce_vpcsc" { + value = module.base_env.enforce_vpcsc + description = "Enable the enforced mode for VPC Service Controls. It is not recommended to enable VPC-SC on the first run deploying your foundation. Review [best practices for enabling VPC Service Controls](https://cloud.google.com/vpc-service-controls/docs/enable), then only enforce the perimeter after you have analyzed the access patterns in your dry-run perimeter and created the necessary exceptions for your use cases." +} + output "restricted_service_perimeter_name" { value = module.base_env.restricted_service_perimeter_name description = "Access context manager service perimeter name" diff --git a/3-networks-dual-svpc/envs/nonproduction/variables.tf b/3-networks-dual-svpc/envs/nonproduction/variables.tf index 12e551dbd..02448e5a9 100644 --- a/3-networks-dual-svpc/envs/nonproduction/variables.tf +++ b/3-networks-dual-svpc/envs/nonproduction/variables.tf @@ -24,18 +24,22 @@ variable "access_context_manager_policy_id" { 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 "perimeter_additional_members" { - description = "The list of additional members to be added to the perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`." - type = list(string) -} - variable "domain" { type = string description = "The DNS name of peering managed zone, for instance 'example.com.'. Must end with a period." } variable "egress_policies" { - description = "A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference), each list object has a `from` and `to` value that describes egress_from and egress_to.\n\nExample: `[{ from={ identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" + description = "A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference) to use in an enforced perimeter. Each list object has a `from` and `to` value that describes egress_from and egress_to.\n\nExample: `[{ from={ identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" + type = list(object({ + from = any + to = any + })) + default = [] +} + +variable "egress_policies_dry_run" { + description = "A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference) to use in a dry-run perimeter. Each list object has a `from` and `to` value that describes egress_from and egress_to.\n\nExample: `[{ from={ identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" type = list(object({ from = any to = any @@ -44,7 +48,7 @@ variable "egress_policies" { } variable "ingress_policies" { - description = "A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference), each list object has a `from` and `to` value that describes ingress_from and ingress_to.\n\nExample: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" + description = "A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference) to use in an enforced perimeter. Each list object has a `from` and `to` value that describes ingress_from and ingress_to.\n\nExample: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" type = list(object({ from = any to = any @@ -52,6 +56,27 @@ variable "ingress_policies" { default = [] } +variable "ingress_policies_dry_run" { + description = "A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference) to use in a dry-run perimeter. Each list object has a `from` and `to` value that describes ingress_from and ingress_to.\n\nExample: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" + type = list(object({ + from = any + to = any + })) + default = [] +} + +variable "perimeter_additional_members" { + description = "The list of additional members to be added to the enforced perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`." + type = list(string) + default = [] +} + +variable "perimeter_additional_members_dry_run" { + description = "The list of additional members to be added to the dry-run perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`." + type = list(string) + default = [] +} + variable "tfc_org_name" { description = "Name of the TFC organization" type = string diff --git a/3-networks-dual-svpc/envs/production/README.md b/3-networks-dual-svpc/envs/production/README.md index e4bbc5c0b..a92f78e34 100644 --- a/3-networks-dual-svpc/envs/production/README.md +++ b/3-networks-dual-svpc/envs/production/README.md @@ -17,9 +17,12 @@ 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 | -| egress\_policies | A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference), each list object has a `from` and `to` value that describes egress\_from and egress\_to.

Example: `[{ from={ identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | -| ingress\_policies | A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference), each list object has a `from` and `to` value that describes ingress\_from and ingress\_to.

Example: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | -| perimeter\_additional\_members | The list of additional members to be added to the perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`. | `list(string)` | n/a | yes | +| egress\_policies | A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference) to use in an enforced perimeter. Each list object has a `from` and `to` value that describes egress\_from and egress\_to.

Example: `[{ from={ identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | +| egress\_policies\_dry\_run | A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference) to use in a dry-run perimeter. Each list object has a `from` and `to` value that describes egress\_from and egress\_to.

Example: `[{ from={ identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | +| ingress\_policies | A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference) to use in an enforced perimeter. Each list object has a `from` and `to` value that describes ingress\_from and ingress\_to.

Example: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | +| ingress\_policies\_dry\_run | A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference) to use in a dry-run perimeter. Each list object has a `from` and `to` value that describes ingress\_from and ingress\_to.

Example: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | +| perimeter\_additional\_members | The list of additional members to be added to the enforced perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`. | `list(string)` | `[]` | no | +| perimeter\_additional\_members\_dry\_run | The list of additional members to be added to the dry-run perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`. | `list(string)` | `[]` | no | | remote\_state\_bucket | Backend bucket to load Terraform Remote State Data from previous steps. | `string` | n/a | yes | | tfc\_org\_name | Name of the TFC organization | `string` | `""` | no | @@ -28,6 +31,8 @@ The purpose of this step is to set up base and restricted shared VPCs with defau | Name | Description | |------|-------------| | access\_context\_manager\_policy\_id | Access Context Manager Policy ID. | +| access\_level\_name | Access context manager access level name | +| access\_level\_name\_dry\_run | Access context manager access level name for the dry-run perimeter | | 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 | @@ -35,7 +40,7 @@ The purpose of this step is to set up base and restricted shared VPCs with defau | 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 | +| enforce\_vpcsc | Enable the enforced mode for VPC Service Controls. It is not recommended to enable VPC-SC on the first run deploying your foundation. Review [best practices for enabling VPC Service Controls](https://cloud.google.com/vpc-service-controls/docs/enable), then only enforce the perimeter after you have analyzed the access patterns in your dry-run perimeter and created the necessary exceptions for your use cases. | | 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 | diff --git a/3-networks-dual-svpc/envs/production/main.tf b/3-networks-dual-svpc/envs/production/main.tf index 35a80fc81..d2ea8490e 100644 --- a/3-networks-dual-svpc/envs/production/main.tf +++ b/3-networks-dual-svpc/envs/production/main.tf @@ -74,11 +74,14 @@ module "base_env" { environment_code = local.environment_code access_context_manager_policy_id = var.access_context_manager_policy_id perimeter_additional_members = var.perimeter_additional_members + perimeter_additional_members_dry_run = var.perimeter_additional_members_dry_run default_region1 = local.default_region1 default_region2 = local.default_region2 domain = var.domain ingress_policies = var.ingress_policies + ingress_policies_dry_run = var.ingress_policies_dry_run egress_policies = var.egress_policies + egress_policies_dry_run = var.egress_policies_dry_run enable_partner_interconnect = false base_private_service_cidr = local.base_private_service_cidr base_subnet_primary_ranges = local.base_subnet_primary_ranges diff --git a/3-networks-dual-svpc/envs/production/outputs.tf b/3-networks-dual-svpc/envs/production/outputs.tf index bcf18cd1d..ae890e4d2 100644 --- a/3-networks-dual-svpc/envs/production/outputs.tf +++ b/3-networks-dual-svpc/envs/production/outputs.tf @@ -58,11 +58,21 @@ output "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 +output "access_level_name" { + value = module.base_env.access_level_name description = "Access context manager access level name" } +output "access_level_name_dry_run" { + value = module.base_env.access_level_name_dry_run + description = "Access context manager access level name for the dry-run perimeter" +} + +output "enforce_vpcsc" { + value = module.base_env.enforce_vpcsc + description = "Enable the enforced mode for VPC Service Controls. It is not recommended to enable VPC-SC on the first run deploying your foundation. Review [best practices for enabling VPC Service Controls](https://cloud.google.com/vpc-service-controls/docs/enable), then only enforce the perimeter after you have analyzed the access patterns in your dry-run perimeter and created the necessary exceptions for your use cases." +} + output "restricted_service_perimeter_name" { value = module.base_env.restricted_service_perimeter_name description = "Access context manager service perimeter name" diff --git a/3-networks-dual-svpc/envs/production/variables.tf b/3-networks-dual-svpc/envs/production/variables.tf index 12e551dbd..02448e5a9 100644 --- a/3-networks-dual-svpc/envs/production/variables.tf +++ b/3-networks-dual-svpc/envs/production/variables.tf @@ -24,18 +24,22 @@ variable "access_context_manager_policy_id" { 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 "perimeter_additional_members" { - description = "The list of additional members to be added to the perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`." - type = list(string) -} - variable "domain" { type = string description = "The DNS name of peering managed zone, for instance 'example.com.'. Must end with a period." } variable "egress_policies" { - description = "A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference), each list object has a `from` and `to` value that describes egress_from and egress_to.\n\nExample: `[{ from={ identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" + description = "A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference) to use in an enforced perimeter. Each list object has a `from` and `to` value that describes egress_from and egress_to.\n\nExample: `[{ from={ identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" + type = list(object({ + from = any + to = any + })) + default = [] +} + +variable "egress_policies_dry_run" { + description = "A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference) to use in a dry-run perimeter. Each list object has a `from` and `to` value that describes egress_from and egress_to.\n\nExample: `[{ from={ identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" type = list(object({ from = any to = any @@ -44,7 +48,7 @@ variable "egress_policies" { } variable "ingress_policies" { - description = "A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference), each list object has a `from` and `to` value that describes ingress_from and ingress_to.\n\nExample: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" + description = "A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference) to use in an enforced perimeter. Each list object has a `from` and `to` value that describes ingress_from and ingress_to.\n\nExample: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" type = list(object({ from = any to = any @@ -52,6 +56,27 @@ variable "ingress_policies" { default = [] } +variable "ingress_policies_dry_run" { + description = "A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference) to use in a dry-run perimeter. Each list object has a `from` and `to` value that describes ingress_from and ingress_to.\n\nExample: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" + type = list(object({ + from = any + to = any + })) + default = [] +} + +variable "perimeter_additional_members" { + description = "The list of additional members to be added to the enforced perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`." + type = list(string) + default = [] +} + +variable "perimeter_additional_members_dry_run" { + description = "The list of additional members to be added to the dry-run perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`." + type = list(string) + default = [] +} + variable "tfc_org_name" { description = "Name of the TFC organization" type = string diff --git a/3-networks-dual-svpc/modules/base_env/README.md b/3-networks-dual-svpc/modules/base_env/README.md index a937b3f80..d543340d4 100644 --- a/3-networks-dual-svpc/modules/base_env/README.md +++ b/3-networks-dual-svpc/modules/base_env/README.md @@ -10,17 +10,21 @@ | base\_subnet\_proxy\_ranges | The base proxy-only 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 | | base\_vpc\_flow\_logs | aggregation\_interval: Toggles the aggregation interval for collecting flow logs. Increasing the interval time will reduce the amount of generated flow logs for long lasting connections. Possible values are: INTERVAL\_5\_SEC, INTERVAL\_30\_SEC, INTERVAL\_1\_MIN, INTERVAL\_5\_MIN, INTERVAL\_10\_MIN, INTERVAL\_15\_MIN.
flow\_sampling: Set the sampling rate of VPC flow logs within the subnetwork where 1.0 means all collected logs are reported and 0.0 means no logs are reported. The value of the field must be in [0, 1].
metadata: Configures whether metadata fields should be added to the reported VPC flow logs. Possible values are: EXCLUDE\_ALL\_METADATA, INCLUDE\_ALL\_METADATA, CUSTOM\_METADATA.
metadata\_fields: ist of metadata fields that should be added to reported logs. Can only be specified if VPC flow logs for this subnetwork is enabled and "metadata" is set to CUSTOM\_METADATA.
filter\_expr: Export filter used to define which VPC flow logs should be logged, as as CEL expression. See https://cloud.google.com/vpc/docs/flow-logs#filtering for details on how to format this field. |
object({
aggregation_interval = optional(string, "INTERVAL_5_SEC")
flow_sampling = optional(string, "0.5")
metadata = optional(string, "INCLUDE_ALL_METADATA")
metadata_fields = optional(list(string), [])
filter_expr = optional(string, "true")
})
| `{}` | no | -| custom\_restricted\_services | List of custom services to be protected by the VPC-SC perimeter. If empty, all supported services (https://cloud.google.com/vpc-service-controls/docs/supported-products) will be protected. | `list(string)` | `[]` | no | +| custom\_restricted\_services | List of custom services to be protected by the enforced VPC-SC perimeter. If empty, all supported services (https://cloud.google.com/vpc-service-controls/docs/supported-products) will be protected. | `list(string)` | `[]` | no | +| custom\_restricted\_services\_dry\_run | List of custom services to be protected by the dry-run VPC-SC perimeter. If empty, all supported services (https://cloud.google.com/vpc-service-controls/docs/supported-products) will be protected. | `list(string)` | `[]` | no | | 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 | -| egress\_policies | A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference), each list object has a `from` and `to` value that describes egress\_from and egress\_to.

Example: `[{ from={ identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | +| egress\_policies | A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference) to use in an enforced perimeter. Each list object has a `from` and `to` value that describes egress\_from and egress\_to.

Example: `[{ from={ identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | +| egress\_policies\_dry\_run | A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference) to use in a dry-run perimeter. Each list object has a `from` and `to` value that describes egress\_from and egress\_to.

Example: `[{ from={ identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | | enable\_dedicated\_interconnect | Enable Dedicated Interconnect in the environment. | `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 | | environment\_code | A short form of the folder level resources (environment) within the Google Cloud organization (ex. d). | `string` | n/a | yes | -| ingress\_policies | A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference), each list object has a `from` and `to` value that describes ingress\_from and ingress\_to.

Example: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | -| perimeter\_additional\_members | The list of additional members to be added to the perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`. | `list(string)` | n/a | yes | +| ingress\_policies | A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference) to use in an enforced perimeter. Each list object has a `from` and `to` value that describes ingress\_from and ingress\_to.

Example: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | +| ingress\_policies\_dry\_run | A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference) to use in a dry-run perimeter. Each list object has a `from` and `to` value that describes ingress\_from and ingress\_to.

Example: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | +| perimeter\_additional\_members | The list of additional members to be added to the enforced perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`. | `list(string)` | `[]` | no | +| perimeter\_additional\_members\_dry\_run | The list of additional members to be added to the dry-run perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`. | `list(string)` | `[]` | no | | remote\_state\_bucket | Backend bucket to load Terraform Remote State Data from previous steps. | `string` | n/a | yes | | 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\_private\_service\_connect\_ip | The base subnet internal IP to be used as the private service connect endpoint in the Restricted Shared VPC | `string` | n/a | yes | @@ -34,6 +38,8 @@ | Name | Description | |------|-------------| +| access\_level\_name | Access context manager access level name for the enforced perimeter | +| access\_level\_name\_dry\_run | Access context manager access level name for the dry-run perimeter | | 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 | @@ -41,11 +47,11 @@ | 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 | +| enforce\_vpcsc | Enable the enforced mode for VPC Service Controls. It is not recommended to enable VPC-SC on the first run deploying your foundation. Review [best practices for enabling VPC Service Controls](https://cloud.google.com/vpc-service-controls/docs/enable), then only enforce the perimeter after you have analyzed the access patterns in your dry-run perimeter and created the necessary exceptions for your use cases. | | 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\_service\_perimeter\_name | Access context manager service perimeter name for the enforced perimeter | | 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 | diff --git a/3-networks-dual-svpc/modules/base_env/main.tf b/3-networks-dual-svpc/modules/base_env/main.tf index a1b8e2612..cfd4958a5 100644 --- a/3-networks-dual-svpc/modules/base_env/main.tf +++ b/3-networks-dual-svpc/modules/base_env/main.tf @@ -159,7 +159,8 @@ locals { "workstations.googleapis.com", ] - restricted_services = length(var.custom_restricted_services) != 0 ? var.custom_restricted_services : local.supported_restricted_service + restricted_services = length(var.custom_restricted_services) != 0 ? var.custom_restricted_services : local.supported_restricted_service + restricted_services_dry_run = length(var.custom_restricted_services_dry_run) != 0 ? var.custom_restricted_services : local.supported_restricted_service } /****************************************** @@ -174,11 +175,17 @@ module "restricted_shared_vpc" { environment_code = var.environment_code access_context_manager_policy_id = var.access_context_manager_policy_id restricted_services = local.restricted_services + restricted_services_dry_run = local.restricted_services_dry_run members = distinct(concat([ "serviceAccount:${local.networks_service_account}", "serviceAccount:${local.projects_service_account}", "serviceAccount:${local.organization_service_account}", ], var.perimeter_additional_members)) + members_dry_run = distinct(concat([ + "serviceAccount:${local.networks_service_account}", + "serviceAccount:${local.projects_service_account}", + "serviceAccount:${local.organization_service_account}", + ], var.perimeter_additional_members)) private_service_cidr = var.restricted_private_service_cidr private_service_connect_ip = var.restricted_private_service_connect_ip bgp_asn_subnet = local.bgp_asn_number @@ -186,11 +193,16 @@ module "restricted_shared_vpc" { default_region2 = var.default_region2 domain = var.domain ingress_policies = var.ingress_policies - + ingress_policies_dry_run = var.ingress_policies_dry_run egress_policies = distinct(concat( local.dedicated_interconnect_egress_policy, var.egress_policies )) + egress_policies_dry_run = distinct(concat( + local.dedicated_interconnect_egress_policy, + var.egress_policies_dry_run + )) + subnets = [ { diff --git a/3-networks-dual-svpc/modules/base_env/outputs.tf b/3-networks-dual-svpc/modules/base_env/outputs.tf index 39cf8f1ee..05dfc0107 100644 --- a/3-networks-dual-svpc/modules/base_env/outputs.tf +++ b/3-networks-dual-svpc/modules/base_env/outputs.tf @@ -53,16 +53,28 @@ output "restricted_subnets_secondary_ranges" { description = "The secondary ranges associated with these subnets" } -output "restricted_access_level_name" { +output "access_level_name" { value = module.restricted_shared_vpc.access_level_name - description = "Access context manager access level name" + description = "Access context manager access level name for the enforced perimeter" +} + +output "access_level_name_dry_run" { + value = module.restricted_shared_vpc.access_level_name_dry_run + description = "Access context manager access level name for the dry-run perimeter" +} + +output "enforce_vpcsc" { + value = module.restricted_shared_vpc.enforce_vpcsc + description = "Enable the enforced mode for VPC Service Controls. It is not recommended to enable VPC-SC on the first run deploying your foundation. Review [best practices for enabling VPC Service Controls](https://cloud.google.com/vpc-service-controls/docs/enable), then only enforce the perimeter after you have analyzed the access patterns in your dry-run perimeter and created the necessary exceptions for your use cases." } output "restricted_service_perimeter_name" { value = module.restricted_shared_vpc.service_perimeter_name - description = "Access context manager service perimeter name" + description = "Access context manager service perimeter name for the enforced perimeter" } + + /****************************************** Private Outputs *****************************************/ diff --git a/3-networks-dual-svpc/modules/base_env/variables.tf b/3-networks-dual-svpc/modules/base_env/variables.tf index f435c2977..963eae139 100644 --- a/3-networks-dual-svpc/modules/base_env/variables.tf +++ b/3-networks-dual-svpc/modules/base_env/variables.tf @@ -148,7 +148,16 @@ EOT } variable "egress_policies" { - description = "A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference), each list object has a `from` and `to` value that describes egress_from and egress_to.\n\nExample: `[{ from={ identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" + description = "A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference) to use in an enforced perimeter. Each list object has a `from` and `to` value that describes egress_from and egress_to.\n\nExample: `[{ from={ identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" + type = list(object({ + from = any + to = any + })) + default = [] +} + +variable "egress_policies_dry_run" { + description = "A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference) to use in a dry-run perimeter. Each list object has a `from` and `to` value that describes egress_from and egress_to.\n\nExample: `[{ from={ identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" type = list(object({ from = any to = any @@ -157,7 +166,16 @@ variable "egress_policies" { } variable "ingress_policies" { - description = "A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference), each list object has a `from` and `to` value that describes ingress_from and ingress_to.\n\nExample: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" + description = "A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference) to use in an enforced perimeter. Each list object has a `from` and `to` value that describes ingress_from and ingress_to.\n\nExample: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" + type = list(object({ + from = any + to = any + })) + default = [] +} + +variable "ingress_policies_dry_run" { + description = "A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference) to use in a dry-run perimeter. Each list object has a `from` and `to` value that describes ingress_from and ingress_to.\n\nExample: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" type = list(object({ from = any to = any @@ -166,12 +184,26 @@ variable "ingress_policies" { } variable "perimeter_additional_members" { - description = "The list of additional members to be added to the perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`." + description = "The list of additional members to be added to the enforced perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`." + type = list(string) + default = [] +} + +variable "perimeter_additional_members_dry_run" { + description = "The list of additional members to be added to the dry-run perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`." type = list(string) + default = [] } + variable "custom_restricted_services" { - description = "List of custom services to be protected by the VPC-SC perimeter. If empty, all supported services (https://cloud.google.com/vpc-service-controls/docs/supported-products) will be protected." + description = "List of custom services to be protected by the enforced VPC-SC perimeter. If empty, all supported services (https://cloud.google.com/vpc-service-controls/docs/supported-products) will be protected." + type = list(string) + default = [] +} + +variable "custom_restricted_services_dry_run" { + description = "List of custom services to be protected by the dry-run VPC-SC perimeter. If empty, all supported services (https://cloud.google.com/vpc-service-controls/docs/supported-products) will be protected." type = list(string) default = [] } diff --git a/3-networks-dual-svpc/modules/restricted_shared_vpc/README.md b/3-networks-dual-svpc/modules/restricted_shared_vpc/README.md index a0c577a24..1ce44d877 100644 --- a/3-networks-dual-svpc/modules/restricted_shared_vpc/README.md +++ b/3-networks-dual-svpc/modules/restricted_shared_vpc/README.md @@ -11,12 +11,16 @@ | dns\_enable\_logging | Toggle DNS logging for VPC DNS. | `bool` | `true` | no | | dns\_hub\_project\_id | The DNS hub project ID | `string` | n/a | yes | | domain | The DNS name of peering managed zone, for instance 'example.com.' | `string` | n/a | yes | -| egress\_policies | A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference), each list object has a `from` and `to` value that describes egress\_from and egress\_to.

Example: `[{ from={ identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | +| egress\_policies | A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference) to use in an enforced perimeter. Each list object has a `from` and `to` value that describes egress\_from and egress\_to.

Example: `[{ from={ identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | +| egress\_policies\_dry\_run | A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference) to use in a dry-run perimeter. Each list object has a `from` and `to` value that describes egress\_from and egress\_to.

Example: `[{ from={ identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | | enable\_all\_vpc\_internal\_traffic | Enable firewall policy rule to allow internal traffic (ingress and egress). | `bool` | `false` | no | +| enforce\_vpcsc | Enable the enforced mode for VPC Service Controls. It is not recommended to enable VPC-SC on the first run deploying your foundation. Review [best practices for enabling VPC Service Controls](https://cloud.google.com/vpc-service-controls/docs/enable), then only enforce the perimeter after you have analyzed the access patterns in your dry-run perimeter and created the necessary exceptions for your use cases. | `bool` | `false` | no | | 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 | -| ingress\_policies | A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference), each list object has a `from` and `to` value that describes ingress\_from and ingress\_to.

Example: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | 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 | +| ingress\_policies | A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference) to use in an enforced perimeter. Each list object has a `from` and `to` value that describes ingress\_from and ingress\_to.

Example: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | +| ingress\_policies\_dry\_run | A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference) to use in a dry-run perimeter. Each list object has a `from` and `to` value that describes ingress\_from and ingress\_to.

Example: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | +| members | An allowed list of members (users, service accounts) for an access level in an enforced perimeter. 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 | +| members\_dry\_run | An allowed list of members (users, service accounts) for an access level in a dry run perimeter. 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 | | 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 | @@ -25,7 +29,8 @@ | private\_service\_connect\_ip | Internal IP to be used as the private service connect endpoint. | `string` | n/a | yes | | 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 | +| restricted\_services | List of services to restrict in an enforced perimeter. | `list(string)` | n/a | yes | +| restricted\_services\_dry\_run | List of services to restrict in a dry-run perimeter. | `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(object({
subnet_name = string
subnet_ip = string
subnet_region = string
subnet_private_access = optional(string, "false")
subnet_private_ipv6_access = optional(string)
subnet_flow_logs = optional(string, "false")
subnet_flow_logs_interval = optional(string, "INTERVAL_5_SEC")
subnet_flow_logs_sampling = optional(string, "0.5")
subnet_flow_logs_metadata = optional(string, "INCLUDE_ALL_METADATA")
subnet_flow_logs_filter = optional(string, "true")
subnet_flow_logs_metadata_fields = optional(list(string), [])
description = optional(string)
purpose = optional(string)
role = optional(string)
stack_type = optional(string)
ipv6_access_type = optional(string)
}))
| `[]` | no | | windows\_activation\_enabled | Enable Windows license activation for Windows workloads. | `bool` | `false` | no | @@ -34,14 +39,16 @@ | Name | Description | |------|-------------| -| access\_level\_name | Access context manager access level name | +| access\_level\_name | Access context manager access level name for the enforced perimeter | +| access\_level\_name\_dry\_run | Access context manager access level name for the dry-run perimeter | +| enforce\_vpcsc | Enable the enforced mode for VPC Service Controls. It is not recommended to enable VPC-SC on the first run deploying your foundation. Review [best practices for enabling VPC Service Controls](https://cloud.google.com/vpc-service-controls/docs/enable), then only enforce the perimeter after you have analyzed the access patterns in your dry-run perimeter and created the necessary exceptions for your use cases. | | network\_name | The name of the VPC being created | | network\_self\_link | The URI of the VPC being created | | region1\_router1 | Router 1 for Region 1 | | region1\_router2 | Router 2 for Region 1 | | region2\_router1 | Router 1 for Region 2 | | region2\_router2 | Router 2 for Region 2 | -| service\_perimeter\_name | Access context manager service perimeter name | +| service\_perimeter\_name | Access context manager service perimeter name for the enforced perimeter | | 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 | diff --git a/3-networks-dual-svpc/modules/restricted_shared_vpc/outputs.tf b/3-networks-dual-svpc/modules/restricted_shared_vpc/outputs.tf index ce0bf824c..af80f106d 100644 --- a/3-networks-dual-svpc/modules/restricted_shared_vpc/outputs.tf +++ b/3-networks-dual-svpc/modules/restricted_shared_vpc/outputs.tf @@ -71,10 +71,20 @@ output "region2_router2" { output "access_level_name" { value = local.access_level_name - description = "Access context manager access level name " + description = "Access context manager access level name for the enforced perimeter" +} + +output "access_level_name_dry_run" { + value = local.access_level_name_dry_run + description = "Access context manager access level name for the dry-run perimeter" +} + +output "enforce_vpcsc" { + value = var.enforce_vpcsc + description = "Enable the enforced mode for VPC Service Controls. It is not recommended to enable VPC-SC on the first run deploying your foundation. Review [best practices for enabling VPC Service Controls](https://cloud.google.com/vpc-service-controls/docs/enable), then only enforce the perimeter after you have analyzed the access patterns in your dry-run perimeter and created the necessary exceptions for your use cases." } output "service_perimeter_name" { value = local.perimeter_name - description = "Access context manager service perimeter name " + description = "Access context manager service perimeter name for the enforced perimeter" } 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 index c872f8b38..38c4ddd3f 100644 --- a/3-networks-dual-svpc/modules/restricted_shared_vpc/service_control.tf +++ b/3-networks-dual-svpc/modules/restricted_shared_vpc/service_control.tf @@ -15,25 +15,36 @@ */ 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}" + prefix = "${var.environment_code}_shared_restricted" + access_level_name = "alp_${local.prefix}_members_${random_id.random_access_level_suffix.hex}" + access_level_name_dry_run = "alp_${local.prefix}_members_dry_run_${random_id.random_access_level_suffix.hex}" + perimeter_name = "sp_${local.prefix}_default_perimeter_${random_id.random_access_level_suffix.hex}" } resource "random_id" "random_access_level_suffix" { byte_length = 2 } -module "access_level_members" { +module "access_level" { source = "terraform-google-modules/vpc-service-controls/google//modules/access_level" version = "~> 6.0" - description = "${local.prefix} Access Level" + description = "${local.prefix} Access Level for use in an enforced perimeter" policy = var.access_context_manager_policy_id name = local.access_level_name members = var.members } +module "access_level_dry_run" { + source = "terraform-google-modules/vpc-service-controls/google//modules/access_level" + version = "~> 5.0" + + description = "${local.prefix} Access Level for testing with a dry run perimeter" + policy = var.access_context_manager_policy_id + name = local.access_level_name_dry_run + members = var.members_dry_run +} + resource "time_sleep" "wait_vpc_sc_propagation" { create_duration = "60s" destroy_duration = "60s" @@ -66,14 +77,22 @@ module "regular_service_perimeter" { policy = var.access_context_manager_policy_id perimeter_name = local.perimeter_name description = "Default VPC Service Controls perimeter" - resources = [var.project_number] - access_levels = [module.access_level_members.name] - restricted_services = var.restricted_services - vpc_accessible_services = ["RESTRICTED-SERVICES"] + # configurations for a perimeter in enforced mode. + resources = var.enforce_vpcsc ? [var.project_number] : [] + access_levels = var.enforce_vpcsc ? [module.access_level.name] : [] + restricted_services = var.enforce_vpcsc ? var.restricted_services : [] + vpc_accessible_services = var.enforce_vpcsc ? ["RESTRICTED-SERVICES"] : [] + ingress_policies = var.enforce_vpcsc ? var.ingress_policies : [] + egress_policies = var.enforce_vpcsc ? var.egress_policies : [] - ingress_policies = var.ingress_policies - egress_policies = var.egress_policies + # configurations for a perimeter in dry run mode. + resources_dry_run = [var.project_number] + access_levels_dry_run = [module.access_level_dry_run.name] + restricted_services_dry_run = var.restricted_services_dry_run + vpc_accessible_services_dry_run = ["RESTRICTED-SERVICES"] + ingress_policies_dry_run = var.ingress_policies_dry_run + egress_policies_dry_run = var.egress_policies_dry_run depends_on = [ time_sleep.wait_vpc_sc_propagation diff --git a/3-networks-dual-svpc/modules/restricted_shared_vpc/variables.tf b/3-networks-dual-svpc/modules/restricted_shared_vpc/variables.tf index 8805fae86..7774c1d49 100644 --- a/3-networks-dual-svpc/modules/restricted_shared_vpc/variables.tf +++ b/3-networks-dual-svpc/modules/restricted_shared_vpc/variables.tf @@ -149,12 +149,22 @@ variable "windows_activation_enabled" { 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}" + description = "An allowed list of members (users, service accounts) for an access level in an enforced perimeter. 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 "members_dry_run" { + type = list(string) + description = "An allowed list of members (users, service accounts) for an access level in a dry run perimeter. 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." + description = "List of services to restrict in an enforced perimeter." +} + +variable "restricted_services_dry_run" { + type = list(string) + description = "List of services to restrict in a dry-run perimeter." } variable "enable_all_vpc_internal_traffic" { @@ -163,8 +173,23 @@ variable "enable_all_vpc_internal_traffic" { default = false } +variable "enforce_vpcsc" { + description = "Enable the enforced mode for VPC Service Controls. It is not recommended to enable VPC-SC on the first run deploying your foundation. Review [best practices for enabling VPC Service Controls](https://cloud.google.com/vpc-service-controls/docs/enable), then only enforce the perimeter after you have analyzed the access patterns in your dry-run perimeter and created the necessary exceptions for your use cases." + type = bool + default = false +} + variable "egress_policies" { - description = "A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference), each list object has a `from` and `to` value that describes egress_from and egress_to.\n\nExample: `[{ from={ identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" + description = "A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference) to use in an enforced perimeter. Each list object has a `from` and `to` value that describes egress_from and egress_to.\n\nExample: `[{ from={ identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" + type = list(object({ + from = any + to = any + })) + default = [] +} + +variable "egress_policies_dry_run" { + description = "A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference) to use in a dry-run perimeter. Each list object has a `from` and `to` value that describes egress_from and egress_to.\n\nExample: `[{ from={ identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" type = list(object({ from = any to = any @@ -173,7 +198,16 @@ variable "egress_policies" { } variable "ingress_policies" { - description = "A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference), each list object has a `from` and `to` value that describes ingress_from and ingress_to.\n\nExample: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" + description = "A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference) to use in an enforced perimeter. Each list object has a `from` and `to` value that describes ingress_from and ingress_to.\n\nExample: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" + type = list(object({ + from = any + to = any + })) + default = [] +} + +variable "ingress_policies_dry_run" { + description = "A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference) to use in a dry-run perimeter. Each list object has a `from` and `to` value that describes ingress_from and ingress_to.\n\nExample: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" type = list(object({ from = any to = any diff --git a/3-networks-hub-and-spoke/README.md b/3-networks-hub-and-spoke/README.md index adad7a225..22bb16932 100644 --- a/3-networks-hub-and-spoke/README.md +++ b/3-networks-hub-and-spoke/README.md @@ -58,7 +58,7 @@ For an overview of the architecture and the parts, see the 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. +- Set up base and restricted Hubs and it corresponding Spokes. With default DNS, NAT (optional), Private Service networking, VPC Service Controls (optional), on-premises Dedicated or Partner Interconnect, and baseline firewall rules for each environment. ## Prerequisites @@ -192,7 +192,7 @@ Run `terraform output cloudbuild_project_id` in the `0-bootstrap` folder to get sed -i'' -e "s/REMOTE_STATE_BUCKET/${backend_bucket}/" ./common.auto.tfvars ``` - **Note:** Make sure that you update the `perimeter_additional_members` variable with your e-mail in order to be able to view/access resources in the project protected by the VPC service controls. + **Note:** Make sure that you update the `perimeter_additional_members` variable with your user identity in order to be able to view/access resources in the project protected by the VPC Service Controls. 1. Commit changes @@ -417,3 +417,11 @@ Before executing the next stages, unset the `GOOGLE_IMPERSONATE_SERVICE_ACCOUNT` ```bash unset GOOGLE_IMPERSONATE_SERVICE_ACCOUNT ``` + +### (Optional) Enforce VPC Service Controls + +Because enabling VPC Service Controls can be a disruptive process, this repo configures VPC Service Controls perimeters in dry run mode by default. This configuration will service traffic that crosses the security perimeter (API requests that originate from inside your perimeter communicating with external resources, or API requests from external resources communicating with resources inside your perimeter) but still allow service traffic normally. + +When you are ready to enforce VPC Service Controls, we recommend that you review the guidance at [Best practices for enabling VPC Service Controls](https://cloud.google.com/vpc-service-controls/docs/enable). After you have added the necessary exceptions and are confident that VPC Service Controls will not disrupt your intended operations, set the variable `enforce_vpcsc` under the module `restricted_shared_vpc` to `true` and re-apply this stage. Then re-apply the 4-projects stage, which will inherit the new setting and include those projects inside the enforced perimeter. + +When you need to make changes to an existing enforced perimeter, you can test safely by modifying the configuration of the dry run perimeter. This will log traffic denied by the dry run perimeter without impacting whether the enforced perimeter allows or denies traffic. diff --git a/3-networks-hub-and-spoke/envs/development/README.md b/3-networks-hub-and-spoke/envs/development/README.md index 48da8fee9..baa2d7ed3 100644 --- a/3-networks-hub-and-spoke/envs/development/README.md +++ b/3-networks-hub-and-spoke/envs/development/README.md @@ -17,10 +17,13 @@ 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 | -| egress\_policies | A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference), each list object has a `from` and `to` value that describes egress\_from and egress\_to.

Example: `[{ from={ identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | +| egress\_policies | A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference) to use in an enforced perimeter. Each list object has a `from` and `to` value that describes egress\_from and egress\_to.

Example: `[{ from={ identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | +| egress\_policies\_dry\_run | A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference) to use in a dry-run perimeter. Each list object has a `from` and `to` value that describes egress\_from and egress\_to.

Example: `[{ from={ identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | | enable\_hub\_and\_spoke\_transitivity | Enable transitivity via gateway VMs on Hub-and-Spoke architecture. | `bool` | `false` | no | -| ingress\_policies | A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference), each list object has a `from` and `to` value that describes ingress\_from and ingress\_to.

Example: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | -| perimeter\_additional\_members | The list of additional members to be added to the perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`. | `list(string)` | n/a | yes | +| ingress\_policies | A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference) to use in an enforced perimeter. Each list object has a `from` and `to` value that describes ingress\_from and ingress\_to.

Example: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | +| ingress\_policies\_dry\_run | A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference) to use in a dry-run perimeter. Each list object has a `from` and `to` value that describes ingress\_from and ingress\_to.

Example: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | +| perimeter\_additional\_members | The list of additional members to be added to the enforced perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`. | `list(string)` | `[]` | no | +| perimeter\_additional\_members\_dry\_run | The list of additional members to be added to the dry-run perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`. | `list(string)` | `[]` | no | | remote\_state\_bucket | Backend bucket to load Terraform Remote State Data from previous steps. | `string` | n/a | yes | | tfc\_org\_name | Name of the TFC organization | `string` | `""` | no | @@ -29,6 +32,8 @@ The purpose of this step is to set up base and restricted shared VPCs with defau | Name | Description | |------|-------------| | access\_context\_manager\_policy\_id | Access Context Manager Policy ID. | +| access\_level\_name | Access context manager access level name | +| access\_level\_name\_dry\_run | Access context manager access level name for the dry-run perimeter | | 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 | @@ -36,7 +41,7 @@ The purpose of this step is to set up base and restricted shared VPCs with defau | 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 | +| enforce\_vpcsc | Enable the enforced mode for VPC Service Controls. It is not recommended to enable VPC-SC on the first run deploying your foundation. Review [best practices for enabling VPC Service Controls](https://cloud.google.com/vpc-service-controls/docs/enable), then only enforce the perimeter after you have analyzed the access patterns in your dry-run perimeter and created the necessary exceptions for your use cases. | | 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 | diff --git a/3-networks-hub-and-spoke/envs/development/outputs.tf b/3-networks-hub-and-spoke/envs/development/outputs.tf index 3adb70885..3e4d2a97e 100644 --- a/3-networks-hub-and-spoke/envs/development/outputs.tf +++ b/3-networks-hub-and-spoke/envs/development/outputs.tf @@ -58,11 +58,21 @@ output "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 +output "access_level_name" { + value = module.base_env.access_level_name description = "Access context manager access level name" } +output "access_level_name_dry_run" { + value = module.base_env.access_level_name_dry_run + description = "Access context manager access level name for the dry-run perimeter" +} + +output "enforce_vpcsc" { + value = module.base_env.enforce_vpcsc + description = "Enable the enforced mode for VPC Service Controls. It is not recommended to enable VPC-SC on the first run deploying your foundation. Review [best practices for enabling VPC Service Controls](https://cloud.google.com/vpc-service-controls/docs/enable), then only enforce the perimeter after you have analyzed the access patterns in your dry-run perimeter and created the necessary exceptions for your use cases." +} + output "restricted_service_perimeter_name" { value = module.base_env.restricted_service_perimeter_name description = "Access context manager service perimeter name" diff --git a/3-networks-hub-and-spoke/envs/development/variables.tf b/3-networks-hub-and-spoke/envs/development/variables.tf index eacfebf82..cf3061211 100644 --- a/3-networks-hub-and-spoke/envs/development/variables.tf +++ b/3-networks-hub-and-spoke/envs/development/variables.tf @@ -24,11 +24,6 @@ variable "access_context_manager_policy_id" { 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 "perimeter_additional_members" { - description = "The list of additional members to be added to the perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`." - type = list(string) -} - variable "domain" { type = string description = "The DNS name of peering managed zone, for instance 'example.com.'. Must end with a period." @@ -41,7 +36,16 @@ variable "enable_hub_and_spoke_transitivity" { } variable "egress_policies" { - description = "A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference), each list object has a `from` and `to` value that describes egress_from and egress_to.\n\nExample: `[{ from={ identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" + description = "A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference) to use in an enforced perimeter. Each list object has a `from` and `to` value that describes egress_from and egress_to.\n\nExample: `[{ from={ identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" + type = list(object({ + from = any + to = any + })) + default = [] +} + +variable "egress_policies_dry_run" { + description = "A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference) to use in a dry-run perimeter. Each list object has a `from` and `to` value that describes egress_from and egress_to.\n\nExample: `[{ from={ identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" type = list(object({ from = any to = any @@ -50,7 +54,7 @@ variable "egress_policies" { } variable "ingress_policies" { - description = "A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference), each list object has a `from` and `to` value that describes ingress_from and ingress_to.\n\nExample: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" + description = "A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference) to use in an enforced perimeter. Each list object has a `from` and `to` value that describes ingress_from and ingress_to.\n\nExample: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" type = list(object({ from = any to = any @@ -58,6 +62,27 @@ variable "ingress_policies" { default = [] } +variable "ingress_policies_dry_run" { + description = "A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference) to use in a dry-run perimeter. Each list object has a `from` and `to` value that describes ingress_from and ingress_to.\n\nExample: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" + type = list(object({ + from = any + to = any + })) + default = [] +} + +variable "perimeter_additional_members" { + description = "The list of additional members to be added to the enforced perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`." + type = list(string) + default = [] +} + +variable "perimeter_additional_members_dry_run" { + description = "The list of additional members to be added to the dry-run perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`." + type = list(string) + default = [] +} + variable "tfc_org_name" { description = "Name of the TFC organization" type = string diff --git a/3-networks-hub-and-spoke/envs/nonproduction/README.md b/3-networks-hub-and-spoke/envs/nonproduction/README.md index aced74c55..60c54d913 100644 --- a/3-networks-hub-and-spoke/envs/nonproduction/README.md +++ b/3-networks-hub-and-spoke/envs/nonproduction/README.md @@ -17,10 +17,13 @@ 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 | -| egress\_policies | A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference), each list object has a `from` and `to` value that describes egress\_from and egress\_to.

Example: `[{ from={ identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | +| egress\_policies | A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference) to use in an enforced perimeter. Each list object has a `from` and `to` value that describes egress\_from and egress\_to.

Example: `[{ from={ identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | +| egress\_policies\_dry\_run | A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference) to use in a dry-run perimeter. Each list object has a `from` and `to` value that describes egress\_from and egress\_to.

Example: `[{ from={ identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | | enable\_hub\_and\_spoke\_transitivity | Enable transitivity via gateway VMs on Hub-and-Spoke architecture. | `bool` | `false` | no | -| ingress\_policies | A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference), each list object has a `from` and `to` value that describes ingress\_from and ingress\_to.

Example: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | -| perimeter\_additional\_members | The list of additional members to be added to the perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`. | `list(string)` | n/a | yes | +| ingress\_policies | A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference) to use in an enforced perimeter. Each list object has a `from` and `to` value that describes ingress\_from and ingress\_to.

Example: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | +| ingress\_policies\_dry\_run | A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference) to use in a dry-run perimeter. Each list object has a `from` and `to` value that describes ingress\_from and ingress\_to.

Example: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | +| perimeter\_additional\_members | The list of additional members to be added to the enforced perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`. | `list(string)` | `[]` | no | +| perimeter\_additional\_members\_dry\_run | The list of additional members to be added to the dry-run perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`. | `list(string)` | `[]` | no | | remote\_state\_bucket | Backend bucket to load Terraform Remote State Data from previous steps. | `string` | n/a | yes | | tfc\_org\_name | Name of the TFC organization | `string` | `""` | no | @@ -29,6 +32,8 @@ The purpose of this step is to set up base and restricted shared VPCs with defau | Name | Description | |------|-------------| | access\_context\_manager\_policy\_id | Access Context Manager Policy ID. | +| access\_level\_name | Access context manager access level name | +| access\_level\_name\_dry\_run | Access context manager access level name for the dry-run perimeter | | 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 | @@ -36,7 +41,7 @@ The purpose of this step is to set up base and restricted shared VPCs with defau | 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 | +| enforce\_vpcsc | Enable the enforced mode for VPC Service Controls. It is not recommended to enable VPC-SC on the first run deploying your foundation. Review [best practices for enabling VPC Service Controls](https://cloud.google.com/vpc-service-controls/docs/enable), then only enforce the perimeter after you have analyzed the access patterns in your dry-run perimeter and created the necessary exceptions for your use cases. | | 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 | diff --git a/3-networks-hub-and-spoke/envs/nonproduction/main.tf b/3-networks-hub-and-spoke/envs/nonproduction/main.tf index f2660a33f..dffcd5170 100644 --- a/3-networks-hub-and-spoke/envs/nonproduction/main.tf +++ b/3-networks-hub-and-spoke/envs/nonproduction/main.tf @@ -74,11 +74,14 @@ module "base_env" { environment_code = local.environment_code access_context_manager_policy_id = var.access_context_manager_policy_id perimeter_additional_members = var.perimeter_additional_members + perimeter_additional_members_dry_run = var.perimeter_additional_members_dry_run default_region1 = local.default_region1 default_region2 = local.default_region2 domain = var.domain ingress_policies = var.ingress_policies + ingress_policies_dry_run = var.ingress_policies_dry_run egress_policies = var.egress_policies + egress_policies_dry_run = var.egress_policies_dry_run 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/nonproduction/outputs.tf b/3-networks-hub-and-spoke/envs/nonproduction/outputs.tf index 3adb70885..3e4d2a97e 100644 --- a/3-networks-hub-and-spoke/envs/nonproduction/outputs.tf +++ b/3-networks-hub-and-spoke/envs/nonproduction/outputs.tf @@ -58,11 +58,21 @@ output "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 +output "access_level_name" { + value = module.base_env.access_level_name description = "Access context manager access level name" } +output "access_level_name_dry_run" { + value = module.base_env.access_level_name_dry_run + description = "Access context manager access level name for the dry-run perimeter" +} + +output "enforce_vpcsc" { + value = module.base_env.enforce_vpcsc + description = "Enable the enforced mode for VPC Service Controls. It is not recommended to enable VPC-SC on the first run deploying your foundation. Review [best practices for enabling VPC Service Controls](https://cloud.google.com/vpc-service-controls/docs/enable), then only enforce the perimeter after you have analyzed the access patterns in your dry-run perimeter and created the necessary exceptions for your use cases." +} + output "restricted_service_perimeter_name" { value = module.base_env.restricted_service_perimeter_name description = "Access context manager service perimeter name" diff --git a/3-networks-hub-and-spoke/envs/nonproduction/variables.tf b/3-networks-hub-and-spoke/envs/nonproduction/variables.tf index eacfebf82..cf3061211 100644 --- a/3-networks-hub-and-spoke/envs/nonproduction/variables.tf +++ b/3-networks-hub-and-spoke/envs/nonproduction/variables.tf @@ -24,11 +24,6 @@ variable "access_context_manager_policy_id" { 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 "perimeter_additional_members" { - description = "The list of additional members to be added to the perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`." - type = list(string) -} - variable "domain" { type = string description = "The DNS name of peering managed zone, for instance 'example.com.'. Must end with a period." @@ -41,7 +36,16 @@ variable "enable_hub_and_spoke_transitivity" { } variable "egress_policies" { - description = "A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference), each list object has a `from` and `to` value that describes egress_from and egress_to.\n\nExample: `[{ from={ identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" + description = "A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference) to use in an enforced perimeter. Each list object has a `from` and `to` value that describes egress_from and egress_to.\n\nExample: `[{ from={ identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" + type = list(object({ + from = any + to = any + })) + default = [] +} + +variable "egress_policies_dry_run" { + description = "A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference) to use in a dry-run perimeter. Each list object has a `from` and `to` value that describes egress_from and egress_to.\n\nExample: `[{ from={ identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" type = list(object({ from = any to = any @@ -50,7 +54,7 @@ variable "egress_policies" { } variable "ingress_policies" { - description = "A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference), each list object has a `from` and `to` value that describes ingress_from and ingress_to.\n\nExample: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" + description = "A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference) to use in an enforced perimeter. Each list object has a `from` and `to` value that describes ingress_from and ingress_to.\n\nExample: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" type = list(object({ from = any to = any @@ -58,6 +62,27 @@ variable "ingress_policies" { default = [] } +variable "ingress_policies_dry_run" { + description = "A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference) to use in a dry-run perimeter. Each list object has a `from` and `to` value that describes ingress_from and ingress_to.\n\nExample: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" + type = list(object({ + from = any + to = any + })) + default = [] +} + +variable "perimeter_additional_members" { + description = "The list of additional members to be added to the enforced perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`." + type = list(string) + default = [] +} + +variable "perimeter_additional_members_dry_run" { + description = "The list of additional members to be added to the dry-run perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`." + type = list(string) + default = [] +} + variable "tfc_org_name" { description = "Name of the TFC organization" type = string diff --git a/3-networks-hub-and-spoke/envs/production/README.md b/3-networks-hub-and-spoke/envs/production/README.md index 1d98a3c31..1ba5a652c 100644 --- a/3-networks-hub-and-spoke/envs/production/README.md +++ b/3-networks-hub-and-spoke/envs/production/README.md @@ -17,10 +17,13 @@ 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 | -| egress\_policies | A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference), each list object has a `from` and `to` value that describes egress\_from and egress\_to.

Example: `[{ from={ identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | +| egress\_policies | A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference) to use in an enforced perimeter. Each list object has a `from` and `to` value that describes egress\_from and egress\_to.

Example: `[{ from={ identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | +| egress\_policies\_dry\_run | A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference) to use in a dry-run perimeter. Each list object has a `from` and `to` value that describes egress\_from and egress\_to.

Example: `[{ from={ identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | | enable\_hub\_and\_spoke\_transitivity | Enable transitivity via gateway VMs on Hub-and-Spoke architecture. | `bool` | `false` | no | -| ingress\_policies | A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference), each list object has a `from` and `to` value that describes ingress\_from and ingress\_to.

Example: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | -| perimeter\_additional\_members | The list of additional members to be added to the perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`. | `list(string)` | n/a | yes | +| ingress\_policies | A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference) to use in an enforced perimeter. Each list object has a `from` and `to` value that describes ingress\_from and ingress\_to.

Example: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | +| ingress\_policies\_dry\_run | A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference) to use in a dry-run perimeter. Each list object has a `from` and `to` value that describes ingress\_from and ingress\_to.

Example: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | +| perimeter\_additional\_members | The list of additional members to be added to the enforced perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`. | `list(string)` | `[]` | no | +| perimeter\_additional\_members\_dry\_run | The list of additional members to be added to the dry-run perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`. | `list(string)` | `[]` | no | | remote\_state\_bucket | Backend bucket to load Terraform Remote State Data from previous steps. | `string` | n/a | yes | | tfc\_org\_name | Name of the TFC organization | `string` | `""` | no | @@ -29,6 +32,8 @@ The purpose of this step is to set up base and restricted shared VPCs with defau | Name | Description | |------|-------------| | access\_context\_manager\_policy\_id | Access Context Manager Policy ID. | +| access\_level\_name | Access context manager access level name | +| access\_level\_name\_dry\_run | Access context manager access level name for the dry-run perimeter | | 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 | @@ -36,7 +41,7 @@ The purpose of this step is to set up base and restricted shared VPCs with defau | 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 | +| enforce\_vpcsc | Enable the enforced mode for VPC Service Controls. It is not recommended to enable VPC-SC on the first run deploying your foundation. Review [best practices for enabling VPC Service Controls](https://cloud.google.com/vpc-service-controls/docs/enable), then only enforce the perimeter after you have analyzed the access patterns in your dry-run perimeter and created the necessary exceptions for your use cases. | | 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 | diff --git a/3-networks-hub-and-spoke/envs/production/main.tf b/3-networks-hub-and-spoke/envs/production/main.tf index 879600aea..cd464258c 100644 --- a/3-networks-hub-and-spoke/envs/production/main.tf +++ b/3-networks-hub-and-spoke/envs/production/main.tf @@ -74,11 +74,14 @@ module "base_env" { environment_code = local.environment_code access_context_manager_policy_id = var.access_context_manager_policy_id perimeter_additional_members = var.perimeter_additional_members + perimeter_additional_members_dry_run = var.perimeter_additional_members_dry_run default_region1 = local.default_region1 default_region2 = local.default_region2 domain = var.domain ingress_policies = var.ingress_policies + ingress_policies_dry_run = var.ingress_policies_dry_run egress_policies = var.egress_policies + egress_policies_dry_run = var.egress_policies_dry_run 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 index 3adb70885..3e4d2a97e 100644 --- a/3-networks-hub-and-spoke/envs/production/outputs.tf +++ b/3-networks-hub-and-spoke/envs/production/outputs.tf @@ -58,11 +58,21 @@ output "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 +output "access_level_name" { + value = module.base_env.access_level_name description = "Access context manager access level name" } +output "access_level_name_dry_run" { + value = module.base_env.access_level_name_dry_run + description = "Access context manager access level name for the dry-run perimeter" +} + +output "enforce_vpcsc" { + value = module.base_env.enforce_vpcsc + description = "Enable the enforced mode for VPC Service Controls. It is not recommended to enable VPC-SC on the first run deploying your foundation. Review [best practices for enabling VPC Service Controls](https://cloud.google.com/vpc-service-controls/docs/enable), then only enforce the perimeter after you have analyzed the access patterns in your dry-run perimeter and created the necessary exceptions for your use cases." +} + output "restricted_service_perimeter_name" { value = module.base_env.restricted_service_perimeter_name description = "Access context manager service perimeter name" diff --git a/3-networks-hub-and-spoke/envs/production/variables.tf b/3-networks-hub-and-spoke/envs/production/variables.tf index eacfebf82..cf3061211 100644 --- a/3-networks-hub-and-spoke/envs/production/variables.tf +++ b/3-networks-hub-and-spoke/envs/production/variables.tf @@ -24,11 +24,6 @@ variable "access_context_manager_policy_id" { 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 "perimeter_additional_members" { - description = "The list of additional members to be added to the perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`." - type = list(string) -} - variable "domain" { type = string description = "The DNS name of peering managed zone, for instance 'example.com.'. Must end with a period." @@ -41,7 +36,16 @@ variable "enable_hub_and_spoke_transitivity" { } variable "egress_policies" { - description = "A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference), each list object has a `from` and `to` value that describes egress_from and egress_to.\n\nExample: `[{ from={ identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" + description = "A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference) to use in an enforced perimeter. Each list object has a `from` and `to` value that describes egress_from and egress_to.\n\nExample: `[{ from={ identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" + type = list(object({ + from = any + to = any + })) + default = [] +} + +variable "egress_policies_dry_run" { + description = "A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference) to use in a dry-run perimeter. Each list object has a `from` and `to` value that describes egress_from and egress_to.\n\nExample: `[{ from={ identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" type = list(object({ from = any to = any @@ -50,7 +54,7 @@ variable "egress_policies" { } variable "ingress_policies" { - description = "A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference), each list object has a `from` and `to` value that describes ingress_from and ingress_to.\n\nExample: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" + description = "A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference) to use in an enforced perimeter. Each list object has a `from` and `to` value that describes ingress_from and ingress_to.\n\nExample: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" type = list(object({ from = any to = any @@ -58,6 +62,27 @@ variable "ingress_policies" { default = [] } +variable "ingress_policies_dry_run" { + description = "A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference) to use in a dry-run perimeter. Each list object has a `from` and `to` value that describes ingress_from and ingress_to.\n\nExample: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" + type = list(object({ + from = any + to = any + })) + default = [] +} + +variable "perimeter_additional_members" { + description = "The list of additional members to be added to the enforced perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`." + type = list(string) + default = [] +} + +variable "perimeter_additional_members_dry_run" { + description = "The list of additional members to be added to the dry-run perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`." + type = list(string) + default = [] +} + variable "tfc_org_name" { description = "Name of the TFC organization" type = string diff --git a/3-networks-hub-and-spoke/envs/shared/net-hubs.tf b/3-networks-hub-and-spoke/envs/shared/net-hubs.tf index 36ffb84d9..ec6a99e84 100644 --- a/3-networks-hub-and-spoke/envs/shared/net-hubs.tf +++ b/3-networks-hub-and-spoke/envs/shared/net-hubs.tf @@ -163,7 +163,8 @@ locals { "workstations.googleapis.com", ] - restricted_services = length(var.custom_restricted_services) != 0 ? var.custom_restricted_services : local.supported_restricted_service + restricted_services = length(var.custom_restricted_services) != 0 ? var.custom_restricted_services : local.supported_restricted_service + restricted_services_dry_run = length(var.custom_restricted_services) != 0 ? var.custom_restricted_services : local.supported_restricted_service } /****************************************** @@ -256,11 +257,17 @@ module "restricted_shared_vpc" { private_service_connect_ip = "10.17.0.5" access_context_manager_policy_id = var.access_context_manager_policy_id restricted_services = local.restricted_services + restricted_services_dry_run = local.restricted_services_dry_run members = distinct(concat([ "serviceAccount:${local.networks_service_account}", "serviceAccount:${local.projects_service_account}", "serviceAccount:${local.organization_service_account}", ], var.perimeter_additional_members)) + members_dry_run = distinct(concat([ + "serviceAccount:${local.networks_service_account}", + "serviceAccount:${local.projects_service_account}", + "serviceAccount:${local.organization_service_account}", + ], var.perimeter_additional_members)) bgp_asn_subnet = local.bgp_asn_number default_region1 = local.default_region1 default_region2 = local.default_region2 diff --git a/3-networks-hub-and-spoke/modules/base_env/README.md b/3-networks-hub-and-spoke/modules/base_env/README.md index 2504080cd..a4f1f2ba6 100644 --- a/3-networks-hub-and-spoke/modules/base_env/README.md +++ b/3-networks-hub-and-spoke/modules/base_env/README.md @@ -10,17 +10,22 @@ | base\_subnet\_proxy\_ranges | The base proxy-only 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 | | base\_vpc\_flow\_logs | aggregation\_interval: Toggles the aggregation interval for collecting flow logs. Increasing the interval time will reduce the amount of generated flow logs for long lasting connections. Possible values are: INTERVAL\_5\_SEC, INTERVAL\_30\_SEC, INTERVAL\_1\_MIN, INTERVAL\_5\_MIN, INTERVAL\_10\_MIN, INTERVAL\_15\_MIN.
flow\_sampling: Set the sampling rate of VPC flow logs within the subnetwork where 1.0 means all collected logs are reported and 0.0 means no logs are reported. The value of the field must be in [0, 1].
metadata: Configures whether metadata fields should be added to the reported VPC flow logs. Possible values are: EXCLUDE\_ALL\_METADATA, INCLUDE\_ALL\_METADATA, CUSTOM\_METADATA.
metadata\_fields: ist of metadata fields that should be added to reported logs. Can only be specified if VPC flow logs for this subnetwork is enabled and "metadata" is set to CUSTOM\_METADATA.
filter\_expr: Export filter used to define which VPC flow logs should be logged, as as CEL expression. See https://cloud.google.com/vpc/docs/flow-logs#filtering for details on how to format this field. |
object({
aggregation_interval = optional(string, "INTERVAL_5_SEC")
flow_sampling = optional(string, "0.5")
metadata = optional(string, "INCLUDE_ALL_METADATA")
metadata_fields = optional(list(string), [])
filter_expr = optional(string, "true")
})
| `{}` | no | -| custom\_restricted\_services | List of custom services to be protected by the VPC-SC perimeter. If empty, all supported services (https://cloud.google.com/vpc-service-controls/docs/supported-products) will be protected. | `list(string)` | `[]` | no | +| custom\_restricted\_services | List of custom services to be protected by the enforced VPC-SC perimeter. If empty, all supported services (https://cloud.google.com/vpc-service-controls/docs/supported-products) will be protected. | `list(string)` | `[]` | no | +| custom\_restricted\_services\_dry\_run | List of custom services to be protected by the dry-run VPC-SC perimeter. If empty, all supported services (https://cloud.google.com/vpc-service-controls/docs/supported-products) will be protected. | `list(string)` | `[]` | no | | 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 | -| egress\_policies | A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference), each list object has a `from` and `to` value that describes egress\_from and egress\_to.

Example: `[{ from={ identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | +| egress\_policies | A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference) to use in an enforced perimeter. Each list object has a `from` and `to` value that describes egress\_from and egress\_to.

Example: `[{ from={ identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | +| egress\_policies\_dry\_run | A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference) to use in a dry-run perimeter. Each list object has a `from` and `to` value that describes egress\_from and egress\_to.

Example: `[{ from={ identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | +| enable\_dedicated\_interconnect | Enable Dedicated Interconnect in the environment. | `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 | | environment\_code | A short form of the folder level resources (environment) within the Google Cloud organization (ex. d). | `string` | n/a | yes | -| ingress\_policies | A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference), each list object has a `from` and `to` value that describes ingress\_from and ingress\_to.

Example: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | -| perimeter\_additional\_members | The list of additional members to be added to the perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`. | `list(string)` | n/a | yes | +| ingress\_policies | A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference) to use in an enforced perimeter. Each list object has a `from` and `to` value that describes ingress\_from and ingress\_to.

Example: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | +| ingress\_policies\_dry\_run | A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference) to use in a dry-run perimeter. Each list object has a `from` and `to` value that describes ingress\_from and ingress\_to.

Example: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | +| perimeter\_additional\_members | The list of additional members to be added to the enforced perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`. | `list(string)` | `[]` | no | +| perimeter\_additional\_members\_dry\_run | The list of additional members to be added to the dry-run perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`. | `list(string)` | `[]` | no | | remote\_state\_bucket | Backend bucket to load Terraform Remote State Data from previous steps. | `string` | n/a | yes | | 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\_private\_service\_connect\_ip | The base subnet internal IP to be used as the private service connect endpoint in the Restricted Shared VPC | `string` | n/a | yes | @@ -34,6 +39,8 @@ | Name | Description | |------|-------------| +| access\_level\_name | Access context manager access level name for the enforced perimeter | +| access\_level\_name\_dry\_run | Access context manager access level name for the dry-run perimeter | | 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 | @@ -41,11 +48,11 @@ | 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 | +| enforce\_vpcsc | Enable the enforced mode for VPC Service Controls. It is not recommended to enable VPC-SC on the first run deploying your foundation. Review [best practices for enabling VPC Service Controls](https://cloud.google.com/vpc-service-controls/docs/enable), then only enforce the perimeter after you have analyzed the access patterns in your dry-run perimeter and created the necessary exceptions for your use cases. | | 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\_service\_perimeter\_name | Access context manager service perimeter name for the enforced perimeter | | 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 | diff --git a/3-networks-hub-and-spoke/modules/base_env/main.tf b/3-networks-hub-and-spoke/modules/base_env/main.tf index 640b36d03..354ce2957 100644 --- a/3-networks-hub-and-spoke/modules/base_env/main.tf +++ b/3-networks-hub-and-spoke/modules/base_env/main.tf @@ -154,7 +154,8 @@ locals { "workstations.googleapis.com", ] - restricted_services = length(var.custom_restricted_services) != 0 ? var.custom_restricted_services : local.supported_restricted_service + restricted_services = length(var.custom_restricted_services) != 0 ? var.custom_restricted_services : local.supported_restricted_service + restricted_services_dry_run = length(var.custom_restricted_services_dry_run) != 0 ? var.custom_restricted_services : local.supported_restricted_service } /****************************************** @@ -171,11 +172,17 @@ module "restricted_shared_vpc" { environment_code = var.environment_code access_context_manager_policy_id = var.access_context_manager_policy_id restricted_services = local.restricted_services + restricted_services_dry_run = local.restricted_services_dry_run members = distinct(concat([ "serviceAccount:${local.networks_service_account}", "serviceAccount:${local.projects_service_account}", "serviceAccount:${local.organization_service_account}", ], var.perimeter_additional_members)) + members_dry_run = distinct(concat([ + "serviceAccount:${local.networks_service_account}", + "serviceAccount:${local.projects_service_account}", + "serviceAccount:${local.organization_service_account}", + ], var.perimeter_additional_members)) private_service_cidr = var.restricted_private_service_cidr private_service_connect_ip = var.restricted_private_service_connect_ip ingress_policies = var.ingress_policies diff --git a/3-networks-hub-and-spoke/modules/base_env/outputs.tf b/3-networks-hub-and-spoke/modules/base_env/outputs.tf index 88acc19f8..b51cda651 100644 --- a/3-networks-hub-and-spoke/modules/base_env/outputs.tf +++ b/3-networks-hub-and-spoke/modules/base_env/outputs.tf @@ -53,16 +53,28 @@ output "restricted_subnets_secondary_ranges" { description = "The secondary ranges associated with these subnets" } -output "restricted_access_level_name" { +output "access_level_name" { value = module.restricted_shared_vpc.access_level_name - description = "Access context manager access level name" + description = "Access context manager access level name for the enforced perimeter" +} + +output "access_level_name_dry_run" { + value = module.restricted_shared_vpc.access_level_name_dry_run + description = "Access context manager access level name for the dry-run perimeter" +} + +output "enforce_vpcsc" { + value = module.restricted_shared_vpc.enforce_vpcsc + description = "Enable the enforced mode for VPC Service Controls. It is not recommended to enable VPC-SC on the first run deploying your foundation. Review [best practices for enabling VPC Service Controls](https://cloud.google.com/vpc-service-controls/docs/enable), then only enforce the perimeter after you have analyzed the access patterns in your dry-run perimeter and created the necessary exceptions for your use cases." } output "restricted_service_perimeter_name" { value = module.restricted_shared_vpc.service_perimeter_name - description = "Access context manager service perimeter name" + description = "Access context manager service perimeter name for the enforced perimeter" } + + /****************************************** Private Outputs *****************************************/ diff --git a/3-networks-hub-and-spoke/modules/base_env/variables.tf b/3-networks-hub-and-spoke/modules/base_env/variables.tf index 71aee8d06..bdbf39987 100644 --- a/3-networks-hub-and-spoke/modules/base_env/variables.tf +++ b/3-networks-hub-and-spoke/modules/base_env/variables.tf @@ -49,6 +49,12 @@ variable "domain" { description = "The DNS name of peering managed zone, for instance 'example.com.'. Must end with a period." } +variable "enable_dedicated_interconnect" { + description = "Enable Dedicated Interconnect in the environment." + type = bool + default = false +} + variable "enable_partner_interconnect" { description = "Enable Partner Interconnect in the environment." type = bool @@ -148,7 +154,16 @@ EOT } variable "egress_policies" { - description = "A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference), each list object has a `from` and `to` value that describes egress_from and egress_to.\n\nExample: `[{ from={ identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" + description = "A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference) to use in an enforced perimeter. Each list object has a `from` and `to` value that describes egress_from and egress_to.\n\nExample: `[{ from={ identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" + type = list(object({ + from = any + to = any + })) + default = [] +} + +variable "egress_policies_dry_run" { + description = "A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference) to use in a dry-run perimeter. Each list object has a `from` and `to` value that describes egress_from and egress_to.\n\nExample: `[{ from={ identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" type = list(object({ from = any to = any @@ -157,7 +172,16 @@ variable "egress_policies" { } variable "ingress_policies" { - description = "A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference), each list object has a `from` and `to` value that describes ingress_from and ingress_to.\n\nExample: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" + description = "A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference) to use in an enforced perimeter. Each list object has a `from` and `to` value that describes ingress_from and ingress_to.\n\nExample: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" + type = list(object({ + from = any + to = any + })) + default = [] +} + +variable "ingress_policies_dry_run" { + description = "A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference) to use in a dry-run perimeter. Each list object has a `from` and `to` value that describes ingress_from and ingress_to.\n\nExample: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" type = list(object({ from = any to = any @@ -166,12 +190,26 @@ variable "ingress_policies" { } variable "perimeter_additional_members" { - description = "The list of additional members to be added to the perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`." + description = "The list of additional members to be added to the enforced perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`." + type = list(string) + default = [] +} + +variable "perimeter_additional_members_dry_run" { + description = "The list of additional members to be added to the dry-run perimeter access level members list. To be able to see the resources protected by the VPC Service Controls in the restricted perimeter, add your user in this list. Entries must be in the standard GCP form: `user:email@example.com` or `serviceAccount:my-service-account@example.com`." type = list(string) + default = [] } + variable "custom_restricted_services" { - description = "List of custom services to be protected by the VPC-SC perimeter. If empty, all supported services (https://cloud.google.com/vpc-service-controls/docs/supported-products) will be protected." + description = "List of custom services to be protected by the enforced VPC-SC perimeter. If empty, all supported services (https://cloud.google.com/vpc-service-controls/docs/supported-products) will be protected." + type = list(string) + default = [] +} + +variable "custom_restricted_services_dry_run" { + description = "List of custom services to be protected by the dry-run VPC-SC perimeter. If empty, all supported services (https://cloud.google.com/vpc-service-controls/docs/supported-products) will be protected." type = list(string) default = [] } 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 index 41edab23c..03b4b29e9 100644 --- a/3-networks-hub-and-spoke/modules/restricted_shared_vpc/README.md +++ b/3-networks-hub-and-spoke/modules/restricted_shared_vpc/README.md @@ -11,13 +11,17 @@ | dns\_enable\_logging | Toggle DNS logging for VPC DNS. | `bool` | `true` | no | | dns\_hub\_project\_id | The DNS hub project ID | `string` | n/a | yes | | domain | The DNS name of peering managed zone, for instance 'example.com.' | `string` | n/a | yes | -| egress\_policies | A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference), each list object has a `from` and `to` value that describes egress\_from and egress\_to.

Example: `[{ from={ identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | +| egress\_policies | A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference) to use in an enforced perimeter. Each list object has a `from` and `to` value that describes egress\_from and egress\_to.

Example: `[{ from={ identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | +| egress\_policies\_dry\_run | A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference) to use in a dry-run perimeter. Each list object has a `from` and `to` value that describes egress\_from and egress\_to.

Example: `[{ from={ identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | | enable\_all\_vpc\_internal\_traffic | Enable firewall policy rule to allow internal traffic (ingress and egress). | `bool` | `false` | no | | enable\_transitivity\_traffic | Enable a firewall policy rule to allow traffic between Hub and Spokes (ingress only). | `bool` | `true` | no | +| enforce\_vpcsc | Enable the enforced mode for VPC Service Controls. It is not recommended to enable VPC-SC on the first run deploying your foundation. Review [best practices for enabling VPC Service Controls](https://cloud.google.com/vpc-service-controls/docs/enable), then only enforce the perimeter after you have analyzed the access patterns in your dry-run perimeter and created the necessary exceptions for your use cases. | `bool` | `false` | no | | 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 | -| ingress\_policies | A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference), each list object has a `from` and `to` value that describes ingress\_from and ingress\_to.

Example: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | 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 | +| ingress\_policies | A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference) to use in an enforced perimeter. Each list object has a `from` and `to` value that describes ingress\_from and ingress\_to.

Example: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | +| ingress\_policies\_dry\_run | A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference) to use in a dry-run perimeter. Each list object has a `from` and `to` value that describes ingress\_from and ingress\_to.

Example: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
from = any
to = any
}))
| `[]` | no | +| members | An allowed list of members (users, service accounts) for an access level in an enforced perimeter. 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 | +| members\_dry\_run | An allowed list of members (users, service accounts) for an access level in a dry run perimeter. 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 | @@ -29,7 +33,8 @@ | project\_number | Project number for Restricted Shared VPC. It is the project INSIDE the regular service perimeter. | `number` | n/a | yes | | restricted\_net\_hub\_project\_id | The restricted net hub project ID | `string` | `""` | no | | restricted\_net\_hub\_project\_number | The restricted net hub project number | `string` | `""` | no | -| restricted\_services | List of services to restrict. | `list(string)` | n/a | yes | +| restricted\_services | List of services to restrict in an enforced perimeter. | `list(string)` | n/a | yes | +| restricted\_services\_dry\_run | List of services to restrict in a dry-run perimeter. | `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(object({
subnet_name = string
subnet_ip = string
subnet_region = string
subnet_private_access = optional(string, "false")
subnet_private_ipv6_access = optional(string)
subnet_flow_logs = optional(string, "false")
subnet_flow_logs_interval = optional(string, "INTERVAL_5_SEC")
subnet_flow_logs_sampling = optional(string, "0.5")
subnet_flow_logs_metadata = optional(string, "INCLUDE_ALL_METADATA")
subnet_flow_logs_filter = optional(string, "true")
subnet_flow_logs_metadata_fields = optional(list(string), [])
description = optional(string)
purpose = optional(string)
role = optional(string)
stack_type = optional(string)
ipv6_access_type = optional(string)
}))
| `[]` | no | | windows\_activation\_enabled | Enable Windows license activation for Windows workloads. | `bool` | `false` | no | @@ -38,7 +43,9 @@ | Name | Description | |------|-------------| -| access\_level\_name | Access context manager access level name | +| access\_level\_name | Access context manager access level name for the enforced perimeter | +| access\_level\_name\_dry\_run | Access context manager access level name for the dry-run perimeter | +| enforce\_vpcsc | Enable the enforced mode for VPC Service Controls. It is not recommended to enable VPC-SC on the first run deploying your foundation. Review [best practices for enabling VPC Service Controls](https://cloud.google.com/vpc-service-controls/docs/enable), then only enforce the perimeter after you have analyzed the access patterns in your dry-run perimeter and created the necessary exceptions for your use cases. | | firewall\_policy | Policy created for firewall policy rules. | | network\_name | The name of the VPC being created | | network\_self\_link | The URI of the VPC being created | @@ -46,7 +53,7 @@ | region1\_router2 | Router 2 for Region 1 | | region2\_router1 | Router 1 for Region 2 | | region2\_router2 | Router 2 for Region 2 | -| service\_perimeter\_name | Access context manager service perimeter name | +| service\_perimeter\_name | Access context manager service perimeter name for the enforced perimeter | | 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 | 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 index 989c1b5b5..40ac84c4c 100644 --- a/3-networks-hub-and-spoke/modules/restricted_shared_vpc/outputs.tf +++ b/3-networks-hub-and-spoke/modules/restricted_shared_vpc/outputs.tf @@ -49,16 +49,6 @@ output "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 " -} - output "region1_router1" { value = try(module.region1_router1[0], null) description = "Router 1 for Region 1" @@ -83,3 +73,23 @@ output "firewall_policy" { value = module.firewall_rules.fw_policy[0].name description = "Policy created for firewall policy rules." } + +output "access_level_name" { + value = local.access_level_name + description = "Access context manager access level name for the enforced perimeter" +} + +output "access_level_name_dry_run" { + value = local.access_level_name_dry_run + description = "Access context manager access level name for the dry-run perimeter" +} + +output "enforce_vpcsc" { + value = var.enforce_vpcsc + description = "Enable the enforced mode for VPC Service Controls. It is not recommended to enable VPC-SC on the first run deploying your foundation. Review [best practices for enabling VPC Service Controls](https://cloud.google.com/vpc-service-controls/docs/enable), then only enforce the perimeter after you have analyzed the access patterns in your dry-run perimeter and created the necessary exceptions for your use cases." +} + +output "service_perimeter_name" { + value = local.perimeter_name + description = "Access context manager service perimeter name for the enforced perimeter" +} diff --git a/3-networks-hub-and-spoke/modules/restricted_shared_vpc/service_control.tf b/3-networks-hub-and-spoke/modules/restricted_shared_vpc/service_control.tf index 31299fb2d..be8c42270 100644 --- a/3-networks-hub-and-spoke/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 2022 Google LLC + * 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. @@ -15,17 +15,18 @@ */ 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}" + prefix = "${var.environment_code}_shared_restricted" + access_level_name = "alp_${local.prefix}_members_${random_id.random_access_level_suffix.hex}" + access_level_name_dry_run = "alp_${local.prefix}_members_dry_run_${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" { +module "access_level" { source = "terraform-google-modules/vpc-service-controls/google//modules/access_level" version = "~> 6.0" @@ -35,6 +36,16 @@ module "access_level_members" { members = var.members } +module "access_level_dry_run" { + source = "terraform-google-modules/vpc-service-controls/google//modules/access_level" + version = "~> 5.0" + + description = "${local.prefix} Access Level for testing with a dry run perimeter" + policy = var.access_context_manager_policy_id + name = local.access_level_name_dry_run + members = var.members_dry_run +} + resource "time_sleep" "wait_vpc_sc_propagation" { create_duration = "60s" destroy_duration = "60s" @@ -68,14 +79,22 @@ module "regular_service_perimeter" { policy = var.access_context_manager_policy_id perimeter_name = local.perimeter_name description = "Default VPC Service Controls perimeter" - resources = [var.project_number] - access_levels = [module.access_level_members.name] - restricted_services = var.restricted_services - vpc_accessible_services = ["RESTRICTED-SERVICES"] + # configurations for a perimeter in enforced mode. + resources = var.enforce_vpcsc ? [var.project_number] : [] + access_levels = var.enforce_vpcsc ? [module.access_level.name] : [] + restricted_services = var.enforce_vpcsc ? var.restricted_services : [] + vpc_accessible_services = var.enforce_vpcsc ? ["RESTRICTED-SERVICES"] : [] + ingress_policies = var.enforce_vpcsc ? var.ingress_policies : [] + egress_policies = var.enforce_vpcsc ? var.egress_policies : [] - ingress_policies = var.ingress_policies - egress_policies = var.egress_policies + # configurations for a perimeter in dry run mode. + resources_dry_run = [var.project_number] + access_levels_dry_run = [module.access_level_dry_run.name] + restricted_services_dry_run = var.restricted_services_dry_run + vpc_accessible_services_dry_run = ["RESTRICTED-SERVICES"] + ingress_policies_dry_run = var.ingress_policies_dry_run + egress_policies_dry_run = var.egress_policies_dry_run depends_on = [ time_sleep.wait_vpc_sc_propagation @@ -90,8 +109,10 @@ resource "google_access_context_manager_service_perimeter" "bridge_to_network_hu name = "accessPolicies/${var.access_context_manager_policy_id}/servicePerimeters/${local.bridge_name}" title = local.bridge_name + use_explicit_dry_run_spec = var.enforce_vpcsc ? false : true + status { - resources = formatlist("projects/%s", [var.project_number, var.restricted_net_hub_project_number]) + resources = var.enforce_vpcsc ? formatlist("projects/%s", [var.project_number, var.restricted_net_hub_project_number]) : [] } depends_on = [module.regular_service_perimeter] diff --git a/3-networks-hub-and-spoke/modules/restricted_shared_vpc/variables.tf b/3-networks-hub-and-spoke/modules/restricted_shared_vpc/variables.tf index 2bd9ecb3e..853e47bdc 100644 --- a/3-networks-hub-and-spoke/modules/restricted_shared_vpc/variables.tf +++ b/3-networks-hub-and-spoke/modules/restricted_shared_vpc/variables.tf @@ -167,12 +167,22 @@ variable "windows_activation_enabled" { 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}" + description = "An allowed list of members (users, service accounts) for an access level in an enforced perimeter. 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 "members_dry_run" { + type = list(string) + description = "An allowed list of members (users, service accounts) for an access level in a dry run perimeter. 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." + description = "List of services to restrict in an enforced perimeter." +} + +variable "restricted_services_dry_run" { + type = list(string) + description = "List of services to restrict in a dry-run perimeter." } variable "enable_all_vpc_internal_traffic" { @@ -187,8 +197,23 @@ variable "enable_transitivity_traffic" { default = true } +variable "enforce_vpcsc" { + description = "Enable the enforced mode for VPC Service Controls. It is not recommended to enable VPC-SC on the first run deploying your foundation. Review [best practices for enabling VPC Service Controls](https://cloud.google.com/vpc-service-controls/docs/enable), then only enforce the perimeter after you have analyzed the access patterns in your dry-run perimeter and created the necessary exceptions for your use cases." + type = bool + default = false +} + variable "egress_policies" { - description = "A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference), each list object has a `from` and `to` value that describes egress_from and egress_to.\n\nExample: `[{ from={ identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" + description = "A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference) to use in an enforced perimeter. Each list object has a `from` and `to` value that describes egress_from and egress_to.\n\nExample: `[{ from={ identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" + type = list(object({ + from = any + to = any + })) + default = [] +} + +variable "egress_policies_dry_run" { + description = "A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference) to use in a dry-run perimeter. Each list object has a `from` and `to` value that describes egress_from and egress_to.\n\nExample: `[{ from={ identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" type = list(object({ from = any to = any @@ -197,7 +222,16 @@ variable "egress_policies" { } variable "ingress_policies" { - description = "A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference), each list object has a `from` and `to` value that describes ingress_from and ingress_to.\n\nExample: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" + description = "A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference) to use in an enforced perimeter. Each list object has a `from` and `to` value that describes ingress_from and ingress_to.\n\nExample: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" + type = list(object({ + from = any + to = any + })) + default = [] +} + +variable "ingress_policies_dry_run" { + description = "A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference) to use in a dry-run perimeter. Each list object has a `from` and `to` value that describes ingress_from and ingress_to.\n\nExample: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type=\"ID_TYPE\" }, to={ resources=[], operations={ \"SRV_NAME\"={ OP_TYPE=[] }}}}]`\n\nValid Values:\n`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`\n`SRV_NAME` = \"`*`\" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)\n`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions)" type = list(object({ from = any to = any diff --git a/4-projects/modules/base_env/README.md b/4-projects/modules/base_env/README.md index 9c4897ef3..70d08bc55 100644 --- a/4-projects/modules/base_env/README.md +++ b/4-projects/modules/base_env/README.md @@ -25,6 +25,8 @@ | subnet\_region | Region which the peered subnet will be created. If "peering\_iap\_fw\_rules\_enabled" is true, this field should not be null. | `string` | `null` | no | | tfc\_org\_name | Name of the TFC organization | `string` | n/a | yes | | vpc\_flow\_logs | aggregation\_interval: Toggles the aggregation interval for collecting flow logs. Increasing the interval time will reduce the amount of generated flow logs for long lasting connections. Possible values are: INTERVAL\_5\_SEC, INTERVAL\_30\_SEC, INTERVAL\_1\_MIN, INTERVAL\_5\_MIN, INTERVAL\_10\_MIN, INTERVAL\_15\_MIN.
flow\_sampling: Set the sampling rate of VPC flow logs within the subnetwork where 1.0 means all collected logs are reported and 0.0 means no logs are reported. The value of the field must be in [0, 1].
metadata: Configures whether metadata fields should be added to the reported VPC flow logs. Possible values are: EXCLUDE\_ALL\_METADATA, INCLUDE\_ALL\_METADATA, CUSTOM\_METADATA.
metadata\_fields: ist of metadata fields that should be added to reported logs. Can only be specified if VPC flow logs for this subnetwork is enabled and "metadata" is set to CUSTOM\_METADATA.
filter\_expr: Export filter used to define which VPC flow logs should be logged, as as CEL expression. See https://cloud.google.com/vpc/docs/flow-logs#filtering for details on how to format this field. |
object({
aggregation_interval = optional(string, "INTERVAL_5_SEC")
flow_sampling = optional(string, "0.5")
metadata = optional(string, "INCLUDE_ALL_METADATA")
metadata_fields = optional(list(string), [])
filter_expr = optional(string, "true")
})
| `{}` | no | +| vpc\_service\_control\_attach\_dry\_run | Whether the project will be attached to a VPC Service Control Perimeter with an explicit dry run spec flag, which may use different values for the dry run perimeter compared to the ENFORCED perimeter. | `bool` | `false` | no | +| vpc\_service\_control\_attach\_enabled | Whether the project will be attached to a VPC Service Control Perimeter in ENFORCED MODE. | `bool` | `false` | no | | windows\_activation\_enabled | Enable Windows license activation for Windows workloads. | `bool` | `false` | no | ## Outputs diff --git a/4-projects/modules/base_env/example_restricted_shared_vpc_project.tf b/4-projects/modules/base_env/example_restricted_shared_vpc_project.tf index 13180b183..252d4ec70 100644 --- a/4-projects/modules/base_env/example_restricted_shared_vpc_project.tf +++ b/4-projects/modules/base_env/example_restricted_shared_vpc_project.tf @@ -29,7 +29,8 @@ module "restricted_shared_vpc_project" { activate_apis = ["accesscontextmanager.googleapis.com"] - vpc_service_control_attach_enabled = "true" + vpc_service_control_attach_enabled = local.enforce_vpcsc ? "true" : "false" + vpc_service_control_attach_dry_run = !local.enforce_vpcsc ? "true" : "false" vpc_service_control_perimeter_name = "accessPolicies/${local.access_context_manager_policy_id}/servicePerimeters/${local.perimeter_name}" vpc_service_control_sleep_duration = "60s" diff --git a/4-projects/modules/base_env/remote.tf b/4-projects/modules/base_env/remote.tf index 36a78f2d7..55942f987 100644 --- a/4-projects/modules/base_env/remote.tf +++ b/4-projects/modules/base_env/remote.tf @@ -26,6 +26,7 @@ locals { restricted_host_project_id = data.terraform_remote_state.network_env.outputs.restricted_host_project_id restricted_subnets_self_links = data.terraform_remote_state.network_env.outputs.restricted_subnets_self_links access_context_manager_policy_id = data.terraform_remote_state.network_env.outputs.access_context_manager_policy_id + enforce_vpcsc = data.terraform_remote_state.network_env.outputs.enforce_vpcsc env_folder_name = data.terraform_remote_state.environments_env.outputs.env_folder app_infra_pipeline_service_accounts = data.terraform_remote_state.business_unit_shared.outputs.terraform_service_accounts enable_cloudbuild_deploy = data.terraform_remote_state.business_unit_shared.outputs.enable_cloudbuild_deploy diff --git a/4-projects/modules/base_env/variables.tf b/4-projects/modules/base_env/variables.tf index 0c81a4110..384d35d05 100644 --- a/4-projects/modules/base_env/variables.tf +++ b/4-projects/modules/base_env/variables.tf @@ -168,3 +168,15 @@ variable "folder_prefix" { type = string default = "fldr" } + +variable "vpc_service_control_attach_enabled" { + description = "Whether the project will be attached to a VPC Service Control Perimeter in ENFORCED MODE." + type = bool + default = false +} + +variable "vpc_service_control_attach_dry_run" { + description = "Whether the project will be attached to a VPC Service Control Perimeter with an explicit dry run spec flag, which may use different values for the dry run perimeter compared to the ENFORCED perimeter." + type = bool + default = false +} diff --git a/4-projects/modules/infra_pipelines/README.md b/4-projects/modules/infra_pipelines/README.md index dd2988283..22f84a7a6 100644 --- a/4-projects/modules/infra_pipelines/README.md +++ b/4-projects/modules/infra_pipelines/README.md @@ -13,6 +13,8 @@ | private\_worker\_pool\_id | ID of the Cloud Build private worker pool. | `string` | n/a | yes | | remote\_tfstate\_bucket | Bucket with remote state data to be used by the pipeline. | `string` | n/a | yes | | terraform\_docker\_tag\_version | TAG version of the terraform docker image. | `string` | `"v1"` | no | +| vpc\_service\_control\_attach\_dry\_run | Whether the project will be attached to a VPC Service Control Perimeter with an explicit dry run spec flag, which may use different values for the dry run perimeter compared to the ENFORCED perimeter. | `bool` | `false` | no | +| vpc\_service\_control\_attach\_enabled | Whether the project will be attached to a VPC Service Control Perimeter in ENFORCED MODE. | `bool` | `false` | no | ## Outputs diff --git a/4-projects/modules/infra_pipelines/variables.tf b/4-projects/modules/infra_pipelines/variables.tf index 63492db1e..c9284d665 100644 --- a/4-projects/modules/infra_pipelines/variables.tf +++ b/4-projects/modules/infra_pipelines/variables.tf @@ -66,3 +66,16 @@ variable "bucket_prefix" { type = string default = "bkt" } + +variable "vpc_service_control_attach_enabled" { + description = "Whether the project will be attached to a VPC Service Control Perimeter in ENFORCED MODE." + type = bool + default = false +} + + +variable "vpc_service_control_attach_dry_run" { + description = "Whether the project will be attached to a VPC Service Control Perimeter with an explicit dry run spec flag, which may use different values for the dry run perimeter compared to the ENFORCED perimeter." + type = bool + default = false +} diff --git a/4-projects/modules/single_project/README.md b/4-projects/modules/single_project/README.md index 8a63319c8..b92f4b388 100644 --- a/4-projects/modules/single_project/README.md +++ b/4-projects/modules/single_project/README.md @@ -22,7 +22,8 @@ | shared\_vpc\_host\_project\_id | Shared VPC host project ID | `string` | `""` | no | | shared\_vpc\_subnets | List of the shared vpc subnets self links. | `list(string)` | `[]` | no | | vpc | The type of VPC to attach the project to. Possible options are none, base, or restricted. | `string` | `"none"` | no | -| vpc\_service\_control\_attach\_enabled | Whether the project will be attached to a VPC Service Control Perimeter | `bool` | `false` | no | +| vpc\_service\_control\_attach\_dry\_run | Whether the project will be attached to a VPC Service Control Perimeter with an explicit dry run spec flag, which may use different values for the dry run perimeter compared to the ENFORCED perimeter. | `bool` | `false` | no | +| vpc\_service\_control\_attach\_enabled | Whether the project will be attached to a VPC Service Control Perimeter in ENFORCED MODE. | `bool` | `false` | no | | vpc\_service\_control\_perimeter\_name | The name of a VPC Service Control Perimeter to add the created project to | `string` | `null` | no | | vpc\_service\_control\_sleep\_duration | The duration to sleep in seconds before adding the project to a shared VPC after the project is added to the VPC Service Control Perimeter | `string` | `"5s"` | no | diff --git a/4-projects/modules/single_project/main.tf b/4-projects/modules/single_project/main.tf index 99873a9bf..529eb24a9 100644 --- a/4-projects/modules/single_project/main.tf +++ b/4-projects/modules/single_project/main.tf @@ -60,6 +60,7 @@ module "project" { shared_vpc_subnets = var.shared_vpc_subnets # Optional: To enable subnetting, replace to "module.networking_project.subnetwork_self_link" vpc_service_control_attach_enabled = var.vpc_service_control_attach_enabled + vpc_service_control_attach_dry_run = var.vpc_service_control_attach_dry_run vpc_service_control_perimeter_name = var.vpc_service_control_perimeter_name vpc_service_control_sleep_duration = var.vpc_service_control_sleep_duration diff --git a/4-projects/modules/single_project/variables.tf b/4-projects/modules/single_project/variables.tf index 72babdcd4..429f6d08f 100644 --- a/4-projects/modules/single_project/variables.tf +++ b/4-projects/modules/single_project/variables.tf @@ -96,7 +96,14 @@ variable "shared_vpc_subnets" { } variable "vpc_service_control_attach_enabled" { - description = "Whether the project will be attached to a VPC Service Control Perimeter" + description = "Whether the project will be attached to a VPC Service Control Perimeter in ENFORCED MODE." + type = bool + default = false +} + + +variable "vpc_service_control_attach_dry_run" { + description = "Whether the project will be attached to a VPC Service Control Perimeter with an explicit dry run spec flag, which may use different values for the dry run perimeter compared to the ENFORCED perimeter." type = bool default = false } diff --git a/test/integration/networks/networks_test.go b/test/integration/networks/networks_test.go index 1963af8b8..51fd8bc7f 100644 --- a/test/integration/networks/networks_test.go +++ b/test/integration/networks/networks_test.go @@ -16,6 +16,7 @@ package networks import ( "fmt" + "strings" "testing" "time" @@ -262,8 +263,6 @@ func TestNetworks(t *testing.T) { }, } - operationService := "storage.googleapis.com" - ingressPolicies := []map[string]interface{}{ { "from": map[string]interface{}{ @@ -350,24 +349,17 @@ func TestNetworks(t *testing.T) { // networks.DefaultVerify(assert) servicePerimeterLink := fmt.Sprintf("accessPolicies/%s/servicePerimeters/%s", policyID, networks.GetStringOutput("restricted_service_perimeter_name")) - accessLevel := fmt.Sprintf("accessPolicies/%s/accessLevels/%s", policyID, networks.GetStringOutput("restricted_access_level_name")) + accessLevel := fmt.Sprintf("accessPolicies/%s/accessLevels/%s", policyID, networks.GetStringOutput("access_level_name_dry_run")) networkNames := getNetworkResourceNames(envCode, networkMode, firewallMode) - 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()) - 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 all supported services", servicePerimeterLink)) - - listIngressPolicies := servicePerimeter.Get("status.ingressPolicies").Array() - assert.Equal(len(listIngressPolicies), len(ingressPolicies), fmt.Sprintf("service perimeter %s should have the same number of input ingress policies (%d)", servicePerimeterLink, len(ingressPolicies))) - ingressOp := servicePerimeter.Get("status.ingressPolicies.0.ingressTo.operations.0") - assert.Equal(operationService, ingressOp.Get("serviceName").String(), fmt.Sprintf("ingress policy should support operations on %s", operationService)) - listEgressPolicies := servicePerimeter.Get("status.egressPolicies").Array() - assert.Equal(len(listEgressPolicies), len(egressPolicies), fmt.Sprintf("service perimeter %s should have the same number of input egress policies (%d)", servicePerimeterLink, len(egressPolicies))) - egressOp := servicePerimeter.Get("status.egressPolicies.0.egressTo.operations.0") - assert.Equal(operationService, egressOp.Get("serviceName").String(), fmt.Sprintf("egress policy should support operations on %s", operationService)) + servicePerimeter, err := gcloud.RunCmdE(t, fmt.Sprintf("access-context-manager perimeters dry-run describe %s --policy %s", servicePerimeterLink, policyID)) + assert.NoError(err) + perimeterName := networks.GetStringOutput("restricted_service_perimeter_name") + assert.True(strings.Contains(servicePerimeter, perimeterName), fmt.Sprintf("service perimeter %s should exist", perimeterName)) + assert.True(strings.Contains(servicePerimeter, accessLevel), fmt.Sprintf("service perimeter %s should have access level %s", servicePerimeterLink, accessLevel)) + for _, service := range restrictedServices { + assert.True(strings.Contains(servicePerimeter, service), fmt.Sprintf("service perimeter %s should restrict all supported services", servicePerimeterLink)) + } for _, networkType := range []string{ "base", diff --git a/test/integration/projects/projects_test.go b/test/integration/projects/projects_test.go index 1b50e507e..27cb910be 100644 --- a/test/integration/projects/projects_test.go +++ b/test/integration/projects/projects_test.go @@ -159,9 +159,9 @@ func TestProjects(t *testing.T) { assert.Subset(listApis, restrictedApisEnabled, "APIs should have been enabled") restrictedProjectNumber := projects.GetStringOutput("restricted_shared_vpc_project_number") - perimeter := gcloud.Runf(t, "access-context-manager perimeters describe %s --policy %s", perimeterName, policyID) - listResources := utils.GetResultStrSlice(perimeter.Get("status.resources").Array()) - assert.Contains(listResources, fmt.Sprintf("projects/%s", restrictedProjectNumber), "restricted project should be in the perimeter") + perimeter, err := gcloud.RunCmdE(t, fmt.Sprintf("access-context-manager perimeters dry-run describe %s --policy %s", perimeterName, policyID)) + assert.NoError(err) + assert.True(strings.Contains(perimeter, restrictedProjectNumber), fmt.Sprintf("dry-run service perimeter %s should contain project %s", perimeterName, restrictedProjectNumber)) sharedVPC := gcloud.Runf(t, "compute shared-vpc get-host-project %s --impersonate-service-account %s", projectID, terraformSA) assert.NotEmpty(sharedVPC.Map())