The Shared Responsibility Model
Cloud security is a shared responsibility between you and your cloud provider. Understanding this boundary is critical.
Provider Responsibilities
Your Responsibilities
Identity and Access Management (IAM)
Principle of Least Privilege
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": "arn:aws:s3:::my-bucket/uploads/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": "10.0.0.0/8"
}
}
}
]
}IAM Best Practices
Service Accounts
// Using IAM roles for service authentication
const AWS = require('aws-sdk');
// The SDK automatically uses the IAM role attached to the resource
const s3 = new AWS.S3(); // No credentials needed!
// For local development, use assume role
const sts = new AWS.STS();
const credentials = await sts.assumeRole({
RoleArn: 'arn:aws:iam::123456789:role/MyRole',
RoleSessionName: 'MySession'
}).promise();Encryption
Encryption at Rest
# AWS KMS-encrypted S3 bucket
AWSTemplateFormatVersion: '2010-09-09'
Resources:
EncryptedBucket:
Type: AWS::S3::Bucket
Properties:
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: aws:kms
KMSMasterKeyID: !Ref MyKMSKey
MyKMSKey:
Type: AWS::KMS::Key
Properties:
EnableKeyRotation: true
KeyPolicy:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
AWS: !Sub 'arn:aws:iam::${AWS::AccountId}:root'
Action: 'kms:*'
Resource: '*'Encryption in Transit
Always use TLS 1.2 or higher:
// Force HTTPS in Express
app.use((req, res, next) => {
if (req.headers['x-forwarded-proto'] !== 'https') {
return res.redirect(`https://${req.hostname}${req.url}`);
}
next();
});
// Configure TLS
const https = require('https');
const fs = require('fs');
const options = {
key: fs.readFileSync('private-key.pem'),
cert: fs.readFileSync('certificate.pem'),
minVersion: 'TLSv1.2',
ciphers: [
'ECDHE-ECDSA-AES128-GCM-SHA256',
'ECDHE-RSA-AES128-GCM-SHA256'
].join(':')
};Network Security
VPC Best Practices
# Terraform VPC configuration
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
enable_dns_hostnames = true
enable_dns_support = true
}
# Public subnet
resource "aws_subnet" "public" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.1.0/24"
availability_zone = "us-east-1a"
}
# Private subnet - no internet gateway
resource "aws_subnet" "private" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.2.0/24"
availability_zone = "us-east-1a"
}
# Security group - restrictive by default
resource "aws_security_group" "app" {
vpc_id = aws_vpc.main.id
ingress {
from_port = 443
to_port = 443
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"]
}
}Web Application Firewall (WAF)
Protect against common attacks:
Security Monitoring
CloudTrail & Logging
{
"eventVersion": "1.08",
"eventName": "ConsoleLogin",
"awsRegion": "us-east-1",
"sourceIPAddress": "192.0.2.1",
"userIdentity": {
"type": "IAMUser",
"userName": "admin"
},
"responseElements": {
"ConsoleLogin": "Success"
}
}Alerting Rules
# CloudWatch alarm for unauthorized API calls
import boto3
cloudwatch = boto3.client('cloudwatch')
cloudwatch.put_metric_alarm(
AlarmName='UnauthorizedAPICalls',
MetricName='UnauthorizedAttemptCount',
Namespace='CloudTrailMetrics',
Statistic='Sum',
Period=300,
EvaluationPeriods=1,
Threshold=1,
ComparisonOperator='GreaterThanOrEqualToThreshold',
AlarmActions=['arn:aws:sns:us-east-1:123456789:SecurityAlerts']
)Compliance Frameworks
Conclusion
Cloud security requires a defense-in-depth approach. Implement multiple layers of security and continuously monitor for threats.
Recommended Reading

Practical Cloud Security
by Chris Dotson
A guide for secure design and deployment
As an Amazon Associate, we earn from qualifying purchases.

Zero Trust Networks
by Evan Gilman
Building secure systems in untrusted networks
As an Amazon Associate, we earn from qualifying purchases.
💬Discussion
No comments yet
Be the first to share your thoughts!