generated from coulomb/repo-seed
- LocalCA: ssh-keygen -s signing, keypair generation, cert parsing via ssh-keygen -L - VaultCA: Vault SSH engine backend via httpx - Inventory: YAML actor registry with ActorType, principals, TTL policy - Scorecard: four cert-side compliance checks (prefixes, principals, no expired/stale) - CLI: sign (cert_command interface), issue, status, scorecard, inventory subcommands - ops-ssh-wrapper: acquire cert and exec SSH command - Fix: principal parser stops at section headers containing ':' (Critical Options, Extensions) - Move WARDEN-WP-0001 workplan from ops-bridge; register repo in state-hub (74df727e) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
100 lines
3.0 KiB
Python
100 lines
3.0 KiB
Python
"""Tests for warden.scorecard."""
|
|
from pathlib import Path
|
|
|
|
|
|
from warden.inventory import ActorEntry, PrincipalsInventory
|
|
from warden.models import ActorType
|
|
from warden.scorecard import (
|
|
check_actor_name_prefixes,
|
|
check_all_actors_have_principals,
|
|
check_no_stale_certs,
|
|
check_no_expired_certs,
|
|
run_scorecard,
|
|
)
|
|
|
|
|
|
def make_inventory(*actors):
|
|
inv = PrincipalsInventory()
|
|
for name, atype, principals in actors:
|
|
inv.actors[name] = ActorEntry(
|
|
name=name, actor_type=atype, principals=principals, ttl_hours=24
|
|
)
|
|
return inv
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# check_actor_name_prefixes
|
|
# ---------------------------------------------------------------------------
|
|
|
|
def test_prefix_check_pass():
|
|
inv = make_inventory(
|
|
("adm-bernd", ActorType.ADM, ["adm-full"]),
|
|
("agt-bridge", ActorType.AGT, ["agt-task-bridge"]),
|
|
("atm-cron", ActorType.ATM, ["atm-cron"]),
|
|
)
|
|
result = check_actor_name_prefixes(inv)
|
|
assert result.passed
|
|
|
|
|
|
def test_prefix_check_fail_bad_name():
|
|
# Bypass validate_actor_name by inserting directly
|
|
inv = PrincipalsInventory()
|
|
inv.actors["bad-name"] = ActorEntry(
|
|
name="bad-name", actor_type=ActorType.AGT, principals=["x"], ttl_hours=24
|
|
)
|
|
result = check_actor_name_prefixes(inv)
|
|
assert not result.passed
|
|
assert "bad-name" in result.detail
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# check_all_actors_have_principals
|
|
# ---------------------------------------------------------------------------
|
|
|
|
def test_principals_check_pass():
|
|
inv = make_inventory(("agt-bridge", ActorType.AGT, ["agt-task-bridge"]))
|
|
result = check_all_actors_have_principals(inv)
|
|
assert result.passed
|
|
|
|
|
|
def test_principals_check_fail_empty():
|
|
inv = PrincipalsInventory()
|
|
inv.actors["agt-bridge"] = ActorEntry(
|
|
name="agt-bridge", actor_type=ActorType.AGT, principals=[], ttl_hours=24
|
|
)
|
|
result = check_all_actors_have_principals(inv)
|
|
assert not result.passed
|
|
assert "agt-bridge" in result.detail
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# check_no_stale_certs
|
|
# ---------------------------------------------------------------------------
|
|
|
|
def test_no_stale_certs_nonexistent_dir():
|
|
result = check_no_stale_certs(Path("/nonexistent/state/dir"))
|
|
assert result.passed
|
|
|
|
|
|
def test_no_stale_certs_empty_dir(tmp_path):
|
|
result = check_no_stale_certs(tmp_path)
|
|
assert result.passed
|
|
|
|
|
|
def test_no_expired_certs_empty_dir(tmp_path):
|
|
result = check_no_expired_certs(tmp_path)
|
|
assert result.passed
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# run_scorecard
|
|
# ---------------------------------------------------------------------------
|
|
|
|
def test_run_scorecard_clean(tmp_path):
|
|
inv = make_inventory(
|
|
("agt-bridge", ActorType.AGT, ["agt-task-bridge"]),
|
|
)
|
|
results = run_scorecard(tmp_path, inv)
|
|
assert all(r.passed for r in results)
|
|
assert len(results) == 4
|