Agent skill
aws-patterns
AWS infrastructure patterns and best practices for Terraform. Provides VPC, IAM, S3, and security group scaffolds. Use when developing AWS infrastructure.
Stars
163
Forks
31
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/data/aws-patterns
SKILL.md
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:
hcl
locals {
name_prefix = "${var.project}-${var.environment}"
}
VPC Pattern
Three-Tier VPC with terraform-aws-modules
hcl
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
hcl
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
hcl
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
hcl
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
hcl
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
hcl
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
hcl
# 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
hcl
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
hcl
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
hcl
# 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"
}
Didn't find tool you were looking for?