WAF-COST-020 โ Cost Budgets & Alerting Configured
Description
Cost budgets MUST be defined as IaC resources (not manually in cloud console UIs) for each cloud account, subscription, or project. Budget alerts MUST be configured at 80% and 100% of the budget limit and automatically routed to the workload owner and FinOps team. Budget resources in IaC ensure they are version-controlled, reviewable, and reproducible.
Rationale
| Risk | Description |
|---|---|
Risk |
Uncontrolled cloud spend erodes budget and project viability. |
Risk |
High lock-in or debt decisions are made without financial impact visibility. |
Requirements
-
Cost budgets MUST be defined as IaC resources (not manually in cloud console UIs) for each cloud account, subscription, or project.
-
Budget alerts MUST be configured at 80% and 100% of the budget limit and automatically routed to the workload owner and FinOps team.
Implementation Guidance
-
Document the requirement in a version-controlled policy or standard.
-
Assign ownership and establish a review cadence (e.g., quarterly).
Maturity Levels
| Level | Name | Criteria |
|---|---|---|
L1 |
Ad hoc โ control not consistently applied |
* Manual evidence exists for some workloads, but coverage is unknown. |
L2 |
Standardised โ policy defined and communicated |
* A version-controlled policy, ADR, or standard describes the requirement. |
L3 |
Integrated โ automated validation in CI/CD |
* Terraform checks run automatically on pull requests and report results. |
L4 |
Auditable โ metrics and exceptions tracked |
* Control coverage, failures, and approved exceptions are reported quarterly. |
L5 |
Optimised โ continuous improvement based on data |
* Control effectiveness is measured and iteratively improved. |
Checks
waf-cost-020.tf.aws.budgets-budget-exists
Engine: terraform | Provider: aws | Automated: Yes
AWS budget must be defined as IaC resource
An aws_budgets_budget resource must exist in the Terraform configuration. Budgets set only in the AWS Console are not version-controlled and may be deleted or modified without audit trail.
Scope: resource โ aws_budgets_budget
Assertions:
* budget_type equals COST โ Budget must be of type COST for cloud spend tracking.
* time_unit in ['MONTHLY', 'QUARTERLY', 'DAILY'] โ Budget time unit must be MONTHLY or QUARTERLY.
Remediation: Add an aws_budgets_budget resource to your Terraform configuration. Set budget_type = "COST", time_unit = "MONTHLY", and configure notification blocks for 80% and 100% thresholds.
resource "aws_budgets_budget" "workload_monthly" {
name = "payment-service-prod-monthly"
budget_type = "COST"
limit_amount = "5000"
limit_unit = "USD"
time_unit = "MONTHLY"
notification {
comparison_operator = "GREATER_THAN"
threshold = 80
threshold_type = "PERCENTAGE"
notification_type = "ACTUAL"
subscriber_email_addresses = ["payments-team@company.com"]
}
notification {
comparison_operator = "GREATER_THAN"
threshold = 100
threshold_type = "PERCENTAGE"
notification_type = "ACTUAL"
subscriber_email_addresses = ["payments-team@company.com", "finops@company.com"]
}
}
# No aws_budgets_budget resource defined.
# Budget was set manually in AWS Console โ not reproducible, not version-controlled.
waf-cost-020.tf.azurerm.consumption-budget-defined
Engine: terraform | Provider: azurerm | Automated: Yes
Azure consumption budget must be defined as IaC resource
An azurerm_consumption_budget_resource_group or azurerm_consumption_budget_subscription resource must exist in the Terraform configuration for Azure spending control.
Scope: resource โ azurerm_consumption_budget_resource_group, azurerm_consumption_budget_subscription, azurerm_consumption_budget_management_group
Assertions:
* amount greater than or equal 1 โ Budget amount must be greater than 0.
Remediation: Add an azurerm_consumption_budget_resource_group or azurerm_consumption_budget_subscription resource to your Terraform configuration with appropriate notification thresholds.
resource "azurerm_consumption_budget_resource_group" "main" {
name = "payment-service-monthly-budget"
resource_group_id = azurerm_resource_group.main.id
amount = 5000
time_grain = "Monthly"
time_period {
start_date = "2025-01-01T00:00:00Z"
}
notification {
enabled = true
threshold = 80
operator = "GreaterThan"
threshold_type = "Actual"
contact_emails = ["payments-team@company.com"]
}
notification {
enabled = true
threshold = 100
operator = "GreaterThan"
threshold_type = "Actual"
contact_emails = ["payments-team@company.com", "finops@company.com"]
}
}
# No azurerm_consumption_budget_* resource defined.
# No automated budget control for this Azure workload.
waf-cost-020.tf.google.billing-budget-exists
Engine: terraform | Provider: google | Automated: Yes
GCP billing budget must be defined as IaC resource
A google_billing_budget resource must exist in the Terraform configuration. GCP budgets set only in the Cloud Console are not version-controlled and may be modified without audit trail.
Scope: resource โ google_billing_budget
Assertions:
* billing_account attribute exists โ GCP billing budget must reference a billing account.
* threshold_rules attribute exists โ GCP billing budget must define threshold rules for alerts.
Remediation: Add a google_billing_budget resource to your Terraform configuration. Define billing_account, display_name, amount, and threshold_rules for 80% and 100% of the budget.
resource "google_billing_budget" "workload_monthly" {
billing_account = data.google_billing_account.main.id
display_name = "payment-service-prod-monthly"
amount {
specified_amount {
currency_code = "EUR"
units = "5000"
}
}
threshold_rules {
threshold_percent = 80
}
threshold_rules {
threshold_percent = 100
}
all_updates_rule {
monitoring_notification_channels = [
google_monitoring_notification_channel.finops.id,
google_monitoring_notification_channel.owner.id,
]
disable_default_iam_recipients = false
}
}
# No google_billing_budget resource defined.
# Budget was set manually in GCP Console โ not reproducible, not version-controlled.
waf-cost-020.tf.stackit.budget-documented
Engine: terraform | Provider: stackit | Automated: Yes
STACKIT cost budgets must be defined and documented
STACKIT cost budgets must be defined and documented. This check validates the Terraform configuration uses the expected resource and attribute.
Scope: resource โ stackit_project
Assertions:
* labels.budget-alert key exists โ STACKIT project is missing the 'budget-alert' label documenting budget enforcement.
Remediation: Review the Terraform configuration for the listed resource types and ensure the required attribute or tag is present. See the control narrative for provider-specific guidance.
# Example resource meets the requirement.
resource "stackit_project" "example" {
# required attribute/tag/label present
}
# Example resource does not meet the requirement.
resource "stackit_project" "example" {
# Missing required attribute/tag/label
}
waf-cost-020.tf.ovh.budget-documented
Engine: terraform | Provider: ovh | Automated: Yes
OVHcloud cost budgets must be defined and documented
OVHcloud cost budgets must be defined and documented. This check validates the Terraform configuration uses the expected resource and attribute.
Scope: resource โ ovh_cloud_project
Assertions:
* labels.budget-alert key exists โ OVHcloud project is missing the 'budget-alert' label documenting budget enforcement.
Remediation: Review the Terraform configuration for the listed resource types and ensure the required attribute or tag is present. See the control narrative for provider-specific guidance.
# Example resource meets the requirement.
resource "ovh_cloud_project" "example" {
# required attribute/tag/label present
}
# Example resource does not meet the requirement.
resource "ovh_cloud_project" "example" {
# Missing required attribute/tag/label
}
waf-cost-020.tf.hcloud.budget-documented
Engine: terraform | Provider: hcloud | Automated: Yes
Hetzner Cloud cost budgets must be defined and documented
Hetzner Cloud cost budgets must be defined and documented. This check validates the Terraform configuration uses the expected resource and attribute.
Scope: resource โ hcloud_server
Assertions:
* labels.budget-alert key exists โ Hetzner Cloud resource is missing the 'budget-alert' label documenting budget enforcement.
Remediation: Review the Terraform configuration for the listed resource types and ensure the required attribute or tag is present. See the control narrative for provider-specific guidance.
# Example resource meets the requirement.
resource "hcloud_server" "example" {
# required attribute/tag/label present
}
# Example resource does not meet the requirement.
resource "hcloud_server" "example" {
# Missing required attribute/tag/label
}
Evidence
| Kind | Required | Description |
|---|---|---|
|
Required |
Terraform configuration implementing the control. |
|
Required |
Policy, ADR, or standard documenting the requirement. |
|
Optional |
Cloud console or API output confirming runtime state. |