Comprehensive Claude Code guidance system with: - 5 agents: tdd-guardian, code-reviewer, security-scanner, refactor-scan, dependency-audit - 18 skills covering languages (Python, TypeScript, Rust, Go, Java, C#), infrastructure (AWS, Azure, GCP, Terraform, Ansible, Docker/K8s, Database, CI/CD), testing (TDD, UI, Browser), and patterns (Monorepo, API Design, Observability) - 3 hooks: secret detection, auto-formatting, TDD git pre-commit - Strict TDD enforcement with 80%+ coverage requirements - Multi-model strategy: Opus for planning, Sonnet for execution (opusplan) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
12 KiB
12 KiB
name, description
| name | description |
|---|---|
| aws-services | AWS service patterns, IAM best practices, and common architectures. Use when designing or implementing AWS infrastructure. |
AWS Services Skill
Common Architecture Patterns
Web Application (ECS + RDS)
┌─────────────────────────────────────────────────────────────┐
│ VPC │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ Public Subnets ││
│ │ ┌─────────────┐ ┌─────────────┐ ││
│ │ │ ALB │ │ NAT GW │ ││
│ │ └──────┬──────┘ └──────┬──────┘ ││
│ └─────────┼───────────────────────────────────┼───────────┘│
│ │ │ │
│ ┌─────────┼───────────────────────────────────┼───────────┐│
│ │ │ Private Subnets │ ││
│ │ ┌──────▼──────┐ ┌───────▼─────┐ ││
│ │ │ ECS Fargate │ │ RDS │ ││
│ │ │ (Tasks) │───────────────────▶│ PostgreSQL │ ││
│ │ └─────────────┘ └─────────────┘ ││
│ └─────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────┘
Serverless (Lambda + API Gateway)
┌────────────┐ ┌─────────────┐ ┌─────────────┐
│ Route53 │────▶│ API Gateway │────▶│ Lambda │
└────────────┘ └─────────────┘ └──────┬──────┘
│
┌──────────────────────────┼──────────────┐
│ │ │
┌──────▼─────┐ ┌─────────┐ ┌────▼────┐
│ DynamoDB │ │ S3 │ │ Secrets │
└────────────┘ └─────────┘ │ Manager │
└─────────┘
IAM Best Practices
Least Privilege Policy
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowS3ReadSpecificBucket",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::my-app-data-bucket",
"arn:aws:s3:::my-app-data-bucket/*"
]
},
{
"Sid": "AllowSecretsAccess",
"Effect": "Allow",
"Action": [
"secretsmanager:GetSecretValue"
],
"Resource": [
"arn:aws:secretsmanager:eu-west-2:123456789:secret:my-app/*"
]
}
]
}
Trust Policy (for ECS Tasks)
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ecs-tasks.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
Cross-Account Access
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::ACCOUNT_ID:role/CrossAccountRole"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "unique-external-id"
}
}
}
]
}
Secrets Management
Using Secrets Manager
# Python - boto3
import boto3
import json
def get_secret(secret_name: str, region: str = "eu-west-2") -> dict:
client = boto3.client("secretsmanager", region_name=region)
response = client.get_secret_value(SecretId=secret_name)
return json.loads(response["SecretString"])
# Usage
db_creds = get_secret("myapp/prod/database")
connection_string = f"postgresql://{db_creds['username']}:{db_creds['password']}@{db_creds['host']}/{db_creds['database']}"
// TypeScript - AWS SDK v3
import { SecretsManagerClient, GetSecretValueCommand } from "@aws-sdk/client-secrets-manager";
async function getSecret(secretName: string): Promise<Record<string, string>> {
const client = new SecretsManagerClient({ region: "eu-west-2" });
const command = new GetSecretValueCommand({ SecretId: secretName });
const response = await client.send(command);
if (!response.SecretString) {
throw new Error("Secret not found");
}
return JSON.parse(response.SecretString);
}
ECS Task with Secrets
// Task definition
{
"containerDefinitions": [
{
"name": "app",
"secrets": [
{
"name": "DATABASE_PASSWORD",
"valueFrom": "arn:aws:secretsmanager:eu-west-2:123456789:secret:myapp/database:password::"
},
{
"name": "API_KEY",
"valueFrom": "arn:aws:secretsmanager:eu-west-2:123456789:secret:myapp/api-key"
}
]
}
]
}
S3 Patterns
Bucket Policy (Least Privilege)
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowECSTaskAccess",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789:role/ecs-task-role"
},
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": "arn:aws:s3:::my-bucket/uploads/*"
},
{
"Sid": "DenyUnencryptedUploads",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::my-bucket/*",
"Condition": {
"StringNotEquals": {
"s3:x-amz-server-side-encryption": "AES256"
}
}
}
]
}
Presigned URLs
import boto3
from botocore.config import Config
def generate_presigned_url(bucket: str, key: str, expiration: int = 3600) -> str:
"""Generate a presigned URL for S3 object access."""
s3_client = boto3.client(
"s3",
config=Config(signature_version="s3v4"),
region_name="eu-west-2"
)
return s3_client.generate_presigned_url(
"get_object",
Params={"Bucket": bucket, "Key": key},
ExpiresIn=expiration
)
DynamoDB Patterns
Single Table Design
# Entity types in same table
ENTITY_TYPES = {
"USER": {"PK": "USER#", "SK": "PROFILE"},
"ORDER": {"PK": "USER#", "SK": "ORDER#"},
"PRODUCT": {"PK": "PRODUCT#", "SK": "DETAILS"},
}
# Access patterns
def get_user(user_id: str) -> dict:
return table.get_item(
Key={"PK": f"USER#{user_id}", "SK": "PROFILE"}
)["Item"]
def get_user_orders(user_id: str) -> list:
response = table.query(
KeyConditionExpression="PK = :pk AND begins_with(SK, :sk)",
ExpressionAttributeValues={
":pk": f"USER#{user_id}",
":sk": "ORDER#"
}
)
return response["Items"]
Lambda Patterns
Handler with Error Handling
import json
import logging
from typing import Any
logger = logging.getLogger()
logger.setLevel(logging.INFO)
def handler(event: dict, context: Any) -> dict:
"""Lambda handler with proper error handling."""
try:
logger.info("Processing event", extra={"event": event})
# Process request
body = json.loads(event.get("body", "{}"))
result = process_request(body)
return {
"statusCode": 200,
"headers": {"Content-Type": "application/json"},
"body": json.dumps(result)
}
except ValidationError as e:
logger.warning("Validation error", extra={"error": str(e)})
return {
"statusCode": 400,
"body": json.dumps({"error": str(e)})
}
except Exception as e:
logger.exception("Unexpected error")
return {
"statusCode": 500,
"body": json.dumps({"error": "Internal server error"})
}
Cold Start Optimization
# Initialize outside handler (runs once per container)
import boto3
# These persist across invocations
dynamodb = boto3.resource("dynamodb")
table = dynamodb.Table("my-table")
secrets_client = boto3.client("secretsmanager")
# Cache secrets
_cached_secrets = {}
def get_cached_secret(name: str) -> dict:
if name not in _cached_secrets:
response = secrets_client.get_secret_value(SecretId=name)
_cached_secrets[name] = json.loads(response["SecretString"])
return _cached_secrets[name]
def handler(event, context):
# Use cached resources
secret = get_cached_secret("my-secret")
# ...
CloudWatch Patterns
Structured Logging
import json
import logging
class JsonFormatter(logging.Formatter):
def format(self, record):
log_record = {
"timestamp": self.formatTime(record),
"level": record.levelname,
"message": record.getMessage(),
"logger": record.name,
}
# Add extra fields
if hasattr(record, "extra"):
log_record.update(record.extra)
return json.dumps(log_record)
# Setup
logger = logging.getLogger()
handler = logging.StreamHandler()
handler.setFormatter(JsonFormatter())
logger.addHandler(handler)
# Usage
logger.info("User created", extra={"user_id": "123", "email": "user@example.com"})
Custom Metrics
import boto3
cloudwatch = boto3.client("cloudwatch")
def publish_metric(name: str, value: float, unit: str = "Count"):
cloudwatch.put_metric_data(
Namespace="MyApp",
MetricData=[
{
"MetricName": name,
"Value": value,
"Unit": unit,
"Dimensions": [
{"Name": "Environment", "Value": "prod"},
{"Name": "Service", "Value": "api"},
]
}
]
)
# Usage
publish_metric("OrdersProcessed", 1)
publish_metric("ProcessingTime", 150, "Milliseconds")
CLI Commands
# IAM
aws iam get-role --role-name MyRole
aws iam list-attached-role-policies --role-name MyRole
aws sts get-caller-identity
# S3
aws s3 ls s3://my-bucket/
aws s3 cp file.txt s3://my-bucket/
aws s3 presign s3://my-bucket/file.txt --expires-in 3600
# Secrets Manager
aws secretsmanager get-secret-value --secret-id my-secret
aws secretsmanager list-secrets
# ECS
aws ecs list-clusters
aws ecs describe-services --cluster my-cluster --services my-service
aws ecs update-service --cluster my-cluster --service my-service --force-new-deployment
# Lambda
aws lambda invoke --function-name my-function output.json
aws lambda list-functions
aws logs tail /aws/lambda/my-function --follow
# CloudWatch
aws logs filter-log-events --log-group-name /aws/lambda/my-function --filter-pattern "ERROR"
Security Checklist
- All S3 buckets have versioning enabled
- All S3 buckets block public access (unless explicitly needed)
- Encryption at rest enabled for all data stores
- Encryption in transit (TLS) for all connections
- IAM roles use least privilege
- No long-term credentials (use IAM roles/instance profiles)
- Secrets in Secrets Manager (not env vars or code)
- VPC endpoints for AWS services (avoid public internet)
- Security groups follow principle of least privilege
- CloudTrail enabled for auditing
- GuardDuty enabled for threat detection