WHITEHAT-WP-0012 records that identity and authorization evidence belongs in the declaring service's CI, and adds an in-process V2/V3/V4 observation judge that injects no failure. Live E4, R4, and V stay wait on an unnamed owner or operator, so the plan is blocked. No packet is authorized. Assistant: grok Assistant-Session: 01a10450-dda4-7253-91a9-b8dccb2f0173
93 lines
4 KiB
Python
93 lines
4 KiB
Python
import json
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
from whitehat_security.engagement import AuthorizationError
|
|
from whitehat_security.targets import load_registration
|
|
from whitehat_security.v import VObservation, evaluate, v_calibration
|
|
|
|
|
|
def test_restart_and_missing_injection_are_not_a_pass():
|
|
restart = evaluate(VObservation(
|
|
"restart", claimed_level="V2", operation="read", failure_injected=True,
|
|
failure_kind="restart", traffic_continued_or_recovered=True,
|
|
rto_recorded=True, rpo_recorded=True, shared_failure_domain_recorded=True,
|
|
))
|
|
assert restart.outcome == "finding"
|
|
absent = evaluate(VObservation(
|
|
"absent", claimed_level="V2", operation="read", failure_injected=False,
|
|
failure_kind="instance-terminated", traffic_continued_or_recovered=True,
|
|
rto_recorded=True, rpo_recorded=True, shared_failure_domain_recorded=True,
|
|
))
|
|
assert absent.outcome == "finding"
|
|
|
|
|
|
def test_missing_measurements_stay_inconclusive():
|
|
missing = evaluate(VObservation(
|
|
"rto", claimed_level="V2", operation="read", failure_injected=True,
|
|
failure_kind="instance-terminated", traffic_continued_or_recovered=True,
|
|
rto_recorded=False, rpo_recorded=True, shared_failure_domain_recorded=True,
|
|
))
|
|
assert missing.outcome == "inconclusive"
|
|
unnamed = evaluate(VObservation(
|
|
"operation", claimed_level="V2", operation=" ", failure_injected=True,
|
|
failure_kind="instance-terminated", traffic_continued_or_recovered=True,
|
|
rto_recorded=True, rpo_recorded=True, shared_failure_domain_recorded=True,
|
|
))
|
|
assert unnamed.outcome == "inconclusive"
|
|
|
|
|
|
def test_v1_is_not_adversarial_evidence_from_this_harness():
|
|
result = evaluate(VObservation(
|
|
"v1", claimed_level="V1", operation="read", failure_injected=True,
|
|
failure_kind="restart", rto_recorded=True,
|
|
))
|
|
assert result.outcome == "inconclusive"
|
|
|
|
|
|
def test_v3_and_v4_reject_the_wrong_shape():
|
|
wrong = evaluate(VObservation(
|
|
"v3", claimed_level="V3", operation="read", failure_injected=True,
|
|
failure_kind="instance-terminated", rto_recorded=True, rpo_recorded=True,
|
|
critical_path_observed=True, degraded_modes_observed=True,
|
|
))
|
|
assert wrong.outcome == "finding"
|
|
region = evaluate(VObservation(
|
|
"v4", claimed_level="V4", operation="read", failure_injected=True,
|
|
failure_kind="region-unavailable", rto_recorded=True, rpo_recorded=True,
|
|
alternate_region_recovered=False,
|
|
))
|
|
assert region.outcome == "finding"
|
|
|
|
|
|
def test_unknown_claim_aborts():
|
|
assert evaluate(VObservation("nope", claimed_level="V9")).outcome == "aborted"
|
|
|
|
|
|
def test_calibration_fails_known_bad_before_trusting_a_pass():
|
|
report = v_calibration()
|
|
assert report["known_bad_failed_first"] is True
|
|
assert report["failure_injected_by_harness"] is False
|
|
assert report["evidence_class"] == "fixture"
|
|
assert report["outcome"] == "pass"
|
|
assert "pass" not in {item["outcome"] for item in report["known_bad"]}
|
|
assert {item["outcome"] for item in report["known_good"]} == {"pass"}
|
|
assert any("no cluster" in item.lower() or "no instance" in item.lower()
|
|
for item in report["limitations"])
|
|
|
|
|
|
def test_fixture_v_projects_no_credential_and_no_live_class(tmp_path: Path):
|
|
registration = json.loads(Path("targets/fixture-v.json").read_text(encoding="utf-8"))
|
|
assert registration["identities"]["count"] == 0
|
|
assert registration["approval_classes"] == ["fixture-v"]
|
|
registration["identities"]["count"] = 1
|
|
path = tmp_path / "counted.json"
|
|
path.write_text(json.dumps(registration), encoding="utf-8")
|
|
with pytest.raises(AuthorizationError, match="project no credential"):
|
|
load_registration(path)
|
|
registration["identities"]["count"] = 0
|
|
registration["approval_classes"] = ["fixture-v", "capacity"]
|
|
path.write_text(json.dumps(registration), encoding="utf-8")
|
|
with pytest.raises(AuthorizationError, match="cannot carry a live approval class"):
|
|
load_registration(path)
|