S3 encryption with KMS - console, policies, and access

S3 encryption with KMS - console, policies, and access

S3 is the default artifact store for CodePipeline, logs, data lakes, and backups. SSE-KMS is required when you need key policies, CloudTrail audit of key use, and separation of duties.

Checklist: DevOps checklist


Use cases

CaseEncryption choice
Pipeline artifactsSSE-KMS CMK per env
App uploadsSSE-KMS + bucket policy deny unencrypted put
Cross-account data shareCMK policy + bucket policy principal
Athena on S3KMS decrypt on workgroup role

Console - bucket default encryption

  1. S3 → bucket → Properties → Default encryption.
  2. Encryption type: SSE-KMS.
  3. Choose AWS managed key (aws/s3) or CMK (preferred for prod).
  4. Bucket Key: enable to reduce KMS API costs (S3 Bucket Keys).

Console - block public access & versioning

  1. Permissions → Block public access - all four ON for private data.
  2. Versioning - enable for recovery and lifecycle compliance.

Bucket policy - deny insecure transport & unencrypted puts

{
  "Sid": "DenyInsecureTransport",
  "Effect": "Deny",
  "Principal": "*",
  "Action": "s3:*",
  "Resource": ["arn:aws:s3:::my-bucket", "arn:aws:s3:::my-bucket/*"],
  "Condition": { "Bool": { "aws:SecureTransport": "false" } }
}

Require SSE-KMS on upload:

{
  "Sid": "DenyUnencryptedObjectUploads",
  "Effect": "Deny",
  "Principal": "*",
  "Action": "s3:PutObject",
  "Resource": "arn:aws:s3:::my-bucket/*",
  "Condition": {
    "StringNotEquals": {
      "s3:x-amz-server-side-encryption": "aws:kms"
    }
  }
}

KMS key policy - S3 usage

CMK must allow:

  • Administrators - kms:* management (separate role).
  • S3 service - via IAM roles used by apps (kms:Decrypt, kms:GenerateDataKey).
  • Optional: kms:ViaService condition s3.region.amazonaws.com.

IAM for application roles

Minimal app role for read/write:

{
  "Effect": "Allow",
  "Action": ["s3:GetObject", "s3:PutObject", "s3:DeleteObject"],
  "Resource": "arn:aws:s3:::my-bucket/*"
},
{
  "Effect": "Allow",
  "Action": ["kms:Decrypt", "kms:GenerateDataKey"],
  "Resource": "arn:aws:kms:region:account:key/KEY_ID"
}

Decryption paths

ConsumerNeeds
Lambda in VPCRole KMS + S3; VPC endpoint for S3/KMS optional
Cross-accountCMK policy Principal other account + bucket policy
AthenaWorkgroup role kms:Decrypt on CMK used by objects
ReplicationDestination CMK permissions for replication role

Commonly missed

  • Bucket owner enforced object ownership for cross-account uploads.
  • Grantee confusion on ACLs (prefer bucket policies).
  • Pipeline artifact bucket not in same region as KMS key.
  • Forgetting ListBucket when only object actions granted.

Troubleshooting

ErrorLikely fix
Access Denied on PutObjectBucket policy, encryption header, or KMS key policy
KMS.DisabledExceptionKey state or scheduled deletion
Cross-account copy failsDestination encryption + role on both sides

Docs: S3 encryption · KMS key policies

← Checklist · IAM conditions