Claude-skill-registry aws-patterns
AWS infrastructure patterns and best practices for Terraform. Provides VPC, IAM, S3, and security group scaffolds. Use when developing AWS infrastructure.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/aws-patterns" ~/.claude/skills/majiayu000-claude-skill-registry-aws-patterns && rm -rf "$T"
manifest:
skills/data/aws-patterns/SKILL.mdsource content
AWS Patterns
Terraform patterns for AWS infrastructure development.
Before Generating Code
ALWAYS use doc-researcher or Terraform MCP to verify current provider schemas.
Naming Convention
Use
{project}-{environment}-{resource} pattern consistently:
locals { name_prefix = "${var.project}-${var.environment}" }
VPC Pattern
Three-Tier VPC with terraform-aws-modules
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) }
VPC Endpoints for AWS Services
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" }) }
IAM Patterns
Service Role with Assume Policy
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 }
Least Privilege Policy
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 }
Dynamic ARN Construction
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 }
S3 Patterns
Secure Bucket with Encryption and Versioning
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 } } }
Security Group Patterns
Security Group Chaining
# 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" }) }
KMS Pattern
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 }
Tagging Strategy
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) }
Common Data Sources
# 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" }