m11p7 — secure the cluster, all opt-in (pre-m11p7 byte-for-byte):
- gRPC replication mTLS by default via a custom tokio-rustls acceptor +
DynamicCertResolver; zero-drop content-hash cert rotation (k8s ..data swap,
no pod restart, no inotify)
- inter-node HTTP TLS sharing the same resolver (one rotation, both planes) +
per-node keyed-BLAKE3 signed x-tidal-node-token; marker-without-token -> 403
- admin audit log (operator-leg only) + per-principal rate limit (engine
RateLimiter; sibling nodes exempt)
- k8s cert-manager manifest (certs.yaml) + scripts/gen-cluster-certs.sh fallback;
secret.example.yaml gains TIDAL_CLUSTER_KEY (file-mounted, hot-rotatable)
- exit gate verified real: mtls.rs (gRPC foreign-pod), cluster_security.rs
(HTTP foreign + zero-drop rotation under load), 7 security unit tests
perf — instrument floor (sweep Wave 1):
- new tidal/benches/wal.rs + tidal-server/benches/scatter.rs
- p99->mean honesty relabel; sweep manifest at docs/reviews/perf-sweep-2026-06-13.md
- add @tidal-performance agent (Martin Thompson)
new: cluster/{audit,http_tls,security}.rs, tests/cluster_security.rs,
docs/planning/milestone-11/phase-7.md
40 lines
1.9 KiB
YAML
40 lines
1.9 KiB
YAML
# TEMPLATE ONLY — do NOT commit a real key. The real secret is created
|
|
# out-of-band and is deliberately excluded from kustomization.yaml so no key
|
|
# lands in git.
|
|
#
|
|
# Secret shape: `tidaldb-credentials` with TWO keys (m11p5 §4 + m11p7):
|
|
# - TIDAL_API_KEY — the external/operator bearer (the stress/Ref-A lineage;
|
|
# the StatefulSet injects it as the `TIDAL_API_KEY` env var). EVERY pod and
|
|
# EVERY external client uses the same bearer (forwarded requests pass the
|
|
# caller's Authorization verbatim).
|
|
# - TIDAL_CLUSTER_KEY — m11p7: the SHARED CLUSTER KEY. Mints/verifies per-node
|
|
# signed internal tokens so inter-node HTTP carries verifiable node identity
|
|
# and the x-tidal-internal marker is honored ONLY from a verified sibling.
|
|
# Mounted as a FILE (TIDAL_CLUSTER_KEY_FILE) so a rotation is hot (no restart).
|
|
# Known ONLY to cluster pods — never hand it to external clients.
|
|
#
|
|
# Create the real one (do not apply this file):
|
|
# kubectl -n tidaldb-cluster create secret generic tidaldb-credentials \
|
|
# --from-literal=TIDAL_API_KEY="$(openssl rand -hex 32)" \
|
|
# --from-literal=TIDAL_CLUSTER_KEY="$(openssl rand -hex 32)"
|
|
#
|
|
# Inter-node TLS material is a SEPARATE Secret (`tidaldb-cluster-tls`), issued by
|
|
# cert-manager (certs.yaml) or provisioned with scripts/gen-cluster-certs.sh.
|
|
#
|
|
# In production manage these with External Secrets Operator / Sealed Secrets /
|
|
# Vault. An empty TIDAL_API_KEY runs UNAUTHENTICATED (WARN); an absent
|
|
# TIDAL_CLUSTER_KEY disables per-node tokens (the marker keeps hint-only
|
|
# behavior, WARN) — never do either on a shared network.
|
|
apiVersion: v1
|
|
kind: Secret
|
|
metadata:
|
|
name: tidaldb-credentials
|
|
namespace: tidaldb-cluster
|
|
labels:
|
|
app.kubernetes.io/name: tidaldb
|
|
app.kubernetes.io/part-of: tidaldb
|
|
type: Opaque
|
|
stringData:
|
|
TIDAL_API_KEY: "replace-me-do-not-commit"
|
|
TIDAL_CLUSTER_KEY: "replace-me-do-not-commit-distinct-from-api-key"
|