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..a4fb0aa24 --- /dev/null +++ b/fast/stages-aw/0-bootstrap/budgets.tf @@ -0,0 +1,47 @@ +/** + * 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. + * 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. + +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-budget" { + source = "../../../modules/billing-account" + count = var.billing_budget_amount != null ? 1 : 0 + id = var.billing_account.id + budgets = { + aw-folder-budget = { + display_name = "Budget for ${local.folder_name} Folder" + 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..b74d318ed 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 = "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]) + }) + default = null +} + variable "bootstrap_project" { description = "Bootstrap project ID." type = string