Add explicit errors when VPC-SC perimeters reference undefined directional policies (#3133)
* Add explicit errors when VPC-SC perimeters reference undefined directional policies * Fix try calls * Update defaults
This commit is contained in:
@@ -410,7 +410,7 @@ to:
|
|||||||
| [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](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> |
|
| [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)) roles = optional(list(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)) roles = optional(list(string)) }) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||||
| [perimeters](variables.tf#L221) | Regular service perimeters. | <code title="map(object({ description = optional(string) ignore_resource_changes = optional(bool, false) title = optional(string) use_explicit_dry_run_spec = optional(bool, false) 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) })) })) }))">map(object({…}))</code> | | <code>{}</code> |
|
| [perimeters](variables.tf#L221) | Regular service perimeters. | <code title="map(object({ description = optional(string) ignore_resource_changes = optional(bool, false) title = optional(string) use_explicit_dry_run_spec = optional(bool, false) 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) })) })) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||||
| [project_id_search_scope](variables.tf#L255) | Set this to an organization or folder ID to use Cloud Asset Inventory to automatically translate project ids to numbers. | <code>string</code> | | <code>null</code> |
|
| [project_id_search_scope](variables.tf#L255) | Set this to an organization or folder ID to use Cloud Asset Inventory to automatically translate project ids to numbers. | <code>string</code> | | <code>null</code> |
|
||||||
|
|
||||||
## Outputs
|
## Outputs
|
||||||
|
|||||||
@@ -48,8 +48,8 @@ resource "google_access_context_manager_service_perimeter" "additive" {
|
|||||||
])
|
])
|
||||||
|
|
||||||
dynamic "egress_policies" {
|
dynamic "egress_policies" {
|
||||||
for_each = spec.value.egress_policies == null ? [] : [
|
for_each = [
|
||||||
for k in spec.value.egress_policies :
|
for k in coalesce(spec.value.egress_policies, []) :
|
||||||
merge(local.egress_policies[k], { key = k })
|
merge(local.egress_policies[k], { key = k })
|
||||||
]
|
]
|
||||||
iterator = policy
|
iterator = policy
|
||||||
@@ -129,8 +129,8 @@ resource "google_access_context_manager_service_perimeter" "additive" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dynamic "ingress_policies" {
|
dynamic "ingress_policies" {
|
||||||
for_each = spec.value.ingress_policies == null ? [] : [
|
for_each = [
|
||||||
for k in spec.value.ingress_policies :
|
for k in coalesce(spec.value.ingress_policies, []) :
|
||||||
merge(local.ingress_policies[k], { key = k })
|
merge(local.ingress_policies[k], { key = k })
|
||||||
]
|
]
|
||||||
iterator = policy
|
iterator = policy
|
||||||
@@ -235,8 +235,8 @@ resource "google_access_context_manager_service_perimeter" "additive" {
|
|||||||
])
|
])
|
||||||
|
|
||||||
dynamic "egress_policies" {
|
dynamic "egress_policies" {
|
||||||
for_each = status.value.egress_policies == null ? [] : [
|
for_each = [
|
||||||
for k in status.value.egress_policies :
|
for k in coalesce(status.value.egress_policies, []) :
|
||||||
merge(local.egress_policies[k], { key = k })
|
merge(local.egress_policies[k], { key = k })
|
||||||
]
|
]
|
||||||
iterator = policy
|
iterator = policy
|
||||||
@@ -310,8 +310,8 @@ resource "google_access_context_manager_service_perimeter" "additive" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dynamic "ingress_policies" {
|
dynamic "ingress_policies" {
|
||||||
for_each = status.value.ingress_policies == null ? [] : [
|
for_each = [
|
||||||
for k in status.value.ingress_policies :
|
for k in coalesce(status.value.ingress_policies, []) :
|
||||||
merge(local.ingress_policies[k], { key = k })
|
merge(local.ingress_policies[k], { key = k })
|
||||||
]
|
]
|
||||||
iterator = policy
|
iterator = policy
|
||||||
@@ -397,6 +397,14 @@ resource "google_access_context_manager_service_perimeter" "additive" {
|
|||||||
}
|
}
|
||||||
lifecycle {
|
lifecycle {
|
||||||
ignore_changes = [spec[0].resources, status[0].resources]
|
ignore_changes = [spec[0].resources, status[0].resources]
|
||||||
|
precondition {
|
||||||
|
condition = length(local._undefined_ingress_policies[each.key]) == 0
|
||||||
|
error_message = "Undefined ingress policies: ${join(", ", local._undefined_ingress_policies[each.key])}"
|
||||||
|
}
|
||||||
|
precondition {
|
||||||
|
condition = length(local._undefined_egress_policies[each.key]) == 0
|
||||||
|
error_message = "Undefined egress policies: ${join(", ", local._undefined_egress_policies[each.key])}"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
depends_on = [
|
depends_on = [
|
||||||
google_access_context_manager_access_policy.default,
|
google_access_context_manager_access_policy.default,
|
||||||
|
|||||||
@@ -20,6 +20,14 @@ locals {
|
|||||||
egress_policies = merge(local.data.egress_policies, var.egress_policies)
|
egress_policies = merge(local.data.egress_policies, var.egress_policies)
|
||||||
ingress_policies = merge(local.data.ingress_policies, var.ingress_policies)
|
ingress_policies = merge(local.data.ingress_policies, var.ingress_policies)
|
||||||
perimeters = merge(local.data.perimeters, var.perimeters)
|
perimeters = merge(local.data.perimeters, var.perimeters)
|
||||||
|
_undefined_egress_policies = {
|
||||||
|
for k, v in local.perimeters :
|
||||||
|
k => setsubtract(concat(try(v.spec.egress_policies, []), try(v.status.egress_policies, [])), keys(local.egress_policies))
|
||||||
|
}
|
||||||
|
_undefined_ingress_policies = {
|
||||||
|
for k, v in local.perimeters :
|
||||||
|
k => setsubtract(concat(try(v.spec.ingress_policies, []), try(v.status.ingress_policies, [])), keys(local.ingress_policies))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "google_access_context_manager_service_perimeter" "regular" {
|
resource "google_access_context_manager_service_perimeter" "regular" {
|
||||||
@@ -54,8 +62,8 @@ resource "google_access_context_manager_service_perimeter" "regular" {
|
|||||||
])
|
])
|
||||||
|
|
||||||
dynamic "egress_policies" {
|
dynamic "egress_policies" {
|
||||||
for_each = spec.value.egress_policies == null ? [] : [
|
for_each = [
|
||||||
for k in spec.value.egress_policies :
|
for k in coalesce(spec.value.egress_policies, []) :
|
||||||
merge(local.egress_policies[k], { key = k })
|
merge(local.egress_policies[k], { key = k })
|
||||||
]
|
]
|
||||||
iterator = policy
|
iterator = policy
|
||||||
@@ -135,8 +143,8 @@ resource "google_access_context_manager_service_perimeter" "regular" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dynamic "ingress_policies" {
|
dynamic "ingress_policies" {
|
||||||
for_each = spec.value.ingress_policies == null ? [] : [
|
for_each = [
|
||||||
for k in spec.value.ingress_policies :
|
for k in coalesce(spec.value.ingress_policies, []) :
|
||||||
merge(local.ingress_policies[k], { key = k })
|
merge(local.ingress_policies[k], { key = k })
|
||||||
]
|
]
|
||||||
iterator = policy
|
iterator = policy
|
||||||
@@ -241,8 +249,8 @@ resource "google_access_context_manager_service_perimeter" "regular" {
|
|||||||
])
|
])
|
||||||
|
|
||||||
dynamic "egress_policies" {
|
dynamic "egress_policies" {
|
||||||
for_each = status.value.egress_policies == null ? [] : [
|
for_each = [
|
||||||
for k in status.value.egress_policies :
|
for k in coalesce(status.value.egress_policies, []) :
|
||||||
merge(local.egress_policies[k], { key = k })
|
merge(local.egress_policies[k], { key = k })
|
||||||
]
|
]
|
||||||
iterator = policy
|
iterator = policy
|
||||||
@@ -321,8 +329,8 @@ resource "google_access_context_manager_service_perimeter" "regular" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dynamic "ingress_policies" {
|
dynamic "ingress_policies" {
|
||||||
for_each = status.value.ingress_policies == null ? [] : [
|
for_each = [
|
||||||
for k in status.value.ingress_policies :
|
for k in coalesce(status.value.ingress_policies, []) :
|
||||||
merge(local.ingress_policies[k], { key = k })
|
merge(local.ingress_policies[k], { key = k })
|
||||||
]
|
]
|
||||||
iterator = policy
|
iterator = policy
|
||||||
@@ -406,6 +414,16 @@ resource "google_access_context_manager_service_perimeter" "regular" {
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
lifecycle {
|
||||||
|
precondition {
|
||||||
|
condition = length(local._undefined_ingress_policies[each.key]) == 0
|
||||||
|
error_message = "Undefined ingress policies: ${join(", ", local._undefined_ingress_policies[each.key])}"
|
||||||
|
}
|
||||||
|
precondition {
|
||||||
|
condition = length(local._undefined_egress_policies[each.key]) == 0
|
||||||
|
error_message = "Undefined egress policies: ${join(", ", local._undefined_egress_policies[each.key])}"
|
||||||
|
}
|
||||||
|
}
|
||||||
depends_on = [
|
depends_on = [
|
||||||
google_access_context_manager_access_policy.default,
|
google_access_context_manager_access_policy.default,
|
||||||
google_access_context_manager_access_level.basic
|
google_access_context_manager_access_level.basic
|
||||||
|
|||||||
@@ -226,22 +226,22 @@ variable "perimeters" {
|
|||||||
title = optional(string)
|
title = optional(string)
|
||||||
use_explicit_dry_run_spec = optional(bool, false)
|
use_explicit_dry_run_spec = optional(bool, false)
|
||||||
spec = optional(object({
|
spec = optional(object({
|
||||||
access_levels = optional(list(string))
|
access_levels = optional(list(string), [])
|
||||||
egress_policies = optional(list(string))
|
egress_policies = optional(list(string), [])
|
||||||
ingress_policies = optional(list(string))
|
ingress_policies = optional(list(string), [])
|
||||||
restricted_services = optional(list(string))
|
restricted_services = optional(list(string), [])
|
||||||
resources = optional(list(string))
|
resources = optional(list(string), [])
|
||||||
vpc_accessible_services = optional(object({
|
vpc_accessible_services = optional(object({
|
||||||
allowed_services = list(string)
|
allowed_services = list(string)
|
||||||
enable_restriction = optional(bool, true)
|
enable_restriction = optional(bool, true)
|
||||||
}))
|
}))
|
||||||
}))
|
}))
|
||||||
status = optional(object({
|
status = optional(object({
|
||||||
access_levels = optional(list(string))
|
access_levels = optional(list(string), [])
|
||||||
egress_policies = optional(list(string))
|
egress_policies = optional(list(string), [])
|
||||||
ingress_policies = optional(list(string))
|
ingress_policies = optional(list(string), [])
|
||||||
resources = optional(list(string))
|
resources = optional(list(string), [])
|
||||||
restricted_services = optional(list(string))
|
restricted_services = optional(list(string), [])
|
||||||
vpc_accessible_services = optional(object({
|
vpc_accessible_services = optional(object({
|
||||||
allowed_services = list(string)
|
allowed_services = list(string)
|
||||||
enable_restriction = optional(bool, true)
|
enable_restriction = optional(bool, true)
|
||||||
|
|||||||
Reference in New Issue
Block a user