ops-mason/tests/test_executor.py
tegwick 33573a35a1 Real build executed for real (MASON-WP-0001-T05, MASON-WP-0001 done 5/5)
Ran the whole approved pipeline against real OpenBao: created the reins/
KV v2 mount (after pausing for explicit founder confirmation -- a bigger
action than the executive summary's blast-radius framing disclosed),
the read-only policy, the AppRole, delivered role_id/secret_id. Caught
and fixed a real bug in the same pass: built with token_num_uses=0
(OpenBao's default = unlimited) instead of the plan's own stated 8;
fixed live and removed the executor's silently-permissive default so it
can't recur. Catalog entry proposed and merged in ops-warden (c0a50bc).

Corrected a real misreading in this repo's own INTENT.md along the way:
pointer fields (auth_method/fetch_command/rotation.steps) are normal on
non-SSH catalog entries; only a bare top-level steps:+cert_command:
pair is SSH-only -- verified against ops-warden's real entries and its
full test suite (326 tests, green).

Plan status: built. Catalog entry status: draft until the founder's
paste-once-provision and glas-harness/GLAS-WP-0002-T02's live
verification succeed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-27 01:25:14 +02:00

131 lines
4.8 KiB
Python

import json
from unittest.mock import MagicMock, patch
import pytest
from ops_mason.executor import AppRoleKVSpec, BuildError, BuildRefused, build_approle_kv_lane
from ops_mason.plan import ConstructionPlan
def _plan(tmp_path, *, status="approved", approved_by="bernd", approved_at="2026-07-27"):
text = (
"---\n"
"id: test-lane\n"
f"status: {status}\n"
+ (f'approved_by: "{approved_by}"\n' if approved_by else "approved_by: null\n")
+ (f'approved_at: "{approved_at}"\n' if approved_at else "approved_at: null\n")
+ "---\n# Plan\n"
)
p = tmp_path / "plan.md"
p.write_text(text)
return ConstructionPlan.load(str(p))
def _spec(tmp_path) -> AppRoleKVSpec:
return AppRoleKVSpec(
policy_name="workload-kv-read-test-lane",
kv_path="reins/test/openrouter",
approle_name="test-lane",
token_num_uses=8,
delivery_dir=tmp_path / "delivery",
audit_log_path=tmp_path / "audit.jsonl",
)
def test_token_num_uses_has_no_silently_unbounded_default() -> None:
import inspect
sig = inspect.signature(AppRoleKVSpec)
assert sig.parameters["token_num_uses"].default is inspect.Parameter.empty
def test_refuses_when_not_approved(tmp_path) -> None:
plan = _plan(tmp_path, status="draft", approved_by=None, approved_at=None)
with pytest.raises(BuildRefused, match="not approved"):
build_approle_kv_lane(plan, _spec(tmp_path))
def test_refuses_when_approved_status_but_missing_approver(tmp_path) -> None:
plan = _plan(tmp_path, status="approved", approved_by=None, approved_at="2026-07-27")
with pytest.raises(BuildRefused, match="not approved"):
build_approle_kv_lane(plan, _spec(tmp_path))
def test_refusal_never_calls_bao(tmp_path) -> None:
plan = _plan(tmp_path, status="reviewed", approved_by=None, approved_at=None)
with patch("ops_mason.executor.subprocess.run") as run:
with pytest.raises(BuildRefused):
build_approle_kv_lane(plan, _spec(tmp_path))
run.assert_not_called()
def test_build_writes_policy_approle_and_delivers_credentials(tmp_path) -> None:
plan = _plan(tmp_path)
spec = _spec(tmp_path)
def fake_run(cmd, input=None, capture_output=True, text=True, timeout=30):
result = MagicMock(returncode=0, stderr="")
if cmd[1:3] == ["read", "-field=role_id"]:
result.stdout = "role-id-value\n"
elif "-field=secret_id" in cmd:
result.stdout = "secret-id-value\n"
else:
result.stdout = ""
return result
with patch("ops_mason.executor.subprocess.run", side_effect=fake_run) as run:
objects = build_approle_kv_lane(plan, spec)
assert objects["policy_name"] == "workload-kv-read-test-lane"
assert objects["approle_name"] == "test-lane"
assert objects["kv_path"] == "reins/test/openrouter"
role_id_file = spec.delivery_dir / "role_id"
secret_id_file = spec.delivery_dir / "secret_id"
assert role_id_file.read_text() == "role-id-value\n"
assert secret_id_file.read_text() == "secret-id-value\n"
assert oct(role_id_file.stat().st_mode)[-3:] == "600"
assert oct(secret_id_file.stat().st_mode)[-3:] == "600"
# policy write call carried the HCL on stdin, not argv -- never in a log line
policy_call = next(c for c in run.call_args_list if c.args[0][:2] == ["bao", "policy"])
assert "reins/test/openrouter" in policy_call.kwargs["input"]
# audit record landed at the explicit path, metadata only, no role_id/secret_id values
audit_text = spec.audit_log_path.read_text()
assert "policy_name" in audit_text
assert "role-id-value" not in audit_text
assert "secret-id-value" not in audit_text
def test_build_appends_audit_record(tmp_path) -> None:
plan = _plan(tmp_path)
spec = _spec(tmp_path)
def fake_run(cmd, input=None, capture_output=True, text=True, timeout=30):
result = MagicMock(returncode=0, stderr="")
result.stdout = "value\n"
return result
with (
patch("ops_mason.executor.subprocess.run", side_effect=fake_run),
patch("ops_mason.executor.record_build") as record_build_mock,
):
build_approle_kv_lane(plan, spec)
record_build_mock.assert_called_once()
kwargs = record_build_mock.call_args.kwargs
assert kwargs["plan_id"] == "test-lane"
assert kwargs["approved_by"] == "bernd"
assert "policy_name" in kwargs["objects"]
assert kwargs["log_path"] == spec.audit_log_path
def test_bao_failure_raises_build_error(tmp_path) -> None:
plan = _plan(tmp_path)
spec = _spec(tmp_path)
fake_result = MagicMock(returncode=1, stderr="permission denied", stdout="")
with patch("ops_mason.executor.subprocess.run", return_value=fake_result):
with pytest.raises(BuildError, match="permission denied"):
build_approle_kv_lane(plan, spec)