feat: Terraform Foundation - AWS Landing Zone

Enterprise-grade multi-tenant AWS cloud foundation.

Modules:
- GitHub OIDC for keyless CI/CD authentication
- IAM account settings and security baseline
- AWS Config Rules for compliance
- ABAC (Attribute-Based Access Control)
- SCPs (Service Control Policies)

Features:
- Multi-account architecture
- Cost optimization patterns
- Security best practices
- Comprehensive documentation

Tech: Terraform, AWS Organizations, IAM Identity Center
This commit is contained in:
2026-02-01 20:06:28 +00:00
commit 6136cde9bb
145 changed files with 30832 additions and 0 deletions

View File

@@ -0,0 +1,38 @@
# tenant-budget
Terraform module for AWS landing zone pattern.
Create tenant-specific AWS budget alerts.
## Planned Features
- [ ] Monthly budget with configurable limit
- [ ] Multi-threshold alerts (50%, 80%, 100%, 120%)
- [ ] Cost allocation tag filtering
- [ ] SNS and email notifications
- [ ] Forecasted spend alerts
- [ ] Auto-actions at budget limits (optional)
## Planned Usage
```hcl
module "tenant_budget" {
source = "../modules/tenant-budget"
tenant_name = "acme-corp"
budget_limit = 500
alert_thresholds = [50, 80, 100]
notification_emails = [
"billing@acme.com",
"admin@acme.com"
]
cost_filter_tags = {
Tenant = "acme-corp"
}
enable_forecasted_alerts = true
}
```

View File

@@ -0,0 +1,144 @@
################################################################################
# Tenant Budget Module
#
# Creates tenant-specific budget with alerts:
# - Monthly budget with configurable limit
# - Multi-threshold alerts
# - Cost allocation tag filtering
# - SNS and email notifications
################################################################################
terraform {
required_version = ">= 1.5.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.0"
}
}
}
data "aws_caller_identity" "current" {}
locals {
account_id = data.aws_caller_identity.current.account_id
# Build cost filters from tags
cost_filters = length(var.cost_filter_tags) > 0 ? {
TagKeyValue = [for k, v in var.cost_filter_tags : "user:${k}$${v}"]
} : {}
}
################################################################################
# SNS Topic for Budget Alerts
################################################################################
resource "aws_sns_topic" "budget" {
count = var.create_sns_topic ? 1 : 0
name = "${var.name}-budget-alerts"
tags = merge(var.tags, {
Name = "${var.name}-budget-alerts"
})
}
resource "aws_sns_topic_policy" "budget" {
count = var.create_sns_topic ? 1 : 0
arn = aws_sns_topic.budget[0].arn
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "AllowBudgetsPublish"
Effect = "Allow"
Principal = {
Service = "budgets.amazonaws.com"
}
Action = "sns:Publish"
Resource = aws_sns_topic.budget[0].arn
Condition = {
StringEquals = {
"aws:SourceAccount" = local.account_id
}
}
}
]
})
}
resource "aws_sns_topic_subscription" "email" {
for_each = var.create_sns_topic ? toset(var.notification_emails) : []
topic_arn = aws_sns_topic.budget[0].arn
protocol = "email"
endpoint = each.value
}
################################################################################
# Budget
################################################################################
resource "aws_budgets_budget" "this" {
name = "${var.name}-monthly-budget"
budget_type = "COST"
limit_amount = tostring(var.budget_limit)
limit_unit = "USD"
time_unit = "MONTHLY"
# Optional: Filter by cost allocation tags
dynamic "cost_filter" {
for_each = local.cost_filters
content {
name = cost_filter.key
values = cost_filter.value
}
}
cost_types {
include_credit = false
include_discount = true
include_other_subscription = true
include_recurring = true
include_refund = false
include_subscription = true
include_support = true
include_tax = true
include_upfront = true
use_amortized = false
use_blended = false
}
# Actual spend notifications
dynamic "notification" {
for_each = var.alert_thresholds
content {
comparison_operator = "GREATER_THAN"
threshold = notification.value
threshold_type = "PERCENTAGE"
notification_type = "ACTUAL"
subscriber_email_addresses = var.create_sns_topic ? [] : var.notification_emails
subscriber_sns_topic_arns = var.create_sns_topic ? [aws_sns_topic.budget[0].arn] : (var.sns_topic_arn != null ? [var.sns_topic_arn] : [])
}
}
# Forecasted spend notifications
dynamic "notification" {
for_each = var.enable_forecasted_alerts ? var.forecasted_thresholds : []
content {
comparison_operator = "GREATER_THAN"
threshold = notification.value
threshold_type = "PERCENTAGE"
notification_type = "FORECASTED"
subscriber_email_addresses = var.create_sns_topic ? [] : var.notification_emails
subscriber_sns_topic_arns = var.create_sns_topic ? [aws_sns_topic.budget[0].arn] : (var.sns_topic_arn != null ? [var.sns_topic_arn] : [])
}
}
tags = merge(var.tags, {
Name = "${var.name}-monthly-budget"
Tenant = var.name
})
}

View File

@@ -0,0 +1,28 @@
################################################################################
# Tenant Budget - Outputs
################################################################################
output "budget_id" {
value = aws_budgets_budget.this.id
description = "Budget ID"
}
output "budget_name" {
value = aws_budgets_budget.this.name
description = "Budget name"
}
output "budget_limit" {
value = var.budget_limit
description = "Budget limit in USD"
}
output "sns_topic_arn" {
value = var.create_sns_topic ? aws_sns_topic.budget[0].arn : var.sns_topic_arn
description = "SNS topic ARN for budget alerts"
}
output "alert_thresholds" {
value = var.alert_thresholds
description = "Configured alert thresholds"
}

View File

@@ -0,0 +1,61 @@
################################################################################
# Tenant Budget - Input Variables
################################################################################
variable "name" {
type = string
description = "Tenant/budget name"
}
variable "budget_limit" {
type = number
description = "Monthly budget limit in USD"
}
variable "alert_thresholds" {
type = list(number)
default = [50, 80, 100]
description = "Percentage thresholds for actual spend alerts"
}
variable "enable_forecasted_alerts" {
type = bool
default = true
description = "Enable forecasted spend alerts"
}
variable "forecasted_thresholds" {
type = list(number)
default = [100]
description = "Percentage thresholds for forecasted spend alerts"
}
variable "notification_emails" {
type = list(string)
default = []
description = "Email addresses for budget alerts"
}
variable "create_sns_topic" {
type = bool
default = true
description = "Create SNS topic for alerts"
}
variable "sns_topic_arn" {
type = string
default = null
description = "Existing SNS topic ARN (if not creating)"
}
variable "cost_filter_tags" {
type = map(string)
default = {}
description = "Cost allocation tags to filter by"
}
variable "tags" {
type = map(string)
default = {}
description = "Tags to apply to resources"
}