AWS code-library high security documentation change
Summary
Comprehensive security hardening updates across multiple AWS service examples including ECS, VPC Lattice, EMR, DocumentDB, MediaConnect, EBS, and VPC peering. Changes include input validation, secure file handling, JSON validation, security group rule restrictions, IMDSv2 enforcement, auto-confirmation for cleanup, and removal of interactive prompts.
Security assessment
The changes explicitly address multiple security vulnerabilities: 1) Added input validation for AWS resource IDs (security groups, VPCs, ENIs) to prevent injection attacks, 2) Implemented secure file deletion (shred) for sensitive files, 3) Added JSON validation before processing to prevent malformed input attacks, 4) Enforced IMDSv2 with hop limit 1 to prevent SSRF attacks, 5) Added security warnings about overly permissive security group rules (0.0.0.0/0), 6) Implemented AWS CLI and credential validation, 7) Added CIDR validation, 8) Secured log file permissions (chmod 600), 9) Added command injection prevention through input sanitization. The diff includes explicit security comments like '# Security improvements applied', '# SECURITY FIX:', and 'WARNING: Security group allows HTTP from 0.0.0.0/0'.
Diff
diff --git a/code-library/latest/ug/bash_2_ec2_code_examples.md b/code-library/latest/ug/bash_2_ec2_code_examples.md index 9e1bfbd18..fb521a53e 100644 --- a//code-library/latest/ug/bash_2_ec2_code_examples.md +++ b//code-library/latest/ug/bash_2_ec2_code_examples.md @@ -5192 +5192 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - read -r CLEANUP_CHOICE + CLEANUP_CHOICE="y" @@ -5924,0 +5925 @@ There's more on GitHub. Find the complete example and learn how to set up and ru + # Security improvements applied @@ -5945 +5946 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - # Function to log and execute commands + # Function to log and execute commands with input validation @@ -5948,0 +5950,7 @@ There's more on GitHub. Find the complete example and learn how to set up and ru + + # Validate that cmd is not empty + if [[ -z "$cmd" ]]; then + echo "ERROR: Command is empty" + return 1 + fi + @@ -5987,0 +5996,10 @@ There's more on GitHub. Find the complete example and learn how to set up and ru + # Function to safely extract JSON values + safe_json_extract() { + local json="$1" + local key="$2" + local value + + value=$(echo "$json" | grep -o "\"$key\": \"[^\"]*\"" | cut -d'"' -f4 2>/dev/null || echo "") + echo "$value" + } + @@ -5993,0 +6012,6 @@ There's more on GitHub. Find the complete example and learn how to set up and ru + # Validate security group ID format + if [[ ! "$security_group_id" =~ ^sg-[a-z0-9]{8,17}$ ]]; then + echo "ERROR: Invalid security group ID format: $security_group_id" + return 1 + fi + @@ -6028,0 +6053,6 @@ There's more on GitHub. Find the complete example and learn how to set up and ru + # Validate security group ID format + if [[ ! "$security_group_id" =~ ^sg-[a-z0-9]{8,17}$ ]]; then + echo "ERROR: Invalid security group ID format: $security_group_id" + return 1 + fi + @@ -6032 +6062 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - if execute_command "aws ec2 delete-security-group --group-id $security_group_id" "Delete security group (attempt $attempt)"; then + if execute_command "aws ec2 delete-security-group --group-id '$security_group_id'" "Delete security group (attempt $attempt)"; then @@ -6062,2 +6092,3 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - echo "Do you want to clean up all created resources? (y/n): " - read -r CLEANUP_CHOICE + echo "Auto-confirming cleanup of all created resources..." + + CLEANUP_CHOICE="y" @@ -6072 +6103 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - if execute_command "aws ecs update-service --cluster $CLUSTER_NAME --service $SERVICE_NAME --desired-count 0" "Scale service to 0 tasks"; then + if execute_command "aws ecs update-service --cluster '$CLUSTER_NAME' --service '$SERVICE_NAME' --desired-count 0" "Scale service to 0 tasks"; then @@ -6074 +6105 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - execute_command "aws ecs wait services-stable --cluster $CLUSTER_NAME --services $SERVICE_NAME" "Wait for service to stabilize" + execute_command "aws ecs wait services-stable --cluster '$CLUSTER_NAME' --services '$SERVICE_NAME'" "Wait for service to stabilize" @@ -6077 +6108 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - execute_command "aws ecs delete-service --cluster $CLUSTER_NAME --service $SERVICE_NAME" "Delete ECS service" + execute_command "aws ecs delete-service --cluster '$CLUSTER_NAME' --service '$SERVICE_NAME'" "Delete ECS service" @@ -6080 +6111 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - execute_command "aws ecs delete-service --cluster $CLUSTER_NAME --service $SERVICE_NAME --force" "Force delete ECS service" + execute_command "aws ecs delete-service --cluster '$CLUSTER_NAME' --service '$SERVICE_NAME' --force" "Force delete ECS service" @@ -6093 +6124 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - execute_command "aws ecs delete-cluster --cluster $CLUSTER_NAME" "Delete ECS cluster" + execute_command "aws ecs delete-cluster --cluster '$CLUSTER_NAME'" "Delete ECS cluster" @@ -6097 +6128 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - if [[ -n "$SECURITY_GROUP_ID" ]]; then + if [[ -n "$SECURITY_GROUP_ID" && "$SECURITY_GROUP_ID" != "None" ]]; then @@ -6120 +6151 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - execute_command "aws ecs deregister-task-definition --task-definition $revision_arn" "Deregister task definition $revision_arn" || true + execute_command "aws ecs deregister-task-definition --task-definition '$revision_arn'" "Deregister task definition $revision_arn" || true @@ -6163,0 +6195,5 @@ There's more on GitHub. Find the complete example and learn how to set up and ru + if [[ ! "$ACCOUNT_ID" =~ ^[0-9]{12}$ ]]; then + echo "ERROR: Invalid AWS Account ID retrieved: $ACCOUNT_ID" + exit 1 + fi + @@ -6172 +6208 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - # Create trust policy + # Create trust policy with strict validation @@ -6187,0 +6224,7 @@ There's more on GitHub. Find the complete example and learn how to set up and ru + # Validate JSON before using + if ! jq empty trust-policy.json 2>/dev/null; then + echo "ERROR: Invalid JSON in trust policy" + rm -f trust-policy.json + exit 1 + fi + @@ -6192,2 +6235,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - # Clean up temporary file - rm -f trust-policy.json + # Clean up temporary file securely + shred -vfz -n 3 trust-policy.json 2>/dev/null || rm -f trust-policy.json @@ -6204 +6247 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - CLUSTER_OUTPUT=$(execute_command "aws ecs create-cluster --cluster-name $CLUSTER_NAME" "Create ECS cluster") + CLUSTER_OUTPUT=$(execute_command "aws ecs create-cluster --cluster-name '$CLUSTER_NAME'" "Create ECS cluster") @@ -6215 +6258 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - # Create task definition JSON + # Create task definition JSON with validated inputs @@ -6227 +6270 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - "image": "public.ecr.aws/docker/library/httpd:latest", + "image": "public.ecr.aws/docker/library/httpd:2.4-alpine", @@ -6239 +6282,9 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - ] + ], + "logConfiguration": { + "logDriver": "awslogs", + "options": { + "awslogs-group": "/ecs/fargate-sample", + "awslogs-region": "us-east-1", + "awslogs-stream-prefix": "ecs" + } + } @@ -6244,0 +6296,7 @@ There's more on GitHub. Find the complete example and learn how to set up and ru + # Validate JSON before using + if ! jq empty task-definition.json 2>/dev/null; then + echo "ERROR: Invalid JSON in task definition" + rm -f task-definition.json + exit 1 + fi + @@ -6248,2 +6306,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - # Clean up temporary file - rm -f task-definition.json + # Clean up temporary file securely + shred -vfz -n 3 task-definition.json 2>/dev/null || rm -f task-definition.json @@ -6264,0 +6323,7 @@ There's more on GitHub. Find the complete example and learn how to set up and ru + + # Validate VPC ID format + if [[ ! "$VPC_ID" =~ ^vpc-[a-z0-9]{8,17}$ ]]; then + echo "ERROR: Invalid VPC ID format: $VPC_ID" + exit 1 + fi + @@ -6270 +6335 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - SECURITY_GROUP_OUTPUT=$(execute_command "aws ec2 create-security-group --group-name $SECURITY_GROUP_NAME --description 'Security group for ECS Fargate tutorial - HTTP access' --vpc-id $VPC_ID" "Create security group") + SECURITY_GROUP_OUTPUT=$(execute_command "aws ec2 create-security-group --group-name '$SECURITY_GROUP_NAME' --description 'Security group for ECS Fargate tutorial - HTTP access' --vpc-id '$VPC_ID'" "Create security group") @@ -6273,3 +6338,9 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - SECURITY_GROUP_ID=$(echo "$SECURITY_GROUP_OUTPUT" | grep -o '"GroupId": "[^"]*"' | cut -d'"' -f4) - if [[ -z "$SECURITY_GROUP_ID" ]]; then - SECURITY_GROUP_ID=$(aws ec2 describe-security-groups --group-names "$SECURITY_GROUP_NAME" --query "SecurityGroups[0].GroupId" --output text) + SECURITY_GROUP_ID=$(echo "$SECURITY_GROUP_OUTPUT" | grep -o '"GroupId": "[^"]*"' | head -1 | cut -d'"' -f4) + if [[ -z "$SECURITY_GROUP_ID" || "$SECURITY_GROUP_ID" == "None" ]]; then + SECURITY_GROUP_ID=$(aws ec2 describe-security-groups --group-names "$SECURITY_GROUP_NAME" --filters "Name=vpc-id,Values=$VPC_ID" --query "SecurityGroups[0].GroupId" --output text) + fi + + # Validate security group ID format + if [[ ! "$SECURITY_GROUP_ID" =~ ^sg-[a-z0-9]{8,17}$ ]]; then + echo "ERROR: Invalid security group ID format: $SECURITY_GROUP_ID" + exit 1 @@ -6284 +6355 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - execute_command "aws ec2 authorize-security-group-ingress --group-id $SECURITY_GROUP_ID --protocol tcp --port 80 --cidr 0.0.0.0/0" "Add HTTP inbound rule to security group" + execute_command "aws ec2 authorize-security-group-ingress --group-id '$SECURITY_GROUP_ID' --protocol tcp --port 80 --cidr 0.0.0.0/0" "Add HTTP inbound rule to security group" @@ -6312 +6383 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - SERVICE_CMD="aws ecs create-service --cluster $CLUSTER_NAME --service-name $SERVICE_NAME --task-definition $TASK_FAMILY --desired-count 1 --launch-type FARGATE --network-configuration '{\"awsvpcConfiguration\":{\"subnets\":[\"$(echo $SUBNET_IDS_COMMA | sed 's/,/","/g')\"],\"securityGroups\":[\"$SECURITY_GROUP_ID\"],\"assignPublicIp\":\"ENABLED\"}}'" + SERVICE_CMD="aws ecs create-service --cluster '$CLUSTER_NAME' --service-name '$SERVICE_NAME' --task-definition '$TASK_FAMILY' --desired-count 1 --launch-type FARGATE --network-configuration '{\"awsvpcConfiguration\":{\"subnets\":[\"$(echo "$SUBNET_IDS_COMMA" | sed 's/,/","/g')\"],\"securityGroups\":[\"$SECURITY_GROUP_ID\"],\"assignPublicIp\":\"ENABLED\"}}'" @@ -6328 +6399 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - execute_command "aws ecs wait services-stable --cluster $CLUSTER_NAME --services $SERVICE_NAME" "Wait for service to stabilize" + execute_command "aws ecs wait services-stable --cluster '$CLUSTER_NAME' --services '$SERVICE_NAME'" "Wait for service to stabilize" @@ -6331 +6402 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - TASK_ARN=$(aws ecs list-tasks --cluster $CLUSTER_NAME --service-name $SERVICE_NAME --query "taskArns[0]" --output text) + TASK_ARN=$(aws ecs list-tasks --cluster "$CLUSTER_NAME" --service-name "$SERVICE_NAME" --query "taskArns[0]" --output text) @@ -6340 +6411 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - ENI_ID=$(aws ecs describe-tasks --cluster $CLUSTER_NAME --tasks $TASK_ARN --query "tasks[0].attachments[0].details[?name=='networkInterfaceId'].value" --output text) + ENI_ID=$(aws ecs describe-tasks --cluster "$CLUSTER_NAME" --tasks "$TASK_ARN" --query "tasks[0].attachments[0].details[?name=='networkInterfaceId'].value" --output text) @@ -6345,0 +6417,6 @@ There's more on GitHub. Find the complete example and learn how to set up and ru + # Validate ENI ID format + if [[ ! "$ENI_ID" =~ ^eni-[a-z0-9]{8,17}$ ]]; then + echo "ERROR: Invalid network interface ID format: $ENI_ID" + exit 1 + fi + @@ -6349 +6426 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - PUBLIC_IP=$(aws ec2 describe-network-interfaces --network-interface-ids $ENI_ID --query "NetworkInterfaces[0].Association.PublicIp" --output text) + PUBLIC_IP=$(aws ec2 describe-network-interfaces --network-interface-ids "$ENI_ID" --query "NetworkInterfaces[0].Association.PublicIp" --output text) @@ -6352,0 +6430,5 @@ There's more on GitHub. Find the complete example and learn how to set up and ru + else + # Validate IP format + if [[ ! "$PUBLIC_IP" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then + echo "ERROR: Invalid IP address format: $PUBLIC_IP" + PUBLIC_IP="" @@ -6361,0 +6444 @@ There's more on GitHub. Find the complete example and learn how to set up and ru + fi @@ -6368 +6451 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - execute_command "aws ecs describe-services --cluster $CLUSTER_NAME --services $SERVICE_NAME" "Get service details" + execute_command "aws ecs describe-services --cluster '$CLUSTER_NAME' --services '$SERVICE_NAME'" "Get service details" @@ -6708 +6790,3 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - # Add HTTP access rule for nginx web server + # Add HTTP access rule for nginx web server with restricted CIDR + # SECURITY FIX: Restrict access to specific CIDR if available, otherwise document the risk + log "WARNING: Security group allows HTTP (port 80) from 0.0.0.0/0 - restrict this in production" @@ -6758,0 +6843,7 @@ There's more on GitHub. Find the complete example and learn how to set up and ru + # SECURITY FIX: Validate JSON before using + if ! jq empty ecs-instance-trust-policy.json 2>/dev/null; then + log "ERROR: Invalid JSON in trust policy" + rm -f ecs-instance-trust-policy.json