feat(P4): pipeline hardening — Checkov before plan, Wiz-or-Checkov on plan (REQ-250)
Nova Slides Render / render (push) Failing after 1m1s
Nova Slides Render / render (push) Failing after 1m1s
Two-stage policy scan per item 20: 1. Checkov on static code BEFORE terraform plan (fail-fast, quick dev feedback). Added to run_platform.sh Step 3c + run_codegen.sh Step 3c (runs on the authored TF dir before plan, using --framework terraform). 2. Runtime policy scan on the plan AFTER terraform plan: Wiz when configured (WIZ_API_TOKEN + WIZ_API_URL), else Checkov against the plan as a drop-in replacement (--framework terraform_plan). Wiz and Checkov are NEVER both run on the plan. Replaces the old single Checkov-on-main.tf step in run_platform.sh Step 5 + run_postapply.sh Step 5. pipelines/contract.yml: stage list updated — 'checkov' stage replaced by 'checkov-static' (before terraform-plan) + 'runtime-policy-scan' (after terraform-plan). 9 stages → 10 stages. Header comment updated. adapters/wiz/wiz_adapter.py: add --plan mode CLI (fetch_and_adapt_plan) for scanning a terraform plan; backward-compat with the positional <wiz_issues.json> <contract-id> mode. is_configured() gates the Wiz path. Tests: test_pipeline_contract.py (9 → 10 stages, new stage names); test_contract_resolver.py (rename test, assert checkov-static + runtime-policy-scan present, old 'checkov' gone). Full suite: 685 pass + 1 pre-existing attestation failure (NOVA_ATTESTATION_SIGNING_KEY_ID unset, unrelated to v1.21, fails on main without these changes too). ---ci--- project: acdl phase: 4 milestone: v1.21 status: execute phase_role: execution ---/ci---
This commit is contained in:
+33
-14
@@ -2,8 +2,9 @@
|
||||
# scripts/run_postapply.sh — post-Terraform steps for the Nova platform pipeline.
|
||||
#
|
||||
# Performs steps 5–9 of run_platform.sh (after terraform apply/destroy):
|
||||
# 5. Checkov policy scan on the emitted main.tf
|
||||
# 6. Checkov adapter → PolicyCheckResult (compliance details)
|
||||
# 3c. Checkov policy scan on static code (fail-fast, in run_codegen.sh)
|
||||
# 5. Runtime policy scan on the terraform plan (Wiz-or-Checkov, never both)
|
||||
# 6. Policy scan adapter → PolicyCheckResult (compliance details)
|
||||
# 7. Confidence signal compute
|
||||
# 7b. HITL attestation gate (qa/prod/dr only)
|
||||
# 8. Write evidence event to DynamoDB outbox
|
||||
@@ -92,19 +93,37 @@ else:
|
||||
" || { echo "FAIL: HITL gate blocked" >&2; return 1; }
|
||||
}
|
||||
|
||||
echo "=== Step 5: run Checkov on $TF_DIR/main.tf ==="
|
||||
if [ "$QUIET" = "0" ]; then
|
||||
checkov -f "$TF_DIR/main.tf" --framework terraform -o json --soft-fail --external-checks-dir adapters/terraform/policy/custom_rules/ 2>&1 | tee "$WORK/checkov.json"
|
||||
echo "=== Step 5: runtime policy scan on the terraform plan (Wiz-or-Checkov, never both) ==="
|
||||
# REQ-250 (v1.21): after terraform plan, run Wiz against the plan when
|
||||
# configured; otherwise run Checkov against the plan as a drop-in
|
||||
# replacement. Wiz and Checkov are NEVER both run on the plan. The
|
||||
# static-code Checkov already ran in run_codegen.sh Step 3c (fail-fast).
|
||||
RUNTIME_SCAN_ENGINE=""
|
||||
if [ -n "${WIZ_API_TOKEN:-}" ] || [ -n "${WIZ_API_URL:-}" ]; then
|
||||
RUNTIME_SCAN_ENGINE="wiz"
|
||||
echo "--- Wiz configured (WIZ_API_TOKEN + WIZ_API_URL) → Wiz on the plan ---"
|
||||
python3 adapters/wiz/wiz_adapter.py --plan "$TF_DIR/tfplan" --contract-id "$CONTRACT_ID" --run-id "${CONTRACT_ID}" > "$WORK/pcr.json" 2> "$WORK/wiz.err" || {
|
||||
echo "WARNING: Wiz scan failed; falling back to Checkov on the plan" >&2
|
||||
RUNTIME_SCAN_ENGINE="checkov-plan"
|
||||
}
|
||||
else
|
||||
checkov -f "$TF_DIR/main.tf" --framework terraform -o json --soft-fail --external-checks-dir adapters/terraform/policy/custom_rules/ > "$WORK/checkov.json" 2> "$WORK/checkov.err"
|
||||
RUNTIME_SCAN_ENGINE="checkov-plan"
|
||||
fi
|
||||
[ -s "$WORK/checkov.json" ] || { echo "FAIL: checkov produced no output" >&2; exit 1; }
|
||||
echo ""
|
||||
echo "checkov summary: $(python3 -c "import json; d=json.load(open('$WORK/checkov.json')); print(len(d.get('results',{}).get('failed_checks',[])), 'failed,', len(d.get('results',{}).get('passed_checks',[])), 'passed')")"
|
||||
|
||||
echo ""
|
||||
echo "=== Step 6: Checkov adapter → PolicyCheckResult (compliance details) ==="
|
||||
python3 adapters/terraform/policy/checkov_adapter.py "$WORK/checkov.json" "$CONTRACT_ID" > "$WORK/pcr.json" || { echo "FAIL: checkov adapter failed" >&2; exit 1; }
|
||||
if [ "$RUNTIME_SCAN_ENGINE" = "checkov-plan" ]; then
|
||||
echo "--- Wiz not configured → Checkov on the plan (drop-in replacement) ---"
|
||||
if [ "$QUIET" = "0" ]; then
|
||||
checkov -f "$TF_DIR/tfplan" --framework terraform_plan -o json --soft-fail --external-checks-dir adapters/terraform/policy/custom_rules/ 2>&1 | tee "$WORK/checkov-plan.json"
|
||||
else
|
||||
checkov -f "$TF_DIR/tfplan" --framework terraform_plan -o json --soft-fail --external-checks-dir adapters/terraform/policy/custom_rules/ > "$WORK/checkov-plan.json" 2> "$WORK/checkov-plan.err"
|
||||
fi
|
||||
[ -s "$WORK/checkov-plan.json" ] || { echo "FAIL: checkov (plan) produced no output" >&2; exit 1; }
|
||||
echo ""
|
||||
echo "checkov (plan) summary: $(python3 -c "import json; d=json.load(open('$WORK/checkov-plan.json')); print(len(d.get('results',{}).get('failed_checks',[])), 'failed,', len(d.get('results',{}).get('passed_checks',[])), 'passed')")"
|
||||
echo ""
|
||||
echo "=== Step 6: Checkov (plan) adapter → PolicyCheckResult (compliance details) ==="
|
||||
python3 adapters/terraform/policy/checkov_adapter.py "$WORK/checkov-plan.json" "$CONTRACT_ID" > "$WORK/pcr.json" || { echo "FAIL: checkov (plan) adapter failed" >&2; exit 1; }
|
||||
fi
|
||||
echo "runtime scan engine: $RUNTIME_SCAN_ENGINE"
|
||||
python3 -c "
|
||||
import json
|
||||
pcrs = json.load(open('$WORK/pcr.json'))
|
||||
@@ -199,4 +218,4 @@ source "$ROOT/scripts/run_uptime.sh"
|
||||
|
||||
echo ""
|
||||
echo "=== POST-APPLY OK ==="
|
||||
echo "Checkov → confidence ($BAND) → outbox → outputs → uptime"
|
||||
echo "Checkov(static, pre-plan) → Wiz-or-Checkov(plan) → confidence ($BAND) → outbox → outputs → uptime"
|
||||
|
||||
Reference in New Issue
Block a user