Files
client-projects/infrastructure/aws-org/main.tf
T

388 lines
9.2 KiB
Terraform

# Terraform configuration for Syslog Solution LLC AWS Organization
# Infrastructure as Code for business AWS setup
terraform {
required_version = ">= 1.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 6.0"
}
}
# Optional: S3 backend for state management (uncomment when ready)
# backend "s3" {
# bucket = "syslog-terraform-state"
# key = "organization/terraform.tfstate"
# region = "us-east-1"
# encrypt = true
# dynamodb_table = "terraform-locks"
# }
}
# Provider configuration for management account
provider "aws" {
region = var.aws_region
alias = "management"
# Use AWS profile or credentials from environment variables
profile = var.aws_profile
default_tags {
tags = {
Project = "Syslog Solution LLC"
Environment = "Management"
ManagedBy = "Terraform"
Owner = "Syslog Solution LLC"
BusinessUnit = "Infrastructure"
}
}
}
# Data source to get current caller identity (for reference)
data "aws_caller_identity" "management" {
provider = aws.management
}
# Create AWS Organization
resource "aws_organizations_organization" "syslog" {
provider = aws.management
feature_set = "ALL" # ALL or CONSOLIDATED_BILLING
# Enable AWS service access for key services
aws_service_access_principals = [
"cloudtrail.amazonaws.com",
"config.amazonaws.com",
"sso.amazonaws.com",
"ram.amazonaws.com",
"servicecatalog.amazonaws.com",
"member.org.stacksets.cloudformation.amazonaws.com"
]
# Enable policy types
enabled_policy_types = ["SERVICE_CONTROL_POLICY"]
tags = {
Name = "Syslog Solution LLC Organization"
Description = "AWS Organization for Syslog Solution LLC business"
}
}
# Get the root ID for creating OUs
data "aws_organizations_organization" "syslog" {
provider = aws.management
depends_on = [aws_organizations_organization.syslog]
}
# Create Organizational Units (OUs)
resource "aws_organizations_organizational_unit" "management" {
provider = aws.management
name = "Management"
parent_id = data.aws_organizations_organization.syslog.roots[0].id
tags = {
Purpose = "Admin and IAM management"
Tier = "Tier 0"
}
}
resource "aws_organizations_organizational_unit" "security" {
provider = aws.management
name = "Security"
parent_id = data.aws_organizations_organization.syslog.roots[0].id
tags = {
Purpose = "Security tools and monitoring"
Tier = "Tier 0"
}
}
resource "aws_organizations_organizational_unit" "workloads" {
provider = aws.management
name = "Workloads"
parent_id = data.aws_organizations_organization.syslog.roots[0].id
tags = {
Purpose = "Application workloads"
Tier = "Tier 1"
}
}
resource "aws_organizations_organizational_unit" "sandbox" {
provider = aws.management
name = "Sandbox"
parent_id = data.aws_organizations_organization.syslog.roots[0].id
tags = {
Purpose = "Experimentation and testing"
Tier = "Tier 2"
}
}
# Create member accounts
resource "aws_organizations_account" "development" {
provider = aws.management
name = "Syslog Development"
email = var.dev_account_email
# Parent OU - place in Workloads OU
parent_id = aws_organizations_organizational_unit.workloads.id
# IAM user access to billing (optional)
iam_user_access_to_billing = "ALLOW"
tags = {
Environment = "Development"
Purpose = "Development and testing"
}
# Ignore role_name changes (managed by AWS)
lifecycle {
ignore_changes = [role_name]
}
}
resource "aws_organizations_account" "staging" {
provider = aws.management
name = "Syslog Staging"
email = var.staging_account_email
# Parent OU - place in Workloads OU
parent_id = aws_organizations_organizational_unit.workloads.id
# IAM user access to billing (optional)
iam_user_access_to_billing = "ALLOW"
tags = {
Environment = "Staging"
Purpose = "Staging and pre-production"
}
lifecycle {
ignore_changes = [role_name]
}
}
# Create IAM users in management account
resource "aws_iam_user" "syslog_admin" {
provider = aws.management
name = "syslog-admin"
path = "/syslog/"
tags = {
Role = "Administrator"
Description = "Full admin access for Syslog Solution LLC"
}
}
resource "aws_iam_user" "syslog_developer" {
provider = aws.management
name = "syslog-developer"
path = "/syslog/"
tags = {
Role = "Developer"
Description = "Developer access for AWS resources"
}
}
resource "aws_iam_user" "syslog_cicd" {
provider = aws.management
name = "syslog-cicd"
path = "/syslog/"
tags = {
Role = "CI/CD"
Description = "CI/CD pipeline service account"
}
}
# Create IAM groups
resource "aws_iam_group" "syslog_admins" {
provider = aws.management
name = "SyslogAdmins"
path = "/syslog/"
}
resource "aws_iam_group" "syslog_developers" {
provider = aws.management
name = "SyslogDevelopers"
path = "/syslog/"
}
# Add users to groups
resource "aws_iam_group_membership" "admin_membership" {
provider = aws.management
name = "admin-group-membership"
users = [
aws_iam_user.syslog_admin.name
]
group = aws_iam_group.syslog_admins.name
}
resource "aws_iam_group_membership" "developer_membership" {
provider = aws.management
name = "developer-group-membership"
users = [
aws_iam_user.syslog_developer.name,
aws_iam_user.syslog_cicd.name
]
group = aws_iam_group.syslog_developers.name
}
# Create IAM policies
resource "aws_iam_policy" "syslog_admin_policy" {
provider = aws.management
name = "SyslogAdminPolicy"
path = "/syslog/"
description = "Administrative policy for Syslog Solution LLC"
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = "*"
Resource = "*"
}
]
})
}
resource "aws_iam_policy" "syslog_developer_policy" {
provider = aws.management
name = "SyslogDeveloperPolicy"
path = "/syslog/"
description = "Developer policy for AWS resources"
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = [
"ec2:*",
"s3:*",
"lambda:*",
"dynamodb:*",
"rds:*",
"cloudformation:*",
"amplify:*",
"bedrock:*",
"sagemaker:*"
]
Resource = "*"
},
{
Effect = "Allow"
Action = [
"iam:Get*",
"iam:List*",
"iam:PassRole"
]
Resource = "*"
}
]
})
}
# Attach policies to groups
resource "aws_iam_group_policy_attachment" "admin_policy_attach" {
provider = aws.management
group = aws_iam_group.syslog_admins.name
policy_arn = aws_iam_policy.syslog_admin_policy.arn
}
resource "aws_iam_group_policy_attachment" "developer_policy_attach" {
provider = aws.management
group = aws_iam_group.syslog_developers.name
policy_arn = aws_iam_policy.syslog_developer_policy.arn
}
# Create SNS topic for billing alerts
resource "aws_sns_topic" "billing_alerts" {
provider = aws.management
name = "syslog-billing-alerts"
tags = {
Purpose = "Billing notifications"
}
}
# Subscribe email to SNS topic
resource "aws_sns_topic_subscription" "billing_email" {
provider = aws.management
topic_arn = aws_sns_topic.billing_alerts.arn
protocol = "email"
endpoint = var.billing_alert_email
}
# CloudWatch billing alarm
resource "aws_cloudwatch_metric_alarm" "monthly_spend" {
provider = aws.management
alarm_name = "syslog-monthly-spend-over-${var.monthly_spend_threshold}"
comparison_operator = "GreaterThanThreshold"
evaluation_periods = "1"
metric_name = "EstimatedCharges"
namespace = "AWS/Billing"
period = "21600" # 6 hours
statistic = "Maximum"
threshold = var.monthly_spend_threshold
alarm_description = "Monthly AWS spend exceeded ${var.monthly_spend_threshold} USD"
alarm_actions = [aws_sns_topic.billing_alerts.arn]
dimensions = {
Currency = "USD"
}
tags = {
AlertType = "Billing"
}
}
# Create S3 bucket for Terraform state (optional - uncomment when ready)
# resource "aws_s3_bucket" "terraform_state" {
# provider = aws.management
# bucket = "syslog-terraform-state-${data.aws_caller_identity.management.account_id}"
#
# tags = {
# Purpose = "Terraform state storage"
# }
# }
#
# resource "aws_s3_bucket_versioning" "terraform_state" {
# provider = aws.management
# bucket = aws_s3_bucket.terraform_state.id
# versioning_configuration {
# status = "Enabled"
# }
# }
#
# resource "aws_s3_bucket_server_side_encryption_configuration" "terraform_state" {
# provider = aws.management
# bucket = aws_s3_bucket.terraform_state.id
#
# rule {
# apply_server_side_encryption_by_default {
# sse_algorithm = "AES256"
# }
# }
# }
#
# # DynamoDB table for state locking
# resource "aws_dynamodb_table" "terraform_locks" {
# provider = aws.management
# name = "terraform-locks"
# billing_mode = "PAY_PER_REQUEST"
# hash_key = "LockID"
#
# attribute {
# name = "LockID"
# type = "S"
# }
#
# tags = {
# Purpose = "Terraform state locking"
# }
# }