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
64 lines
2.6 KiB
YAML
64 lines
2.6 KiB
YAML
# m11p7 inter-node TLS — cluster CA + the shared node cert (cert-manager).
|
|
#
|
|
# The whole cluster runs over mutual TLS: gRPC replication (mTLS — client certs
|
|
# required) and the inter-node HTTP plane (server TLS + signed node tokens). This
|
|
# manifest provisions the material with cert-manager so renewal is automatic and
|
|
# hot — cert-manager rewrites the mounted Secret, the kubelet swaps the `..data`
|
|
# symlink, and tidalDB's content-hash cert poller hot-swaps the in-memory cert
|
|
# with ZERO connection drop (no pod restart). See docs/runbooks/cluster.md §10.
|
|
#
|
|
# Prereq: cert-manager installed in the cluster (https://cert-manager.io). If you
|
|
# do not run cert-manager, provision the same Secret out-of-band — e.g. with
|
|
# `scripts/gen-cluster-certs.sh` (openssl) — keeping the keys `tls.crt`, `tls.key`,
|
|
# `ca.crt`.
|
|
#
|
|
# ONE shared node cert with EVERY pod's stable DNS as a SAN (the standard
|
|
# StatefulSet pattern): any pod may present it for its own DNS name, and a peer
|
|
# dialing `tidaldb-N.tidaldb-peers...` verifies the name against the SAN list.
|
|
---
|
|
apiVersion: cert-manager.io/v1
|
|
kind: Issuer
|
|
metadata:
|
|
name: tidaldb-cluster-ca-issuer
|
|
namespace: tidaldb-cluster
|
|
labels:
|
|
app.kubernetes.io/name: tidaldb
|
|
app.kubernetes.io/part-of: tidaldb
|
|
spec:
|
|
# A self-signed CA root for the cluster's private inter-node PKI. Swap for a
|
|
# `ca:` issuer backed by your org PKI to chain to an existing root.
|
|
selfSigned: {}
|
|
---
|
|
apiVersion: cert-manager.io/v1
|
|
kind: Certificate
|
|
metadata:
|
|
name: tidaldb-cluster-tls
|
|
namespace: tidaldb-cluster
|
|
labels:
|
|
app.kubernetes.io/name: tidaldb
|
|
app.kubernetes.io/part-of: tidaldb
|
|
spec:
|
|
# cert-manager writes tls.crt / tls.key / ca.crt into this Secret; the
|
|
# StatefulSet mounts it read-only at /etc/tidaldb/tls.
|
|
secretName: tidaldb-cluster-tls
|
|
# Renew well before expiry; each renewal is hot-swapped without a restart.
|
|
duration: 2160h # 90d
|
|
renewBefore: 720h # 30d
|
|
isCA: false
|
|
usages:
|
|
- server auth # the gRPC + HTTP server identity
|
|
- client auth # the gRPC mTLS client identity (peer dials)
|
|
# SANs: every initial pod's stable headless-Service DNS, plus the headless and
|
|
# client Services. Scaling past 3 with `--seed` requires adding the new pod's
|
|
# DNS here (or switching to a per-pod Certificate template).
|
|
dnsNames:
|
|
- tidaldb-0.tidaldb-peers.tidaldb-cluster.svc.cluster.local
|
|
- tidaldb-1.tidaldb-peers.tidaldb-cluster.svc.cluster.local
|
|
- tidaldb-2.tidaldb-peers.tidaldb-cluster.svc.cluster.local
|
|
- tidaldb-peers.tidaldb-cluster.svc.cluster.local
|
|
- tidaldb.tidaldb-cluster.svc.cluster.local
|
|
issuerRef:
|
|
name: tidaldb-cluster-ca-issuer
|
|
kind: Issuer
|
|
group: cert-manager.io
|