Skip to content

Commit 303f8f9

Browse files
committed
docs(admin): fix HS256 key size, audit log sample, cross-ref, data-plane label
Three substantive findings + one nit from claude review on #674: 1. **HS256 key size (high)**: said "≥ 32 raw bytes / 44 base64 chars" but the validator in internal/admin/config.go enforces exactly 64 raw bytes. A 32-byte key fails startup with a confusing error. Updated to "exactly 64 raw bytes — 88 base64 chars (standard padding) or 86 (RawURLEncoding)". Operators copying the doc into key-generation tooling now produce a key that actually validates. 2. **Audit log sample (moderate)**: showed method=POST / path=... / status=201 / duration=8.2ms — none of those fields are emitted. The actual slog entries use operation= + a resource key (bucket= or table=). Replaced the example with two real shapes (leader-direct and forwarded), so an operator building a log parser against the documented contract finds matches. 3. **Cross-reference link (moderate)**: line 249 used the _partial_ filename for the design doc, but #675 (the rename PR) hasnt landed yet. Point to _proposed_ (matches main today) with an inline note that the link will follow once #675 lands. The intro paragraph at line 5 already used _proposed_, so this removes the inconsistency claude flagged. 4. **"data-plane" label nit**: /admin/api/v1/cluster is an admin- plane endpoint, not data-plane. "data-plane" implied the DynamoDB / S3 / Redis ports. Replaced with "admin". The cosmetic Last-updated / Status verbosity items on #675 are tracked separately.
1 parent a3425e5 commit 303f8f9

1 file changed

Lines changed: 20 additions & 10 deletions

File tree

docs/admin.md

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ with the access key + secret pair from the credentials file.
4242
| Flag | Description |
4343
|---|---|
4444
| `-adminEnabled` | Master on/off switch. Default `false`. |
45-
| `-adminSessionSigningKey` *or* `-adminSessionSigningKeyFile` *or* `ELASTICKV_ADMIN_SESSION_SIGNING_KEY` | Cluster-shared base64-encoded HS256 key (≥ 32 raw bytes / 44 base64 chars). **Must be the same on every node** — JWTs minted by node A are verified by node B during follower→leader forwarding, so a mismatch breaks the dashboard's read paths on follower nodes. The `*File` / env-var forms keep the secret out of `/proc/<pid>/cmdline`. |
45+
| `-adminSessionSigningKey` *or* `-adminSessionSigningKeyFile` *or* `ELASTICKV_ADMIN_SESSION_SIGNING_KEY` | Cluster-shared base64-encoded HS256 key **exactly 64 raw bytes** (88 base64 chars with standard padding, or 86 with `RawURLEncoding`). The validator rejects any other length at startup with a precise error message. **Must be the same on every node** — JWTs minted by node A are verified by node B during follower→leader forwarding, so a mismatch breaks the dashboard's read paths on follower nodes. The `*File` / env-var forms keep the secret out of `/proc/<pid>/cmdline`. |
4646
| `-s3CredentialsFile` | JSON file with at least one access key + secret key pair. Same file the S3 adapter uses for SigV4; the admin dashboard reuses it for login authentication. |
4747
| `-adminFullAccessKeys` *and/or* `-adminReadOnlyAccessKeys` | Comma-separated allow-lists. Only access keys listed here may log into the dashboard, even if their SigV4 secret validates against the credentials file. Keys must not appear in both lists. |
4848

@@ -176,17 +176,27 @@ should look at Raft leader-churn logs first.
176176

177177
Every state-changing admin request emits a structured slog line at
178178
`INFO` level on the leader's stdout (or wherever the process slog
179-
handler is wired):
179+
handler is wired). Two shapes:
180+
181+
**Leader-direct write** (`DynamoHandler` / `S3Handler` after a
182+
successful mutation):
183+
184+
```
185+
admin_audit actor=AKIA_ADMIN role=full operation=create_bucket bucket=my-bucket
186+
admin_audit actor=AKIA_ADMIN role=full operation=delete_table table=orders
187+
```
188+
189+
**Forwarded write** (logged by the leader's `ForwardServer` after a
190+
follower handed the request off):
180191

181192
```
182-
admin_audit actor=AKIA_ADMIN role=full method=POST path=/admin/api/v1/dynamo/tables status=201 duration=8.2ms
193+
admin_audit actor=AKIA_ADMIN role=full forwarded_from=n2 operation=put_bucket_acl bucket=my-bucket acl=public-read
183194
```
184195

185-
For forwarded requests, an extra `forwarded_from=<node-id>` field
186-
identifies the follower that received the original HTTP call. CR
187-
and LF in the field are stripped at the entry point — a hostile
188-
follower cannot split a single audit line into two by smuggling
189-
control characters into its node ID.
196+
`forwarded_from` is the originating follower's node ID. CR and LF
197+
in that field are stripped at the entry point — a hostile follower
198+
cannot split a single audit line into two by smuggling control
199+
characters into its node ID.
190200

191201
Login and logout emit their own audit lines (`action=login` /
192202
`action=logout`) so the JWT's lifetime can be correlated with the
@@ -227,7 +237,7 @@ node's live role index picks up the change.
227237

228238
The Raft cluster is mid-election. Re-issue the request after the
229239
`Retry-After: 1` header tells you to. If it persists past one or
230-
two seconds, check Raft leader status via the data-plane
240+
two seconds, check Raft leader status via the admin
231241
`/admin/api/v1/cluster` endpoint or `cmd/elastickv-admin`.
232242

233243
### `bucket_not_empty` on DELETE
@@ -246,6 +256,6 @@ to populate the embedded `dist` directory, then rebuild the binary.
246256

247257
## Cross-references
248258

249-
- Design rationale: [docs/design/2026_04_24_partial_admin_dashboard.md](design/2026_04_24_partial_admin_dashboard.md)
259+
- Design rationale: [docs/design/2026_04_24_proposed_admin_dashboard.md](design/2026_04_24_proposed_admin_dashboard.md) (renamed to `_partial_` in PR #675; this link will follow once that lands)
250260
- Architecture overview: [docs/architecture_overview.md](architecture_overview.md)
251261
- AdminForward RPC contract: `proto/admin_forward.proto`

0 commit comments

Comments
 (0)