From 20ebefa7c72b89897a39ecd965d8bd56cc69baef Mon Sep 17 00:00:00 2001 From: Calvin Cheng Date: Mon, 8 Jun 2026 16:46:24 +0000 Subject: [PATCH 1/3] Add optional billing budgets for AW folder and updated associated docs. --- fast/stages-aw/0-bootstrap/README.md | 5 +++ fast/stages-aw/0-bootstrap/budgets.tf | 43 +++++++++++++++++++ .../0-bootstrap/terraform.tfvars.sample | 5 +++ fast/stages-aw/0-bootstrap/variables.tf | 9 ++++ 4 files changed, 62 insertions(+) create mode 100644 fast/stages-aw/0-bootstrap/budgets.tf diff --git a/fast/stages-aw/0-bootstrap/README.md b/fast/stages-aw/0-bootstrap/README.md index 93423fe18..9edeed107 100644 --- a/fast/stages-aw/0-bootstrap/README.md +++ b/fast/stages-aw/0-bootstrap/README.md @@ -114,6 +114,10 @@ For details on configuring the different billing account modes, refer to the [Ho Due to limitations of API availability, manual steps have to be followed to enable billing export within the billing Google Cloud Project to BigQuery dataset `billing_export`, which will be created as part of the bootstrap stage. The process to share billing data [is outlined here](https://cloud.google.com/billing/docs/how-to/export-data-bigquery-setup#enable-bq-export). +#### Billing Budgets + +A default billing budget can be created for the top-level folder of the landing zone by setting the `billing_budget_amount` variable. This budget will cover all projects created within the Assured Workload folder (or the "no-compliance" folder if Assured Workloads are disabled). The variable is an object that allows specifying the budget amount and optional threshold rules (defaults to 0.5, 0.75, and 0.9). + ### Google Cloud Organization Level Logging We create Google Cloud Organization level log sinks early in the bootstrap process to ensure a proper audit trail is in place from the very beginning. By default, we provide log filters to capture [Cloud Audit Logs](https://cloud.google.com/logging/docs/audit), [VPC Service Controls violations](https://cloud.google.com/vpc-service-controls/docs/troubleshooting#vpc-sc-errors) and [Workspace Logs](https://cloud.google.com/logging/docs/audit/configure-gsuite-audit-logs) into logging buckets in the top-level audit logging Google Cloud Project. In addition, a log sink with an empty filter is included to comply with [Center for Internet Security (CIS) Benchmarks](https://cloud.google.com/security/compliance/cis) related to log sinks. @@ -374,6 +378,7 @@ The `fast_features` variable consists of 4 toggles |---|---|:---:|:---:|:---:| | [alert_email](variables.tf#L16) | Email to receive log alerts. | string | ✓ | | | [billing_account](variables.tf#L34) | Billing account id. If billing account is not part of the same org set `is_org_level` to `false`. To disable handling of billing IAM roles set `no_iam` to `true`. | object({…}) | ✓ | | +| [billing_budget_amount](variables.tf#L44) | Budget configuration for the AW folder. Includes amount and optional threshold rules (defaults to 0.5, 0.75, 0.9). If null, no budget will be created. | object({…}) | | null | | [bootstrap_project](variables.tf#L44) | Bootstrap project ID. | string | ✓ | | | [organization](variables.tf#L260) | Organization details. | object({…}) | ✓ | | | [prefix](variables.tf#L275) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | diff --git a/fast/stages-aw/0-bootstrap/budgets.tf b/fast/stages-aw/0-bootstrap/budgets.tf new file mode 100644 index 000000000..83435e62c --- /dev/null +++ b/fast/stages-aw/0-bootstrap/budgets.tf @@ -0,0 +1,43 @@ +/** + * 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. + * 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. + */ + +# tfdoc:file:description Billing budgets. + +module "billing-account" { + source = "../../../modules/billing-account" + count = var.billing_budget_amount != null ? 1 : 0 + id = var.billing_account.id + budgets = { + aw-folder-budget = { + display_name = "AW Folder Budget - ${var.prefix}" + amount = { + units = var.billing_budget_amount.amount + } + threshold_rules = [ + for t in var.billing_budget_amount.threshold_rules : { + percent = t + } + ] + filter = { + resource_ancestors = [ + var.assured_workloads.regime != "COMPLIANCE_REGIME_UNSPECIFIED" + ? "folders/${google_assured_workloads_workload.primary[0].resources[0].resource_id}" + : module.no-compliance-folder[0].folder.id + ] + } + } + } +} diff --git a/fast/stages-aw/0-bootstrap/terraform.tfvars.sample b/fast/stages-aw/0-bootstrap/terraform.tfvars.sample index b71fd8c14..1019c9b4e 100644 --- a/fast/stages-aw/0-bootstrap/terraform.tfvars.sample +++ b/fast/stages-aw/0-bootstrap/terraform.tfvars.sample @@ -4,6 +4,11 @@ billing_account = { id = "012345-67890A-BCDEF0" } +# Optional Billing budget for the Assured Workload folder. If not set, no budget will be created. +# billing_budget_amount = { +# amount = 1000 +# } + # region configuration - this will automatically populate locations for GCS, BigQuery, KMS, and logging buckets # Default to us-east4 for IL5/FedRAMP compliance - adjust as needed regions = { diff --git a/fast/stages-aw/0-bootstrap/variables.tf b/fast/stages-aw/0-bootstrap/variables.tf index 5385cef11..006ff3185 100644 --- a/fast/stages-aw/0-bootstrap/variables.tf +++ b/fast/stages-aw/0-bootstrap/variables.tf @@ -41,6 +41,15 @@ variable "billing_account" { nullable = false } +variable "billing_budget_amount" { + description = "Budget configuration for the AW folder. Includes amount and optional threshold rules (defaults to 0.5, 0.75, 0.9). If null, no budget will be created." + type = object({ + amount = number + threshold_rules = optional(list(number), [0.5, 0.75, 0.9]) + }) + default = null +} + variable "bootstrap_project" { description = "Bootstrap project ID." type = string From cadd3b50ceb94d8cbae7b73291f3094e32db7cc7 Mon Sep 17 00:00:00 2001 From: Calvin Cheng Date: Mon, 8 Jun 2026 17:57:31 +0000 Subject: [PATCH 2/3] Update budgets.tf with copyright and locals var. --- fast/stages-aw/0-bootstrap/budgets.tf | 8 ++++++-- fast/stages-aw/0-bootstrap/variables.tf | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/fast/stages-aw/0-bootstrap/budgets.tf b/fast/stages-aw/0-bootstrap/budgets.tf index 83435e62c..6d5768a64 100644 --- a/fast/stages-aw/0-bootstrap/budgets.tf +++ b/fast/stages-aw/0-bootstrap/budgets.tf @@ -1,5 +1,5 @@ /** - * Copyright 2024 Google LLC + * Copyright 2026 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,13 +16,17 @@ # tfdoc:file:description Billing budgets. +locals { + folder_name = var.assured_workloads.regime != "COMPLIANCE_REGIME_UNSPECIFIED" ? "${google_assured_workloads_workload.primary[0].display_name}" : "${module.no-compliance-folder[0].folder.name}" +} + module "billing-account" { source = "../../../modules/billing-account" count = var.billing_budget_amount != null ? 1 : 0 id = var.billing_account.id budgets = { aw-folder-budget = { - display_name = "AW Folder Budget - ${var.prefix}" + display_name = "Budget for ${local.folder_name} Folder" amount = { units = var.billing_budget_amount.amount } diff --git a/fast/stages-aw/0-bootstrap/variables.tf b/fast/stages-aw/0-bootstrap/variables.tf index 006ff3185..b74d318ed 100644 --- a/fast/stages-aw/0-bootstrap/variables.tf +++ b/fast/stages-aw/0-bootstrap/variables.tf @@ -42,7 +42,7 @@ variable "billing_account" { } variable "billing_budget_amount" { - description = "Budget configuration for the AW folder. Includes amount and optional threshold rules (defaults to 0.5, 0.75, 0.9). If null, no budget will be created." + description = "Optional Budget configuration for the AW folder. Includes amount and optional threshold rules (defaults to 0.5, 0.75, 0.9). If null, no budget will be created." type = object({ amount = number threshold_rules = optional(list(number), [0.5, 0.75, 0.9]) From 416823f7fc491c26b33f5bd52b90a610dfaabf6a Mon Sep 17 00:00:00 2001 From: Calvin Cheng Date: Tue, 9 Jun 2026 20:00:29 +0000 Subject: [PATCH 3/3] Update module to billing-account-budget --- fast/stages-aw/0-bootstrap/budgets.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fast/stages-aw/0-bootstrap/budgets.tf b/fast/stages-aw/0-bootstrap/budgets.tf index 6d5768a64..a4fb0aa24 100644 --- a/fast/stages-aw/0-bootstrap/budgets.tf +++ b/fast/stages-aw/0-bootstrap/budgets.tf @@ -20,7 +20,7 @@ locals { folder_name = var.assured_workloads.regime != "COMPLIANCE_REGIME_UNSPECIFIED" ? "${google_assured_workloads_workload.primary[0].display_name}" : "${module.no-compliance-folder[0].folder.name}" } -module "billing-account" { +module "billing-account-budget" { source = "../../../modules/billing-account" count = var.billing_budget_amount != null ? 1 : 0 id = var.billing_account.id