AWS can scale your business overnight — or expose it if misconfigured. From IAM sprawl to open S3 buckets, mistakes are common. Security in AWS requires defense in depth.
1. IAM as the First Line
- Favor least privilege roles
- Avoid all-powerful
AdministratorAccess
policies
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": "arn:aws:s3:::my-app-bucket/user-uploads/*",
"Condition": {
"StringEquals": {
"s3:x-amz-server-side-encryption": "aws:kms"
}
}
}
]
}
2. VPC for Layered Defense
- Public subnets for entry points
- Private subnets for app and database tiers
- Restrictive security groups between layers
AppSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Application tier security group
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 443
ToPort: 443
SourceSecurityGroupId: !Ref LoadBalancerSecurityGroup
3. Encrypt at Rest and in Transit
- KMS for S3 and RDS
- SSL enforcement on databases
- TLS for all APIs
const AWS = require('aws-sdk');
const s3 = new AWS.S3();
const params = {
Bucket: 'secure-bucket',
Key: 'data.json',
Body: JSON.stringify({ secure: true }),
ServerSideEncryption: 'aws:kms',
SSEKMSKeyId: process.env.KMS_KEY_ID
};
await s3.upload(params).promise();
4. Monitor and Detect
- CloudTrail for audit logs
- CloudWatch alarms for anomalies
- GuardDuty for threat detection
CloudTrail:
Type: AWS::CloudTrail::Trail
Properties:
TrailName: my-audit-trail
S3BucketName: !Ref AuditLogsBucket
IsMultiRegionTrail: true
EnableLogFileValidation: true
5. Manage Secrets Properly
Leverage Secrets Manager or SSM Parameter Store with automated rotation.
const AWS = require('aws-sdk');
const sm = new AWS.SecretsManager();
const secret = await sm.getSecretValue({ SecretId: 'prod/db-password' }).promise();
console.log(secret.SecretString);
6. Automate Compliance
Use Lambda or Config Rules to detect — and remediate — insecure configurations in real time.
import boto3
def lambda_handler(event, context):
ec2 = boto3.client('ec2')
sgs = ec2.describe_security_groups()['SecurityGroups']
for sg in sgs:
for rule in sg.get('IpPermissions', []):
for ip_range in rule.get('IpRanges', []):
if ip_range.get('CidrIp') == '0.0.0.0/0':
print(f"Insecure SG found: {sg['GroupId']}")
The cloud is only as secure as the guardrails you define.
With the right practices, AWS becomes not just scalable, but dependable.
Thanks for reading! If this post was insightful for you, please share it with your team or leave a comment with your own security wins.
I design AWS environments where security is baked in, not bolted on.
See case studies and services: kodex.studio
Top comments (0)