Skip to content

Commit

Permalink
FAST security stage refactor (#2203)
Browse files Browse the repository at this point in the history
* first working change, missing docs and tests

* fixes

* tests

* boilerplate

* tfdoc
  • Loading branch information
ludoo authored Apr 8, 2024
1 parent c420f17 commit 8511170
Show file tree
Hide file tree
Showing 19 changed files with 290 additions and 1,559 deletions.
1 change: 1 addition & 0 deletions fast/stages/0-bootstrap/automation.tf
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ module "automation-project" {
"bigqueryreservation.googleapis.com",
"bigquerystorage.googleapis.com",
"billingbudgets.googleapis.com",
"cloudasset.googleapis.com",
"cloudbilling.googleapis.com",
"cloudkms.googleapis.com",
"cloudresourcemanager.googleapis.com",
Expand Down
1 change: 1 addition & 0 deletions fast/stages/0-bootstrap/organization.tf
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ module "organization" {
"api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([%s])",
join(",", formatlist("'%s'", [
"roles/accesscontextmanager.policyAdmin",
"roles/cloudasset.viewer",
"roles/compute.orgFirewallPolicyAdmin",
"roles/compute.xpnAdmin",
"roles/orgpolicy.policyAdmin",
Expand Down
4 changes: 4 additions & 0 deletions fast/stages/1-resman/organization-iam.tf
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ locals {
member = module.branch-network-sa.iam_email
role = "roles/compute.xpnAdmin"
}
sa_sec_asset_viewer = {
member = module.branch-security-sa.iam_email
role = "roles/cloudasset.viewer"
}
sa_sec_vpcsc_admin = {
member = module.branch-security-sa.iam_email
role = "roles/accesscontextmanager.policyAdmin"
Expand Down
169 changes: 56 additions & 113 deletions fast/stages/2-security/README.md

Large diffs are not rendered by default.

Binary file modified fast/stages/2-security/diagram.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1,157 changes: 0 additions & 1,157 deletions fast/stages/2-security/diagram.svg

This file was deleted.

20 changes: 6 additions & 14 deletions fast/stages/2-security/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ locals {
}
}

# generate files for subsequent stages

resource "local_file" "tfvars" {
for_each = var.outputs_location == null ? {} : { 1 = 1 }
file_permission = "0644"
Expand All @@ -54,25 +52,19 @@ resource "google_storage_bucket_object" "tfvars" {
content = jsonencode(local.tfvars)
}

# outputs

output "kms_keys" {
description = "KMS key ids."
value = local.output_kms_keys
}

output "stage_perimeter_projects" {
description = "Security project numbers. They can be added to perimeter resources."
value = {
dev = ["projects/${module.dev-sec-project.number}"]
prod = ["projects/${module.prod-sec-project.number}"]
}
}

# ready to use variable values for subsequent stages

output "tfvars" {
description = "Terraform variable files for the following stages."
sensitive = true
value = local.tfvars
}

output "vpc_sc_perimeter_default" {
description = "Raw default perimeter resource."
sensitive = true
value = try(module.vpc-sc.0.service_perimeters_regular["default"], null)
}
133 changes: 43 additions & 90 deletions fast/stages/2-security/variables.tf
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright 2023 Google LLC
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -41,6 +41,20 @@ variable "essential_contacts" {
default = null
}

variable "factories_config" {
description = "Paths to folders that enable factory functionality."
type = object({
vpc_sc = optional(object({
access_levels = optional(string, "data/vpc-sc/access-levels")
egress_policies = optional(string, "data/vpc-sc/egress-policies")
ingress_policies = optional(string, "data/vpc-sc/ingress-policies")
restricted_services = optional(string, "data/vpc-sc/restricted-services.yaml")
}), {})
})
nullable = false
default = {}
}

variable "folder_ids" {
# tfdoc:variable:source 1-resman
description = "Folder name => id mappings, the 'security' folder name must exist."
Expand All @@ -52,9 +66,11 @@ variable "folder_ids" {
variable "kms_keys" {
description = "KMS keys to create, keyed by name."
type = map(object({
rotation_period = optional(string, "7776000s")
labels = optional(map(string))
locations = optional(list(string), ["europe", "europe-west1", "europe-west3", "global"])
rotation_period = optional(string, "7776000s")
labels = optional(map(string))
locations = optional(list(string), [
"europe", "europe-west1", "europe-west3", "global"
])
purpose = optional(string, "ENCRYPT_DECRYPT")
skip_initial_version_creation = optional(bool, false)
version_template = optional(object({
Expand Down Expand Up @@ -86,6 +102,16 @@ variable "kms_keys" {
nullable = false
}

variable "logging" {
# tfdoc:variable:source 0-bootstrap
description = "Log writer identities for organization / folders."
type = object({
project_number = string
writer_identities = map(string)
})
default = null
}

variable "organization" {
# tfdoc:variable:source 0-bootstrap
description = "Organization details."
Expand All @@ -106,7 +132,6 @@ variable "prefix" {
# tfdoc:variable:source 0-bootstrap
description = "Prefix used for resources that need unique names. Use 9 characters or less."
type = string

validation {
condition = try(length(var.prefix), 0) < 10
error_message = "Use a maximum of 9 characters for prefix."
Expand All @@ -124,96 +149,24 @@ variable "service_accounts" {
})
}

variable "vpc_sc_access_levels" {
description = "VPC SC access level definitions."
type = 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), [])
})), [])
description = optional(string)
}))
default = {}
nullable = false
}

variable "vpc_sc_egress_policies" {
description = "VPC SC egress policy definitions."
type = map(object({
from = object({
identity_type = optional(string, "ANY_IDENTITY")
identities = optional(list(string))
})
to = object({
operations = optional(list(object({
method_selectors = optional(list(string))
service_name = string
})), [])
resources = optional(list(string))
resource_type_external = optional(bool, false)
})
}))
default = {}
nullable = false
}

variable "vpc_sc_ingress_policies" {
description = "VPC SC ingress policy definitions."
type = map(object({
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))
service_name = string
})), [])
resources = optional(list(string))
})
}))
default = {}
nullable = false
}

variable "vpc_sc_perimeters" {
description = "VPC SC regular perimeter definitions."
variable "vpc_sc" {
description = "VPC SC configuration."
type = object({
dev = optional(object({
access_levels = optional(list(string), [])
egress_policies = optional(list(string), [])
ingress_policies = optional(list(string), [])
resources = optional(list(string), [])
}), {})
landing = optional(object({
access_levels = optional(list(string), [])
egress_policies = optional(list(string), [])
ingress_policies = optional(list(string), [])
resources = optional(list(string), [])
}), {})
prod = optional(object({
access_levels = optional(map(any), {})
egress_policies = optional(map(any), {})
ingress_policies = optional(map(any), {})
perimeter_default = optional(object({
access_levels = optional(list(string), [])
dry_run = optional(bool, false)
egress_policies = optional(list(string), [])
ingress_policies = optional(list(string), [])
resources = optional(list(string), [])
}))
resource_discovery = optional(object({
enabled = optional(bool, true)
ignore_folders = optional(list(string), [])
ignore_projects = optional(list(string), [])
include_projects = optional(list(string), [])
}), {})
})
default = {}
Expand Down
Loading

0 comments on commit 8511170

Please sign in to comment.