Files
cephrgw-operator/docs/ceph-setup.md
benvin fa7d7281f0
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
docs: make Vault/VSO the primary credential method
Document sourcing cephrgw-credentials from Vault via VSO as the primary path,
using the shared default k8s auth role and the templated KV path
kubernetes/namespace/cephrgw-system/default/cephrgw-credentials (no dedicated
Vault role/policy needed). Keep the plain-Secret method as a fallback for
non-cluster/kind use.
2026-07-18 16:27:52 +10:00

197 lines
7.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Ceph setup: credentials and permissions the operator needs
`cephrgw-operator` never talks to RADOS or the RGW admin socket directly. It
drives the **Ceph manager dashboard REST API** (the same API the web dashboard
uses) at `https://dashboard.ceph.unkin.net`. Everything below is about giving
the operator a dashboard login with enough RGW authority, and making sure the
dashboard itself is wired to your RGW.
There are **two** credentials involved. Don't confuse them:
| # | Credential | Who uses it | What it is |
|---|------------|-------------|------------|
| 1 | Dashboard login (username + password) | the operator → `POST /api/auth` | a **dashboard account** with the `rgw-manager` role |
| 2 | RGW admin connection | the dashboard → RGW | a **radosgw system user** (access/secret key) the dashboard is configured with |
The operator only holds #1. #2 is what actually lets the dashboard create RGW
users, buckets and bucket policies on the operator's behalf, so it must exist
and be privileged.
---
## 1. Create the dashboard login for the operator
Create a dedicated dashboard user with the built-in **`rgw-manager`** role. That
role grants full create/read/update/delete on the dashboard's `rgw` scope
(users, buckets, policies) and nothing else — least privilege for this operator.
```bash
# Put the password in a file so it never lands in shell history.
printf '%s' 'REPLACE-WITH-A-STRONG-PASSWORD' > /tmp/cephrgw.pw
ceph dashboard ac-user-create k8s-cephrgw-operator -i /tmp/cephrgw.pw rgw-manager
rm -f /tmp/cephrgw.pw
```
If your Ceph version wants the arguments in a different order, check
`ceph dashboard ac-user-create -h`. To confirm the role exists and what it
grants:
```bash
ceph dashboard ac-role-show rgw-manager
```
> Prefer `rgw-manager` over `administrator`. The operator only needs RGW
> authority; giving it full dashboard admin is unnecessary blast radius.
## 2. Make sure the dashboard can manage RGW
The dashboard performs RGW operations through a **radosgw system user**. On
recent Ceph (Pacific and later) the mgr/dashboard module usually auto-discovers
and configures this. Verify it first:
```bash
ceph dashboard get-rgw-api-access-key # should print a key, not empty
```
If it is empty, create a system user and point the dashboard at it:
```bash
radosgw-admin user create \
--uid=dashboard \
--display-name="Ceph Dashboard" \
--system
# Feed the returned keys to the dashboard.
radosgw-admin user info --uid=dashboard \
| jq -r '.keys[0].access_key' > /tmp/ak
radosgw-admin user info --uid=dashboard \
| jq -r '.keys[0].secret_key' > /tmp/sk
ceph dashboard set-rgw-api-access-key -i /tmp/ak
ceph dashboard set-rgw-api-secret-key -i /tmp/sk
rm -f /tmp/ak /tmp/sk
```
A `--system` user has the admin caps the dashboard needs to create/delete RGW
users and buckets and to set bucket policies on any bucket. If you would rather
not use `--system`, grant an equivalent admin cap set instead:
```bash
radosgw-admin caps add --uid=dashboard \
--caps="users=*;buckets=*;metadata=*;usage=read;zone=read"
```
If the dashboard reaches RGW over TLS with a private CA, you may also need:
```bash
ceph dashboard set-rgw-api-ssl-verify true # keep verification on in prod
```
## 3. Bucket policy support (read-only / non-owner read-write)
The operator enforces `read-only` and non-owner `read-write` grants by writing
an **S3 bucket policy** through the dashboard's bucket API (the `bucket_policy`
field on `PUT /api/rgw/bucket/{name}`). That field is available on **Ceph Reef
18.2+ / Squid**. On older releases bucket creation and owner (`full`) access
still work, but policy-based grants will fail — upgrade the cluster, or only use
owner credentials, if you are pre-Reef.
Check your version:
```bash
ceph versions | jq -r '.mon | keys[]'
```
## 4. (Optional) S3 endpoint for consumers
The operator can stamp the S3 endpoint into every credential Secret it writes
(`S3_ENDPOINT` and `BUCKET_HOST`) so applications don't have to hard-code it.
This is the RGW/S3 endpoint your clients use — **not** the dashboard URL. Provide
it via `CEPH_RGW_ENDPOINT` (see below); if unset, those keys are simply omitted.
---
## 5. Give the operator its credentials (the `cephrgw-credentials` Secret)
The operator reads its configuration from environment variables, which the
deployment sources (via `envFrom`) from a Secret named **`cephrgw-credentials`**
in its namespace (`cephrgw-system`). The Secret data keys map 1:1 to the env
vars:
| Secret key | Required | Meaning |
|------------|----------|---------|
| `CEPH_DASHBOARD_URL` | yes | dashboard base URL, e.g. `https://dashboard.ceph.unkin.net` |
| `CEPH_DASHBOARD_USERNAME` | yes | the `rgw-manager` account from step 1 |
| `CEPH_DASHBOARD_PASSWORD` | yes | its password |
| `CEPH_RGW_ENDPOINT` | no | S3 endpoint written into consumer Secrets |
| `CEPH_DASHBOARD_CA` | no | PEM CA bundle to verify the dashboard TLS cert (inline) |
| `CEPH_DASHBOARD_CA_FILE` | no | path to a mounted CA file (alternative to the above) |
| `CEPH_DASHBOARD_INSECURE` | no | `"true"` to skip TLS verification (dev only) |
### Primary method: Vault + VSO
The Secret is not managed in GitOps; it is rendered from Vault by the Vault
Secrets Operator (VSO). The argocd-apps `cephrgw-system` app ships a `VaultAuth`
and a `VaultStaticSecret` that authenticate with the shared `default` Kubernetes
auth role and render the KV path
`kubernetes/namespace/cephrgw-system/default/cephrgw-credentials` into the
`cephrgw-credentials` Secret. That path sits under the cluster's templated
default policy (`kv/data/kubernetes/namespace/<ns>/<sa>/*`), so **no dedicated
Vault role or policy is required** — you only seed the values:
```bash
vault kv put kv/kubernetes/namespace/cephrgw-system/default/cephrgw-credentials \
CEPH_DASHBOARD_URL=https://dashboard.ceph.unkin.net \
CEPH_DASHBOARD_USERNAME=k8s-cephrgw-operator \
CEPH_DASHBOARD_PASSWORD='REPLACE-WITH-A-STRONG-PASSWORD' \
CEPH_RGW_ENDPOINT=https://s3.ceph.unkin.net
```
The keys under that KV path are copied verbatim into the Secret, so they must be
named exactly as the table above. VSO refreshes the Secret every few minutes,
and the deployment's `reloader.stakater.com/auto: "true"` annotation restarts the
operator when it changes — so rotating the credential is just a new `vault kv
put`, no manual rollout.
### Fallback: a plain Secret
Outside this cluster (or for a quick `kind` test) you can create the Secret
directly instead of using Vault:
```bash
kubectl -n cephrgw-system create secret generic cephrgw-credentials \
--from-literal=CEPH_DASHBOARD_URL=https://dashboard.ceph.unkin.net \
--from-literal=CEPH_DASHBOARD_USERNAME=k8s-cephrgw-operator \
--from-literal=CEPH_DASHBOARD_PASSWORD='REPLACE-WITH-A-STRONG-PASSWORD' \
--from-literal=CEPH_RGW_ENDPOINT=https://s3.ceph.unkin.net
```
The operator does not care where the Secret comes from, only that those keys
exist.
---
## Quick verification
Once the Secret and dashboard account exist, a smoke test from your workstation:
```bash
# 1. Log in and capture a token.
TOKEN=$(curl -sk -X POST https://dashboard.ceph.unkin.net/api/auth \
-H 'Accept: application/vnd.ceph.api.v1.0+json' \
-H 'Content-Type: application/json' \
-d '{"username":"k8s-cephrgw-operator","password":"REPLACE-WITH-A-STRONG-PASSWORD"}' \
| jq -r .token)
# 2. List RGW users — a 200 with a JSON array means the role + RGW wiring work.
curl -sk https://dashboard.ceph.unkin.net/api/rgw/user \
-H 'Accept: application/vnd.ceph.api.v1.0+json' \
-H "Authorization: Bearer $TOKEN"
```
If step 1 fails the login/role is wrong (step 12 above); if step 1 works but
step 2 returns 500/empty, the dashboard→RGW connection is not configured
(step 2).