whitehat-security/tests/test_engagement.py
tegwick beab2a04d1 Build authorization-gated tenancy evidence harness
Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a0260c-4067-7052-9647-ad000d576e38
2026-08-21 23:53:27 +02:00

63 lines
2.4 KiB
Python

import json
from datetime import UTC, datetime
import pytest
from whitehat_security.engagement import AuthorizationError, Engagement
def record():
return {
"engagement_id": "WH-ENG-1", "authorization_id": "auth-1",
"authorizer": "operator", "approved_at": "2026-08-21T08:00:00Z",
"expires_at": "2026-08-21T12:00:00Z", "target": "https://fixture.invalid",
"target_owner": "target-repo", "environment": "build", "source": "runner",
"routes": ["GET /objects/{id}"], "fixture_ids": ["object-a", "object-b"],
"credential_lane": "openbao", "credential_role": "runtime",
"credential_max_ttl_seconds": 900, "techniques": ["e2-differential"],
"prohibited_techniques": ["saturation"], "rate_limit_per_minute": 10,
"max_concurrency": 1, "window_start": "2026-08-21T08:00:00Z",
"window_end": "2026-08-21T10:00:00Z", "operator_contact": "operator",
"abort_contact": "target-owner", "posture_claim": "E2",
"attacker_model": "E2-authenticated-tenant-a", "finding_destination": "risk-nexus",
"target_owner_acknowledged_at": "2026-08-21T08:01:00Z",
}
def load(tmp_path, data):
path = tmp_path / "engagement.json"
path.write_text(json.dumps(data), encoding="utf-8")
return Engagement.load(path, now=datetime(2026, 8, 21, 9, tzinfo=UTC))
def test_complete_current_record_is_accepted(tmp_path):
engagement = load(tmp_path, record())
engagement.permits(technique="e2-differential", route="GET /objects/{id}")
@pytest.mark.parametrize("field", ["target_owner_acknowledged_at", "abort_contact", "fixture_ids"])
def test_incomplete_record_fails_closed(tmp_path, field):
data = record()
del data[field]
with pytest.raises(AuthorizationError):
load(tmp_path, data)
def test_expired_record_fails_closed(tmp_path):
with pytest.raises(AuthorizationError, match="outside"):
Engagement.load(
_write(tmp_path, record()), now=datetime(2026, 8, 21, 13, tzinfo=UTC)
)
def test_unauthorized_route_fails_closed(tmp_path):
engagement = load(tmp_path, record())
with pytest.raises(AuthorizationError, match="route"):
engagement.permits(technique="e2-differential", route="DELETE /objects/{id}")
def _write(tmp_path, data):
path = tmp_path / "engagement.json"
path.write_text(json.dumps(data), encoding="utf-8")
return path