T-0.5 Kyverno L0 policies + CLI tests + admission scaffolding (R-TEST-01, R-NET-01, R-SEC-01/02, R-IDP-02, R-GITOPS-02)

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
This commit is contained in:
jakman85andClaude Opus 4.8 committed 2026-08-16 00:08:32 -05:00
1 parent bb08d0e048
commit bb2e9fc931
28 files changed
+1243 -2

No files matched your search

@@ -0,0 +1,58 @@
# ServiceDefinition L0 validation (R-GITOPS-02)
Validates the shape of each `catalog/` **ServiceDefinition** against the canonical
schema and invariants in the read-only spec `docs/13-service-catalog.md` (with
`auth` from `docs/15`, `egress` from `docs/03`). Runs in CI **without a cluster**.
## Why kyverno-json (not the resource CLI)
A ServiceDefinition is **arbitrary YAML** — its own `kind:` field means
`container | vm`, not a Kubernetes Kind — so it cannot be validated by
`kyverno apply`/`kyverno test` (which expect Kubernetes resources). Per
[ADR-0011] the Kyverno-ecosystem tool for arbitrary YAML/JSON is **kyverno-json**.
## Invariants enforced (`validate-servicedefinition.yaml`)
- `name` is a DNS-1123 label (→ `<name>.home.keithjackson.dev`).
- `kind` ∈ {`container`, `vm`}; container ⇒ `source.image`, vm ⇒ `source.vmTemplate`.
- `exposure` ∈ {`internal`, `public`}.
- `egress` ∈ {`internet`, `vpn`}.
- `auth.mode` ∈ {`oidc`, `forward-auth`, `native`, `none`}.
- **`public` exposure ⇒ `auth.mode` ≠ `none`** (no unauthenticated public UI, docs/15).
- each `dependencies[]` has `to`, `port` ∈ 1–65535, `protocol` ∈ {`tcp`, `udp`}.
- each `storage[].class` ∈ {`longhorn`, `bulk`}.
## Fixtures
`payloads/valid-*.yaml` must PASS; `payloads/invalid-*.yaml` must FAIL — one failure
reason each (bad egress, public+none auth, missing image, bad dependency).
## Run (CI entrypoint)
```bash
# Valid payloads: scan must exit 0
kyverno-json scan \
--policy validate-servicedefinition.yaml \
--payload payloads/valid-plex.yaml \
--payload payloads/valid-sonarr.yaml
# Invalid payloads: each scan must exit NON-zero (loop asserts failure)
for f in payloads/invalid-*.yaml; do
if kyverno-json scan --policy validate-servicedefinition.yaml --payload "$f"; then
echo "FAIL: expected $f to be rejected"; exit 1
fi
done
```
The `scripts/run-l0.sh` wrapper (see `../README.md`) runs both halves and is what CI
invokes.
## Caveat (escalated in the T-0.5 report)
kyverno-json is **pre-1.0**; its assertion syntax evolves. The **invariants above are
the normative content**. The CI agent must pin an exact kyverno-json version and
confirm the `check:` expressions parse under it; adjust syntax (never the invariants)
if the pinned release differs. The overlapping JSON Schema from WS-GITOPS (T-0.3) is
the complementary structural contract.
[ADR-0011]: ../../../../home-network-k3s/decisions/adr-0011-test-tooling-kyverno-chainsaw.md