Back to Blog
Controls 6 min read

S3 Encryption for SOC 2: Buckets, KMS, and Evidence

Configure S3 encryption for SOC 2 CC6.6. Covers SSE-S3 vs SSE-KMS, enforcing encryption in bucket policies, key management, and auditor evidence requirements.

Key Takeaways
  • All S3 buckets containing sensitive or customer data must have server-side encryption enabled for CC6.6.
  • SSE-KMS with a customer-managed KMS key provides stronger control and audit trail than SSE-S3.
  • Bucket policies should deny PUT requests that don't specify encryption — enforcing encryption by default.
  • Public access block must be enabled on all buckets not intentionally public.
  • AWS Config rules provide automated, ongoing evidence of S3 encryption compliance.

Why S3 Encryption Matters for SOC 2

S3 is the most commonly used storage service in AWS and a frequent location for sensitive data — customer documents, database backups, application logs, and evidence files. CC6.6 requires encryption of sensitive data at rest, which directly applies to S3 buckets holding such data.

S3 data exposure through misconfigured access controls is one of the most common causes of cloud data breaches. Encryption at rest ensures that even if an attacker gains access to the underlying storage media or if a bucket is briefly misconfigured to be publicly accessible, the data is still protected.

SSE-S3 vs SSE-KMS

SSE-S3 (Server-Side Encryption with S3-managed keys): S3 manages the encryption keys. Objects are encrypted using AES-256. No additional cost beyond API calls. Simplest to configure. Provides encryption at rest but limited key management audit trail.

SSE-KMS (Server-Side Encryption with AWS KMS keys): Uses AWS Key Management Service to manage encryption keys. Provides a detailed audit trail of key usage in CloudTrail (who decrypted what, when). Supports customer-managed keys (CMK) for fine-grained access control. Adds cost: $1/month per KMS key + $0.03 per 10,000 API calls.

For SOC 2, SSE-KMS with a customer-managed key is the preferred approach for buckets containing sensitive or customer data. It provides both encryption and the key usage audit trail that supports CC7.2 anomaly detection. Use SSE-S3 for non-sensitive data (build artifacts, public static files) to manage costs.

Enabling Default Encryption on Buckets

Enable default bucket encryption in S3 > Bucket > Properties > Default encryption. Select SSE-KMS, choose your KMS key (customer-managed for sensitive data, AWS managed key for lower-sensitivity data), and save.

Via AWS CLI: aws s3api put-bucket-encryption --bucket your-bucket --server-side-encryption-configuration '{"Rules":[{"ApplyServerSideEncryptionByDefault":{"SSEAlgorithm":"aws:kms","KMSMasterKeyID":"arn:aws:kms:region:account:key/key-id"},"BucketKeyEnabled":true}]}'.

Enable Bucket Key when using SSE-KMS to reduce KMS API call costs by generating a data key per-bucket rather than per-object. This reduces KMS costs by up to 99% for buckets with many objects.

Enforcing Encryption via Bucket Policy

Default bucket encryption applies to objects uploaded without encryption headers, but doesn't prevent a requester from explicitly specifying no encryption. Add a bucket policy condition to deny PutObject requests that don't use your required encryption: Condition: {"StringNotEquals": {"s3:x-amz-server-side-encryption": "aws:kms"}}.

Also enforce TLS-in-transit with a bucket policy condition: Condition: {"Bool": {"aws:SecureTransport": "false"}} with Effect: Deny — this denies any request not made over HTTPS.

Combine both conditions in your bucket policy for comprehensive protection: deny unencrypted uploads and deny non-HTTPS access.

Blocking Public Access

Accidentally public S3 buckets are a leading cause of data breaches. Enable S3 Block Public Access at the account level (S3 > Block Public Access settings for this account) and at the bucket level. Block all four settings: BlockPublicAcls, IgnorePublicAcls, BlockPublicPolicy, RestrictPublicBuckets.

For buckets that legitimately serve public content (static websites, public documentation): document the business justification, whitelist them in an exception log, and ensure they contain no sensitive data.

AWS Config rule "s3-bucket-public-read-prohibited" and "s3-bucket-public-write-prohibited" automatically detect buckets violating the public access policy. Ensure these rules report compliant for all sensitive buckets.

S3 Evidence for SOC 2 Auditors

(1) S3 bucket inventory listing all buckets with encryption status and public access settings. (2) AWS Config findings for "s3-bucket-server-side-encryption-enabled" and "s3-bucket-public-read-prohibited" — all compliant. (3) Sample bucket encryption configuration screenshots for key buckets (production data, backups). (4) Bucket policies for key buckets showing encryption enforcement and TLS-only conditions. (5) KMS key policy screenshot for customer-managed keys. (6) Account-level S3 Block Public Access settings screenshot.

Frequently Asked Questions

Do all S3 buckets need encryption for SOC 2, or just those with customer data?
Strictly, CC6.6 requires encryption for sensitive data. However, the practical advice is to enable default encryption on all buckets — it costs nothing extra with SSE-S3, and it eliminates the need to classify every bucket. Enable SSE-KMS for buckets confirmed to contain sensitive data.
Does S3 encryption protect against a misconfigured public bucket?
No. If a bucket is publicly accessible, an attacker can download the objects and the encryption is decrypted by S3 before delivery. Encryption at rest protects against physical media theft and storage-layer access — not against misconfigured access controls. Use both encryption and Block Public Access together.
We have existing buckets without encryption — can we enable encryption retroactively?
Yes. Enabling default bucket encryption on an existing bucket will encrypt new objects going forward. Existing unencrypted objects remain unencrypted unless you copy them (aws s3 cp s3://bucket s3://bucket --recursive --sse aws:kms) to trigger re-encryption. For SOC 2, enable encryption now and re-encrypt existing sensitive objects before the audit.
What is Macie, and should we enable it alongside S3 encryption?
AWS Macie uses machine learning to automatically discover and protect sensitive data in S3 — it identifies buckets containing PII, credentials, and financial data. Enabling Macie provides visibility into what sensitive data you have in S3 and supports CC6.1 data classification. It's complementary to encryption, not a replacement.
Do CloudTrail data events need to be enabled to evidence S3 encryption for SOC 2?
Not specifically for encryption evidence — the encryption configuration itself (bucket properties screenshot, AWS Config rule status) is sufficient. CloudTrail S3 data events (logging GetObject, PutObject) are valuable for CC7.2 anomaly detection and CC6.1 access control evidence, but are separate from the encryption controls.

Automate your compliance today

AuditPath runs 86+ automated checks across AWS, GitHub, Okta, and 14 more integrations. SOC 2 and DPDP Act. Free plan available.

Start for free