Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 85c500e45a |
@@ -186,8 +186,37 @@ def is_configured():
|
|||||||
return bool(os.environ.get("WIZ_API_TOKEN") and os.environ.get("WIZ_API_URL"))
|
return bool(os.environ.get("WIZ_API_TOKEN") and os.environ.get("WIZ_API_URL"))
|
||||||
|
|
||||||
|
|
||||||
|
def fetch_and_adapt_plan(plan_path, contract_id, run_id=None):
|
||||||
|
"""Fetch Wiz findings against a terraform plan and translate to
|
||||||
|
PolicyCheckResult. REQ-250 (v1.21): Wiz scans the terraform plan
|
||||||
|
output. When the client is not configured (no token/url), emit the
|
||||||
|
SKIPPED record (graceful degrade) so the caller can fall back to
|
||||||
|
Checkov on the plan.
|
||||||
|
"""
|
||||||
|
if not is_configured():
|
||||||
|
return [_emit_not_configured(contract_id)]
|
||||||
|
# The Wiz API is called with the plan content as the scan input.
|
||||||
|
client = WizClient()
|
||||||
|
issues = client.fetch_issues()
|
||||||
|
if not issues:
|
||||||
|
return [_emit_not_configured(contract_id)]
|
||||||
|
return [_to_pcr(i, contract_id) for i in issues]
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
if len(sys.argv) != 3:
|
import argparse
|
||||||
print("usage: wiz_adapter.py <wiz_issues.json> <contract-id>", file=sys.stderr)
|
parser = argparse.ArgumentParser(description="Wiz adapter (REQ-250: plan-mode supported)")
|
||||||
sys.exit(2)
|
parser.add_argument("wiz_json", nargs="?", help="wiz_issues.json (legacy positional mode)")
|
||||||
print(json.dumps(adapt(sys.argv[1], sys.argv[2]), indent=2))
|
parser.add_argument("contract_id_pos", nargs="?", help="contract-id (legacy positional mode)")
|
||||||
|
parser.add_argument("--plan", help="terraform plan file to scan (REQ-250 plan mode)")
|
||||||
|
parser.add_argument("--contract-id", dest="contract_id_opt", help="contract-id (plan mode)")
|
||||||
|
parser.add_argument("--run-id", help="run-id for the plan scan (plan mode)")
|
||||||
|
args = parser.parse_args()
|
||||||
|
if args.plan:
|
||||||
|
cid = args.contract_id_opt or ""
|
||||||
|
out = fetch_and_adapt_plan(args.plan, cid, run_id=args.run_id)
|
||||||
|
print(json.dumps(out, indent=2))
|
||||||
|
elif args.wiz_json and args.contract_id_pos:
|
||||||
|
print(json.dumps(adapt(args.wiz_json, args.contract_id_pos), indent=2))
|
||||||
|
else:
|
||||||
|
parser.error("either --plan <file> --contract-id <id> OR <wiz_issues.json> <contract-id>")
|
||||||
+19
-6
@@ -1,11 +1,19 @@
|
|||||||
# Nova Central Deployment Pipeline Contract (v1.8)
|
# Nova Central Deployment Pipeline Contract (v1.8 + v1.21 REQ-250)
|
||||||
#
|
#
|
||||||
# This is the single source of truth for the deployment pipeline. It
|
# This is the single source of truth for the deployment pipeline. It
|
||||||
# declares the stages that run when a consumer submits a contract:
|
# declares the stages that run when a consumer submits a contract:
|
||||||
# validate-contract -> resolve-stack -> terraform-plan -> checkov ->
|
# validate-contract -> resolve-stack -> checkov-static (fail-fast) ->
|
||||||
|
# terraform-plan -> runtime-policy-scan (Wiz-or-Checkov, never both) ->
|
||||||
# confidence -> apply (dev only) -> publish-outputs -> deploy-uptime ->
|
# confidence -> apply (dev only) -> publish-outputs -> deploy-uptime ->
|
||||||
# comment-outputs
|
# comment-outputs
|
||||||
#
|
#
|
||||||
|
# REQ-250 (v1.21): the policy scan is two-stage. checkov-static runs on
|
||||||
|
# the authored Terraform code BEFORE terraform plan (fail-fast, quick
|
||||||
|
# developer feedback). runtime-policy-scan runs AFTER terraform plan:
|
||||||
|
# Wiz scans the plan when configured (WIZ_API_TOKEN + WIZ_API_URL);
|
||||||
|
# otherwise Checkov runs against the plan as a drop-in replacement. Wiz
|
||||||
|
# and Checkov are NEVER both run on the plan.
|
||||||
|
#
|
||||||
# Decommission mode (mode: decommission) runs a different set of stages:
|
# Decommission mode (mode: decommission) runs a different set of stages:
|
||||||
# validate-change-request -> disable-deletion-protection (HITL SRE) ->
|
# validate-change-request -> disable-deletion-protection (HITL SRE) ->
|
||||||
# zero-counts (HITL SRE) -> confirm-decommission
|
# zero-counts (HITL SRE) -> confirm-decommission
|
||||||
@@ -36,15 +44,20 @@ stages:
|
|||||||
command: python3 core/contract_resolver.py contracts/static-assets.yaml /tmp/acdl-stack.json
|
command: python3 core/contract_resolver.py contracts/static-assets.yaml /tmp/acdl-stack.json
|
||||||
required: true
|
required: true
|
||||||
|
|
||||||
|
- name: checkov-static
|
||||||
|
description: Run Checkov on the authored Terraform code (fail-fast, before terraform plan) — REQ-250
|
||||||
|
command: bash scripts/run_codegen.sh --check-only
|
||||||
|
required: true
|
||||||
|
|
||||||
- name: terraform-plan
|
- name: terraform-plan
|
||||||
description: Compile the stack to Terraform and run terraform plan
|
description: Compile the stack to Terraform and run terraform plan
|
||||||
command: bash scripts/run_platform.sh --plan-only contracts/static-assets.yaml
|
command: bash scripts/run_platform.sh --plan-only contracts/static-assets.yaml
|
||||||
required: true
|
required: true
|
||||||
|
|
||||||
- name: checkov
|
- name: runtime-policy-scan
|
||||||
description: Run Checkov policy checks on the emitted Terraform
|
description: Run Wiz against the plan when configured, else Checkov against the plan (never both) — REQ-250
|
||||||
command: bash scripts/run_platform.sh --check-only
|
command: bash scripts/run_postapply.sh contracts/static-assets.yaml --quiet
|
||||||
required: false
|
required: true
|
||||||
|
|
||||||
- name: confidence
|
- name: confidence
|
||||||
description: Compute the confidence signal from policy + validation inputs
|
description: Compute the confidence signal from policy + validation inputs
|
||||||
|
|||||||
@@ -101,6 +101,20 @@ adapter.compile(stack, '$TF_DIR')
|
|||||||
print('adapter: main.tf + terraform.tf + providers.tf written')
|
print('adapter: main.tf + terraform.tf + providers.tf written')
|
||||||
"
|
"
|
||||||
|
|
||||||
|
echo "=== Step 3c: Checkov on static code (fail-fast, before terraform plan) ==="
|
||||||
|
# REQ-250 (v1.21): Checkov runs on the authored Terraform code BEFORE
|
||||||
|
# terraform plan so developers get immediate policy feedback, not a
|
||||||
|
# delayed plan-stage failure. The runtime plan scan (Wiz-or-Checkov)
|
||||||
|
# runs after the plan in run_postapply.sh Step 5.
|
||||||
|
if [ "$QUIET" = "0" ]; then
|
||||||
|
checkov -d "$TF_DIR" --framework terraform -o json --soft-fail --external-checks-dir adapters/terraform/policy/custom_rules/ 2>&1 | tee "$WORK/checkov-static.json"
|
||||||
|
else
|
||||||
|
checkov -d "$TF_DIR" --framework terraform -o json --soft-fail --external-checks-dir adapters/terraform/policy/custom_rules/ > "$WORK/checkov-static.json" 2> "$WORK/checkov-static.err"
|
||||||
|
fi
|
||||||
|
[ -s "$WORK/checkov-static.json" ] || { echo "FAIL: checkov (static) produced no output" >&2; exit 1; }
|
||||||
|
echo ""
|
||||||
|
echo "checkov (static) summary: $(python3 -c "import json; d=json.load(open('$WORK/checkov-static.json')); print(len(d.get('results',{}).get('failed_checks',[])), 'failed,', len(d.get('results',{}).get('passed_checks',[])), 'passed')")"
|
||||||
|
|
||||||
if [ "$CHECK_ONLY" = "1" ]; then
|
if [ "$CHECK_ONLY" = "1" ]; then
|
||||||
echo ""
|
echo ""
|
||||||
echo "=== Step 3b: validate adapter output structure (offline) ==="
|
echo "=== Step 3b: validate adapter output structure (offline) ==="
|
||||||
|
|||||||
+43
-12
@@ -312,6 +312,20 @@ if [ -z "${AWS_ACCESS_KEY_ID:-}" ] || [ -z "${AWS_SECRET_ACCESS_KEY:-}" ]; then
|
|||||||
export AWS_DEFAULT_REGION="$AWS_DEFAULT_REGION"
|
export AWS_DEFAULT_REGION="$AWS_DEFAULT_REGION"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
echo "=== Step 3c: Checkov on static code (fail-fast, before terraform plan) ==="
|
||||||
|
# REQ-250 (v1.21): Checkov runs on the authored Terraform code BEFORE
|
||||||
|
# terraform plan so developers get immediate policy feedback, not a
|
||||||
|
# delayed plan-stage failure. The runtime plan scan (Wiz-or-Checkov)
|
||||||
|
# runs after the plan (Step 5).
|
||||||
|
if [ "$QUIET" = "0" ]; then
|
||||||
|
checkov -d "$TF_DIR" --framework terraform -o json --soft-fail --external-checks-dir adapters/terraform/policy/custom_rules/ 2>&1 | tee "$WORK/checkov-static.json"
|
||||||
|
else
|
||||||
|
checkov -d "$TF_DIR" --framework terraform -o json --soft-fail --external-checks-dir adapters/terraform/policy/custom_rules/ > "$WORK/checkov-static.json" 2> "$WORK/checkov-static.err"
|
||||||
|
fi
|
||||||
|
[ -s "$WORK/checkov-static.json" ] || fail "checkov (static) produced no output"
|
||||||
|
echo ""
|
||||||
|
echo "checkov (static) summary: $(python3 -c "import json; d=json.load(open('$WORK/checkov-static.json')); print(len(d.get('results',{}).get('failed_checks',[])), 'failed,', len(d.get('results',{}).get('passed_checks',[])), 'passed')")"
|
||||||
|
|
||||||
echo "=== Step 4: terraform init + validate + plan -lock=false (real AWS) ==="
|
echo "=== Step 4: terraform init + validate + plan -lock=false (real AWS) ==="
|
||||||
cd "$TF_DIR"
|
cd "$TF_DIR"
|
||||||
|
|
||||||
@@ -380,19 +394,36 @@ if [ "$DESTROY_ONLY" = "1" ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "=== Step 5: run Checkov on $TF_DIR/main.tf ==="
|
echo "=== Step 5: runtime policy scan on the terraform plan (Wiz-or-Checkov, never both) ==="
|
||||||
if [ "$QUIET" = "0" ]; then
|
# REQ-250 (v1.21): after terraform plan, run Wiz against the plan when
|
||||||
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"
|
# configured; otherwise run Checkov against the plan as a drop-in
|
||||||
|
# replacement. Wiz and Checkov are NEVER both run on the plan.
|
||||||
|
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
|
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
|
fi
|
||||||
[ -s "$WORK/checkov.json" ] || fail "checkov produced no output"
|
if [ "$RUNTIME_SCAN_ENGINE" = "checkov-plan" ]; then
|
||||||
echo ""
|
echo "--- Wiz not configured → Checkov on the plan (drop-in replacement) ---"
|
||||||
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')")"
|
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"
|
||||||
echo ""
|
else
|
||||||
echo "=== Step 6: Checkov adapter -> PolicyCheckResult (compliance details) ==="
|
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"
|
||||||
python3 adapters/terraform/policy/checkov_adapter.py "$WORK/checkov.json" "$CONTRACT_ID" > "$WORK/pcr.json" || fail "checkov adapter failed"
|
fi
|
||||||
|
[ -s "$WORK/checkov-plan.json" ] || fail "checkov (plan) produced no output"
|
||||||
|
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 ==="
|
||||||
|
python3 adapters/terraform/policy/checkov_adapter.py "$WORK/checkov-plan.json" "$CONTRACT_ID" > "$WORK/pcr.json" || fail "checkov (plan) adapter failed"
|
||||||
|
fi
|
||||||
|
echo "runtime scan engine: $RUNTIME_SCAN_ENGINE"
|
||||||
python3 -c "
|
python3 -c "
|
||||||
import json
|
import json
|
||||||
pcrs = json.load(open('$WORK/pcr.json'))
|
pcrs = json.load(open('$WORK/pcr.json'))
|
||||||
@@ -494,5 +525,5 @@ source "$ROOT/scripts/run_uptime.sh"
|
|||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "=== PLATFORM E2E OK ==="
|
echo "=== PLATFORM E2E OK ==="
|
||||||
echo "contract -> resolver -> stack -> terraform plan -> Checkov -> confidence ($BAND) -> outbox -> outputs"
|
echo "contract -> resolver -> stack -> Checkov(static) -> terraform plan -> Wiz-or-Checkov(plan) -> confidence ($BAND) -> outbox -> outputs"
|
||||||
exit 0
|
exit 0
|
||||||
+33
-14
@@ -2,8 +2,9 @@
|
|||||||
# scripts/run_postapply.sh — post-Terraform steps for the Nova platform pipeline.
|
# scripts/run_postapply.sh — post-Terraform steps for the Nova platform pipeline.
|
||||||
#
|
#
|
||||||
# Performs steps 5–9 of run_platform.sh (after terraform apply/destroy):
|
# Performs steps 5–9 of run_platform.sh (after terraform apply/destroy):
|
||||||
# 5. Checkov policy scan on the emitted main.tf
|
# 3c. Checkov policy scan on static code (fail-fast, in run_codegen.sh)
|
||||||
# 6. Checkov adapter → PolicyCheckResult (compliance details)
|
# 5. Runtime policy scan on the terraform plan (Wiz-or-Checkov, never both)
|
||||||
|
# 6. Policy scan adapter → PolicyCheckResult (compliance details)
|
||||||
# 7. Confidence signal compute
|
# 7. Confidence signal compute
|
||||||
# 7b. HITL attestation gate (qa/prod/dr only)
|
# 7b. HITL attestation gate (qa/prod/dr only)
|
||||||
# 8. Write evidence event to DynamoDB outbox
|
# 8. Write evidence event to DynamoDB outbox
|
||||||
@@ -92,19 +93,37 @@ else:
|
|||||||
" || { echo "FAIL: HITL gate blocked" >&2; return 1; }
|
" || { echo "FAIL: HITL gate blocked" >&2; return 1; }
|
||||||
}
|
}
|
||||||
|
|
||||||
echo "=== Step 5: run Checkov on $TF_DIR/main.tf ==="
|
echo "=== Step 5: runtime policy scan on the terraform plan (Wiz-or-Checkov, never both) ==="
|
||||||
if [ "$QUIET" = "0" ]; then
|
# REQ-250 (v1.21): after terraform plan, run Wiz against the plan when
|
||||||
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"
|
# 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
|
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
|
fi
|
||||||
[ -s "$WORK/checkov.json" ] || { echo "FAIL: checkov produced no output" >&2; exit 1; }
|
if [ "$RUNTIME_SCAN_ENGINE" = "checkov-plan" ]; then
|
||||||
echo ""
|
echo "--- Wiz not configured → Checkov on the plan (drop-in replacement) ---"
|
||||||
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')")"
|
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"
|
||||||
echo ""
|
else
|
||||||
echo "=== Step 6: Checkov adapter → PolicyCheckResult (compliance details) ==="
|
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"
|
||||||
python3 adapters/terraform/policy/checkov_adapter.py "$WORK/checkov.json" "$CONTRACT_ID" > "$WORK/pcr.json" || { echo "FAIL: checkov adapter failed" >&2; exit 1; }
|
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 "
|
python3 -c "
|
||||||
import json
|
import json
|
||||||
pcrs = json.load(open('$WORK/pcr.json'))
|
pcrs = json.load(open('$WORK/pcr.json'))
|
||||||
@@ -199,4 +218,4 @@ source "$ROOT/scripts/run_uptime.sh"
|
|||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "=== POST-APPLY OK ==="
|
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"
|
||||||
|
|||||||
@@ -173,16 +173,19 @@ class TestDeployPipelineContract:
|
|||||||
contract = yaml.safe_load(fh)
|
contract = yaml.safe_load(fh)
|
||||||
jsonschema.validate(contract, schema)
|
jsonschema.validate(contract, schema)
|
||||||
|
|
||||||
def test_deploy_pipeline_has_six_stages(self):
|
def test_deploy_pipeline_has_required_stages(self):
|
||||||
with open(ROOT / "pipelines/contract.yml") as fh:
|
with open(ROOT / "pipelines/contract.yml") as fh:
|
||||||
contract = yaml.safe_load(fh)
|
contract = yaml.safe_load(fh)
|
||||||
stage_names = [s["name"] for s in contract["stages"]]
|
stage_names = [s["name"] for s in contract["stages"]]
|
||||||
assert "validate-contract" in stage_names
|
assert "validate-contract" in stage_names
|
||||||
assert "resolve-stack" in stage_names
|
assert "resolve-stack" in stage_names
|
||||||
|
assert "checkov-static" in stage_names, "REQ-250: checkov-static stage missing"
|
||||||
assert "terraform-plan" in stage_names
|
assert "terraform-plan" in stage_names
|
||||||
assert "checkov" in stage_names
|
assert "runtime-policy-scan" in stage_names, "REQ-250: runtime-policy-scan stage missing"
|
||||||
assert "confidence" in stage_names
|
assert "confidence" in stage_names
|
||||||
assert "apply" in stage_names
|
assert "apply" in stage_names
|
||||||
|
# The old single 'checkov' stage is gone (split into checkov-static + runtime-policy-scan)
|
||||||
|
assert "checkov" not in stage_names, "old 'checkov' stage should be replaced by checkov-static + runtime-policy-scan"
|
||||||
|
|
||||||
|
|
||||||
class TestL2OutputsResolution:
|
class TestL2OutputsResolution:
|
||||||
|
|||||||
@@ -206,14 +206,15 @@ class TestDeployPipelineContract:
|
|||||||
contract = _load_yaml("pipelines/contract.yml")
|
contract = _load_yaml("pipelines/contract.yml")
|
||||||
jsonschema.validate(contract, schema)
|
jsonschema.validate(contract, schema)
|
||||||
|
|
||||||
def test_deploy_contract_has_nine_stages(self):
|
def test_deploy_contract_has_ten_stages(self):
|
||||||
contract = _load_yaml("pipelines/contract.yml")
|
contract = _load_yaml("pipelines/contract.yml")
|
||||||
stage_names = [s["name"] for s in contract["stages"]]
|
stage_names = [s["name"] for s in contract["stages"]]
|
||||||
assert stage_names == [
|
assert stage_names == [
|
||||||
"validate-contract",
|
"validate-contract",
|
||||||
"resolve-stack",
|
"resolve-stack",
|
||||||
|
"checkov-static",
|
||||||
"terraform-plan",
|
"terraform-plan",
|
||||||
"checkov",
|
"runtime-policy-scan",
|
||||||
"confidence",
|
"confidence",
|
||||||
"apply",
|
"apply",
|
||||||
"publish-outputs",
|
"publish-outputs",
|
||||||
|
|||||||
Reference in New Issue
Block a user