T02. deploy/attest-cronjob.yaml: daily at 03:17 UTC against the 168h window, its own ServiceAccount, and a Role reaching exactly one named ConfigMap — get/update/patch, no create, no list. audit_core/attest_publish.py does the publish in stdlib; the image carries no kubectl, and adding one to an audit receiver's image to write a single file is the worse trade. Three refusals, all deliberate: The producer is not the receiver. A receiver that could rewrite its own attestation could forge it. audit-core-egress is now scoped to component: receiver and a separate audit-core-attest-egress carries the 6443 rule, so the receiver never gains API-server reach. Asserted by test. It refuses to publish over a broken chain. A fresh head written over a break replaces an honest chain_break with a fresh-looking attestation. Stale degrades the claim visibly; false does not. Mounted as a directory, not subPath. Found while writing the manifest: a subPath ConfigMap mount is resolved once at pod start and never updates, so the daily attestation would land in the ConfigMap and never reach the running receiver — tamper_evidence would age out to false while the job reported success every night, silent in both directions. The offsite copy stays an operator step. audit-core holds no Nextcloud credential and should not acquire one to publish a hash, so docs/integrity.md states the bound plainly: until that copy exists the delivered control defends against a database owner, not a cluster owner, and no stronger claim may be made from it. T10. layer.yaml lists four infrastructure contacts — platform-pg, state-hub, kube-apiserver, the container registry — each with its role and whether another layer reads it. tooling_contacts stays [], which is true under §5 as written; the companion's totality request is met by the uncatalogued list rather than by inventing a Tooling row. tests/test_layer_conformance.py derives the egress destinations from the manifests and the registry from the pinned digests, so a new contact appearing in deploy/ without a row fails the test rather than waiting for a reviewer to notice. Applying the manifests remains an operator action; nothing here was applied. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nb7Q6ZmXppNDkTWytfYqfv Assistant: claude-code Assistant-Model: opus Assistant-Process: 2069992@bnt-lap001 Assistant-Session: 167dd7f8-2a25-4be1-aa46-3b6f1a5f94c6 |
||
|---|---|---|
| .. | ||
| attest-cronjob.yaml | ||
| audit-core.yaml | ||
| clustersecretstore.yaml | ||
| externalsecret-senders.yaml | ||
| externalsecrets.yaml | ||
| migrate-job.yaml | ||
| networkpolicies.yaml | ||
| README.md | ||
| senders-scope.json | ||
| senders-scope.yaml | ||
railiance01 package
Target: railiance01 only. The workstation kubeconfig that talks to that API
is the k3s-api-railiance01 tunnel (local port 16444).
~/.kube/config-hosteurope currently points at 16443 (coulombcore); rewrite
the server port or export a copy before applying.
Apply order is documented in docs/operator-runbook.md. Do not apply the
Deployment until:
- The image digest is pinned (currently
sha256:c2fe39a0…from commitabd22fa). - Secrets
audit-core-database,audit-core-database-migrate, andaudit-core-sendersexist. ConfigMapaudit-core-senders-scopeis applied (deploy/senders-scope.yaml) before the Deployment mounts it. - Job
audit-core-migratehas completed.
make image-build
make deploy-dry-run