The Problem
A hospital needs to store patient records in S3. Compliance requires:
- All PHI encrypted in transit
- All PHI encrypted at rest
- The compliance team must administer the encryption key
You need a solution that enforces both encryption boundaries and hands the compliance team full key control.
The Solution
Two layers:
- Bucket policy with
aws:SecureTransportcondition — rejects any request not using HTTPS/TLS (in transit) - Default encryption using SSE-KMS with a customer-managed key — compliance team owns the key policy (at rest)
How It Works
Step 1: Bucket Policy That Blocks Non-HTTPS
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"Version": "2012-10-17",
"Statement": [{
"Sid": "DenyInsecureTransport",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::phi-records",
"arn:aws:s3:::phi-records/*"
],
"Condition": {
"Bool": { "aws:SecureTransport": "false" }
}
}]
}
Any request over HTTP (not HTTPS) evaluates aws:SecureTransport as false and gets denied. This is a hard block — even if IAM would allow the action, the bucket policy deny wins.
Step 2: Create the KMS Key Owned by Compliance
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
aws kms create-key --description "PHI encryption key" \
--policy '{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowComplianceAdmin",
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::123456789012:role/ComplianceTeam" },
"Action": ["kms:*"],
"Resource": "*"
},
{
"Sid": "AllowS3UseOfTheKey",
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::123456789012:role/PhiApp" },
"Action": ["kms:Encrypt", "kms:Decrypt", "kms:GenerateDataKey*"],
"Resource": "*"
}
]
}'
The compliance team can manage rotation, disable the key, or delete it. Application roles can only use it.
Step 3: Set SSE-KMS as Default Bucket Encryption
1
2
3
4
5
6
7
8
9
10
aws s3api put-bucket-encryption \
--bucket phi-records \
--server-side-encryption-configuration '{
"Rules": [{
"ApplyServerSideEncryptionByDefault": {
"SSEAlgorithm": "aws:kms",
"KMSMasterKeyID": "alias/phi-encryption"
}
}]
}'
Why Not the Alternatives?
ACM certificate on S3 — You cannot attach an ACM cert to an S3 bucket endpoint. S3 provides its own TLS certificates automatically.
aws:SecureTransport + SSE-S3 — SSE-S3 keys are fully AWS-managed. The compliance team cannot administer them. Fails the key administration requirement.
aws:SecureTransport + Macie — Macie is a discovery service, not an encryption service. It finds PII but doesn’t encrypt anything at rest.
Key Takeaways
aws:SecureTransportcondition in a bucket policy enforces HTTPS for all requests- SSE-KMS with a customer-managed key lets you separate key administration from data usage
- Split the KMS key policy: compliance team gets
kms:*, applications get onlykms:Encrypt/kms:Decrypt - S3 does not accept custom certificates — encryption in transit is enforced via bucket policy, not cert configuration
- Always use
Denyfor security-critical bucket policies — deny statements are the last word in policy evaluation
Never miss a story from us, subscribe to our newsletter