Help us improve
Share bugs, ideas, or general feedback.
From terraform-aws-eks
AWS infrastructure patterns and best practices for Terraform. Provides VPC, IAM, S3, and security group scaffolds. Use when developing AWS infrastructure.
npx claudepluginhub joshuarweaver/cascade-code-devops-misc-1 --plugin lgbarn-terraform-aws-eksHow this skill is triggered — by the user, by Claude, or both
Slash command
/terraform-aws-eks:skills/aws-patternsThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Terraform patterns for AWS infrastructure development.
Provides AWS production patterns for ECS Fargate with Terraform, 3-tier VPC architecture, IAM least privilege via OIDC, Multi-AZ RDS/ElastiCache, S3 lifecycle, CloudWatch alarms, Secrets Manager rotation. Use for designing architectures, writing Terraform, reviewing IAM.
Provides AWS cloud infrastructure patterns and best practices for EC2, Lambda, S3, RDS, ECS/EKS, including Well-Architected Framework, security, cost optimization, and Terraform IaC examples.
Provides Terraform HCL snippets for AWS compute (ECS/Fargate, EKS, Lambda) and storage (S3) with security-first and production-ready patterns. Useful for infrastructure automation.
Share bugs, ideas, or general feedback.
Terraform patterns for AWS infrastructure development.
ALWAYS use doc-researcher or Terraform MCP to verify current provider schemas.
Use {project}-{environment}-{resource} pattern consistently:
locals {
name_prefix = "${var.project}-${var.environment}"
}
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 5.0"
name = "${local.name_prefix}-vpc"
cidr = var.vpc_cidr # e.g., "10.0.0.0/16"
azs = data.aws_availability_zones.available.names
private_subnets = [for k, v in local.azs : cidrsubnet(var.vpc_cidr, 4, k)]
public_subnets = [for k, v in local.azs : cidrsubnet(var.vpc_cidr, 8, k + 48)]
intra_subnets = [for k, v in local.azs : cidrsubnet(var.vpc_cidr, 8, k + 52)]
enable_nat_gateway = true
single_nat_gateway = var.environment != "prod"
enable_dns_hostnames = true
enable_dns_support = true
# EKS requirements
public_subnet_tags = {
"kubernetes.io/role/elb" = 1
}
private_subnet_tags = {
"kubernetes.io/role/internal-elb" = 1
}
tags = var.tags
}
data "aws_availability_zones" "available" {
state = "available"
}
locals {
azs = slice(data.aws_availability_zones.available.names, 0, 3)
}
module "vpc_endpoints" {
source = "terraform-aws-modules/vpc/aws//modules/vpc-endpoints"
version = "~> 5.0"
vpc_id = module.vpc.vpc_id
endpoints = {
s3 = {
service = "s3"
service_type = "Gateway"
route_table_ids = module.vpc.private_route_table_ids
tags = { Name = "${local.name_prefix}-s3-endpoint" }
}
ecr_api = {
service = "ecr.api"
private_dns_enabled = true
subnet_ids = module.vpc.private_subnets
security_group_ids = [aws_security_group.vpc_endpoints.id]
}
ecr_dkr = {
service = "ecr.dkr"
private_dns_enabled = true
subnet_ids = module.vpc.private_subnets
security_group_ids = [aws_security_group.vpc_endpoints.id]
}
sts = {
service = "sts"
private_dns_enabled = true
subnet_ids = module.vpc.private_subnets
security_group_ids = [aws_security_group.vpc_endpoints.id]
}
}
tags = var.tags
}
resource "aws_security_group" "vpc_endpoints" {
name_prefix = "${local.name_prefix}-vpc-endpoints-"
vpc_id = module.vpc.vpc_id
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = [module.vpc.vpc_cidr_block]
}
tags = merge(var.tags, { Name = "${local.name_prefix}-vpc-endpoints" })
}
data "aws_iam_policy_document" "assume_role" {
statement {
effect = "Allow"
principals {
type = "Service"
identifiers = ["ec2.amazonaws.com"]
}
actions = ["sts:AssumeRole"]
}
}
resource "aws_iam_role" "service" {
name = "${local.name_prefix}-service-role"
assume_role_policy = data.aws_iam_policy_document.assume_role.json
tags = var.tags
}
resource "aws_iam_instance_profile" "service" {
name = "${local.name_prefix}-service-profile"
role = aws_iam_role.service.name
}
data "aws_iam_policy_document" "permissions" {
statement {
sid = "S3ReadAccess"
effect = "Allow"
actions = [
"s3:GetObject",
"s3:ListBucket"
]
resources = [
aws_s3_bucket.data.arn,
"${aws_s3_bucket.data.arn}/*"
]
}
statement {
sid = "SecretsManagerAccess"
effect = "Allow"
actions = [
"secretsmanager:GetSecretValue"
]
resources = [
"arn:aws:secretsmanager:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:secret:${var.project}/*"
]
}
}
resource "aws_iam_role_policy" "service" {
name = "${local.name_prefix}-service-policy"
role = aws_iam_role.service.id
policy = data.aws_iam_policy_document.permissions.json
}
data "aws_caller_identity" "current" {}
data "aws_region" "current" {}
locals {
account_id = data.aws_caller_identity.current.account_id
region = data.aws_region.current.name
}
resource "aws_s3_bucket" "data" {
bucket = "${local.name_prefix}-data-${local.account_id}"
tags = var.tags
}
resource "aws_s3_bucket_versioning" "data" {
bucket = aws_s3_bucket.data.id
versioning_configuration {
status = "Enabled"
}
}
resource "aws_s3_bucket_server_side_encryption_configuration" "data" {
bucket = aws_s3_bucket.data.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "aws:kms"
kms_master_key_id = aws_kms_key.s3.arn
}
bucket_key_enabled = true
}
}
resource "aws_s3_bucket_public_access_block" "data" {
bucket = aws_s3_bucket.data.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
resource "aws_s3_bucket_lifecycle_configuration" "data" {
bucket = aws_s3_bucket.data.id
rule {
id = "transition-to-ia"
status = "Enabled"
transition {
days = 30
storage_class = "STANDARD_IA"
}
transition {
days = 90
storage_class = "GLACIER"
}
noncurrent_version_expiration {
noncurrent_days = 30
}
}
}
# ALB Security Group - Public facing
resource "aws_security_group" "alb" {
name_prefix = "${local.name_prefix}-alb-"
vpc_id = module.vpc.vpc_id
ingress {
description = "HTTPS from internet"
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
lifecycle {
create_before_destroy = true
}
tags = merge(var.tags, { Name = "${local.name_prefix}-alb" })
}
# Application Security Group - Only from ALB
resource "aws_security_group" "app" {
name_prefix = "${local.name_prefix}-app-"
vpc_id = module.vpc.vpc_id
ingress {
description = "From ALB"
from_port = 8080
to_port = 8080
protocol = "tcp"
security_groups = [aws_security_group.alb.id]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
lifecycle {
create_before_destroy = true
}
tags = merge(var.tags, { Name = "${local.name_prefix}-app" })
}
# Database Security Group - Only from App
resource "aws_security_group" "db" {
name_prefix = "${local.name_prefix}-db-"
vpc_id = module.vpc.vpc_id
ingress {
description = "PostgreSQL from app"
from_port = 5432
to_port = 5432
protocol = "tcp"
security_groups = [aws_security_group.app.id]
}
lifecycle {
create_before_destroy = true
}
tags = merge(var.tags, { Name = "${local.name_prefix}-db" })
}
resource "aws_kms_key" "main" {
description = "KMS key for ${local.name_prefix}"
deletion_window_in_days = 7
enable_key_rotation = true
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "Enable IAM User Permissions"
Effect = "Allow"
Principal = {
AWS = "arn:aws:iam::${local.account_id}:root"
}
Action = "kms:*"
Resource = "*"
}
]
})
tags = var.tags
}
resource "aws_kms_alias" "main" {
name = "alias/${local.name_prefix}-main"
target_key_id = aws_kms_key.main.key_id
}
variable "project" {
description = "Project name for resource naming and tagging"
type = string
}
variable "environment" {
description = "Environment name (dev, staging, prod)"
type = string
validation {
condition = contains(["dev", "staging", "prod"], var.environment)
error_message = "Environment must be dev, staging, or prod."
}
}
variable "additional_tags" {
description = "Additional tags to apply to all resources"
type = map(string)
default = {}
}
locals {
default_tags = {
Project = var.project
Environment = var.environment
Terraform = "true"
ManagedBy = "terraform"
}
tags = merge(local.default_tags, var.additional_tags)
}
# Current AWS context
data "aws_caller_identity" "current" {}
data "aws_region" "current" {}
data "aws_partition" "current" {}
# Availability zones
data "aws_availability_zones" "available" {
state = "available"
}
# Latest Amazon Linux 2 AMI
data "aws_ami" "amazon_linux_2" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["amzn2-ami-hvm-*-x86_64-gp2"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
}
# SSM Parameter for EKS AMI
data "aws_ssm_parameter" "eks_ami" {
name = "/aws/service/eks/optimized-ami/${var.cluster_version}/amazon-linux-2/recommended/image_id"
}