Use VPC-SC perimeter factory in FAST 1-vpcsc stage (#2928)
* Use VPC-SC perimeter factory in FAST 1-vpcsc stage * Add boilerplate * Fix linter and schema checks * Fix tests * Fix schemas
This commit is contained in:
@@ -306,12 +306,12 @@ Some references that might be useful in setting up this stage:
|
||||
| [access_levels](variables.tf#L17) | Access level definitions. | <code title="map(object({ combining_function = optional(string) conditions = optional(list(object({ device_policy = optional(object({ allowed_device_management_levels = optional(list(string)) allowed_encryption_statuses = optional(list(string)) require_admin_approval = bool require_corp_owned = bool require_screen_lock = optional(bool) os_constraints = optional(list(object({ os_type = string minimum_version = optional(string) require_verified_chrome_os = optional(bool) }))) })) ip_subnetworks = optional(list(string), []) members = optional(list(string), []) negate = optional(bool) regions = optional(list(string), []) required_access_levels = optional(list(string), []) vpc_subnets = optional(map(list(string)), {}) })), []) description = optional(string) }))">map(object({…}))</code> | | <code>{}</code> | |
|
||||
| [access_policy](variables.tf#L67) | Access policy id (used for tenant-level VPC-SC configurations). | <code>number</code> | | <code>null</code> | |
|
||||
| [egress_policies](variables.tf#L73) | Egress policy definitions that can be referenced in perimeters. | <code title="map(object({ title = optional(string) from = object({ access_levels = optional(list(string), []) identity_type = optional(string) identities = optional(list(string)) resources = optional(list(string), []) }) to = object({ external_resources = optional(list(string)) operations = optional(list(object({ method_selectors = optional(list(string)) permission_selectors = optional(list(string)) service_name = string })), []) resources = optional(list(string)) }) }))">map(object({…}))</code> | | <code>{}</code> | |
|
||||
| [factories_config](variables.tf#L115) | Paths to folders that enable factory functionality. | <code title="object({ access_levels = optional(string, "data/access-levels") egress_policies = optional(string, "data/egress-policies") ingress_policies = optional(string, "data/ingress-policies") })">object({…})</code> | | <code>{}</code> | |
|
||||
| [ingress_policies](variables.tf#L126) | Ingress policy definitions that can be referenced in perimeters. | <code title="map(object({ title = optional(string) from = object({ access_levels = optional(list(string), []) identity_type = optional(string) identities = optional(list(string)) resources = optional(list(string), []) }) to = object({ operations = optional(list(object({ method_selectors = optional(list(string)) permission_selectors = optional(list(string)) service_name = string })), []) resources = optional(list(string)) }) }))">map(object({…}))</code> | | <code>{}</code> | |
|
||||
| [factories_config](variables.tf#L115) | Paths to folders that enable factory functionality. | <code title="object({ access_levels = optional(string, "data/access-levels") egress_policies = optional(string, "data/egress-policies") ingress_policies = optional(string, "data/ingress-policies") perimeters = optional(string, "data/perimeters") context = optional(object({ identity_sets = optional(map(list(string)), {}) resource_sets = optional(map(list(string)), {}) service_sets = optional(map(list(string)), {}) }), {}) })">object({…})</code> | | <code>{}</code> | |
|
||||
| [ingress_policies](variables.tf#L132) | Ingress policy definitions that can be referenced in perimeters. | <code title="map(object({ title = optional(string) from = object({ access_levels = optional(list(string), []) identity_type = optional(string) identities = optional(list(string)) resources = optional(list(string), []) }) to = object({ operations = optional(list(object({ method_selectors = optional(list(string)) permission_selectors = optional(list(string)) service_name = string })), []) resources = optional(list(string)) }) }))">map(object({…}))</code> | | <code>{}</code> | |
|
||||
| [logging](variables-fast.tf#L25) | Log writer identities for organization / folders. | <code title="object({ project_number = string writer_identities = map(string) })">object({…})</code> | | <code>null</code> | <code>0-bootstrap</code> |
|
||||
| [outputs_location](variables.tf#L167) | Path where providers, tfvars files, and lists for the following stages are written. Leave empty to disable. | <code>string</code> | | <code>null</code> | |
|
||||
| [perimeters](variables.tf#L173) | Perimeter definitions. | <code title="map(object({ access_levels = optional(list(string), []) dry_run = optional(bool, true) egress_policies = optional(list(string), []) ingress_policies = optional(list(string), []) resources = optional(list(string), []) restricted_services = optional(list(string)) vpc_accessible_services = optional(object({ allowed_services = list(string) enable_restriction = optional(bool, true) })) }))">map(object({…}))</code> | | <code title="{ default = { access_levels = ["geo"] ingress_policies = ["fast-org-log-sinks"] } }">{…}</code> | |
|
||||
| [resource_discovery](variables.tf#L196) | Automatic discovery of perimeter projects. | <code title="object({ enabled = optional(bool, true) ignore_folders = optional(list(string), []) ignore_projects = optional(list(string), []) include_projects = optional(list(string), []) })">object({…})</code> | | <code>{}</code> | |
|
||||
| [outputs_location](variables.tf#L173) | Path where providers, tfvars files, and lists for the following stages are written. Leave empty to disable. | <code>string</code> | | <code>null</code> | |
|
||||
| [perimeters](variables.tf#L179) | Perimeter definitions. | <code title="map(object({ description = optional(string) title = optional(string) spec = optional(object({ access_levels = optional(list(string)) egress_policies = optional(list(string)) ingress_policies = optional(list(string)) restricted_services = optional(list(string)) resources = optional(list(string)) vpc_accessible_services = optional(object({ allowed_services = list(string) enable_restriction = optional(bool, true) })) })) status = optional(object({ access_levels = optional(list(string)) egress_policies = optional(list(string)) ingress_policies = optional(list(string)) resources = optional(list(string)) restricted_services = optional(list(string)) vpc_accessible_services = optional(object({ allowed_services = list(string) enable_restriction = optional(bool, true) })) })) use_explicit_dry_run_spec = optional(bool, false) }))">map(object({…}))</code> | | <code>{}</code> | |
|
||||
| [resource_discovery](variables.tf#L212) | Automatic discovery of perimeter projects. | <code title="object({ enabled = optional(bool, true) ignore_folders = optional(list(string), []) ignore_projects = optional(list(string), []) include_projects = optional(list(string), []) })">object({…})</code> | | <code>{}</code> | |
|
||||
| [root_node](variables-fast.tf#L45) | Root node for the hierarchy, if running in tenant mode. | <code>string</code> | | <code>null</code> | <code>0-bootstrap</code> |
|
||||
|
||||
## Outputs
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright 2024 Google LLC
|
||||
# Copyright 2025 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
# Copyright 2025 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# yaml-language-server: $schema=../../schemas/ingress-policy.schema.json
|
||||
|
||||
from:
|
||||
access_levels:
|
||||
- "*"
|
||||
identities:
|
||||
- org_logging_writer_identities
|
||||
to:
|
||||
operations:
|
||||
- service_name: "*"
|
||||
resources:
|
||||
- logging_project
|
||||
26
fast/stages/1-vpcsc/data/perimeters/default.yaml
Normal file
26
fast/stages/1-vpcsc/data/perimeters/default.yaml
Normal file
@@ -0,0 +1,26 @@
|
||||
# Copyright 2025 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# yaml-language-server: $schema=../../schemas/perimeter.schema.json
|
||||
|
||||
use_explicit_dry_run_spec: true
|
||||
spec:
|
||||
access_levels:
|
||||
- geo
|
||||
resources:
|
||||
- discovered_projects
|
||||
ingress_policies:
|
||||
- fast-org-log-sinks
|
||||
restricted_services:
|
||||
- restricted_services
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2024 Google LLC
|
||||
* Copyright 2025 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,35 +15,25 @@
|
||||
*/
|
||||
|
||||
locals {
|
||||
fast_ingress_policies = var.logging == null ? {} : {
|
||||
fast-org-log-sinks = {
|
||||
from = {
|
||||
access_levels = ["*"]
|
||||
identities = values(var.logging.writer_identities)
|
||||
}
|
||||
to = {
|
||||
operations = [{ service_name = "*" }]
|
||||
resources = ["projects/${var.logging.project_number}"]
|
||||
}
|
||||
}
|
||||
}
|
||||
perimeters = {
|
||||
for k, v in var.perimeters : k => merge(v, {
|
||||
restricted_services = (
|
||||
v.restricted_services == null
|
||||
? local.restricted_services
|
||||
: v.restricted_services
|
||||
)
|
||||
resources = distinct(concat(
|
||||
v.resources,
|
||||
k != "default" || var.resource_discovery.enabled != true ? [] : [
|
||||
for v in module.vpc-sc-discovery[0].project_numbers :
|
||||
"projects/${v}"
|
||||
]
|
||||
))
|
||||
discovered_projects = var.resource_discovery.enabled != true ? [] : [
|
||||
for v in module.vpc-sc-discovery[0].project_numbers :
|
||||
"projects/${v}"
|
||||
]
|
||||
restricted_services = yamldecode(file("data/restricted-services.yaml"))
|
||||
|
||||
# extend context with our own data
|
||||
context = {
|
||||
identity_sets = merge(var.factories_config.context.identity_sets, {
|
||||
org_logging_writer_identities = distinct(values(var.logging.writer_identities))
|
||||
})
|
||||
resource_sets = merge(var.factories_config.context.resource_sets, {
|
||||
discovered_projects = local.discovered_projects
|
||||
logging_project = ["projects/${var.logging.project_number}"]
|
||||
})
|
||||
service_sets = merge(var.factories_config.context.service_sets, {
|
||||
restricted_services = local.restricted_services
|
||||
})
|
||||
}
|
||||
restricted_services = yamldecode(file("data/restricted-services.yaml"))
|
||||
}
|
||||
|
||||
module "vpc-sc-discovery" {
|
||||
@@ -56,26 +46,19 @@ module "vpc-sc-discovery" {
|
||||
}
|
||||
|
||||
module "vpc-sc" {
|
||||
source = "../../../modules/vpc-sc"
|
||||
# only enable if the default perimeter is defined
|
||||
count = var.perimeters.default == null ? 0 : 1
|
||||
source = "../../../modules/vpc-sc"
|
||||
access_policy = var.access_policy
|
||||
access_policy_create = var.access_policy != null ? null : {
|
||||
parent = "organizations/${var.organization.id}"
|
||||
title = "default"
|
||||
}
|
||||
access_levels = var.access_levels
|
||||
egress_policies = var.egress_policies
|
||||
factories_config = var.factories_config
|
||||
ingress_policies = merge(
|
||||
local.fast_ingress_policies,
|
||||
var.ingress_policies
|
||||
)
|
||||
service_perimeters_regular = {
|
||||
for k, v in local.perimeters : k => {
|
||||
spec = v.dry_run ? v : null
|
||||
status = !v.dry_run ? v : null
|
||||
use_explicit_dry_run_spec = v.dry_run
|
||||
access_levels = var.access_levels
|
||||
egress_policies = var.egress_policies
|
||||
factories_config = merge(
|
||||
var.factories_config, {
|
||||
context = local.context
|
||||
}
|
||||
}
|
||||
)
|
||||
ingress_policies = var.ingress_policies
|
||||
service_perimeters_regular = var.perimeters
|
||||
}
|
||||
|
||||
30
fast/stages/1-vpcsc/moved/v38.0.0-v39.0.0.tf
Normal file
30
fast/stages/1-vpcsc/moved/v38.0.0-v39.0.0.tf
Normal file
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Copyright 2025 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
moved {
|
||||
from = module.vpc-sc[0].google_access_context_manager_service_perimeter.regular["default"]
|
||||
to = module.vpc-sc.google_access_context_manager_service_perimeter.regular["default"]
|
||||
}
|
||||
|
||||
moved {
|
||||
from = module.vpc-sc[0].google_access_context_manager_access_level.basic["geo"]
|
||||
to = module.vpc-sc.google_access_context_manager_access_level.basic["geo"]
|
||||
}
|
||||
|
||||
moved {
|
||||
from = module.vpc-sc[0].google_access_context_manager_access_policy.default[0]
|
||||
to = module.vpc-sc.google_access_context_manager_access_policy.default[0]
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2024 Google LLC
|
||||
* Copyright 2025 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
1
fast/stages/1-vpcsc/schemas/perimeter.schema.json
Symbolic link
1
fast/stages/1-vpcsc/schemas/perimeter.schema.json
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../../modules/vpc-sc/schemas/perimeters.schema.json
|
||||
@@ -118,6 +118,12 @@ variable "factories_config" {
|
||||
access_levels = optional(string, "data/access-levels")
|
||||
egress_policies = optional(string, "data/egress-policies")
|
||||
ingress_policies = optional(string, "data/ingress-policies")
|
||||
perimeters = optional(string, "data/perimeters")
|
||||
context = optional(object({
|
||||
identity_sets = optional(map(list(string)), {})
|
||||
resource_sets = optional(map(list(string)), {})
|
||||
service_sets = optional(map(list(string)), {})
|
||||
}), {})
|
||||
})
|
||||
nullable = false
|
||||
default = {}
|
||||
@@ -173,24 +179,34 @@ variable "outputs_location" {
|
||||
variable "perimeters" {
|
||||
description = "Perimeter definitions."
|
||||
type = map(object({
|
||||
access_levels = optional(list(string), [])
|
||||
dry_run = optional(bool, true)
|
||||
egress_policies = optional(list(string), [])
|
||||
ingress_policies = optional(list(string), [])
|
||||
resources = optional(list(string), [])
|
||||
restricted_services = optional(list(string))
|
||||
vpc_accessible_services = optional(object({
|
||||
allowed_services = list(string)
|
||||
enable_restriction = optional(bool, true)
|
||||
description = optional(string)
|
||||
title = optional(string)
|
||||
spec = optional(object({
|
||||
access_levels = optional(list(string))
|
||||
egress_policies = optional(list(string))
|
||||
ingress_policies = optional(list(string))
|
||||
restricted_services = optional(list(string))
|
||||
resources = optional(list(string))
|
||||
vpc_accessible_services = optional(object({
|
||||
allowed_services = list(string)
|
||||
enable_restriction = optional(bool, true)
|
||||
}))
|
||||
}))
|
||||
status = optional(object({
|
||||
access_levels = optional(list(string))
|
||||
egress_policies = optional(list(string))
|
||||
ingress_policies = optional(list(string))
|
||||
resources = optional(list(string))
|
||||
restricted_services = optional(list(string))
|
||||
vpc_accessible_services = optional(object({
|
||||
allowed_services = list(string)
|
||||
enable_restriction = optional(bool, true)
|
||||
}))
|
||||
}))
|
||||
use_explicit_dry_run_spec = optional(bool, false)
|
||||
}))
|
||||
nullable = false
|
||||
default = {
|
||||
default = {
|
||||
access_levels = ["geo"]
|
||||
ingress_policies = ["fast-org-log-sinks"]
|
||||
}
|
||||
}
|
||||
default = {}
|
||||
}
|
||||
|
||||
variable "resource_discovery" {
|
||||
|
||||
@@ -395,13 +395,13 @@ status:
|
||||
| [access_levels](variables.tf#L17) | Access level definitions. | <code title="map(object({ combining_function = optional(string) conditions = optional(list(object({ device_policy = optional(object({ allowed_device_management_levels = optional(list(string)) allowed_encryption_statuses = optional(list(string)) require_admin_approval = bool require_corp_owned = bool require_screen_lock = optional(bool) os_constraints = optional(list(object({ os_type = string minimum_version = optional(string) require_verified_chrome_os = optional(bool) }))) })) ip_subnetworks = optional(list(string), []) members = optional(list(string), []) negate = optional(bool) regions = optional(list(string), []) required_access_levels = optional(list(string), []) vpc_subnets = optional(map(list(string)), {}) })), []) description = optional(string) title = optional(string) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||
| [access_policy_create](variables.tf#L73) | Access Policy configuration, fill in to create. Parent is in 'organizations/123456' format, scopes are in 'folders/456789' or 'projects/project_id' format. | <code title="object({ parent = string title = string scopes = optional(list(string), null) })">object({…})</code> | | <code>null</code> |
|
||||
| [egress_policies](variables.tf#L83) | Egress policy definitions that can be referenced in perimeters. | <code title="map(object({ title = optional(string) from = object({ access_levels = optional(list(string), []) identity_type = optional(string) identities = optional(list(string)) resources = optional(list(string), []) }) to = object({ external_resources = optional(list(string)) operations = optional(list(object({ method_selectors = optional(list(string)) permission_selectors = optional(list(string)) service_name = string })), []) resources = optional(list(string)) }) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||
| [factories_config](variables.tf#L125) | Paths to folders that enable factory functionality. | <code title="object({ access_levels = optional(string) bridges = optional(string) egress_policies = optional(string) ingress_policies = optional(string) perimeters = optional(string) context = optional(object({ resource_sets = optional(map(list(string)), {}) service_sets = optional(map(list(string)), {}) }), {}) })">object({…})</code> | | <code>{}</code> |
|
||||
| [iam](variables.tf#L142) | IAM bindings in {ROLE => [MEMBERS]} format. | <code>map(list(string))</code> | | <code>{}</code> |
|
||||
| [iam_bindings](variables.tf#L148) | Authoritative IAM bindings in {KEY => {role = ROLE, members = [], condition = {}}}. Keys are arbitrary. | <code title="map(object({ members = list(string) role = string condition = optional(object({ expression = string title = string description = optional(string) })) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||
| [iam_bindings_additive](variables.tf#L163) | Individual additive IAM bindings. Keys are arbitrary. | <code title="map(object({ member = string role = string condition = optional(object({ expression = string title = string description = optional(string) })) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||
| [ingress_policies](variables.tf#L178) | Ingress policy definitions that can be referenced in perimeters. | <code title="map(object({ title = optional(string) from = object({ access_levels = optional(list(string), []) identity_type = optional(string) identities = optional(list(string)) resources = optional(list(string), []) }) to = object({ operations = optional(list(object({ method_selectors = optional(list(string)) permission_selectors = optional(list(string)) service_name = string })), []) resources = optional(list(string)) }) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||
| [service_perimeters_bridge](variables.tf#L219) | Bridge service perimeters. | <code title="map(object({ description = optional(string) title = optional(string) spec_resources = optional(list(string)) status_resources = optional(list(string)) use_explicit_dry_run_spec = optional(bool, false) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||
| [service_perimeters_regular](variables.tf#L231) | Regular service perimeters. | <code title="map(object({ description = optional(string) title = optional(string) spec = optional(object({ access_levels = optional(list(string)) egress_policies = optional(list(string)) ingress_policies = optional(list(string)) restricted_services = optional(list(string)) resources = optional(list(string)) vpc_accessible_services = optional(object({ allowed_services = list(string) enable_restriction = optional(bool, true) })) })) status = optional(object({ access_levels = optional(list(string)) egress_policies = optional(list(string)) ingress_policies = optional(list(string)) resources = optional(list(string)) restricted_services = optional(list(string)) vpc_accessible_services = optional(object({ allowed_services = list(string) enable_restriction = optional(bool, true) })) })) use_explicit_dry_run_spec = optional(bool, false) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||
| [factories_config](variables.tf#L125) | Paths to folders that enable factory functionality. | <code title="object({ access_levels = optional(string) bridges = optional(string) egress_policies = optional(string) ingress_policies = optional(string) perimeters = optional(string) context = optional(object({ resource_sets = optional(map(list(string)), {}) service_sets = optional(map(list(string)), {}) identity_sets = optional(map(list(string)), {}) }), {}) })">object({…})</code> | | <code>{}</code> |
|
||||
| [iam](variables.tf#L143) | IAM bindings in {ROLE => [MEMBERS]} format. | <code>map(list(string))</code> | | <code>{}</code> |
|
||||
| [iam_bindings](variables.tf#L149) | Authoritative IAM bindings in {KEY => {role = ROLE, members = [], condition = {}}}. Keys are arbitrary. | <code title="map(object({ members = list(string) role = string condition = optional(object({ expression = string title = string description = optional(string) })) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||
| [iam_bindings_additive](variables.tf#L164) | Individual additive IAM bindings. Keys are arbitrary. | <code title="map(object({ member = string role = string condition = optional(object({ expression = string title = string description = optional(string) })) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||
| [ingress_policies](variables.tf#L179) | Ingress policy definitions that can be referenced in perimeters. | <code title="map(object({ title = optional(string) from = object({ access_levels = optional(list(string), []) identity_type = optional(string) identities = optional(list(string)) resources = optional(list(string), []) }) to = object({ operations = optional(list(object({ method_selectors = optional(list(string)) permission_selectors = optional(list(string)) service_name = string })), []) resources = optional(list(string)) }) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||
| [service_perimeters_bridge](variables.tf#L220) | Bridge service perimeters. | <code title="map(object({ description = optional(string) title = optional(string) spec_resources = optional(list(string)) status_resources = optional(list(string)) use_explicit_dry_run_spec = optional(bool, false) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||
| [service_perimeters_regular](variables.tf#L232) | Regular service perimeters. | <code title="map(object({ description = optional(string) title = optional(string) spec = optional(object({ access_levels = optional(list(string)) egress_policies = optional(list(string)) ingress_policies = optional(list(string)) restricted_services = optional(list(string)) resources = optional(list(string)) vpc_accessible_services = optional(object({ allowed_services = list(string) enable_restriction = optional(bool, true) })) })) status = optional(object({ access_levels = optional(list(string)) egress_policies = optional(list(string)) ingress_policies = optional(list(string)) resources = optional(list(string)) restricted_services = optional(list(string)) vpc_accessible_services = optional(object({ allowed_services = list(string) enable_restriction = optional(bool, true) })) })) use_explicit_dry_run_spec = optional(bool, false) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||
|
||||
## Outputs
|
||||
|
||||
|
||||
@@ -34,8 +34,11 @@ resource "google_access_context_manager_access_level" "basic" {
|
||||
for_each = toset(each.value.conditions)
|
||||
iterator = c
|
||||
content {
|
||||
ip_subnetworks = c.value.ip_subnetworks
|
||||
members = c.value.members
|
||||
ip_subnetworks = c.value.ip_subnetworks
|
||||
members = flatten([
|
||||
for i in c.value.members :
|
||||
lookup(var.factories_config.context.identity_sets, i, [i])
|
||||
])
|
||||
negate = c.value.negate
|
||||
regions = c.value.regions
|
||||
required_access_levels = coalesce(c.value.required_access_levels, [])
|
||||
|
||||
@@ -74,8 +74,7 @@
|
||||
"members": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"pattern": "^(?:serviceAccount:|user:)"
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"negate": {
|
||||
|
||||
@@ -33,8 +33,7 @@
|
||||
"identities": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"pattern": "^(?:serviceAccount:|user:|group:|principal:)"
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"resources": {
|
||||
|
||||
@@ -65,7 +65,10 @@ resource "google_access_context_manager_service_perimeter" "regular" {
|
||||
for_each = policy.value.from == null ? [] : [""]
|
||||
content {
|
||||
identity_type = policy.value.from.identity_type
|
||||
identities = policy.value.from.identities
|
||||
identities = flatten([
|
||||
for i in policy.value.from.identities :
|
||||
lookup(var.factories_config.context.identity_sets, i, [i])
|
||||
])
|
||||
source_restriction = (
|
||||
length(policy.value.from.access_levels) > 0 || length(policy.value.from.resources) > 0
|
||||
? "SOURCE_RESTRICTION_ENABLED"
|
||||
@@ -138,7 +141,10 @@ resource "google_access_context_manager_service_perimeter" "regular" {
|
||||
for_each = policy.value.from == null ? [] : [""]
|
||||
content {
|
||||
identity_type = policy.value.from.identity_type
|
||||
identities = policy.value.from.identities
|
||||
identities = flatten([
|
||||
for i in policy.value.from.identities :
|
||||
lookup(var.factories_config.context.identity_sets, i, [i])
|
||||
])
|
||||
dynamic "sources" {
|
||||
for_each = toset(policy.value.from.access_levels)
|
||||
iterator = s
|
||||
@@ -234,7 +240,10 @@ resource "google_access_context_manager_service_perimeter" "regular" {
|
||||
for_each = policy.value.from == null ? [] : [""]
|
||||
content {
|
||||
identity_type = policy.value.from.identity_type
|
||||
identities = policy.value.from.identities
|
||||
identities = flatten([
|
||||
for i in policy.value.from.identities :
|
||||
lookup(var.factories_config.context.identity_sets, i, [i])
|
||||
])
|
||||
source_restriction = (
|
||||
length(policy.value.from.access_levels) > 0 || length(policy.value.from.resources) > 0
|
||||
? "SOURCE_RESTRICTION_ENABLED"
|
||||
@@ -303,7 +312,10 @@ resource "google_access_context_manager_service_perimeter" "regular" {
|
||||
for_each = policy.value.from == null ? [] : [""]
|
||||
content {
|
||||
identity_type = policy.value.from.identity_type
|
||||
identities = policy.value.from.identities
|
||||
identities = flatten([
|
||||
for i in policy.value.from.identities :
|
||||
lookup(var.factories_config.context.identity_sets, i, [i])
|
||||
])
|
||||
dynamic "sources" {
|
||||
for_each = toset(policy.value.from.access_levels)
|
||||
iterator = s
|
||||
|
||||
@@ -133,6 +133,7 @@ variable "factories_config" {
|
||||
context = optional(object({
|
||||
resource_sets = optional(map(list(string)), {})
|
||||
service_sets = optional(map(list(string)), {})
|
||||
identity_sets = optional(map(list(string)), {})
|
||||
}), {})
|
||||
})
|
||||
nullable = false
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright 2024 Google LLC
|
||||
# Copyright 2025 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@@ -12,6 +12,8 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# yaml-language-server: $schema=../../../../../../../modules/vpc-sc/schemas/access-level.schema.json
|
||||
|
||||
conditions:
|
||||
- regions:
|
||||
- IT
|
||||
- IT
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright 2024 Google LLC
|
||||
# Copyright 2025 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@@ -12,6 +12,8 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# yaml-language-server: $schema=../../../../../../../modules/vpc-sc/schemas/access-level.schema.json
|
||||
|
||||
conditions:
|
||||
- members:
|
||||
- user:user@fast.example.com
|
||||
- user:user@fast.example.com
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright 2024 Google LLC
|
||||
# Copyright 2025 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@@ -12,6 +12,8 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# yaml-language-server: $schema=../../../../../../../modules/vpc-sc/schemas/egress-policy.schema.json
|
||||
|
||||
from:
|
||||
identities:
|
||||
- user:user@fast.example.com
|
||||
@@ -24,4 +26,4 @@ to:
|
||||
method_selectors:
|
||||
- "*"
|
||||
resources:
|
||||
- "*"
|
||||
- "*"
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
# Copyright 2025 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# yaml-language-server: $schema=../../../../../../../modules/vpc-sc/schemas/ingress-policy.schema.json
|
||||
|
||||
from:
|
||||
access_levels:
|
||||
- "*"
|
||||
identities:
|
||||
- org_logging_writer_identities
|
||||
to:
|
||||
operations:
|
||||
- service_name: "*"
|
||||
resources:
|
||||
- logging_project
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright 2024 Google LLC
|
||||
# Copyright 2025 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@@ -12,6 +12,8 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# yaml-language-server: $schema=../../../../../../../modules/vpc-sc/schemas/ingress-policy.schema.json
|
||||
|
||||
from:
|
||||
access_levels:
|
||||
- "*"
|
||||
@@ -26,4 +28,4 @@ to:
|
||||
method_selectors:
|
||||
- "*"
|
||||
resources:
|
||||
- "*"
|
||||
- "*"
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
# Copyright 2025 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# yaml-language-server: $schema=../../../../../../../modules/vpc-sc/schemas/perimeters.schema.json
|
||||
|
||||
use_explicit_dry_run_spec: true
|
||||
spec:
|
||||
access_levels:
|
||||
- geo_it
|
||||
- identity_me
|
||||
ingress_policies:
|
||||
- fast-org-log-sinks
|
||||
- test
|
||||
egress_policies:
|
||||
- test
|
||||
restricted_services:
|
||||
- restricted_services
|
||||
resources:
|
||||
- projects/1234567890
|
||||
27
tests/fast/stages/s1_vpcsc/factory.tfvars
Normal file
27
tests/fast/stages/s1_vpcsc/factory.tfvars
Normal file
@@ -0,0 +1,27 @@
|
||||
automation = {
|
||||
outputs_bucket = "test"
|
||||
}
|
||||
logging = {
|
||||
project_number = "1234567890"
|
||||
writer_identities = {
|
||||
audit-logs = "serviceAccount:service-org-1234567890@gcp-sa-logging.iam.gserviceaccount.com"
|
||||
iam = "serviceAccount:service-org-1234567890@gcp-sa-logging.iam.gserviceaccount.com"
|
||||
vpc-sc = "serviceAccount:service-org-1234567890@gcp-sa-logging.iam.gserviceaccount.com"
|
||||
workspace-audit-logs = "serviceAccount:o1234567890-1234567890@gcp-sa-logging.iam.gserviceaccount.com"
|
||||
}
|
||||
}
|
||||
organization = {
|
||||
domain = "fast.example.com"
|
||||
id = 123456789012
|
||||
customer_id = "C00000000"
|
||||
}
|
||||
prefix = "fast"
|
||||
factories_config = {
|
||||
access_levels = "../../../tests/fast/stages/s1_vpcsc/data/vpc-sc/access-levels"
|
||||
egress_policies = "../../../tests/fast/stages/s1_vpcsc/data/vpc-sc/egress-policies"
|
||||
ingress_policies = "../../../tests/fast/stages/s1_vpcsc/data/vpc-sc/ingress-policies"
|
||||
perimeters = "../../../tests/fast/stages/s1_vpcsc/data/vpc-sc/perimeters"
|
||||
}
|
||||
resource_discovery = {
|
||||
enabled = false
|
||||
}
|
||||
@@ -23,12 +23,16 @@ factories_config = {
|
||||
}
|
||||
perimeters = {
|
||||
default = {
|
||||
access_levels = ["geo_it", "identity_me"]
|
||||
egress_policies = ["test"]
|
||||
ingress_policies = ["fast-org-log-sinks", "test"]
|
||||
resources = [
|
||||
"projects/1234567890"
|
||||
]
|
||||
use_explicit_dry_run_spec = true
|
||||
spec = {
|
||||
access_levels = ["geo_it", "identity_me"]
|
||||
egress_policies = ["test"]
|
||||
ingress_policies = ["fast-org-log-sinks", "test"]
|
||||
restricted_services = ["restricted_services"]
|
||||
resources = [
|
||||
"projects/1234567890"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
resource_discovery = {
|
||||
|
||||
@@ -28,7 +28,7 @@ values:
|
||||
source: null
|
||||
temporary_hold: null
|
||||
timeouts: null
|
||||
module.vpc-sc[0].google_access_context_manager_access_level.basic["geo_it"]:
|
||||
module.vpc-sc.google_access_context_manager_access_level.basic["geo_it"]:
|
||||
basic:
|
||||
- combining_function: AND
|
||||
conditions:
|
||||
@@ -44,7 +44,7 @@ values:
|
||||
description: null
|
||||
timeouts: null
|
||||
title: geo_it
|
||||
module.vpc-sc[0].google_access_context_manager_access_level.basic["identity_me"]:
|
||||
module.vpc-sc.google_access_context_manager_access_level.basic["identity_me"]:
|
||||
basic:
|
||||
- combining_function: AND
|
||||
conditions:
|
||||
@@ -60,12 +60,12 @@ values:
|
||||
description: null
|
||||
timeouts: null
|
||||
title: identity_me
|
||||
module.vpc-sc[0].google_access_context_manager_access_policy.default[0]:
|
||||
module.vpc-sc.google_access_context_manager_access_policy.default[0]:
|
||||
parent: organizations/123456789012
|
||||
scopes: null
|
||||
timeouts: null
|
||||
title: default
|
||||
module.vpc-sc[0].google_access_context_manager_service_perimeter.regular["default"]:
|
||||
module.vpc-sc.google_access_context_manager_service_perimeter.regular["default"]:
|
||||
description: null
|
||||
perimeter_type: PERIMETER_TYPE_REGULAR
|
||||
spec:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright 2024 Google LLC
|
||||
# Copyright 2025 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@@ -16,3 +16,6 @@ module: fast/stages/1-vpcsc
|
||||
|
||||
tests:
|
||||
simple:
|
||||
factory:
|
||||
inventory:
|
||||
- simple.yaml
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
# skip boilerplate check
|
||||
# tftest schema=modules/vpc-sc/schemas/access-level.schema.json fail
|
||||
# fails because members must be prefixed with serviceAccount: or user:
|
||||
conditions:
|
||||
- members:
|
||||
- "group:group@example.com"
|
||||
@@ -1,6 +0,0 @@
|
||||
# skip boilerplate check
|
||||
# tftest schema=modules/vpc-sc/schemas/access-level.schema.json fail
|
||||
# fails because members must be prefixed with serviceAccount: or user:
|
||||
conditions:
|
||||
- members:
|
||||
- "user@example.com"
|
||||
Reference in New Issue
Block a user