import * as cdk from "aws-cdk-lib"; import * as budgets from "aws-cdk-lib/aws-budgets"; import { Construct } from "constructs"; export interface GovernanceTogglesProps { /** Physical name of the AWS Budget (account-scoped, e.g. "seahaven-monthly-cost"). */ readonly budgetName: string; /** Monthly cost budget ceiling in USD. */ readonly monthlyLimitUsd: number; /** Email that receives the budget threshold alerts. */ readonly alertEmail: string; } /** * Account-level governance toggles that *are* expressible as CloudFormation * (audit Day 1). Serves both the management-account baseline and member-account * baselines (budget name parameterized per account). * * Closes: * M-10 Monthly AWS Budget with 80% / 100% actual + 100% forecast alerts * * The remaining Day 1 governance items have no CloudFormation resource and are * applied via CLI + documented in the README runbook (Adam's call, Day 1): * M-6 Inspector2 enable (EC2 + Lambda + ECR) * M-3 EBS encryption-by-default * M-7 IAM account password policy * L-8 Billing-metrics preference (us-east-1) * M-11 Cost-allocation tag activation */ export class GovernanceToggles extends Construct { constructor(scope: Construct, id: string, props: GovernanceTogglesProps) { super(scope, id); const subscriber = [ { subscriptionType: "EMAIL", address: props.alertEmail, }, ]; new budgets.CfnBudget(this, "MonthlyCostBudget", { budget: { budgetName: props.budgetName, budgetType: "COST", timeUnit: "MONTHLY", budgetLimit: { amount: props.monthlyLimitUsd, unit: "USD", }, }, notificationsWithSubscribers: [ { notification: { notificationType: "ACTUAL", comparisonOperator: "GREATER_THAN", threshold: 80, thresholdType: "PERCENTAGE", }, subscribers: subscriber, }, { notification: { notificationType: "ACTUAL", comparisonOperator: "GREATER_THAN", threshold: 100, thresholdType: "PERCENTAGE", }, subscribers: subscriber, }, { notification: { notificationType: "FORECASTED", comparisonOperator: "GREATER_THAN", threshold: 100, thresholdType: "PERCENTAGE", }, subscribers: subscriber, }, ], }); cdk.Annotations.of(this).addInfo( "Budget alerts: 80%/100% actual + 100% forecast of $" + props.monthlyLimitUsd + " to " + props.alertEmail ); } }