Storage & Data Security
Encryption at Rest and in Transit
4 min read
Encryption is non-negotiable in cloud security. Every major compliance framework requires it, and modern cloud providers make it nearly effortless—yet many organizations still get it wrong.
Encryption at Rest
AWS S3 Encryption Options
| Option | Key Management | Use Case |
|---|---|---|
| SSE-S3 | AWS-managed (free) | Default, baseline protection |
| SSE-KMS | Customer-managed in KMS | Audit trail, key rotation |
| SSE-C | Customer-provided | Strict key control requirements |
| Client-side | Customer-managed | End-to-end encryption |
Enabling default encryption:
# Enable default SSE-KMS encryption on bucket
aws s3api put-bucket-encryption --bucket my-bucket \
--server-side-encryption-configuration '{
"Rules": [{
"ApplyServerSideEncryptionByDefault": {
"SSEAlgorithm": "aws:kms",
"KMSMasterKeyID": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012"
},
"BucketKeyEnabled": true
}]
}'
KMS key policy for S3:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowS3Service",
"Effect": "Allow",
"Principal": {
"Service": "s3.amazonaws.com"
},
"Action": [
"kms:Decrypt",
"kms:GenerateDataKey"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"kms:CallerAccount": "123456789012"
}
}
}
]
}
Azure Encryption Options
| Option | Key Management | Use Case |
|---|---|---|
| Microsoft-managed | Azure-managed | Default |
| Customer-managed key (CMK) | Azure Key Vault | Compliance requirements |
| Double encryption | Infrastructure + service | High security |
Configure CMK encryption:
# Create Key Vault and key
az keyvault create --name myKeyVault --resource-group myRG --location eastus
az keyvault key create --vault-name myKeyVault --name storageKey --protection software
# Configure storage account with CMK
az storage account update \
--name mystorageaccount \
--resource-group myRG \
--encryption-key-name storageKey \
--encryption-key-vault "https://myKeyVault.vault.azure.net/" \
--encryption-key-source Microsoft.Keyvault
GCP Encryption Options
| Option | Key Management | Use Case |
|---|---|---|
| Google-managed | Google-managed | Default |
| Customer-managed (CMEK) | Cloud KMS | Compliance |
| Customer-supplied (CSEK) | Customer holds keys | Strict control |
Configure CMEK for Cloud Storage:
# Create key ring and key
gcloud kms keyrings create my-keyring --location=global
gcloud kms keys create my-key \
--location=global \
--keyring=my-keyring \
--purpose=encryption
# Create bucket with CMEK
gcloud storage buckets create gs://my-encrypted-bucket \
--default-encryption-key=projects/my-project/locations/global/keyRings/my-keyring/cryptoKeys/my-key
Encryption in Transit
TLS Requirements
All modern cloud services enforce TLS, but you must ensure clients respect it:
AWS S3 - Enforce HTTPS only:
{
"Version": "2012-10-17",
"Statement": [{
"Sid": "DenyHTTP",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::my-bucket",
"arn:aws:s3:::my-bucket/*"
],
"Condition": {
"Bool": {
"aws:SecureTransport": "false"
}
}
}]
}
Azure - Require secure transfer:
az storage account update \
--name mystorageaccount \
--resource-group myRG \
--https-only true \
--min-tls-version TLS1_2
GCP - TLS is always enforced for Cloud Storage.
VPC Endpoints / Private Link
Avoid traversing the public internet entirely:
AWS VPC Endpoint:
# Terraform - S3 VPC Gateway Endpoint
resource "aws_vpc_endpoint" "s3" {
vpc_id = aws_vpc.main.id
service_name = "com.amazonaws.us-east-1.s3"
route_table_ids = [
aws_route_table.private.id
]
policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Principal = "*"
Action = "s3:*"
Resource = ["arn:aws:s3:::my-bucket/*"]
}]
})
}
Azure Private Endpoint:
az network private-endpoint create \
--name myStoragePrivateEndpoint \
--resource-group myRG \
--vnet-name myVNet \
--subnet mySubnet \
--private-connection-resource-id "/subscriptions/.../storageAccounts/mystorageaccount" \
--group-id blob \
--connection-name myConnection
Key Management Best Practices
Key Rotation
| Provider | Default Rotation | Recommendation |
|---|---|---|
| AWS KMS | Automatic (yearly) | Enable automatic rotation |
| Azure Key Vault | Manual by default | Configure auto-rotation |
| GCP Cloud KMS | Manual | Schedule rotation |
AWS KMS automatic rotation:
aws kms enable-key-rotation --key-id 12345678-1234-1234-1234-123456789012
Key Access Auditing
# AWS - View KMS key usage in CloudTrail
aws cloudtrail lookup-events \
--lookup-attributes AttributeKey=ResourceType,AttributeValue=AWS::KMS::Key
# Azure - Key Vault diagnostics
az monitor diagnostic-settings create \
--name KeyVaultDiagnostics \
--resource "/subscriptions/.../vaults/myKeyVault" \
--logs '[{"category": "AuditEvent", "enabled": true}]'
Encryption Decision Matrix
| Scenario | At Rest | In Transit | Key Management |
|---|---|---|---|
| General data | SSE-S3/Default | HTTPS | Provider-managed |
| PII/PHI | SSE-KMS/CMK | HTTPS + VPC | Customer-managed |
| Financial data | SSE-KMS/CMK | Private Link | Customer-managed + HSM |
| Top secret | Client-side | Private Link | Customer-supplied |
Next, we'll explore access policy patterns and how to prevent accidental public exposure. :::