38b51f3e6d
regression/ policies (3): cap-013-adapter-dedup, cap-023-metrics-collector, cap-024-deck-structure — declarative mirrors of core/regression_verify.py over capability-inventory JSON. The imperative regression_verify.py is kept (drives CI gate); the policies are the declarative mirror (IDEATE I1 quality improvement). tests: test_regression_policies.py + clean/drifted fixtures. Skip-without-kj. docs: adapters/README.md (new kyverno-json row + PolicyEngine Protocol section with how-to-add-OpaEngine), adapters/kyverno-json/README.md (engine, install, policy directory layout, 4 categories, severity convention), schemas/README.md (D-116 engine enum reuse note), modules/STANDARDS.md §10 Policy Authoring Standard, docs/METRICS.md (swappable engine narrative). ---ci--- project: acdl phase: 4 milestone: v1.25 status: execute phase_role: execution requirements: covered: [REQ-304, REQ-305, REQ-306, REQ-307] partial: [] ---/ci---
103 lines
3.9 KiB
Markdown
103 lines
3.9 KiB
Markdown
# kyverno-json Engine Adapter (v1.25)
|
|
|
|
The `kyverno-json` engine is Nova's **primary compliance/policy tool**
|
|
(v1.25), implemented behind the swappable `PolicyEngine` protocol so
|
|
OPA (or any other engine) can replace it one day.
|
|
|
|
## What kyverno-json is
|
|
|
|
[kyverno-json](https://github.com/kyverno/kyverno-json) is a standalone
|
|
Go binary from the Kyverno project — a **separate runtime** from the
|
|
K8s Kyverno admission controller. It applies Kyverno `ValidatingPolicy`
|
|
resources to **any** JSON or YAML payload file via the `kj scan` CLI.
|
|
Unlike the K8s Kyverno adapter (`adapters/kyverno/`), which only
|
|
speaks to K8s manifests, kyverno-json evaluates consumer contracts,
|
|
resolved Stack IR, terraform plan JSON, and even the merged PCR list
|
|
itself (meta-policies).
|
|
|
|
## Install
|
|
|
|
```bash
|
|
bash scripts/install-kyverno-json.sh
|
|
# or directly:
|
|
go install github.com/kyverno/kyverno-json/cmd/kj@latest
|
|
kj version
|
|
```
|
|
|
|
The platform functions without the binary — `is_configured()` returns
|
|
`False` when `which kj` is absent → `evaluate()` returns a single
|
|
`SKIPPED` PCR (`KJ_ENGINE_NOT_CONFIGURED`). The confidence signal
|
|
proceeds with a neutral `policy` input (D-120 graceful degradation).
|
|
|
|
## Policy directory layout
|
|
|
|
```
|
|
adapters/kyverno-json/policies/
|
|
├── _smoke.json # round-trip smoke test
|
|
├── contract/ # consumer contract JSON policies
|
|
│ ├── require-id-pattern.json
|
|
│ ├── require-env-in-enum.json
|
|
│ ├── require-infrastructure-min-1.json
|
|
│ └── forbid-unknown-fields.json
|
|
├── stack-ir/ # resolved Stack IR policies
|
|
│ ├── require-tagging-standard.json
|
|
│ ├── forbid-public-ingress.json
|
|
│ └── require-encryption-by-default.json
|
|
├── plan-json/ # terraform show -json policies
|
|
│ ├── forbid-plaintext-secrets.json
|
|
│ ├── forbid-iam-wildcard.json
|
|
│ └── require-kms-reference.json
|
|
├── meta/ # policies over the merged PCR list
|
|
│ ├── block-on-any-critical.json
|
|
│ └── tagging-rules-agree.json
|
|
└── regression/ # capability-inventory policies
|
|
├── cap-013-adapter-dedup.json
|
|
├── cap-023-metrics-collector.json
|
|
└── cap-024-deck-structure.json
|
|
```
|
|
|
|
## The four policy categories
|
|
|
|
1. **contract/** — over the consumer contract JSON (pre-resolve).
|
|
2. **stack-ir/** — over the resolved Target Stack IR (post-resolve).
|
|
3. **plan-json/** — over `terraform show -json` output (pipeline Step 5b).
|
|
4. **meta/** — over the merged `list[PolicyCheckResult]` (meta-policies).
|
|
5. **regression/** — over the capability-inventory JSON (declarative
|
|
mirrors of `core/regression_verify.py`).
|
|
|
|
## Severity convention
|
|
|
|
kyverno-json does not natively assign severities. Each Nova policy
|
|
declares its severity via a `metadata.annotations` field:
|
|
|
|
```yaml
|
|
metadata:
|
|
annotations:
|
|
nova.cloudinit.dev/severity: high
|
|
```
|
|
|
|
Valid values: `critical`, `high`, `medium`, `low`, `info` (default
|
|
when absent).
|
|
|
|
## Engine enum reuse (D-116)
|
|
|
|
kyverno-json PCR records carry `engine: "kyverno"` (no new enum value).
|
|
The `engine` field records the policy-engine *family*, not the specific
|
|
binary. The K8s Kyverno adapter and the kyverno-json engine are
|
|
distinguished by `ruleId` prefix (`KYVERNO_` vs `KJ_`) and `evidence`
|
|
payload shape (`namespace`/`kind` vs `assertion`/`jmespath`).
|
|
|
|
## Schema path
|
|
|
|
The output records validate against
|
|
[`schemas/policy_check_result.schema.json`](../../schemas/policy_check_result.schema.json)
|
|
(`engine: "kyverno"` is in the enum). The confidence signal consumes
|
|
the merged PCR list engine-agnostically.
|
|
|
|
## Swap boundary
|
|
|
|
The `PolicyEngine` protocol (`core/policy_engine.py`) is the swap
|
|
boundary. The OPA-equivalent surface is documented in
|
|
`.ciagent/RESEARCH.md` §4.2 — a future `OpaEngine` implements the same
|
|
protocol without touching the confidence signal, the PCR schema, or
|
|
the pipeline. |