> ## Documentation Index
> Fetch the complete documentation index at: https://docs.casebender.com/llms.txt
> Use this file to discover all available pages before exploring further.

# OpenShift ODF and Ceph RGW Storage

> Connect CaseBender to customer-managed OBC or standalone Ceph RGW storage

This profile connects CaseBender to existing customer-managed OpenShift Data
Foundation (ODF) or Ceph RGW. CaseBender is an S3 client; it does not install,
upgrade, back up, monitor, or administer ODF, Ceph, RGW, users, or buckets.

<Warning>
  Current live certification is pending customer credentials and exact-version
  evidence. The overlay is configured and qualification-ready, not certified.
</Warning>

## Storage layout

Provision three independent external buckets:

| Purpose profile | Required behavior                                                           |
| --------------- | --------------------------------------------------------------------------- |
| `quarantine`    | Initial user uploads; scanner-only promotion path; no public access         |
| `records`       | Durable attachments/evidence/exports; versioning and required WORM controls |
| `ephemeral`     | Deep canaries and short-lived exports; bounded lifecycle policy             |

All three must exist before startup. The runtime adapter never creates a bucket.
The overlay uses HTTPS, path-style S3 addressing, verified private CA trust,
AES-256 server-side encryption requests, and SHA-256 application integrity.

## Option A: external managed OBCs

Identify the customer-approved RGW bucket StorageClass:

```bash theme={null}
oc get storageclass \
  -o custom-columns=NAME:.metadata.name,PROVISIONER:.provisioner
oc api-resources | rg -i objectbucketclaim
```

Copy
`k8s/overlays/openshift-odf-rgw/object-bucket-claims.example.yaml`
to the customer environment repository, replace the StorageClass placeholder,
and apply it separately from CaseBender. Bucket lifecycle remains owned by the
storage operator.

```bash theme={null}
oc apply -f '<customer-obc-manifest.yaml>'
oc -n casebender wait --for=jsonpath='{.status.phase}'=Bound \
  objectbucketclaim/casebender-quarantine \
  objectbucketclaim/casebender-records \
  objectbucketclaim/casebender-ephemeral \
  --timeout=10m
```

Confirm, without printing values, that each generated ConfigMap provides
`BUCKET_HOST`, `BUCKET_PORT`, `BUCKET_NAME`, and `BUCKET_REGION`, and each
Secret provides `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`. If the OBC
operator uses other keys, patch `valueFrom`; never copy credentials into a
ConfigMap or Kustomize file.

## Option B: standalone external RGW

Use
`k8s/overlays/openshift-odf-rgw/standalone-rgw-resources.example.yaml`
as a mapping example. Replace every `.invalid` endpoint and bucket placeholder
in the customer overlay. Use the installed external-secret controller or
another approved secret injector. Keep endpoints and bucket names in
ConfigMaps, credentials in Secrets, and all real values outside this repository.

The restricted init container reads these resources and writes a strict
`STORAGE_CONFIG_FILE` to a memory-backed `emptyDir` with mode `0400`. Web and
worker mount it read-only.

## Private CA

Create a CA ConfigMap containing only the issuing chain:

```bash theme={null}
oc -n casebender create configmap casebender-rgw-ca \
  --from-file=ca.crt='<customer-rgw-ca-chain.pem>' \
  --dry-run=client -o yaml | oc apply -f -
```

The certificate must cover the exact RGW hostname. TLS verification remains
enabled. Never use an unlisted IP address, an HTTP endpoint, `--insecure`, or a
certificate-bypass option.

## Egress

The included policy permits web and worker to reach TCP 443 on pods labelled
`app=rook-ceph-rgw` in `openshift-storage`. Verify the actual namespace, labels,
port, and CNI behavior.

For external RGW, copy and adapt
`external-rgw-network-policy.example.yaml` with stable approved CIDRs, or route
through an operator-controlled egress proxy. Kubernetes NetworkPolicy cannot
select FQDNs. Do not restore wildcard `0.0.0.0/0` or `::/0` egress.

Add separate least-privilege policies for PostgreSQL, Redis, identity, scanner,
and approved integrations.

## Scanner prerequisite

Production user uploads require external `clamd`. The provided worker patch
expects `casebender-malware-scanner` (`host`, `port`) and
`casebender-malware-scanner-ca` (`ca.crt`) and enables TLS. A same-pod scanner
may instead use `CLAMD_SOCKET_PATH`. If the scanner is unavailable, objects
remain quarantined and retries can eventually dead-letter; downloads do not
fail open.

## Render and validate

```bash theme={null}
kubectl kustomize k8s/overlays/openshift-odf-rgw \
  > /tmp/casebender-openshift-odf-rgw.yaml
./scripts/openshift/validate.sh \
  /tmp/casebender-openshift-odf-rgw.yaml
oc apply --server-side --dry-run=server \
  -f /tmp/casebender-openshift-odf-rgw.yaml
oc apply --server-side \
  -f /tmp/casebender-openshift-odf-rgw.yaml
oc -n casebender rollout status deployment/webapp deployment/worker \
  --timeout=10m
```

Then run live qualification from the workload network and trust context:

```bash theme={null}
STORAGE_TEST_ENDPOINT='https://<rgw-host>' \
STORAGE_TEST_BUCKET='<dedicated-test-bucket>' \
AWS_REGION='<rgw-region>' \
STORAGE_TEST_CA_BUNDLE='<private-ca-file>' \
STORAGE_TEST_ODF_VERSION='<exact-odf-version>' \
STORAGE_TEST_CEPH_VERSION='<exact-ceph-version>' \
STORAGE_TEST_CAP_VERSIONING='<true-or-false>' \
STORAGE_TEST_CAP_DELETE_MARKERS='<true-or-false>' \
STORAGE_TEST_CAP_OBJECT_LOCK='<true-or-false>' \
./scripts/storage/validate-ceph-rgw.sh
```

Supply credentials through the AWS credential chain, scoped to the dedicated
test bucket/prefix. Complete and sign
`apps/docs/en/deployment/odf-ceph-rgw-validation-evidence.md`. A render,
emulator test, or unsigned transcript is not live certification.

## Credential rotation

1. Rotate through the supported ODF/Ceph procedure; do not hand-edit an
   operator-owned OBC Secret.
2. Allow a bounded overlap while the generated Secret or ExternalSecret
   refreshes.
3. Restart web and worker so the init container regenerates the mounted file.
4. Require `/api/health/ready` and live contract validation to pass.
5. Revoke the old credential and check sanitized authentication metrics/logs.

## CA rotation

1. Publish a temporary CA bundle containing old and new issuing CAs.
2. Restart and validate web and worker.
3. Rotate the RGW serving certificate.
4. Publish the new-only CA bundle, restart, and validate again.
5. Record ConfigMap resource versions, CA SHA-256 hashes, exact ODF/Ceph
   versions, and evidence—never credential values.

See [Storage Health and Troubleshooting](/en/deployment/storage-health-troubleshooting)
and the in-repository
`k8s/overlays/openshift-odf-rgw/README.md` for overlay details.
