Skip to content

Commit

Permalink
feat!: Enable CMEK for Terraform state buckets (#1030)
Browse files Browse the repository at this point in the history
Co-authored-by: Grant Sorbo <[email protected]>
  • Loading branch information
daniel-cit and gtsorbo authored Dec 12, 2023
1 parent 15bab38 commit 63906d8
Show file tree
Hide file tree
Showing 10 changed files with 55 additions and 27 deletions.
1 change: 1 addition & 0 deletions 0-bootstrap/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,7 @@ Each step has instructions for this change.
| billing\_account | The ID of the billing account to associate projects with. | `string` | n/a | yes |
| bucket\_force\_destroy | When deleting a bucket, this boolean option will delete all contained objects. If false, Terraform will fail to delete buckets which contain objects. | `bool` | `false` | no |
| bucket\_prefix | Name prefix to use for state bucket created. | `string` | `"bkt"` | no |
| bucket\_tfstate\_kms\_force\_destroy | When deleting a bucket, this boolean option will delete the KMS keys used for the Terraform state bucket. | `bool` | `false` | no |
| default\_region | Default region to create resources where applicable. | `string` | `"us-central1"` | no |
| folder\_prefix | Name prefix to use for folders created. Should be the same in all steps. | `string` | `"fldr"` | no |
| group\_billing\_admins | Google Group for GCP Billing Administrators | `string` | n/a | yes |
Expand Down
8 changes: 8 additions & 0 deletions 0-bootstrap/cb.tf
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ locals {

cicd_project_id = module.tf_source.cloudbuild_project_id

state_bucket_kms_key = "projects/${module.seed_bootstrap.seed_project_id}/locations/${var.default_region}/keyRings/${var.project_prefix}-keyring/cryptoKeys/${var.project_prefix}-key"

bucket_self_link_prefix = "https://www.googleapis.com/storage/v1/b/"
default_state_bucket_self_link = "${local.bucket_self_link_prefix}${module.seed_bootstrap.gcs_bucket_tfstate}"
gcp_projects_state_bucket_self_link = module.gcp_projects_state_bucket.bucket.self_link
Expand Down Expand Up @@ -74,6 +76,12 @@ module "gcp_projects_state_bucket" {
project_id = module.seed_bootstrap.seed_project_id
location = var.default_region
force_destroy = var.bucket_force_destroy

encryption = {
default_kms_key_name = local.state_bucket_kms_key
}

depends_on = [module.seed_bootstrap.gcs_bucket_tfstate]
}

module "tf_source" {
Expand Down
3 changes: 3 additions & 0 deletions 0-bootstrap/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ module "seed_bootstrap" {
parent_folder = var.parent_folder == "" ? "" : local.parent
org_admins_org_iam_permissions = local.org_admins_org_iam_permissions
project_prefix = var.project_prefix
encrypt_gcs_bucket_tfstate = true
key_rotation_period = "7776000s"
kms_prevent_destroy = !var.bucket_tfstate_kms_force_destroy

project_labels = {
environment = "bootstrap"
Expand Down
1 change: 1 addition & 0 deletions 0-bootstrap/sa.tf
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ locals {
"roles/storage.admin",
"roles/iam.serviceAccountAdmin",
"roles/resourcemanager.projectDeleter",
"roles/cloudkms.admin",
],
"org" = [
"roles/storage.objectAdmin",
Expand Down
6 changes: 6 additions & 0 deletions 0-bootstrap/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@ variable "bucket_force_destroy" {
default = false
}

variable "bucket_tfstate_kms_force_destroy" {
description = "When deleting a bucket, this boolean option will delete the KMS keys used for the Terraform state bucket."
type = bool
default = false
}

/* ----------------------------------------
Specific to Groups creation
---------------------------------------- */
Expand Down
8 changes: 5 additions & 3 deletions helpers/foundation-deployer/global.tfvars.example
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,11 @@ group_org_admins = "REPLACE_ME" # "[email protected]"
group_billing_admins = "REPLACE_ME" # "[email protected]"
org_project_creators = []

bucket_force_destroy = false
project_prefix = "prj"
folder_prefix = "fldr"
bucket_force_destroy = false
bucket_tfstate_kms_force_destroy = false

project_prefix = "prj"
folder_prefix = "fldr"

// Optional - for an organization with existing projects or for development/validation.
// Uncomment this variable to place all the example foundation resources under
Expand Down
25 changes: 13 additions & 12 deletions helpers/foundation-deployer/stages/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,19 @@ import (

func DeployBootstrapStage(t testing.TB, s steps.Steps, tfvars GlobalTFVars, c CommonConf) error {
bootstrapTfvars := BootstrapTfvars{
OrgID: tfvars.OrgID,
DefaultRegion: tfvars.DefaultRegion,
BillingAccount: tfvars.BillingAccount,
GroupOrgAdmins: tfvars.GroupOrgAdmins,
GroupBillingAdmins: tfvars.GroupBillingAdmins,
OrgProjectCreators: tfvars.OrgProjectCreators,
ParentFolder: tfvars.ParentFolder,
ProjectPrefix: tfvars.ProjectPrefix,
FolderPrefix: tfvars.FolderPrefix,
BucketForceDestroy: tfvars.BucketForceDestroy,
Groups: tfvars.Groups,
InitialGroupConfig: tfvars.InitialGroupConfig,
OrgID: tfvars.OrgID,
DefaultRegion: tfvars.DefaultRegion,
BillingAccount: tfvars.BillingAccount,
GroupOrgAdmins: tfvars.GroupOrgAdmins,
GroupBillingAdmins: tfvars.GroupBillingAdmins,
OrgProjectCreators: tfvars.OrgProjectCreators,
ParentFolder: tfvars.ParentFolder,
ProjectPrefix: tfvars.ProjectPrefix,
FolderPrefix: tfvars.FolderPrefix,
BucketForceDestroy: tfvars.BucketForceDestroy,
BucketTfstateKmsForceDestroy: tfvars.BucketTfstateKmsForceDestroy,
Groups: tfvars.Groups,
InitialGroupConfig: tfvars.InitialGroupConfig,
}

err := utils.WriteTfvars(filepath.Join(c.FoundationPath, BootstrapStep, "terraform.tfvars"), bootstrapTfvars)
Expand Down
26 changes: 14 additions & 12 deletions helpers/foundation-deployer/stages/data.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ type GlobalTFVars struct {
FolderPrefix *string `hcl:"folder_prefix"`
CaiMonitoringKmsForceDestroy *bool `hcl:"cai_monitoring_kms_force_destroy"`
BucketForceDestroy *bool `hcl:"bucket_force_destroy"`
BucketTfstateKmsForceDestroy *bool `hcl:"bucket_tfstate_kms_force_destroy"`
AuditLogsTableDeleteContentsOnDestroy *bool `hcl:"audit_logs_table_delete_contents_on_destroy"`
LogExportStorageForceDestroy *bool `hcl:"log_export_storage_force_destroy"`
LogExportStorageLocation string `hcl:"log_export_storage_location"`
Expand Down Expand Up @@ -193,18 +194,19 @@ func (g GlobalTFVars) CheckString(s string) {
}

type BootstrapTfvars struct {
OrgID string `hcl:"org_id"`
BillingAccount string `hcl:"billing_account"`
GroupOrgAdmins string `hcl:"group_org_admins"`
GroupBillingAdmins string `hcl:"group_billing_admins"`
DefaultRegion string `hcl:"default_region"`
ParentFolder *string `hcl:"parent_folder"`
ProjectPrefix *string `hcl:"project_prefix"`
FolderPrefix *string `hcl:"folder_prefix"`
BucketForceDestroy *bool `hcl:"bucket_force_destroy"`
OrgProjectCreators []string `hcl:"org_project_creators"`
Groups *Groups `hcl:"groups"`
InitialGroupConfig *string `hcl:"initial_group_config"`
OrgID string `hcl:"org_id"`
BillingAccount string `hcl:"billing_account"`
GroupOrgAdmins string `hcl:"group_org_admins"`
GroupBillingAdmins string `hcl:"group_billing_admins"`
DefaultRegion string `hcl:"default_region"`
ParentFolder *string `hcl:"parent_folder"`
ProjectPrefix *string `hcl:"project_prefix"`
FolderPrefix *string `hcl:"folder_prefix"`
BucketForceDestroy *bool `hcl:"bucket_force_destroy"`
BucketTfstateKmsForceDestroy *bool `hcl:"bucket_tfstate_kms_force_destroy"`
OrgProjectCreators []string `hcl:"org_project_creators"`
Groups *Groups `hcl:"groups"`
InitialGroupConfig *string `hcl:"initial_group_config"`
}

type OrgTfvars struct {
Expand Down
3 changes: 3 additions & 0 deletions helpers/foundation-deployer/stages/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ func ValidateDestroyFlags(t testing.TB, g GlobalTFVars) {
if g.LogExportStorageForceDestroy == nil || !*g.LogExportStorageForceDestroy {
flags = append(flags, "log_export_storage_force_destroy")
}
if g.BucketTfstateKmsForceDestroy == nil || !*g.BucketTfstateKmsForceDestroy {
flags = append(flags, "bucket_tfstate_kms_force_destroy")
}
if g.CaiMonitoringKmsForceDestroy == nil || !*g.CaiMonitoringKmsForceDestroy {
flags = append(flags, "cai_monitoring_kms_force_destroy")
}
Expand Down
1 change: 1 addition & 0 deletions test/integration/bootstrap/bootstrap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ func TestBootstrap(t *testing.T) {

vars := map[string]interface{}{
"bucket_force_destroy": true,
"bucket_tfstate_kms_force_destroy": true,
}

temp := tft.NewTFBlueprintTest(t,
Expand Down

0 comments on commit 63906d8

Please sign in to comment.