Files
ewoooc/tests/test_security_governance_review_service.py
ogt b4284693e4
Some checks failed
CD Pipeline / deploy (push) Has been cancelled
feat(governance): persist production security readback
2026-07-10 19:40:04 +08:00

271 lines
9.5 KiB
Python

import json
import subprocess
import sys
from pathlib import Path
import pytest
from flask import Blueprint, Flask, jsonify
ROOT = Path(__file__).resolve().parents[1]
def test_security_governance_review_is_honest_and_release_gate_passes():
from services.security_governance_review_service import (
build_security_governance_review,
)
report = build_security_governance_review(root=ROOT, detail_limit=12)
assert report["status"] == "partial"
assert report["release_gate"]["status"] == "pass"
assert report["release_gate"]["blocking_failure_count"] == 0
assert report["completion"]["asset_field_coverage_percent"] == 100.0
assert report["completion"]["asset_runtime_reconciliation_complete"] is False
assert report["completion"]["runtime_closure_passed"] < report["completion"]["runtime_closure_total"]
assert report["work_items"][0]["id"] == "SEC-P0-001"
assert len(report["work_items"]) == 22
assert report["work_items"][9]["id"] == "REL-P0-001"
assert any(item["id"] == "QA-P1-001" for item in report["work_items"])
assert report["work_items"][-1]["id"] == "CHAOS-P2-001"
checks = {item["id"]: item for item in report["checks"]}
access = checks["PR.AA-route-access-control"]["evidence"]
assert access["mutating_unguarded_count"] == 0
assert access["unclassified_unguarded_count"] == 0
assert access["unguarded_count"] == 8
dependencies = checks["ID.RA-dependency-vulnerability-management"]["evidence"]
assert dependencies["sbom_files"] == []
supply = checks["GV.SC-gitea-only-supply-chain"]
assert supply["status"] == "pass"
assert supply["evidence"]["docker_build_context"]["safe"] is True
quality = checks["GV.QA-test-governance"]
assert quality["status"] == "partial"
assert quality["evidence"]["collection_error_count"] == 1
assert quality["evidence"]["full_suite_passed"] == 1701
assert report["safety"] == {
"read_only": True,
"network_calls": False,
"database_reads": False,
"database_writes": False,
"secret_reads": False,
"external_side_effects": False,
}
def test_security_governance_cli_strict_mode_passes_source_gate():
completed = subprocess.run(
[
sys.executable,
str(ROOT / "scripts" / "ops" / "report_security_governance_review.py"),
"--root",
str(ROOT),
"--compact",
"--strict",
],
cwd=ROOT,
capture_output=True,
text=True,
timeout=30,
check=False,
)
assert completed.returncode == 0, completed.stderr or completed.stdout
payload = json.loads(completed.stdout)
assert payload["release_gate"]["status"] == "pass"
assert payload["status"] == "partial"
def test_security_governance_cli_can_emit_commit_bound_source_receipt():
source_commit = "a" * 40
completed = subprocess.run(
[
sys.executable,
str(ROOT / "scripts" / "ops" / "report_security_governance_review.py"),
"--root",
str(ROOT),
"--strict",
"--source-commit",
source_commit,
],
cwd=ROOT,
capture_output=True,
text=True,
timeout=30,
check=False,
)
assert completed.returncode == 0, completed.stderr or completed.stdout
payload = json.loads(completed.stdout)
assert payload["receipt_kind"] == "security_governance_source_receipt"
assert payload["source_commit"] == source_commit
assert payload["release_gate"]["status"] == "pass"
def test_runtime_subset_uses_commit_bound_source_receipt(tmp_path):
from services.security_governance_review_service import (
build_security_governance_review,
)
source_report = build_security_governance_review(root=ROOT)
source_report["receipt_kind"] = "security_governance_source_receipt"
source_report["source_commit"] = "b" * 40
governance = tmp_path / "governance"
governance.mkdir()
(governance / "security_governance_source_receipt.json").write_text(
json.dumps(source_report, ensure_ascii=False),
encoding="utf-8",
)
runtime_report = build_security_governance_review(root=tmp_path)
checks = {item["id"]: item for item in runtime_report["checks"]}
supply = checks["GV.SC-gitea-only-supply-chain"]
policy = checks["GV.PO-policy-alignment"]
assert supply["status"] == "pass"
assert supply["evidence"]["evidence_source"] == "cd_source_receipt"
assert policy["status"] == "pass"
assert policy["evidence"]["evidence_source"] == "cd_source_receipt"
def test_runtime_receipt_advances_access_readback_without_hiding_remaining_debt(tmp_path):
from services.security_governance_review_service import (
_runtime_receipt,
)
governance = tmp_path / "governance"
governance.mkdir()
payload = {
"receipt_kind": "security_governance_runtime_receipt",
"trace_id": "secgov-test",
"run_id": "secgov-test-run",
"work_item_id": "SEC-P0-001",
"source_commit": "c" * 40,
"deployed_version": "V10.773",
"deployment_mode": "controlled_manual_fallback",
"access_control": {
"status": "pass",
"sensitive_routes_denied": True,
"security_headers_passed": True,
"secure_cookie": True,
"sensitive_route_count": 8,
"denied_route_count": 8,
"metrics_public": True,
},
"database": {"unchanged": True},
"post_verifier": {
"health_status": "healthy",
"governance_gate": "pass",
},
"cd": {
"run_id": 1095,
"status": "waiting",
"blocker": "no_ewoooc_host_runner",
},
"learning_recorded": False,
"next_machine_action": "move_metrics_behind_edge_auth_with_prometheus_canary",
}
(governance / "security_governance_runtime_receipt.json").write_text(
json.dumps(payload, ensure_ascii=False),
encoding="utf-8",
)
receipt = _runtime_receipt(tmp_path)
assert receipt["security_readback_passed"] is True
assert receipt["database_unchanged"] is True
assert receipt["metrics_public"] is True
assert receipt["cd_status"] == "waiting"
assert receipt["learning_recorded"] is False
def test_sensitive_blueprint_policy_denies_anonymous_api(monkeypatch):
import auth
from services.http_access_policy_service import enforce_http_access_policy
monkeypatch.setattr(auth, "DISABLE_LOGIN", False)
app = Flask(__name__)
app.secret_key = "test"
vendor = Blueprint("vendor", __name__)
@vendor.route("/vendor-stockout/api/vendor/list")
def list_vendors():
return jsonify({"success": True})
app.register_blueprint(vendor)
app.before_request(enforce_http_access_policy)
client = app.test_client()
anonymous = client.get("/vendor-stockout/api/vendor/list")
assert anonymous.status_code == 401
assert anonymous.get_json()["error"] == "authentication_required"
with client.session_transaction() as session:
session["logged_in"] = True
authenticated = client.get("/vendor-stockout/api/vendor/list")
assert authenticated.status_code == 200
def test_public_url_validator_blocks_ssrf_targets(monkeypatch):
from utils import security
monkeypatch.setattr(
security.socket,
"getaddrinfo",
lambda *_args, **_kwargs: [(2, 1, 6, "", ("93.184.216.34", 443))],
)
assert security.validate_public_http_url("https://example.com/path") == "https://example.com/path"
monkeypatch.setattr(
security.socket,
"getaddrinfo",
lambda *_args, **_kwargs: [(2, 1, 6, "", ("127.0.0.1", 80))],
)
with pytest.raises(ValueError, match="loopback"):
security.validate_public_http_url("http://example.com/")
def test_alert_auto_fix_protects_database_and_denies_unknown_container(monkeypatch):
from routes import alert_routes
def fail_if_called(*_args, **_kwargs):
raise AssertionError("subprocess must not run for denied containers")
monkeypatch.setattr(alert_routes.subprocess, "run", fail_if_called)
protected = alert_routes.auto_fix_container("momo-db", "memory")
assert protected["success"] is False
assert "受保護" in protected["message"]
unknown = alert_routes.auto_fix_container("stock-platform", "memory")
assert unknown["success"] is False
assert "白名單" in unknown["message"]
def test_security_governance_smoke_family_is_warning_for_nonblocking_debt(monkeypatch):
from services import ai_automation_smoke_service as smoke
from services import security_governance_review_service as review_service
monkeypatch.setattr(
review_service,
"build_security_governance_review",
lambda **_kwargs: {
"policy": "test-policy",
"status": "partial",
"completion": {
"program_percent": 45.0,
"asset_field_coverage_percent": 100.0,
"asset_runtime_reconciliation_complete": False,
"runtime_closure_passed": 0,
"runtime_closure_total": 4,
},
"release_gate": {"blocking_failure_count": 0},
"next_machine_action": "close_access_control",
},
)
check = smoke._security_governance_review_check()
assert check["status"] == "warning"
assert check["details"]["blocking_failure_count"] == 0
assert check["details"]["next_machine_action"] == "close_access_control"