|
||
---|---|---|
.. | ||
README.md | ||
access-levels.tf | ||
main.tf | ||
outputs.tf | ||
service-perimeters-bridge.tf | ||
service-perimeters-regular.tf | ||
variables.tf | ||
versions.tf |
README.md
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
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
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
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
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@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
Notes
- To remove an access level, first remove the binding between perimeter and the access level in
status
and/orspec
without removing the access level itself. Once you have runterraform apply
, you'll then be able to remove the access level and runterraform apply
again.
TODO
- implement support for the
google_access_context_manager_gcp_user_access_binding
resource
Files
name | description | resources |
---|---|---|
access-levels.tf | Access level resources. | google_access_context_manager_access_level |
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({…})) |
{} |
|
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. | |
service_perimeters_bridge | Bridge service perimeter resources. | |
service_perimeters_regular | Regular service perimeter resources. |