Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: Enable CMEK for Terraform state buckets #1030

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading