* Add confidential compute support to google_dataproc_cluster in the dataproc module * fix parent id lookup for networking and security stages (#2744) * Add optional automated MD5 generation in net-vlan-attachment module (#2745) * Bump path-to-regexp and express in /blueprints/gke/binauthz/image (#2749) Bumps [path-to-regexp](https://github.com/pillarjs/path-to-regexp) to 0.1.12 and updates ancestor dependency [express](https://github.com/expressjs/express). These dependencies need to be updated together. Updates `path-to-regexp` from 0.1.10 to 0.1.12 - [Release notes](https://github.com/pillarjs/path-to-regexp/releases) - [Changelog](https://github.com/pillarjs/path-to-regexp/blob/master/History.md) - [Commits](https://github.com/pillarjs/path-to-regexp/compare/v0.1.10...v0.1.12) Updates `express` from 4.21.1 to 4.21.2 - [Release notes](https://github.com/expressjs/express/releases) - [Changelog](https://github.com/expressjs/express/blob/4.21.2/History.md) - [Commits](https://github.com/expressjs/express/compare/4.21.1...4.21.2) --- updated-dependencies: - dependency-name: path-to-regexp dependency-type: indirect - dependency-name: express dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Add ability to autogenerate md5 keys in net-vpn-ha (#2748) * Add ability to optionally generate MD5 secrets in VPN module * Add ability to autogenerate MD5 keys in net-vpn-ha module * restore missing output * fix test counts --------- Co-authored-by: Luca Prete <lucaprete@google.com> Co-authored-by: Ludovico Magnocavallo <ludomagno@google.com> * update changelog * Bump path-to-regexp and express (#2752) Bumps [path-to-regexp](https://github.com/pillarjs/path-to-regexp) and [express](https://github.com/expressjs/express). These dependencies needed to be updated together. Updates `path-to-regexp` from 0.1.10 to 0.1.12 - [Release notes](https://github.com/pillarjs/path-to-regexp/releases) - [Changelog](https://github.com/pillarjs/path-to-regexp/blob/master/History.md) - [Commits](https://github.com/pillarjs/path-to-regexp/compare/v0.1.10...v0.1.12) Updates `express` from 4.21.1 to 4.21.2 - [Release notes](https://github.com/expressjs/express/releases) - [Changelog](https://github.com/expressjs/express/blob/4.21.2/History.md) - [Commits](https://github.com/expressjs/express/compare/4.21.1...4.21.2) --- updated-dependencies: - dependency-name: path-to-regexp dependency-type: indirect - dependency-name: express dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * add support for routing mode to net-swp module (#2751) Co-authored-by: Julio Castillo <jccb@google.com> * remove default location in tag value - cloud-run-v2 tags.tf (#2755) The Parent resource has a default to europe-west1 when it should be for the resource block from where the cloud run actually is. Changed to use the var.region instead * Add path_template_match and path_template_rewrite support to net-lb-app-ext (required for React apps for example). * Add rest of load balancers. * Add path_template_match and path_template_rewrite support to internal load balancers * Add disk encyption key to the google_compute_instance_template - Sovereign support (#2750) * add disk encyption key to the google_compute_instance_template * add a condition to the kms_key_self_link * use dynamic variable for disk_encryption_key * remove the getpip from the repo --------- Co-authored-by: Julio Castillo <jccb@google.com> Co-authored-by: Ludovico Magnocavallo <ludomagno@google.com> * Add support for password validation policy to cloudsql module (#2740) * add support for password validation policy to cloudsql module * fix defaults * update changelog * bump provider version constraint --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: Ludovico Magnocavallo <ludomagno@google.com> Co-authored-by: Luca Prete <preteluca@gmail.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Luca Prete <lucaprete@google.com> Co-authored-by: Julio Castillo <jccb@google.com> Co-authored-by: Matthew Callinan <47421139+Mattible@users.noreply.github.com> Co-authored-by: Taneli Leppä <taneli@google.com> Co-authored-by: Wiktor Niesiobędzki <wiktorn@google.com> Co-authored-by: Kovács Dávid <david-kovacs@t-systems.com>
VPC Service Controls
This module offers a unified interface to manage VPC Service Controls Access Policy, Access Levels, and Service Perimeters.
Given the complexity of the underlying resources, the module intentionally mimics their interfaces to make it easier to map their documentation onto its variables, and reduce the internal complexity.
If you are using Application Default Credentials with Terraform and run into permissions issues, make sure to check out the recommended provider configuration in the VPC SC resources documentation.
Examples
Access policy
By default, the module is configured to use an existing policy, passed in by name in the access_policy variable:
module "test" {
source = "./fabric/modules/vpc-sc"
access_policy = "12345678"
}
# tftest modules=0 resources=0
If you need the module to create the policy for you, use the access_policy_create variable, and set access_policy to null:
module "test" {
source = "./fabric/modules/vpc-sc"
access_policy = null
access_policy_create = {
parent = "organizations/123456"
title = "vpcsc-policy"
}
}
# tftest modules=1 resources=1 inventory=access-policy.yaml
Scoped policy
If you need the module to create a scoped policy for you, specify 'scopes' of the policy in the access_policy_create variable:
module "test" {
source = "./fabric/modules/vpc-sc"
access_policy = null
access_policy_create = {
parent = "organizations/123456"
title = "vpcsc-policy"
scopes = ["folders/456789"]
}
}
# tftest modules=1 resources=1 inventory=scoped-access-policy.yaml
Access policy IAM
The usual IAM interface is also implemented here, and can be used with service accounts or user principals:
module "test" {
source = "./fabric/modules/vpc-sc"
access_policy = "12345678"
iam = {
"roles/accesscontextmanager.policyAdmin" = [
"user:foo@example.org"
]
}
}
# tftest modules=1 resources=1
Access levels
As highlighted above, the access_levels type replicates the underlying resource structure.
module "test" {
source = "./fabric/modules/vpc-sc"
access_policy = "12345678"
access_levels = {
a1 = {
conditions = [
{ members = ["user:user1@example.com"] }
]
}
a2 = {
combining_function = "OR"
conditions = [
{ regions = ["IT", "FR"] },
{ ip_subnetworks = ["101.101.101.0/24"] }
]
}
}
}
# tftest modules=1 resources=2 inventory=access-levels.yaml
Service perimeters
Bridge and regular service perimeters use two separate variables, as bridge perimeters only accept a limited number of arguments, and can leverage a much simpler interface.
The regular perimeters variable exposes all the complexity of the underlying resource, use its documentation as a reference about the possible values and configurations.
If you need to refer to access levels created by the same module in regular service perimeters, you can either use the module's outputs in the provided variables, or the key used to identify the relevant access level. The example below shows how to do this in practice.
/*
Resources for both perimeters have a lifecycle block that ignores changes to spec and status resources (projects), to allow using the additive resource google_access_context_manager_service_perimeter_resource at project creation. If this is not needed, the lifecycle blocks can be safely commented in the code.
*/
Bridge type
module "test" {
source = "./fabric/modules/vpc-sc"
access_policy = "12345678"
service_perimeters_bridge = {
b1 = {
status_resources = ["projects/111110", "projects/111111"]
}
b2 = {
spec_resources = ["projects/222220", "projects/222221"]
use_explicit_dry_run_spec = true
}
}
}
# tftest modules=1 resources=2 inventory=bridge.yaml
Regular type
module "test" {
source = "./fabric/modules/vpc-sc"
access_policy = "12345678"
access_levels = {
a1 = {
conditions = [
{ members = ["user:user1@example.com"] }
]
}
a2 = {
conditions = [
{ members = ["user:user2@example.com"] }
]
}
}
egress_policies = {
# allow writing to external GCS bucket from a specific SA
gcs-sa-foo = {
from = {
identities = [
"serviceAccount:foo@myproject.iam.gserviceaccount.com"
]
}
to = {
operations = [{
method_selectors = ["*"]
service_name = "storage.googleapis.com"
}]
resources = ["projects/123456789"]
}
}
}
ingress_policies = {
# allow management from external automation SA
sa-tf-test = {
from = {
identities = [
"serviceAccount:test-tf-0@myproject.iam.gserviceaccount.com",
"serviceAccount:test-tf-1@myproject.iam.gserviceaccount.com"
]
access_levels = ["*"]
}
to = {
operations = [{ service_name = "*" }]
resources = ["*"]
}
}
}
service_perimeters_regular = {
r1 = {
status = {
access_levels = ["a1", "a2"]
resources = ["projects/11111", "projects/111111"]
restricted_services = ["storage.googleapis.com"]
egress_policies = ["gcs-sa-foo"]
ingress_policies = ["sa-tf-test"]
vpc_accessible_services = {
allowed_services = ["storage.googleapis.com"]
enable_restriction = true
}
}
}
}
}
# tftest modules=1 resources=3 inventory=regular.yaml
Factories
This module implements support for three distinct factories, used to create and manage access levels, egress policies and ingress policies via YAML files. The YAML files syntax is a 1:1 match for the corresponding variables, and the factory data is merged at runtime with any data set in variables, which take precedence in case of key overlaps.
JSON Schema files for each factory object are available in the schemas folder, and can be used to validate input YAML data with validate-yaml or any of the available tools and libraries.
This is an example that uses all three factories. Note that the factory configuration points to folders, where each file represents one resource.
module "test" {
source = "./fabric/modules/vpc-sc"
access_policy = "12345678"
factories_config = {
access_levels = "data/access-levels"
egress_policies = "data/egress-policies"
ingress_policies = "data/ingress-policies"
}
service_perimeters_regular = {
r1 = {
status = {
access_levels = ["geo-it", "identity-user1"]
resources = ["projects/11111", "projects/111111"]
restricted_services = ["storage.googleapis.com"]
egress_policies = ["gcs-sa-foo"]
ingress_policies = ["sa-tf-test-geo", "sa-tf-test"]
vpc_accessible_services = {
allowed_services = ["storage.googleapis.com"]
enable_restriction = true
}
}
}
}
}
# tftest modules=1 resources=3 files=a1,a2,e1,i1,i2 inventory=factory.yaml
conditions:
- members:
- user:user1@example.com
# tftest-file id=a1 path=data/access-levels/identity-user1.yaml schema=access-level.schema.json
conditions:
- regions:
- IT
# tftest-file id=a2 path=data/access-levels/geo-it.yaml schema=access-level.schema.json
from:
identities:
- serviceAccount:foo@myproject.iam.gserviceaccount.com
- serviceAccount:bar@myproject.iam.gserviceaccount.com
to:
operations:
- method_selectors:
- "*"
service_name: storage.googleapis.com
resources:
- projects/123456789
# tftest-file id=e1 path=data/egress-policies/gcs-sa-foo.yaml schema=egress-policy.schema.json
from:
access_levels:
- "*"
identities:
- serviceAccount:test-tf-0@myproject.iam.gserviceaccount.com
- serviceAccount:test-tf-1@myproject.iam.gserviceaccount.com
to:
operations:
- service_name: compute.googleapis.com
method_selectors:
- ProjectsService.Get
- RegionsService.Get
resources:
- "*"
# tftest-file id=i1 path=data/ingress-policies/sa-tf-test.yaml schema=ingress-policy.schema.json
from:
access_levels:
- geo-it
identities:
- serviceAccount:test-tf@myproject.iam.gserviceaccount.com
to:
operations:
- service_name: "*"
resources:
- projects/1234567890
# tftest-file id=i2 path=data/ingress-policies/sa-tf-test-geo.yaml schema=ingress-policy.schema.json
Notes
- To remove an access level, first remove the binding between perimeter and the access level in
statusand/orspecwithout removing the access level itself. Once you have runterraform apply, you'll then be able to remove the access level and runterraform applyagain.
TODO
- implement support for the
google_access_context_manager_gcp_user_access_bindingresource
Files
| name | description | resources |
|---|---|---|
| access-levels.tf | Access level resources. | google_access_context_manager_access_level |
| factory.tf | None | |
| iam.tf | IAM bindings | google_access_context_manager_access_policy_iam_binding · google_access_context_manager_access_policy_iam_member |
| main.tf | Module-level locals and resources. | google_access_context_manager_access_policy |
| outputs.tf | Module outputs. | |
| service-perimeters-bridge.tf | Bridge service perimeter resources. | google_access_context_manager_service_perimeter |
| service-perimeters-regular.tf | Regular service perimeter resources. | google_access_context_manager_service_perimeter |
| variables.tf | Module variables. | |
| versions.tf | Version pins. |
Variables
| name | description | type | required | default |
|---|---|---|---|---|
| access_policy | Access Policy name, set to null if creating one. | string |
✓ | |
| access_levels | Access level definitions. | map(object({…})) |
{} |
|
| access_policy_create | Access Policy configuration, fill in to create. Parent is in 'organizations/123456' format, scopes are in 'folders/456789' or 'projects/project_id' format. | object({…}) |
null |
|
| egress_policies | Egress policy definitions that can be referenced in perimeters. | map(object({…})) |
{} |
|
| factories_config | Paths to folders that enable factory functionality. | object({…}) |
{} |
|
| iam | IAM bindings in {ROLE => [MEMBERS]} format. | map(list(string)) |
{} |
|
| iam_bindings | Authoritative IAM bindings in {KEY => {role = ROLE, members = [], condition = {}}}. Keys are arbitrary. | map(object({…})) |
{} |
|
| iam_bindings_additive | Individual additive IAM bindings. Keys are arbitrary. | map(object({…})) |
{} |
|
| ingress_policies | Ingress policy definitions that can be referenced in perimeters. | map(object({…})) |
{} |
|
| service_perimeters_bridge | Bridge service perimeters. | map(object({…})) |
{} |
|
| service_perimeters_regular | Regular service perimeters. | map(object({…})) |
{} |
Outputs
| name | description | sensitive |
|---|---|---|
| access_level_names | Access level resources. | |
| access_levels | Access level resources. | |
| access_policy | Access policy resource, if autocreated. | |
| access_policy_name | Access policy name. | |
| id | Fully qualified access policy id. | |
| service_perimeters_bridge | Bridge service perimeter resources. | |
| service_perimeters_regular | Regular service perimeter resources. |
Tests
module "test" {
source = "./fabric/modules/vpc-sc"
access_policy = "12345678"
factories_config = {
access_levels = "data/access-levels"
egress_policies = "data/egress-policies"
ingress_policies = "data/ingress-policies"
}
ingress_policies = {
variable-policy = {
from = {
identities = [
"serviceAccount:sa-0@myproject.iam.gserviceaccount.com"
]
access_levels = ["*"]
}
to = {
operations = [{ service_name = "*" }]
resources = ["*"]
}
}
}
service_perimeters_regular = {
default = {
status = {
access_levels = ["geo-it"]
resources = ["projects/11111"]
egress_policies = ["variable-policy", "factory-egress-policy"]
ingress_policies = ["variable-policy", "factory-ingress-policy"]
}
}
}
}
# tftest modules=1 resources=2 files=t1a1,t1i1,t1e1
conditions:
- regions:
- IT
# tftest-file id=t1a1 path=data/access-levels/geo-it.yaml schema=access-level.schema.json
from:
access_levels:
- geo-it
identity_type: ANY_IDENTITY
to:
operations:
- service_name: "*"
resources:
- projects/1234567890
# tftest-file id=t1i1 path=data/ingress-policies/factory-ingress-policy.yaml schema=ingress-policy.schema.json
from:
identity_type: ANY_IDENTITY
to:
operations:
- service_name: "*"
resources:
- "*"
# tftest-file id=t1e1 path=data/egress-policies/factory-egress-policy.yaml schema=egress-policy.schema.json