Add WHITEHAT-WP-0002 receipt example, CLI coverage, and abort records
Meantime polish while live E2 waits on a new trial. Example receipts carry handles only. admit-plane --receipt is tested. Aborts can be queued without being target assurance. Assistant: grok Assistant-Session: 01a02670-3345-76f2-a014-70fde8e2a2bb
This commit is contained in:
parent
45548e44a2
commit
481ed6add5
11 changed files with 247 additions and 5 deletions
|
|
@ -1,8 +1,10 @@
|
|||
import json
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from whitehat_security.cli import main
|
||||
from whitehat_security.plane import ReceiptBroker
|
||||
|
||||
|
||||
def test_validate_engagement_reports_clean_denial(tmp_path, capsys):
|
||||
|
|
@ -57,6 +59,108 @@ def test_admit_plane_refuses_cancelled_engagement(capsys):
|
|||
assert "not authorized:" in capsys.readouterr().err
|
||||
|
||||
|
||||
def _live_e2_record():
|
||||
return {
|
||||
"engagement_id": "WH-ENG-CLI-RECEIPT",
|
||||
"authorization_id": "auth-cli",
|
||||
"authorizer": "operator",
|
||||
"approved_at": "2026-08-22T00:00:00Z",
|
||||
"expires_at": "2099-01-01T00:00:00Z",
|
||||
"target": "https://fixture.invalid",
|
||||
"target_id": "audit-core",
|
||||
"target_owner": "audit-core",
|
||||
"environment": "build",
|
||||
"source": "runner",
|
||||
"approval_class": "live-e2",
|
||||
"plane_namespace": "whitehat",
|
||||
"runner_image_digest": "sha256:abc",
|
||||
"routes": ["POST /v1/events"],
|
||||
"fixture_ids": ["object-a", "object-b"],
|
||||
"credential_lane": "receipt",
|
||||
"credential_role": "runtime",
|
||||
"credential_max_ttl_seconds": 900,
|
||||
"techniques": ["e2-differential"],
|
||||
"prohibited_techniques": ["saturation"],
|
||||
"rate_limit_per_minute": 10,
|
||||
"max_concurrency": 1,
|
||||
"maximum_requests": 8,
|
||||
"window_start": "2026-08-22T00:00:00Z",
|
||||
"window_end": "2099-01-01T00:00:00Z",
|
||||
"operator_contact": "operator",
|
||||
"abort_contact": "operator",
|
||||
"posture_claim": "E2",
|
||||
"attacker_model": "E2-authenticated-tenant-a",
|
||||
"finding_destination": "risk-nexus",
|
||||
"target_owner_acknowledged_at": "2026-08-22T00:01:00Z",
|
||||
}
|
||||
|
||||
|
||||
def _receipt(**overrides):
|
||||
data = {
|
||||
"engagement_id": "WH-ENG-CLI-RECEIPT",
|
||||
"projected_at": "2026-08-22T19:17:54Z",
|
||||
"expires_at": "2099-01-01T00:00:00Z",
|
||||
"identities": ["whitehat-e2-a-example", "whitehat-e2-b-example"],
|
||||
"mounted_secret": "whitehat/whitehat-e2-audit-credentials",
|
||||
"mounted_keys": ["token-a", "token-b"],
|
||||
"target_ready": True,
|
||||
"secret_values_observed": False,
|
||||
}
|
||||
data.update(overrides)
|
||||
return data
|
||||
|
||||
|
||||
def test_admit_plane_without_receipt_still_fails_closed(tmp_path, capsys):
|
||||
path = tmp_path / "engagement.json"
|
||||
path.write_text(json.dumps(_live_e2_record()), encoding="utf-8")
|
||||
with pytest.raises(SystemExit) as stopped:
|
||||
main(["admit-plane", str(path), "targets/audit-core-e2.json"])
|
||||
assert stopped.value.code == 2
|
||||
assert "no credential was requested" in capsys.readouterr().err
|
||||
|
||||
|
||||
def test_admit_plane_receipt_issues_lease(tmp_path, capsys):
|
||||
engagement = tmp_path / "engagement.json"
|
||||
receipt = tmp_path / "receipt.json"
|
||||
engagement.write_text(json.dumps(_live_e2_record()), encoding="utf-8")
|
||||
receipt.write_text(json.dumps(_receipt()), encoding="utf-8")
|
||||
main(["admit-plane", str(engagement), "targets/audit-core-e2.json", "--receipt", str(receipt)])
|
||||
out = capsys.readouterr().out
|
||||
assert out.startswith("admitted: WH-ENG-CLI-RECEIPT")
|
||||
|
||||
|
||||
def test_admit_plane_receipt_refuses_secret_material(tmp_path, capsys):
|
||||
engagement = tmp_path / "engagement.json"
|
||||
receipt = tmp_path / "receipt.json"
|
||||
engagement.write_text(json.dumps(_live_e2_record()), encoding="utf-8")
|
||||
receipt.write_text(json.dumps(_receipt(token="must-not-appear")), encoding="utf-8")
|
||||
with pytest.raises(SystemExit) as stopped:
|
||||
main(["admit-plane", str(engagement), "targets/audit-core-e2.json", "--receipt", str(receipt)])
|
||||
assert stopped.value.code == 2
|
||||
assert "secret material" in capsys.readouterr().err
|
||||
|
||||
|
||||
def test_example_projection_receipt_is_value_safe():
|
||||
broker = ReceiptBroker.load("engagements/receipts/example-projection-receipt.json")
|
||||
assert broker.receipt["engagement_id"] == "WH-ENG-EXAMPLE"
|
||||
assert broker.receipt["secret_values_observed"] is False
|
||||
assert broker.receipt["mounted_keys"] == ["token-a", "token-b"]
|
||||
|
||||
|
||||
def test_deliver_queues_abort_without_calling_it_target_assurance(tmp_path, capsys):
|
||||
report = json.loads(
|
||||
Path("evidence/WH-ENG-20260822-AUDIT-E2-02-abort.json").read_text(encoding="utf-8")
|
||||
)
|
||||
path = tmp_path / "abort.json"
|
||||
path.write_text(json.dumps(report), encoding="utf-8")
|
||||
main(["deliver", str(path), "--outbox", str(tmp_path / "outbox")])
|
||||
queued = (tmp_path / "outbox" / f"{report['run_id']}.md").read_text(encoding="utf-8")
|
||||
assert capsys.readouterr().out.startswith("queued:")
|
||||
assert "abort" in queued
|
||||
assert "not target assurance" in queued
|
||||
assert "Severity" not in queued
|
||||
|
||||
|
||||
def test_deliver_refuses_fixture_calibration(tmp_path, capsys):
|
||||
report = tmp_path / "fixture.json"
|
||||
report.write_text(json.dumps({
|
||||
|
|
|
|||
|
|
@ -48,3 +48,18 @@ def test_risk_message_contains_pass_and_no_severity():
|
|||
assert "**pass**" in message
|
||||
assert "Severity" not in message
|
||||
assert "not proof" in message
|
||||
|
||||
|
||||
def test_abort_message_is_not_target_assurance():
|
||||
report = RunReport(
|
||||
schema_version="whitehat-run/v1", run_id="abort-1", evidence_class="abort",
|
||||
engagement_id="eng-1", authorization_id="auth-1", target="audit-core",
|
||||
target_revision="abc", posture_claim="E2", attacker_model="E2",
|
||||
started_at="2026-08-22T19:17:54Z", ended_at="2026-08-22T19:21:39Z",
|
||||
outcome="aborted", attempted_operations=0, cleanup="complete",
|
||||
credential_revocation="custody-owned",
|
||||
)
|
||||
message = risk_nexus_message(report)
|
||||
assert "`abort`" in message
|
||||
assert "not target assurance" in message
|
||||
assert "Severity" not in message
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue