cloud-foundation-fabric/modules/vpc-sc
Ludovico Magnocavallo 682041b369 add versions to vpc-sc module 2022-01-05 08:55:05 +01:00
..
README.md disable device policy support in vpc-sc module 2022-01-04 16:22:15 +01:00
access_levels.tf disable device policy support in vpc-sc module 2022-01-04 16:22:15 +01:00
main.tf Copyright bump (#410) 2022-01-01 15:52:31 +01:00
outputs.tf Copyright bump (#410) 2022-01-01 15:52:31 +01:00
service_perimeters_bridge.tf depend bridge from regular perimeters in vpc sc module 2022-01-05 03:14:30 +01:00
service_perimeters_regular.tf fix ingress policies in vpc sc module 2022-01-04 16:01:03 +01:00
variables.tf disable device policy support in vpc-sc module 2022-01-04 16:22:15 +01:00
versions.tf add versions to vpc-sc module 2022-01-05 08:55:05 +01:00

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. The tradeoff is some verbosity, and a very complex type for the service_perimeters_regular variable (while optional type attributes are still an experiment).

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        = "./modules/vpc-sc"
  access_policy = "accessPolicies/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        = "./modules/vpc-sc"
  access_policy = null
  access_policy_create = {
    parent = "organizations/123456"
    title  = "vpcsc-policy"
  }
}
# tftest:modules=1:resources=1

Access levels

As highlighted above, the access_levels type replicates the underlying resource structure.

module "test" {
  source        = "./modules/vpc-sc"
  access_policy = "accessPolicies/12345678"
  access_levels = {
    a1 = {
      combining_function = null
      conditions = [{
        members = ["user:user1@example.com"], ip_subnetworks = null,
        negate = null, regions = null,  required_access_levels = null
      }]
    }
    a2 = {
      combining_function = "OR"
      conditions = [{
        regions       = ["IT", "FR"], ip_subnetworks = null,
        members = null, negate = null, required_access_levels = null
      },{
        ip_subnetworks = ["101.101.101.0/24"], members = null,
        negate = null, regions = null, required_access_levels = null
      }]
    }
  }
}
# 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        = "./modules/vpc-sc"
  access_policy = "accessPolicies/12345678"
  service_perimeters_bridge = {
    b1 = {
      status_resources          = ["projects/111110", "projects/111111"]
      spec_resources            = null
      use_explicit_dry_run_spec = false
    }
    b2 = {
      status_resources          = null
      spec_resources            = ["projects/222220", "projects/222221"]
      use_explicit_dry_run_spec = true
    }
  }
}
# tftest:modules=1:resources=2

Regular type

module "test" {
  source        = "./modules/vpc-sc"
  access_policy = "accessPolicies/12345678"
  access_levels = {
    a1 = {
      combining_function = null
      conditions = [{
        members       = ["user:user1@example.com"], ip_subnetworks = null,
        negate = null, regions = null, required_access_levels = null
      }]
    }
    a2 = {
      combining_function = null
      conditions = [{
        members       = ["user:user2@example.com"], ip_subnetworks = null,
        negate = null, regions       = null, required_access_levels = null
      }]
    }
  }
  service_perimeters_regular = {
    r1 = {
      spec = null
      status = {
        access_levels       = [module.test.access_level_names["a1"], "a2"]
        resources           = ["projects/11111", "projects/111111"]
        restricted_services = ["storage.googleapis.com"]
        egress_policies     = null
        ingress_policies    = null
        vpc_accessible_services = {
          allowed_services   = ["compute.googleapis.com"]
          enable_restriction = true
        }
      }
      use_explicit_dry_run_spec = false
    }
  }
}
# tftest:modules=1:resources=3

TODO

  • implement support for the google_access_context_manager_gcp_user_access_binding resource

Variables

name description type required default
access_policy Access Policy name, leave null to use auto-created one. string
access_levels Map of access levels in name => [conditions] format. map(object({…})) {}
access_policy_create Access Policy configuration, fill in to create. Parent is in 'organizations/123456' format. object({…}) null
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.