# 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" # } # }