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---
96 lines
5.0 KiB
Markdown
96 lines
5.0 KiB
Markdown
# Nova Adapters
|
|
|
|
## Overview
|
|
|
|
Adapters translate the engine-agnostic Target Stack IR to engine-specific formats. The Terraform adapter is the primary adapter (IR → HCL). Policy adapters translate security tool output into normalized `PolicyCheckResult` records that the confidence signal consumes in an engine-agnostic way.
|
|
|
|
## Existing Adapters
|
|
|
|
| Adapter | Path | Input | Output | Purpose |
|
|
| --- | --- | --- | --- | --- |
|
|
| Terraform adapter | `adapters/terraform/adapter.py` | Stack instance JSON | Terraform HCL (`main.tf`, `terraform.tf`, `providers.tf`) | Compiles IR to Terraform |
|
|
| Checkov adapter | `adapters/terraform/policy/checkov_adapter.py` | Checkov JSON | `PolicyCheckResult` records | Translates Checkov results |
|
|
| Wiz adapter | `adapters/wiz/wiz_adapter.py` | Wiz API issues JSON | `PolicyCheckResult` records | Translates Wiz security findings |
|
|
| Kyverno adapter | `adapters/kyverno/kyverno_adapter.py` | Kyverno PolicyReport JSON | `PolicyCheckResult` records | K8s-native policy translation |
|
|
| kyverno-json engine | `adapters/kyverno-json/kyverno_json_engine.py` | Any JSON/YAML payload | `PolicyCheckResult` records | **v1.25 primary policy engine** (swappable via `PolicyEngine` protocol) |
|
|
|
|
## Policy Engine Protocol (v1.25)
|
|
|
|
The `core/policy_engine.py` module defines the **swap boundary** between
|
|
Nova and its policy engines. A `PolicyEngine` Python Protocol (PEP 544)
|
|
with three members (`name`, `is_configured()`, `evaluate()`) is the
|
|
contract; a `PolicyEngineRegistry` selects the active engine from
|
|
`config.json`'s `policy.engine` key. The confidence signal and pipeline
|
|
never import an engine directly — they go through the registry.
|
|
|
|
**Implementations:**
|
|
- `KyvernoJsonEngine` (`adapters/kyverno-json/`) — shells to the `kj`
|
|
CLI; the v1.25 default.
|
|
- `NullEngine` (`core/policy_engine.py`) — fallback when the `policy`
|
|
key is absent (emits `SKIPPED`).
|
|
- Future: `OpaEngine` — implements the same protocol, shells to
|
|
`opa eval`. The OPA-equivalent surface is documented in
|
|
`.ciagent/RESEARCH.md` §4.2.
|
|
|
|
**How to add a new engine:**
|
|
1. Create `adapters/<name>/<name>_engine.py` implementing the
|
|
`PolicyEngine` protocol (`name`, `is_configured()`, `evaluate()`).
|
|
2. `evaluate()` returns `list[dict]` where each dict conforms to
|
|
`schemas/policy_check_result.schema.json`.
|
|
3. Register the engine in `core/policy_engine.py`'s `_autoload_*`
|
|
function (or call `register(name, factory)` at startup).
|
|
4. Set `config.json.policy.engine` to the engine's `name`.
|
|
5. Add the engine to the `engine` enum in
|
|
`schemas/policy_check_result.schema.json` if it needs a distinct
|
|
enum value (v1.25 reuses `"kyverno"` — see D-116).
|
|
|
|
## How to Write an Adapter
|
|
|
|
### Terraform Adapter Extension
|
|
|
|
1. Add a stack type → Terraform type mapping to `TYPE_MAP`.
|
|
2. Add non-identity input mappings to `INPUT_MAP`.
|
|
3. Add non-identity output mappings to `OUTPUT_MAP`.
|
|
4. Add a specialized `_emit_resource` branch if the resource needs nested blocks (e.g. inline policies, rule sets).
|
|
|
|
### Policy Adapter Pattern
|
|
|
|
1. Define `SEVERITY_MAP` and `RESULT_MAP` dicts that translate the engine's native severity/result vocabulary to the `PolicyCheckResult` enums.
|
|
2. Implement `_to_pcr(raw_record, contract_id)` → `PolicyCheckResult` dict.
|
|
3. Implement `adapt(input_path, contract_id)` → list of `PolicyCheckResult` dicts.
|
|
4. Implement `is_configured()` → bool (env var check) so the platform can skip the adapter when credentials are absent.
|
|
|
|
## How to Wire an Adapter
|
|
|
|
- **Terraform adapter** — invoked by `scripts/run_platform.sh` Step 3 (`terraform-plan`).
|
|
- **Checkov adapter** — invoked by `scripts/run_platform.sh` Step 5 (`checkov`).
|
|
- **Wiz / Kyverno adapters** — optional Steps 5b/5c, run only when the relevant env vars are set.
|
|
- All policy adapters output records that are validated against `schemas/policy_check_result.schema.json`.
|
|
|
|
## Dependencies
|
|
|
|
- `jsonschema`, `pyyaml` — used by all adapters for loading and validating inputs.
|
|
- `boto3` — used by the Wiz adapter for AWS API access.
|
|
- `checkov` — used by the Checkov adapter to run policy scans.
|
|
- No external deps for the Terraform adapter (pure Python).
|
|
|
|
## How to Test Adapters
|
|
|
|
- `tests/test_adapter.py` — Terraform adapter (`TYPE_MAP`, resource emission, refs, outputs).
|
|
- `tests/test_checkov_adapter.py` — Checkov adapter.
|
|
- `tests/test_wiz_adapter.py` — Wiz adapter.
|
|
- `tests/test_kyverno_adapter.py` — Kyverno adapter.
|
|
- All adapter tests load fixtures from `tests/fixtures/` and use `moto` for AWS mocking.
|
|
|
|
## Where to Write Tests
|
|
|
|
- `tests/test_<adapter_name>.py` paired with `tests/fixtures/<adapter>_fixture.json`.
|
|
|
|
## Adding a New Adapter
|
|
|
|
1. Create `adapters/<name>/<name>_adapter.py`.
|
|
2. Implement `adapt()` and (for policy adapters) `is_configured()`.
|
|
3. Add the adapter's engine name to the `engine` enum in `schemas/policy_check_result.schema.json` if it is a policy adapter.
|
|
4. Write a test (`tests/test_<name>_adapter.py`) plus a fixture (`tests/fixtures/<name>_fixture.json`).
|
|
5. Add it to `scripts/run_platform.sh` if it is invoked at runtime.
|
|
6. Update this README. |