RCLUSTER-WP-0021: propose k3s API audit policy and shipping to audit-core (NK-WP-0055-T11)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 4515@bnt-lap001 Assistant-Session: 0bf96127-6e04-41be-bfda-d11717c3f354
This commit is contained in:
parent
8fad4effee
commit
3ed1ac19c5
2 changed files with 146 additions and 0 deletions
|
|
@ -24,6 +24,7 @@
|
||||||
| workplan | RCLUSTER-WP-0018 | active | — | workplans/RCLUSTER-WP-0018-keycape-original-tls-recovery.md |
|
| workplan | RCLUSTER-WP-0018 | active | — | workplans/RCLUSTER-WP-0018-keycape-original-tls-recovery.md |
|
||||||
| workplan | RCLUSTER-WP-0019 | active | — | workplans/RCLUSTER-WP-0019-k3s-admin-kubeconfig-mode.md |
|
| workplan | RCLUSTER-WP-0019 | active | — | workplans/RCLUSTER-WP-0019-k3s-admin-kubeconfig-mode.md |
|
||||||
| workplan | RCLUSTER-WP-0020 | active | — | workplans/RCLUSTER-WP-0020-node-budget-knative-caps-and-wave2-allocation.md |
|
| workplan | RCLUSTER-WP-0020 | active | — | workplans/RCLUSTER-WP-0020-node-budget-knative-caps-and-wave2-allocation.md |
|
||||||
|
| workplan | RCLUSTER-WP-0021 | proposed | — | workplans/RCLUSTER-WP-0021-k3s-api-audit-to-audit-core.md |
|
||||||
| task | RCLUSTER-WP-ADHOC-2026-07-27-T01 | done | — | workplans/ADHOC-2026-07-27.md |
|
| task | RCLUSTER-WP-ADHOC-2026-07-27-T01 | done | — | workplans/ADHOC-2026-07-27.md |
|
||||||
| task | RAIL-BS-WP-0008-T01 | done | — | workplans/RAIL-BS-WP-0008-activity-core-wp0016-triage-output-deploy.md |
|
| task | RAIL-BS-WP-0008-T01 | done | — | workplans/RAIL-BS-WP-0008-activity-core-wp0016-triage-output-deploy.md |
|
||||||
| task | RAIL-BS-WP-0008-T02 | done | — | workplans/RAIL-BS-WP-0008-activity-core-wp0016-triage-output-deploy.md |
|
| task | RAIL-BS-WP-0008-T02 | done | — | workplans/RAIL-BS-WP-0008-activity-core-wp0016-triage-output-deploy.md |
|
||||||
|
|
@ -80,3 +81,8 @@
|
||||||
| task | RCLUSTER-WP-0020-T02 | done | — | workplans/RCLUSTER-WP-0020-node-budget-knative-caps-and-wave2-allocation.md |
|
| task | RCLUSTER-WP-0020-T02 | done | — | workplans/RCLUSTER-WP-0020-node-budget-knative-caps-and-wave2-allocation.md |
|
||||||
| task | RCLUSTER-WP-0020-T03 | wait | — | workplans/RCLUSTER-WP-0020-node-budget-knative-caps-and-wave2-allocation.md |
|
| task | RCLUSTER-WP-0020-T03 | wait | — | workplans/RCLUSTER-WP-0020-node-budget-knative-caps-and-wave2-allocation.md |
|
||||||
| task | RCLUSTER-WP-0020-T04 | todo | — | workplans/RCLUSTER-WP-0020-node-budget-knative-caps-and-wave2-allocation.md |
|
| task | RCLUSTER-WP-0020-T04 | todo | — | workplans/RCLUSTER-WP-0020-node-budget-knative-caps-and-wave2-allocation.md |
|
||||||
|
| task | RCLUSTER-WP-0021-T01 | todo | — | workplans/RCLUSTER-WP-0021-k3s-api-audit-to-audit-core.md |
|
||||||
|
| task | RCLUSTER-WP-0021-T02 | todo | — | workplans/RCLUSTER-WP-0021-k3s-api-audit-to-audit-core.md |
|
||||||
|
| task | RCLUSTER-WP-0021-T03 | wait | — | workplans/RCLUSTER-WP-0021-k3s-api-audit-to-audit-core.md |
|
||||||
|
| task | RCLUSTER-WP-0021-T04 | wait | — | workplans/RCLUSTER-WP-0021-k3s-api-audit-to-audit-core.md |
|
||||||
|
| task | RCLUSTER-WP-0021-T05 | wait | — | workplans/RCLUSTER-WP-0021-k3s-api-audit-to-audit-core.md |
|
||||||
|
|
|
||||||
140
workplans/RCLUSTER-WP-0021-k3s-api-audit-to-audit-core.md
Normal file
140
workplans/RCLUSTER-WP-0021-k3s-api-audit-to-audit-core.md
Normal file
|
|
@ -0,0 +1,140 @@
|
||||||
|
---
|
||||||
|
id: RCLUSTER-WP-0021
|
||||||
|
type: workplan
|
||||||
|
title: "k3s API-server audit policy, node log backend and durable shipping to audit-core"
|
||||||
|
domain: financials
|
||||||
|
repo: railiance-cluster
|
||||||
|
status: proposed
|
||||||
|
owner: claude
|
||||||
|
topic_slug: railiance
|
||||||
|
created: "2026-10-27"
|
||||||
|
updated: "2026-10-27"
|
||||||
|
flavor: implementation
|
||||||
|
depends_on: []
|
||||||
|
related: [NK-WP-0055, AUDIT-WP-0005, AUDIT-WP-0007, AUDIT-WP-0015, RCLUSTER-WP-0019]
|
||||||
|
---
|
||||||
|
|
||||||
|
Owner source work for NetKingdom NK-WP-0055-T11 (production-readiness ledger,
|
||||||
|
area 9 "Audit sink", row "Kubernetes API audit: absent"). The single-node k3s
|
||||||
|
server on railiance01 runs with no `audit-policy-file` and no audit log, so no
|
||||||
|
Kubernetes API record exists for secrets access, RBAC changes or exec/attach.
|
||||||
|
|
||||||
|
Boundary: this repo owns the k3s server flags, the audit policy, the node-local
|
||||||
|
log backend and rotation, and the shipper that runs on the node. audit-core owns
|
||||||
|
the receiving API, sender registration, schema, hash chain, retention in its
|
||||||
|
store and its restore drill. Nothing here is auto-applied; every host change runs
|
||||||
|
through an attended playbook. The k3s restart is a founder-run live step.
|
||||||
|
|
||||||
|
## Audit policy (source)
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: RCLUSTER-WP-0021-T01
|
||||||
|
status: todo
|
||||||
|
priority: high
|
||||||
|
assignee: claude
|
||||||
|
```
|
||||||
|
|
||||||
|
Add `ansible/files/k3s-audit-policy.yaml` (`audit.k8s.io/v1`, rules first-match):
|
||||||
|
|
||||||
|
1. `omitStages: [RequestReceived]` globally.
|
||||||
|
2. `secrets`, `serviceaccounts/token`, `tokenreviews`, `subjectaccessreviews`:
|
||||||
|
**Metadata only, in every namespace**. The policy must contain no
|
||||||
|
Request/RequestResponse rule that can match `secrets`; a test enforces this.
|
||||||
|
3. RBAC (`rbac.authorization.k8s.io`: roles, rolebindings, clusterroles,
|
||||||
|
clusterrolebindings) write verbs: RequestResponse (no secret payloads).
|
||||||
|
4. `pods/exec`, `pods/attach`, `pods/portforward`, `nodes/proxy`: Metadata
|
||||||
|
(the request body carries no stream content).
|
||||||
|
5. cert-manager (`cert-manager.io`, `acme.cert-manager.io`) writes: Request.
|
||||||
|
6. Namespaces `sso`, `mfa`, `openbao` (exact list confirmed against the cluster
|
||||||
|
in T05): all write verbs at Request, reads at Metadata; still never above
|
||||||
|
Metadata for secrets/configmaps (rule 2 precedes; configmaps held at Metadata
|
||||||
|
here because some carry credentials-adjacent config).
|
||||||
|
7. Drop noise: `system:kube-proxy` watches, `/healthz*`, `/readyz*`, `/livez*`,
|
||||||
|
`/metrics`, events, leases and node status heartbeats: None.
|
||||||
|
8. Catch-all: Metadata for write verbs, None for read verbs elsewhere.
|
||||||
|
|
||||||
|
Done when: policy file, a `make audit-policy-check` target (kubeconform-style
|
||||||
|
schema check plus a script asserting rule 2 and the absence of any secrets match
|
||||||
|
above Metadata), and an offline unit test on synthetic request fixtures.
|
||||||
|
|
||||||
|
## Node log backend and rotation (source)
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: RCLUSTER-WP-0021-T02
|
||||||
|
status: todo
|
||||||
|
priority: high
|
||||||
|
assignee: claude
|
||||||
|
```
|
||||||
|
|
||||||
|
Extend the existing-host pattern of `ansible/k3s-kubeconfig-mode.yml` into
|
||||||
|
`ansible/k3s-api-audit.yml` (and `bootstrap.yml` for fresh installs), writing
|
||||||
|
k3s `config.yaml` `kube-apiserver-arg` entries:
|
||||||
|
|
||||||
|
- `audit-policy-file=/etc/rancher/k3s/audit-policy.yaml` (root:root 0600)
|
||||||
|
- `audit-log-path=/var/lib/rancher/k3s/server/logs/audit.log` (dir 0700)
|
||||||
|
- `audit-log-maxage=7`, `audit-log-maxbackup=10`, `audit-log-maxsize=100`
|
||||||
|
- `audit-log-format=json`, `audit-log-mode=batch` (buffer sized so a slow disk
|
||||||
|
cannot stall the API server)
|
||||||
|
|
||||||
|
Same guards as RCLUSTER-WP-0019: pinned preimage hashes, refuse on drift or
|
||||||
|
foreign config.yaml keys, root-only backup, `--check`/`--diff` with content
|
||||||
|
suppressed, a rollback action that removes the args. Validate offline only
|
||||||
|
(syntax-check, ansible-lint production profile). Disk headroom check: refuse
|
||||||
|
if `/var/lib/rancher` has less than 5 GiB free.
|
||||||
|
|
||||||
|
## Shipping to audit-core (source; depends on audit-core contract)
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: RCLUSTER-WP-0021-T03
|
||||||
|
status: wait
|
||||||
|
priority: high
|
||||||
|
assignee: claude
|
||||||
|
```
|
||||||
|
|
||||||
|
A node-local shipper (Fluent Bit DaemonSet with hostPath read-only on the log
|
||||||
|
dir, or a systemd unit on the host; choose after audit-core states its intake)
|
||||||
|
tails `audit.log`, keeps a persisted file offset, maps each event to the
|
||||||
|
audit-core envelope (`auditID` as idempotency key, `stageTimestamp`, user,
|
||||||
|
verb, objectRef, responseStatus, source `kubernetes-api/railiance01`) and posts
|
||||||
|
with retry and back-pressure. Sender credential comes from OpenBao via the
|
||||||
|
`warden route` owner path; never a static token in Git. Fail mode: the node log
|
||||||
|
is the buffer; shipper lag is exported as a metric and alerted.
|
||||||
|
|
||||||
|
Waits on audit-core: sender registration for `railiance-cluster` /
|
||||||
|
`kubernetes-api`, the intake endpoint and auth method, envelope/schema version,
|
||||||
|
expected volume ceiling (estimate in T05), and the correlation-id field from
|
||||||
|
NK-WP-0055-T11.
|
||||||
|
|
||||||
|
## Retention and restore check (source)
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: RCLUSTER-WP-0021-T04
|
||||||
|
status: wait
|
||||||
|
priority: medium
|
||||||
|
assignee: claude
|
||||||
|
```
|
||||||
|
|
||||||
|
Node retention is a buffer only (7 days / 10 x 100 MB). Durable retention
|
||||||
|
(proposed: 400 days for Kubernetes API records) lives in audit-core and its
|
||||||
|
backups. Add `make audit-k8s-restore-check`: read-only, emits a synthetic
|
||||||
|
marker request (a labelled `SelfSubjectAccessReview` by a named operator
|
||||||
|
identity), then confirms its `auditID` is present in audit-core and, during
|
||||||
|
audit-core's recurring restore drill, in the restored copy with an intact hash
|
||||||
|
chain. Receipt goes to `docs/evidence/`. Waits on T03 and audit-core's drill.
|
||||||
|
|
||||||
|
## Founder-run live rollout (attended k3s restart)
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: RCLUSTER-WP-0021-T05
|
||||||
|
status: wait
|
||||||
|
priority: high
|
||||||
|
assignee: founder
|
||||||
|
```
|
||||||
|
|
||||||
|
Founder runs, attended, after T01/T02 are reviewed:
|
||||||
|
`ansible-playbook ansible/k3s-api-audit.yml --check --diff`, then the apply,
|
||||||
|
which restarts k3s (single node: brief API outage, workloads keep running).
|
||||||
|
Verify `/readyz`, node Ready, `audit.log` growing, a test `kubectl get secret`
|
||||||
|
logged at Metadata with no `requestObject`/`responseObject`, then a 24 h
|
||||||
|
volume sample to size T03/T04. Rollback is the playbook's rollback action.
|
||||||
|
Agents prepare and hand over the exact commands; they do not run them.
|
||||||
Loading…
Add table
Add a link
Reference in a new issue