AWS provides powerful security tools, but the shared responsibility model means your organization is accountable for securing everything you build on top of AWS infrastructure. This guide covers the essential security practices every team should implement to protect their AWS workloads.
Understanding the Shared Responsibility Model
Before diving into specific practices, it's crucial to understand what AWS secures versus what you're responsible for:
- AWS Responsibility: Physical security, hardware, networking infrastructure, and the hypervisor layer
- Your Responsibility: Operating systems, applications, data, IAM, network configuration, and encryption
Most AWS security breaches occur due to misconfigurations on the customer side - not vulnerabilities in AWS itself.
1. Identity and Access Management (IAM)
IAM misconfigurations are the #1 cause of AWS security incidents. Here's how to get it right:
Enforce Least Privilege Access
Every IAM policy should grant the minimum permissions required to perform a task. Avoid using wildcards (*) in resource ARNs and actions.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": "arn:aws:s3:::my-app-bucket/uploads/*"
}
]
}
Use IAM Roles Instead of Long-Term Credentials
Never embed AWS access keys in your application code. Instead:
- Use IAM roles for EC2 instances, Lambda functions, and ECS tasks
- Use IRSA (IAM Roles for Service Accounts) for EKS workloads
- Use IAM Identity Center (formerly AWS SSO) for human access
Implement MFA Everywhere
Require MFA for:
- All IAM users with console access
- Root account (use hardware MFA for root)
- Sensitive API operations via MFA-protected API calls
Use Permission Boundaries
Permission boundaries prevent privilege escalation by setting maximum permissions that IAM policies can grant:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "*",
"Resource": "*",
"Condition": {
"StringEquals": {
"aws:RequestedRegion": ["us-east-1", "us-west-2"]
}
}
},
{
"Effect": "Deny",
"Action": [
"iam:CreateUser",
"iam:DeleteUser",
"organizations:*"
],
"Resource": "*"
}
]
}
2. Network Security
VPC Design Principles
- Use private subnets: Place databases, application servers, and internal services in private subnets with no direct internet access
- Implement network segmentation: Separate workloads by environment (dev/staging/prod) and function (web/app/data)
- Use VPC endpoints: Access AWS services like S3, DynamoDB, and Secrets Manager without traversing the internet
Security Groups Best Practices
- Never use 0.0.0.0/0 for ingress rules except for public-facing load balancers on ports 80/443
- Reference other security groups instead of IP ranges where possible
- Use descriptive names and tags for audit purposes
- Regularly review and remove unused rules
Enable VPC Flow Logs
VPC Flow Logs capture network traffic metadata for security analysis and troubleshooting:
aws ec2 create-flow-logs \
--resource-type VPC \
--resource-ids vpc-1234567890abcdef0 \
--traffic-type ALL \
--log-destination-type cloud-watch-logs \
--log-group-name /aws/vpc/flow-logs
3. Data Protection
Encryption at Rest
Enable encryption for all data stores:
- S3: Enable default bucket encryption with SSE-S3 or SSE-KMS
- RDS: Enable encryption at database creation (cannot be added later)
- EBS: Enable default EBS encryption at the account level
- DynamoDB: Use AWS-managed or customer-managed KMS keys
Encryption in Transit
- Enforce HTTPS for all public endpoints using ACM certificates
- Enable TLS for RDS connections
- Use VPC endpoints to keep traffic within the AWS network
S3 Bucket Security
S3 bucket misconfigurations are a leading cause of data breaches. Implement these controls:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::my-bucket",
"arn:aws:s3:::my-bucket/*"
],
"Condition": {
"Bool": {
"aws:SecureTransport": "false"
}
}
}
]
}
- Enable S3 Block Public Access at the account level
- Use bucket policies to enforce encryption and HTTPS
- Enable versioning and MFA delete for critical buckets
- Use S3 Object Lock for compliance requirements
4. Logging and Monitoring
Enable AWS CloudTrail
CloudTrail logs all API calls across your AWS account. Enable it organization-wide with these settings:
- Multi-region trail to capture activity in all regions
- Log file validation to detect tampering
- S3 bucket with versioning and MFA delete
- CloudWatch Logs integration for real-time alerting
Set Up Security Alerts
Create CloudWatch alarms for critical security events:
- Root account usage
- IAM policy changes
- Security group modifications
- Failed console login attempts
- KMS key deletion or disabling
Use AWS Security Hub
Security Hub aggregates findings from multiple AWS services and third-party tools:
- Enable the AWS Foundational Security Best Practices standard
- Enable CIS AWS Foundations Benchmark checks
- Integrate with GuardDuty, Inspector, and Macie
- Set up automated remediation for common findings
5. Secrets Management
Use AWS Secrets Manager
Never hardcode credentials. Store and rotate secrets automatically:
# Retrieve secret in application code
import boto3
import json
def get_secret(secret_name):
client = boto3.client('secretsmanager')
response = client.get_secret_value(SecretId=secret_name)
return json.loads(response['SecretString'])
Enable Automatic Rotation
Configure automatic rotation for database credentials and API keys. Secrets Manager supports native rotation for RDS, Redshift, and DocumentDB.
6. Infrastructure as Code Security
Scan Terraform/CloudFormation Before Deployment
Use tools like Checkov, tfsec, or cfn-nag to catch misconfigurations before they reach AWS:
# Example: Running Checkov on Terraform
checkov -d ./terraform --framework terraform
# Common findings:
# - S3 buckets without encryption
# - Security groups with 0.0.0.0/0
# - RDS instances without encryption
# - IAM policies with wildcard permissions
Use Service Control Policies (SCPs)
In AWS Organizations, use SCPs to enforce guardrails across all accounts:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Action": [
"ec2:RunInstances"
],
"Resource": "arn:aws:ec2:*:*:instance/*",
"Condition": {
"StringNotEquals": {
"ec2:InstanceType": [
"t3.micro",
"t3.small",
"t3.medium"
]
}
}
}
]
}
7. Incident Response Preparation
Enable AWS GuardDuty
GuardDuty uses machine learning to detect threats across your AWS environment:
- Cryptocurrency mining detection
- Compromised EC2 instances
- Unauthorized access patterns
- S3 bucket compromise
Create Incident Response Runbooks
Document procedures for common scenarios:
- Compromised IAM credentials
- Exposed S3 bucket
- Cryptominer detected on EC2
- Unusual API activity from GuardDuty
Quick Wins Checklist
Start with these high-impact, low-effort security improvements:
- Enable MFA on root and all IAM users
- Enable S3 Block Public Access at account level
- Enable default EBS encryption
- Enable CloudTrail in all regions
- Enable GuardDuty
- Enable Security Hub with AWS Foundational Security Best Practices
- Review and remove unused IAM users, roles, and access keys
- Enable AWS Config to track resource configurations
Next Steps
AWS security is an ongoing process, not a one-time setup. Regularly review your security posture using AWS Security Hub, conduct access reviews, and stay updated on new AWS security features.
Need help securing your AWS infrastructure? Contact us for a comprehensive security assessment and implementation support.