Restatement
The requirement is:
Update the bucket policy so that any
PutObjectrequest will be denied unless it includes thex-amz-server-side-encryptionheader.
This is AWS S3 bucket policy enforcement to require server-side encryption for all objects uploaded.
Why this is needed
- By default, anyone with permission to upload to a bucket can upload data without encryption.
- Security best practice often requires all objects to be encrypted.
- Enforcing via a bucket policy prevents users from bypassing encryption requirements.
How it works
When you upload an object to S3 (PutObject), you can include headers that control encryption, such as:
x-amz-server-side-encryption: AES256
or
x-amz-server-side-encryption: aws:kms
A bucket policy can check for this header and deny the upload if it’s missing.
Example Bucket Policy
Here’s a sample policy that enforces server-side encryption:
{
"Version": "2012-10-17",
"Id": "EnforceSSE",
"Statement": [
{
"Sid": "DenyUnencryptedObjectUploads",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::my-bucket-name/*",
"Condition": {
"StringNotEquals": {
"s3:x-amz-server-side-encryption": "AES256"
}
}
}
]
}
Breaking this policy down
| Field | Meaning |
|---|---|
"Effect": "Deny" |
Denies the action if the condition matches |
"Principal": "*" |
Applies to all users |
"Action": "s3:PutObject" |
Applies to object uploads |
"Resource": "arn:aws:s3:::my-bucket-name/*" |
Applies to all objects in the bucket |
"Condition" |
Specifies the requirement |
"StringNotEquals" |
Deny if the header does not equal "AES256"
|
"s3:x-amz-server-side-encryption" |
The encryption header |
Example in Practice
Allowed request
PUT /my-object HTTP/1.1
Host: my-bucket-name.s3.amazonaws.com
x-amz-server-side-encryption: AES256
✅ Allowed — encryption header is present.
Denied request
PUT /my-object HTTP/1.1
Host: my-bucket-name.s3.amazonaws.com
❌ Denied — encryption header missing.
Key points for exams
- The Condition key
s3:x-amz-server-side-encryptionenforces encryption headers. - Bucket policies are evaluated before IAM policies — so this is a powerful enforcement tool.
- This is often asked in SAA exam scenarios where compliance and security policies are involved.
Top comments (1)
KMS encryption enforcement at the bucket policy layer is the cleanest pattern we have for compliance, but three production gotchas to watch for:
Deny-without-explicit-Deny — operators frequently confuse Deny + not-Deny with implicit Deny. Once SSE-KMS is required, every request without the right header gets blocked. Mount layers that synthesize their own client (drive-letter S3 mounts) often skip the header silently, so admin-side mounts suddenly stop working after the policy ships.
Cross-account key access — when buckets move to a centralized KMS key, the policy on the key itself has to allow the bucket account. S3 policy says yes, KMS policy says no — failures look like a 403 with no clue which side rejected.
PutObject alone is not enough — GetObject also has to enforce the same key, otherwise a no-SSE object lands via multipart upload and survives any read-side check. Pair the bucket policy with a lifecycle rule that aborts incomplete multipart uploads within 7 days — that one alone saved us from a few surprise storage bills.
Mount layer: ScsDriver