CephXXXIII · EncryptionEncryption
RGW server-side encryption: SSE-S3, SSE-KMS, and SSE-C
What you'll learn
- Distinguish SSE-S3, SSE-KMS, and SSE-C
- Configure RGW server-side encryption
- Choose a mode against a stated key-control requirement
- Enforce encryption with bucket policy
Prerequisites
None — start here.
Verified against Ceph Tentacle 20.2.x · Ceph Squid 19.2.x (supported previous) · cephadm matches the verified Ceph release · podman 4.x · csi-rbd and csi-cephfs current · RBD / CephFS / RGW current (matches Ceph release) · Linux kernel 5.15+ (5.10 minimum) · Ubuntu 24.04 LTS (Ceph host baseline) · Debian 12 (Bookworm) (Ceph host baseline) · Rocky Linux / RHEL / AlmaLinux 9.x (Ceph host baseline) · Proxmox VE 9.x (cross-course integration) · Kubernetes 1.31+ (cross-course integration) · 2026-08-18
Why this matters in production
Object storage encryption requirements are usually expressed as “data must be encrypted at rest”, which every one of these modes satisfies. The requirement that actually distinguishes them is who controls the key, and that is the question to ask before choosing.
The three modes
| Mode | Key held by | Client involvement |
|---|---|---|
| SSE-S3 | RGW, from a configured backend | none — transparent |
| SSE-KMS | external KMS, per-key-id | client names a key id |
| SSE-C | the client, supplied per request | client sends the key with every request |
All three encrypt object data before it is written to RADOS, so the stored objects are ciphertext regardless of the underlying pool.
SSE-S3
Transparent to clients. RGW obtains keys from its configured backend and manages them.
BASE64_KEY=report.pdf
ceph config set client.rgw rgw_crypt_default_encryption_key ${BASE64_KEY}
That per-gateway static key form is suitable for a single-key deployment. For anything more, back SSE-S3 with a KMS so keys are managed properly rather than living in the gateway configuration.
SSE-KMS
The strongest option where key control is the requirement, because keys live in a system Ceph does not control.
ceph config set client.rgw rgw_crypt_s3_kms_backend vault
ceph config set client.rgw rgw_crypt_vault_addr https://vault.example.com:8200
ceph config set client.rgw rgw_crypt_vault_auth token
ceph config set client.rgw rgw_crypt_vault_secret_engine transit
Clients then name a key:
aws s3 cp file.dat s3://bucket/file.dat \
--sse aws:kms --sse-kms-key-id my-key-id
The properties that matter: keys are revocable outside Ceph, key use is audited by the KMS, and a compromised gateway does not yield the keys — only the ability to request decryption while it is trusted.
SSE-C
The client supplies the key with every request. RGW uses it, then discards it.
aws s3 cp file.dat s3://bucket/file.dat \
--sse-c AES256 --sse-c-key fileb://key.bin
Maximum client control, and the client bears full responsibility: lose the key and the object is unrecoverable, with no path to recovery through Ceph. Requires HTTPS, since the key traverses the connection.
Enforcing it
Encryption that clients may opt into is encryption most clients will not use. Enforce with a bucket policy that denies unencrypted uploads:
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Deny",
"Principal": "*",
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::sensitive/*",
"Condition": {
"StringNotEquals": { "s3:x-amz-server-side-encryption": "aws:kms" }
}
}]
}
Quiz
Knowledge check · 4 questions
Q1. A requirement states that the storage operator must be unable to decrypt customer data. Which mode satisfies it?
Q2. Enabling both compression and server-side encryption on the same RGW data yields the expected compression benefit.
Q3. Design encryption for a multi-tenant object service.
A service provider hosts S3 storage for external customers. Contracts require that customer data be encrypted at rest and that the provider cannot access plaintext. Customers vary in technical sophistication and some cannot manage keys themselves.
Q4. Why does SSE compose with dm-crypt rather than being redundant?
Passing score: 75%. Answers are checked in this browser.
Production discipline
Ask who must control the key before choosing a mode; every option satisfies a naive “encrypted at rest” requirement and they differ entirely on that question. Enforce encryption with bucket policy rather than relying on clients to opt in, and state plainly in the service description that SSE-C key loss is unrecoverable.
Cross-course references
- Kubernetes: Secret encryption providers offer the same range of key-custody options
- Linux: file-level encryption alongside full-disk encryption is the same layered reasoning