Introduction
Cloud security is a shared responsibility between you and your cloud provider. While providers secure the underlying infrastructure, you’re responsible for securing your data, access, and configurations.
This guide covers essential cloud security practices across identity, networking, data, and compliance.
Cloud Security Fundamentals
Shared Responsibility Model
┌─────────────────────────────────────────────────────────────────┐
│ SHARED RESPONSIBILITY MODEL │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ AWS / Azure / GCP │ │
│ │ │ │
│ │ Provider Responsibility (Security OF the Cloud): │ │
│ │ ┌─────────────────────────────────────────────────┐ │ │
│ │ │ • Physical infrastructure │ │ │
│ │ │ • Network infrastructure │ │ │
│ │ │ • Hypervisor/Host security │ │ │
│ │ │ • Global services availability │ │ │
│ │ │ • Hardware compliance │ │ │
│ │ └─────────────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ▼ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Customer Responsibility │ │
│ │ (Security IN the Cloud): │ │
│ │ ┌─────────────────────────────────────────────────┐ │ │
│ │ │ • Data (encryption, access) │ │ │
│ │ │ • Applications (code, config) │ │ │
│ │ │ • Identity and Access Management │ │ │
│ │ │ • Network configuration │ │ │
│ │ │ • OS and runtime (if using VMs/containers) │ │ │
│ │ │ • Client-side data │ │ │
│ │ └─────────────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
Security Principles
┌─────────────────────────────────────────────────────────────────┐
│ CLOUD SECURITY PRINCIPLES │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 1. LEAST PRIVILEGE │ │
│ │ Grant only the permissions needed, nothing more │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 2. DEFENSE IN DEPTH │ │
│ │ Multiple layers of security controls │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 3. ZERO TRUST │ │
│ │ Never trust, always verify - inside and outside │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 4. AUTOMATION │ │
│ │ Automate security responses and compliance checks │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 5. SECURE BY DEFAULT │ │
│ │ Safe configurations out of the box │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
Identity and Access Management
Identity and Access Management (IAM)
// AWS IAM Policy - Least Privilege Example
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::my-bucket",
"arn:aws:s3:::my-bucket/*"
],
"Condition": {
"IpAddress": {
"aws:SourceIp": "10.0.0.0/8"
},
"Bool": {
"aws:MultiFactorAuthPresent": "true"
}
}
},
{
"Effect": "Deny",
"Action": "s3:DeleteObject",
"Resource": "arn:aws:s3:::my-bucket/*"
}
]
}
IAM Best Practices
┌─────────────────────────────────────────────────────────────────┐
│ IAM BEST PRACTICES │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ ✓ Use IAM Users Only for Programmatic Access │ │
│ │ • Use roles for human access │ │
│ │ • Use federated identity (SSO) │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ ✓ Enable MFA for All Users │ │
│ │ • Especially for console and root │ │
│ │ • Use hardware MFA for privileged users │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ ✓ Use Roles, Not Long-Term Credentials │ │
│ │ • Assume roles for temporary access │ │
│ │ • No access keys in code or config files │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ ✓ Implement Permission Boundaries │ │
│ │ • Set maximum permissions for users/roles │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ ✓ Regular Access Reviews │ │
│ │ • Audit who has access to what │ │
│ │ • Remove unnecessary access │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
Role-Based Access Control
# Kubernetes RBAC Example
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: production
name: app-reader
rules:
- apiGroups: [""]
resources: ["pods", "services", "configmaps"]
verbs: ["get", "list", "watch"]
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: developers-app-reader
namespace: production
subjects:
- kind: Group
name: developers
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: app-reader
apiGroup: rbac.authorization.k8s.io
Network Security
Network Segmentation
┌─────────────────────────────────────────────────────────────────┐
│ CLOUD NETWORK SEGMENTATION │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Traditional: Modern (Zero Trust): │
│ │
│ ┌─────────┐ ┌─────────┐ │
│ │ Public │ │ Web │ │
│ │ Internet│ │ Tier │ │
│ └───┬───┘ └───┬───┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────┐ ┌─────────┐ │
│ │ DMZ │ │ App │ │
│ │ (ALB) │ │ Tier │ │
│ └───┬───┘ └───┬───┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────┐ ┌─────────┐ │
│ │Private │ │ Data │ │
│ │Subnet │ │ Tier │ │
│ └─────────┘ └─────────┘ │
│ │
│ Everything inside │ Each tier verifies │
│ can talk to │ every request │
│ everything │ │
│ │
└─────────────────────────────────────────────────────────────────┘
Security Groups / Firewall Rules
# Terraform - AWS Security Groups
# Web Tier Security Group
resource "aws_security_group" "web" {
name = "web-tier-sg"
description = "Security group for web tier"
vpc_id = module.vpc.vpc_id
# Ingress - Allow HTTP/HTTPS from anywhere
ingress {
description = "HTTP"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
description = "HTTPS"
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
# Ingress - Allow SSH from bastion only
ingress {
description = "SSH from bastion"
from_port = 22
to_port = 22
protocol = "tcp"
security_groups = [aws_security_group.bastion.id]
}
# Egress - Allow all outbound
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "web-tier-sg"
}
}
# App Tier Security Group
resource "aws_security_group" "app" {
name = "app-tier-sg"
description = "Security group for app tier"
vpc_id = module.vpc.vpc_id
# Only allow traffic from web tier
ingress {
description = "App traffic from web tier"
from_port = 8080
to_port = 8080
protocol = "tcp"
security_groups = [aws_security_group.web.id]
}
# Allow outbound to database
egress {
description = "Database traffic"
from_port = 5432
to_port = 5432
protocol = "tcp"
security_groups = [aws_security_group.database.id]
}
}
# Database Tier Security Group
resource "aws_security_group" "database" {
name = "database-tier-sg"
description = "Security group for database tier"
vpc_id = module.vpc.vpc_id
# Only allow traffic from app tier
ingress {
description = "PostgreSQL from app tier"
from_port = 5432
to_port = 5432
protocol = "tcp"
security_groups = [aws_security_group.app.id]
}
}
Data Protection
Encryption
┌─────────────────────────────────────────────────────────────────┐
│ DATA ENCRYPTION │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Data at Rest: │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Storage Services: │ │
│ │ • AWS: S3 (SSE-S3, SSE-KMS, SSE-C) │ │
│ │ • Azure: Storage (AES-256) │ │
│ │ • GCP: Cloud Storage (AES-256) │ │
│ │ │ │
│ │ Databases: │ │
│ │ • AWS: RDS, DynamoDB (encryption at rest) │ │
│ │ • Azure: SQL Database, Cosmos DB │ │
│ │ • GCP: Cloud SQL, Firestore │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ Data in Transit: │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ • TLS 1.2+ for all network communication │ │
│ │ • Certificate management (ACM, Certificate Manager) │ │
│ │ • Perfect Forward Secrecy (PFS) │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ Key Management: │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ • AWS: KMS (Key Management Service) │ │
│ │ • Azure: Key Vault │ │
│ │ • GCP: Cloud KMS │ │
│ │ │ │
│ │ Best Practices: │ │
│ │ • Use customer-managed keys (CMK) │ │
│ │ • Rotate keys regularly │ │
│ │ • Use envelope encryption for large data │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
Data Classification
# Terraform - S3 Bucket with encryption and versioning
resource "aws_s3_bucket" "sensitive_data" {
bucket = "company-sensitive-data"
tags = {
Name = "sensitive-data"
DataClassification = "confidential"
}
}
resource "aws_s3_bucket_server_side_encryption_configuration" "sensitive_data" {
bucket = aws_s3_bucket.sensitive_data.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "aws:kms"
kms_master_key_id = aws_kms_key.s3_encryption.arn
}
}
}
resource "aws_s3_bucket_versioning" "sensitive_data" {
bucket = aws_s3_bucket.sensitive_data.id
versioning_configuration {
status = "Enabled"
}
}
resource "aws_s3_bucket_public_access_block" "sensitive_data" {
bucket = aws_s3_bucket.sensitive_data.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
# Block sensitive data uploads without encryption
resource "aws_s3_bucket_policy" "enforce_encryption" {
bucket = aws_s3_bucket.sensitive_data.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Sid = "DenyUnencryptedObjectUploads"
Effect = "Deny"
Principal = "*"
Action = "s3:PutObject"
Resource = "${aws_s3_bucket.sensitive_data.arn}/*"
Condition = {
Bool = {
"aws:SecureTransport" = "false"
}
}
}]
})
}
Compliance
Common Compliance Frameworks
┌─────────────────────────────────────────────────────────────────┐
│ COMPLIANCE FRAMEWORKS │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ SOC 2 │ │
│ │ • Security, Availability, Confidentiality │ │
│ │ • Trust service criteria │ │
│ │ • Annual audits │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ GDPR (EU) │ │
│ │ • Personal data protection │ │
│ │ • Data subject rights │ │
│ │ • 72-hour breach notification │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ HIPAA (US Healthcare) │ │
│ │ • PHI (Protected Health Information) │ │
│ │ • Technical and administrative safeguards │ │
│ │ • Business associate agreements │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ PCI DSS (Payments) │ │
│ │ • Cardholder data protection │ │
│ │ • Network security, access control │ │
│ │ • Annual assessment required │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ ISO 27001 │ │
│ │ • Information security management │ │
│ │ • ISMS certification │ │
│ │ • Third-party audits │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
Cloud Compliance Tools
# AWS Config Rules - Compliance as Code
resource "aws_config_rule" "s3_encrypted" {
name = "s3-bucket-encryption-enabled"
source {
owner = "AWS"
source_identifier = "S3_BUCKET_SERVER_SIDE_ENCRYPTION_ENABLED"
}
scope {
resource_types = ["AWS::S3::Bucket"]
}
tags = {
ComplianceType = "SECURITY"
}
}
resource "aws_config_rule" "mfa_enabled" {
name = "iam-mfa-enabled-for-iam-user"
source {
owner = "AWS"
source_identifier = "IAM_USER_MFA_ENABLED"
}
scope {
resource_types = ["AWS::IAM::User"]
}
}
resource "aws_config_rule" "security_group_open" {
name = "security-groups-no-unrestricted-ssh"
source {
owner = "AWS"
source_identifier = "INCOMING_SSH_DISABLED"
}
scope {
resource_types = ["AWS::EC2::SecurityGroup"]
}
}
Security Monitoring
CloudTrail and Monitoring
# Terraform - CloudTrail with organization-wide logging
resource "aws_cloudtrail" "organization" {
name = "organization-trail"
s3_bucket_name = aws_s3_bucket.cloudtrail.id
is_organization_trail = true
enable_log_file_validation = true
is_multi_region_trail = true
include_global_service_events = true
event_selector {
read_write_type = "All"
include_management_events = true
data_resource {
type = "AWS::S3::Bucket"
values = ["arn:aws:s3:::*"]
}
}
tags = {
Name = "organization-trail"
}
}
# CloudWatch Logs - Centralized logging
resource "aws_cloudwatch_log_group" "vpc_flow_logs" {
name = "/aws/vpc/flow-logs"
retention_in_days = 90
tags = {
Environment = "production"
}
}
resource "aws_flow_log" "vpc" {
iam_role_arn = aws_iam_role.flow_log.arn
log_destination = aws_cloudwatch_log_group.vpc_flow_logs.arn
traffic_type = "ALL"
vpc_id = aws_vpc.main.id
}
Security Event Monitoring
┌─────────────────────────────────────────────────────────────────┐
│ SECURITY MONITORING ARCHITECTURE │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Sources │───►│ Aggregation │───►│ Analysis │ │
│ │ │ │ │ │ │ │
│ │ • CloudTrail │ │ • CloudWatch │ │ • GuardDuty │ │
│ │ • VPC Flow │ │ Logs │ │ • Security │ │
│ │ • Config │ │ • S3 Events │ │ Hub │ │
│ │ • API Calls │ │ • EventBridge│ │ • SIEM │ │
│ │ • DNS Logs │ │ │ │ • Custom │ │
│ └──────────────┘ └──────────────┘ └──────┬───────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Response & Alerting │ │
│ │ • SNS notifications │ │
│ │ • Security incident response │ │
│ │ • Automated remediation │ │
│ │ • SOAR integration │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
Security Automation
Automated Remediation
# AWS Lambda - Auto-remediate unsecured S3 buckets
import json
import boto3
def lambda_handler(event, context):
# Get bucket name from event
bucket_name = event['detail']['requestParameters']['bucketName']
s3_client = boto3.client('s3')
# Check if bucket is public
try:
block_public_acls = s3_client.get_public_access_block(
Bucket=bucket_name
)
public_access = block_public_acls.get('PublicAccessBlockConfiguration', {})
if not all([
public_access.get('BlockPublicAcls'),
public_access.get('BlockPublicPolicy'),
public_access.get('IgnorePublicAcls'),
public_access.get('RestrictPublicBuckets')
]):
# Apply public access block
s3_client.put_public_access_block(
Bucket=bucket_name,
PublicAccessBlockConfiguration={
'BlockPublicAcls': True,
'BlockPublicPolicy': True,
'IgnorePublicAcls': True,
'RestrictPublicBuckets': True
}
)
print(f"Fixed public access for bucket: {bucket_name}")
except s3_client.exceptions.NoSuchPublicAccessBlockConfiguration:
# Bucket doesn't have any protection - apply it
s3_client.put_public_access_block(
Bucket=bucket_name,
PublicAccessBlockConfiguration={
'BlockPublicAcls': True,
'BlockPublicPolicy': True,
'IgnorePublicAcls': True,
'RestrictPublicBuckets': True
}
)
return {
'statusCode': 200,
'body': json.dumps('Completed')
}
Incident Response
Cloud Security Incident Response Plan
┌─────────────────────────────────────────────────────────────────┐
│ INCIDENT RESPONSE PHASES │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 1. PREPARATION │ │
│ │ • Define incident response team │ │
│ │ • Document procedures │ │
│ │ • Set up communication channels │ │
│ │ • Enable logging and monitoring │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 2. DETECTION & ANALYSIS │ │
│ │ • Identify the incident │ │
│ │ • Assess scope and severity │ │
│ │ • Determine root cause │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 3. CONTAINMENT │ │
│ │ • Isolate affected systems │ │
│ │ • Preserve evidence │ │
│ │ • Stop the bleeding │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 4. ERADICATION & RECOVERY │ │
│ │ • Remove threat │ │
│ │ • Restore clean systems │ │
│ │ • Verify recovery │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 5. POST-INCIDENT ACTIVITIES │ │
│ │ • Document lessons learned │ │
│ │ • Update procedures │ │
│ │ • Implement improvements │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
Conclusion
Cloud security requires a comprehensive approach. Key takeaways:
- Shared responsibility - Provider secures infrastructure, you secure your data and access
- Least privilege - Grant minimum permissions required
- Defense in depth - Multiple layers of security controls
- Automate - Use IaC, automated remediation, and compliance checks
- Monitor - Continuous logging, alerting, and incident response
Security is not a product but a process. Regular reviews, updates, and improvements are essential.
Comments