To secure S3 buckets on Ceph RGW properly, treat it as three layers:
- Harden the RGW endpoint
- Use least-privilege identities and bucket policies
- Turn on data-protection features per bucket
Here’s the practical baseline.
1) Secure the RGW endpoint first
Never expose RGW over plain HTTP. Use HTTPS only. Ceph’s RGW supports TLS with the Beast frontend, and cephadm documents HTTPS setup for RGW services. Also, Ceph’s encryption docs explicitly note that requests involving server-side encryption must use HTTPS so secrets are not sent in plaintext.
Do this:
- Terminate TLS on RGW itself or on a trusted reverse proxy/load balancer
- Disable/avoid plaintext listeners
- Restrict inbound access with firewall rules to trusted networks, apps, or gateways
- Keep Ceph on a supported, patched release because RGW security fixes do land in point releases and past RGW vulnerabilities have required upgrades.
2) Do not use broad S3 credentials
Use separate users/roles per app, not shared cluster-wide access keys. Ceph RGW supports accounts, users, IAM-style policies, and roles; account users start with no permissions by default, which is exactly what you want for least privilege. Temporary credentials via roles/STS are preferable to long-lived static keys where your app stack can support them.
Good pattern
- One app = one IAM user or role
- One environment = separate credentials
- Prefer temporary creds for workloads
- Rotate long-lived keys regularly
- Never let applications use the account root identity except for administration
3) Block public access by policy, not by assumption
Ceph RGW supports bucket policies through standard S3 operations. Use them to explicitly deny public access unless a bucket is intentionally public.
Baseline rule:
- No wildcard
Principal: "*"unless the bucket is intentionally public - No anonymous read/write
- No bucket ACL sprawl; prefer bucket policy + IAM policy over ad hoc ACLs
A strong design is:
- Identity policy grants an app access only to its bucket/prefix
- Bucket policy adds guardrails, such as denying insecure transport, denying deletes, or restricting to certain principals
4) Enforce encryption at rest
Ceph RGW supports server-side encryption, including SSE with managed keys and SSE-KMS integrations; Ceph also documents KMIP-backed KMS integration for SSE-KMS.
Best practice
- Require encryption on every object
- Prefer SSE-KMS when you need tighter key control, auditability, or separation of duties
- Use separate keys per environment or data class
- Restrict who can use KMS keys
Why this matters: bucket compromise is less damaging when raw object data is encrypted and key access is separately controlled.
5) Enable versioning on important buckets
Ceph RGW supports S3 bucket versioning. This is one of the most useful controls against accidental overwrite, delete, and many ransomware-like operational failures.
Use versioning for: backups, logs, artifacts, and user-generated content you cannot easily recreate.
Without versioning, a delete or overwrite is final at the bucket layer.
6) Use Object Lock for immutable data
Ceph RGW supports S3 Object Lock and retention/legal hold APIs. On current docs, Ceph also notes newer behavior allowing PutObjectLockConfiguration on an existing versioning-enabled bucket in newer releases, while older behavior required object lock at bucket creation time.
Use Object Lock for: backups, audit logs, compliance archives, and anything you must make WORM-like.
Important detail: Object Lock depends on versioning. In older RGW behavior, you had to create the bucket with object lock enabled; newer releases relaxed this. So check your exact Ceph release before designing the rollout.
7) Keep CORS extremely narrow
RGW has had a past CORS-related vulnerability, and in general CORS is a common bucket exposure point. Keep allowed origins, methods, and headers as tight as possible.
Do this:
- exact origins only, not
*, for sensitive buckets - only needed methods (
GET,PUT, etc.) - minimal exposed headers
- separate browser-facing buckets from private app buckets
8) Turn on bucket logging and auditability
Ceph documents bucket logging, including the option for the log bucket itself to use object lock/retention.
Good pattern
- send access logs to a separate dedicated log bucket
- restrict write/read permissions tightly
- enable retention or object lock on log buckets
- monitor for anonymous access, policy changes, and delete spikes
9) Separate tenants, buckets, and prefixes cleanly
Do not build a multi-tenant design where many unrelated apps share one broad bucket and one broad credential.
Safer pattern
- separate accounts or users per team/app
- separate buckets per sensitivity class
- separate prefixes only when bucket split is impractical
- give each principal only the prefix it truly needs
This limits blast radius when one credential is leaked.
10) Prefer explicit deny guardrails
On sensitive buckets, add explicit deny statements for things you never want:
- deny requests not using TLS
- deny deletes except backup/admin roles
- deny object uploads without encryption headers
- deny access outside approved principals
This is usually more reliable than relying only on allows.
11) Patch level matters
This is not optional. Ceph publishes security advisories and multiple RGW fixes have shipped in point releases. Running old RGW releases is a real security risk.
A baseline I would be comfortable starting from
For a production private bucket on RGW, I’d set this as the default:
- HTTPS only
- Dedicated IAM user/role per app
- No public bucket policy
- Least-privilege access to one bucket or one prefix
- Server-side encryption required
- Versioning enabled
- Object Lock enabled for backups/logs/critical data
- Narrow CORS or none
- Access logging enabled
- Regular key rotation
- Ceph kept on supported patched release
Mistakes worth checking twice
- Using one access key for many apps
- Leaving buckets private “by convention” with no explicit policy guardrails
- No versioning on backup buckets
- Enabling permissive CORS
- Exposing RGW over HTTP internally because “it’s only inside the network”
- Treating Ceph RGW root/admin credentials like normal app credentials
The short version
Properly securing Ceph RGW S3 buckets means: HTTPS + least-privilege IAM + deny-public bucket policies + encryption + versioning + object lock where needed + logging + patching.
Keep policy examples release-specific
RGW supports a subset of the S3 policy language and that subset can differ by release. Verify the actions and condition keys you depend on against the Ceph bucket-policy documentation.