feat: adopt security zones and explicit workload refs
Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a0291a-1e87-7151-9934-fcbfe3f65eb1
This commit is contained in:
parent
12c637cbf2
commit
7ce58ae638
52 changed files with 1547 additions and 658 deletions
|
|
@ -84,13 +84,13 @@ def test_default_vault_token_env(tmp_path):
|
|||
assert cfg.vault.token_env == "VAULT_TOKEN"
|
||||
|
||||
|
||||
def test_policy_defaults_disabled(tmp_path):
|
||||
def test_policy_defaults_to_unknown_zone_profile(tmp_path):
|
||||
cfg_path = tmp_path / "warden.yaml"
|
||||
write_yaml(cfg_path, {"backend": "local", "ca_key": str(tmp_path / "ca")})
|
||||
cfg = load_config(cfg_path)
|
||||
assert cfg.policy.enabled is False
|
||||
assert cfg.policy.flex_auth_url == "http://127.0.0.1:8080"
|
||||
assert cfg.policy.fail_closed is True
|
||||
assert cfg.policy.flex_auth_url is None
|
||||
assert cfg.policy.failure_modes["unknown"] == "fail_open"
|
||||
assert cfg.policy.failure_modes["z3-critical"] == "fail_closed"
|
||||
|
||||
|
||||
def test_policy_block_parsed(tmp_path):
|
||||
|
|
@ -99,18 +99,30 @@ def test_policy_block_parsed(tmp_path):
|
|||
"backend": "local",
|
||||
"ca_key": str(tmp_path / "ca"),
|
||||
"policy": {
|
||||
"enabled": True,
|
||||
"flex_auth_url": "http://flex-auth:8080",
|
||||
"fail_closed": False,
|
||||
"zone_registry_path": str(tmp_path / "zones.json"),
|
||||
"failure_modes": {"z2-protected": "fail_closed"},
|
||||
"tenant": "tenant:coulomb",
|
||||
"subject_env": "MY_SUBJECT",
|
||||
"system": "warden-test",
|
||||
},
|
||||
})
|
||||
cfg = load_config(cfg_path)
|
||||
assert cfg.policy.enabled is True
|
||||
assert cfg.policy.flex_auth_url == "http://flex-auth:8080"
|
||||
assert cfg.policy.fail_closed is False
|
||||
assert cfg.policy.zone_registry_path == tmp_path / "zones.json"
|
||||
assert cfg.policy.failure_modes["z2-protected"] == "fail_closed"
|
||||
assert cfg.policy.tenant == "tenant:coulomb"
|
||||
assert cfg.policy.subject_env == "MY_SUBJECT"
|
||||
assert cfg.policy.system == "warden-test"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("retired", ["enabled", "fail_closed"])
|
||||
def test_retired_global_policy_switches_are_rejected(tmp_path, retired):
|
||||
cfg_path = tmp_path / "warden.yaml"
|
||||
write_yaml(cfg_path, {
|
||||
"backend": "local",
|
||||
"ca_key": str(tmp_path / "ca"),
|
||||
"policy": {retired: True},
|
||||
})
|
||||
with pytest.raises(ConfigError, match=f"policy.{retired}"):
|
||||
load_config(cfg_path)
|
||||
|
|
|
|||
|
|
@ -1,14 +1,11 @@
|
|||
"""Tests for warden desk (WARDEN-WP-0029 T03)."""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import threading
|
||||
import urllib.error
|
||||
import urllib.parse
|
||||
import urllib.request
|
||||
from http.server import ThreadingHTTPServer
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from typer.testing import CliRunner
|
||||
|
||||
|
|
|
|||
|
|
@ -31,4 +31,53 @@ def test_build_registry_from_inventory_seed(tmp_path):
|
|||
)
|
||||
assert bridge["attributes"]["actor_type"] == "agt"
|
||||
assert bridge["attributes"]["max_ttl_hours"] == 24
|
||||
assert "agt-task-bridge" in bridge["attributes"]["allowed_principals"]
|
||||
assert "agt-task-bridge" in bridge["attributes"]["allowed_principals"]
|
||||
assert "trust_zone" not in bridge
|
||||
assert bridge["attributes"]["security_zone"] == "unknown"
|
||||
assert bridge["attributes"]["security_zone_admission"] == "unknown"
|
||||
assert bridge["attributes"]["workload_id"] == "ops-bridge-tunnel"
|
||||
|
||||
human = next(
|
||||
r
|
||||
for r in registry["resource_manifests"][0]["resources"]
|
||||
if r["id"] == "ssh-cert:actor/adm-example"
|
||||
)
|
||||
assert human["attributes"]["security_zone_admission"] == "not-applicable"
|
||||
|
||||
|
||||
def test_compiler_joins_explicit_workload_reference_to_resolved_zone(tmp_path):
|
||||
zones = tmp_path / "zones.json"
|
||||
zones.write_text(json.dumps({
|
||||
"records": [{
|
||||
"workload_id": "ops-bridge-tunnel",
|
||||
"declared_zone": "z2-continuity",
|
||||
"admission": "satisfied",
|
||||
"admission_reason": "admission_floor_met",
|
||||
"effective_zone": "z2-continuity",
|
||||
"membership_revision": "sha256:zone-revision",
|
||||
}]
|
||||
}))
|
||||
out = tmp_path / "registry.json"
|
||||
subprocess.run(
|
||||
[
|
||||
sys.executable,
|
||||
str(SCRIPT),
|
||||
str(INVENTORY),
|
||||
"--zone-resolutions",
|
||||
str(zones),
|
||||
"-o",
|
||||
str(out),
|
||||
],
|
||||
check=True,
|
||||
cwd=ROOT,
|
||||
)
|
||||
registry = json.loads(out.read_text())
|
||||
bridge = next(
|
||||
r
|
||||
for r in registry["resource_manifests"][0]["resources"]
|
||||
if r["id"] == "ssh-cert:actor/agt-state-hub-bridge"
|
||||
)
|
||||
attrs = bridge["attributes"]
|
||||
assert attrs["security_zone"] == "z2-continuity"
|
||||
assert attrs["security_zone_admission"] == "satisfied"
|
||||
assert attrs["security_zone_revision"] == "sha256:zone-revision"
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import json
|
|||
from typer.testing import CliRunner
|
||||
|
||||
from warden.cli import app
|
||||
from warden.memory import activate, enabled, record_command_episode, status, store_path
|
||||
from warden.memory import activate, record_command_episode, status, store_path
|
||||
from warden.worker import RuleBrain, _plan_with_memory, build_plans
|
||||
|
||||
runner = CliRunner()
|
||||
|
|
@ -140,4 +140,4 @@ def test_route_find_implicitly_activates_memory_without_explicit_command(tmp_pat
|
|||
activation = ensure_memory_context(need="ssh tunnel", implicit=True)
|
||||
assert activation is not None
|
||||
assert activation.get("implicit") is True
|
||||
assert status()["episode_count"] >= 1
|
||||
assert status()["episode_count"] >= 1
|
||||
|
|
|
|||
|
|
@ -27,6 +27,17 @@ def _spec(pubkey_path: Path) -> CertSpec:
|
|||
)
|
||||
|
||||
|
||||
def _zone_registry(tmp_path: Path, zone: str) -> Path:
|
||||
path = tmp_path / "registry.json"
|
||||
path.write_text(
|
||||
'{"resource_manifests":[{"resources":[{"id":'
|
||||
'"ssh-cert:actor/agt-state-hub-bridge","attributes":{'
|
||||
f'"security_zone":"{zone}","security_zone_admission":"satisfied"'
|
||||
'}}]}]}'
|
||||
)
|
||||
return path
|
||||
|
||||
|
||||
def test_pubkey_fingerprint(tmp_path):
|
||||
pubkey = tmp_path / "key.pub"
|
||||
pubkey.write_text("ssh-ed25519 AAAA test\n")
|
||||
|
|
@ -35,26 +46,32 @@ def test_pubkey_fingerprint(tmp_path):
|
|||
assert len(fp) == 7 + 64
|
||||
|
||||
|
||||
def test_disabled_returns_none(tmp_path):
|
||||
def test_unconfigured_evaluator_uses_unknown_fail_open_profile(tmp_path):
|
||||
pubkey = tmp_path / "key.pub"
|
||||
pubkey.write_text("ssh-ed25519 AAAA\n")
|
||||
cfg = PolicyConfig(enabled=False)
|
||||
assert check_sign_policy(cfg, _spec(pubkey)) is None
|
||||
cfg = PolicyConfig()
|
||||
spec = _spec(pubkey)
|
||||
assert check_sign_policy(cfg, spec) is None
|
||||
assert spec.policy_zone == "unknown"
|
||||
assert spec.policy_failure_mode == "fail_open"
|
||||
assert spec.policy_outcome == "fail_open"
|
||||
|
||||
|
||||
def test_allow_returns_decision_id(tmp_path):
|
||||
pubkey = tmp_path / "key.pub"
|
||||
pubkey.write_text("ssh-ed25519 AAAA\n")
|
||||
cfg = PolicyConfig(enabled=True, flex_auth_url="http://flex-auth.test")
|
||||
cfg = PolicyConfig(flex_auth_url="http://flex-auth.test")
|
||||
|
||||
mock_response = MagicMock()
|
||||
mock_response.json.return_value = {"effect": "allow", "id": "dec-123"}
|
||||
mock_response.raise_for_status = MagicMock()
|
||||
|
||||
spec = _spec(pubkey)
|
||||
with patch("warden.policy.httpx.post", return_value=mock_response) as post:
|
||||
result = check_sign_policy(cfg, _spec(pubkey))
|
||||
result = check_sign_policy(cfg, spec)
|
||||
|
||||
assert result == "dec-123"
|
||||
assert spec.policy_outcome == "allow"
|
||||
post.assert_called_once()
|
||||
call_kwargs = post.call_args
|
||||
assert call_kwargs[0][0] == "http://flex-auth.test/v1/check"
|
||||
|
|
@ -67,7 +84,7 @@ def test_allow_returns_decision_id(tmp_path):
|
|||
def test_deny_raises_ca_error(tmp_path):
|
||||
pubkey = tmp_path / "key.pub"
|
||||
pubkey.write_text("ssh-ed25519 AAAA\n")
|
||||
cfg = PolicyConfig(enabled=True)
|
||||
cfg = PolicyConfig(flex_auth_url="http://flex-auth.test")
|
||||
|
||||
mock_response = MagicMock()
|
||||
mock_response.json.return_value = {
|
||||
|
|
@ -84,7 +101,10 @@ def test_deny_raises_ca_error(tmp_path):
|
|||
def test_unreachable_fail_closed_raises(tmp_path):
|
||||
pubkey = tmp_path / "key.pub"
|
||||
pubkey.write_text("ssh-ed25519 AAAA\n")
|
||||
cfg = PolicyConfig(enabled=True, fail_closed=True)
|
||||
cfg = PolicyConfig(
|
||||
flex_auth_url="http://flex-auth.test",
|
||||
zone_registry_path=_zone_registry(tmp_path, "z3-critical"),
|
||||
)
|
||||
|
||||
with patch(
|
||||
"warden.policy.httpx.post",
|
||||
|
|
@ -97,7 +117,7 @@ def test_unreachable_fail_closed_raises(tmp_path):
|
|||
def test_unreachable_fail_open_returns_none(tmp_path):
|
||||
pubkey = tmp_path / "key.pub"
|
||||
pubkey.write_text("ssh-ed25519 AAAA\n")
|
||||
cfg = PolicyConfig(enabled=True, fail_closed=False)
|
||||
cfg = PolicyConfig(flex_auth_url="http://flex-auth.test")
|
||||
|
||||
with patch(
|
||||
"warden.policy.httpx.post",
|
||||
|
|
@ -109,7 +129,10 @@ def test_unreachable_fail_open_returns_none(tmp_path):
|
|||
def test_http_error_fail_closed_raises(tmp_path):
|
||||
pubkey = tmp_path / "key.pub"
|
||||
pubkey.write_text("ssh-ed25519 AAAA\n")
|
||||
cfg = PolicyConfig(enabled=True, fail_closed=True)
|
||||
cfg = PolicyConfig(
|
||||
flex_auth_url="http://flex-auth.test",
|
||||
zone_registry_path=_zone_registry(tmp_path, "z3-critical"),
|
||||
)
|
||||
|
||||
mock_response = MagicMock()
|
||||
mock_response.status_code = 403
|
||||
|
|
@ -123,7 +146,7 @@ def test_http_error_fail_closed_raises(tmp_path):
|
|||
|
||||
|
||||
def test_missing_pubkey_raises(tmp_path):
|
||||
cfg = PolicyConfig(enabled=True)
|
||||
cfg = PolicyConfig(flex_auth_url="http://flex-auth.test")
|
||||
spec = _spec(tmp_path / "missing.pub")
|
||||
with pytest.raises(CAError, match="Public key not found"):
|
||||
check_sign_policy(cfg, spec)
|
||||
|
|
@ -132,7 +155,10 @@ def test_missing_pubkey_raises(tmp_path):
|
|||
def test_subject_from_env(tmp_path, monkeypatch):
|
||||
pubkey = tmp_path / "key.pub"
|
||||
pubkey.write_text("ssh-ed25519 AAAA\n")
|
||||
cfg = PolicyConfig(enabled=True, subject_env="WARDEN_POLICY_SUBJECT")
|
||||
cfg = PolicyConfig(
|
||||
flex_auth_url="http://flex-auth.test",
|
||||
subject_env="WARDEN_POLICY_SUBJECT",
|
||||
)
|
||||
monkeypatch.setenv("WARDEN_POLICY_SUBJECT", "iam:bernd")
|
||||
|
||||
mock_response = MagicMock()
|
||||
|
|
@ -212,7 +238,7 @@ def test_sign_policy_sends_authorization_header(tmp_path, monkeypatch):
|
|||
pubkey.write_text("ssh-ed25519 AAAA test\n")
|
||||
|
||||
cfg = PolicyConfig(
|
||||
enabled=True,
|
||||
flex_auth_url="http://flex-auth.test",
|
||||
caller_auth=CallerAuthConfig(mode="file", token_path=token_file),
|
||||
)
|
||||
spec = CertSpec(
|
||||
|
|
@ -250,8 +276,8 @@ def test_sign_policy_fail_closed_when_caller_token_unavailable(tmp_path):
|
|||
pubkey = tmp_path / "id.pub"
|
||||
pubkey.write_text("ssh-ed25519 AAAA test\n")
|
||||
cfg = PolicyConfig(
|
||||
enabled=True,
|
||||
fail_closed=True,
|
||||
flex_auth_url="http://flex-auth.test",
|
||||
zone_registry_path=_zone_registry(tmp_path, "z3-critical"),
|
||||
caller_auth=CallerAuthConfig(mode="file", token_path=tmp_path / "absent"),
|
||||
)
|
||||
spec = CertSpec(
|
||||
|
|
@ -263,3 +289,21 @@ def test_sign_policy_fail_closed_when_caller_token_unavailable(tmp_path):
|
|||
)
|
||||
with pytest.raises(CAError, match="caller identity unavailable"):
|
||||
policy_mod.check_sign_policy(cfg, spec)
|
||||
|
||||
|
||||
def test_advisory_decision_is_recorded_and_does_not_block(tmp_path):
|
||||
pubkey = tmp_path / "id.pub"
|
||||
pubkey.write_text("ssh-ed25519 AAAA test\n")
|
||||
cfg = PolicyConfig(flex_auth_url="http://flex-auth.test")
|
||||
response = MagicMock()
|
||||
response.json.return_value = {
|
||||
"effect": "audit_only",
|
||||
"reason": "advisory_would_deny_disallowed_principal",
|
||||
"id": "decision:advisory",
|
||||
}
|
||||
response.raise_for_status = MagicMock()
|
||||
spec = _spec(pubkey)
|
||||
with patch("warden.policy.httpx.post", return_value=response):
|
||||
assert check_sign_policy(cfg, spec) == "decision:advisory"
|
||||
assert spec.policy_zone == "unknown"
|
||||
assert spec.policy_outcome == "audit_only"
|
||||
|
|
|
|||
|
|
@ -193,7 +193,6 @@ def _warden_yaml(tmp_path: Path) -> Path:
|
|||
(tmp_path / "ca").write_text("")
|
||||
cfg.write_text(
|
||||
f"backend: local\nca_key: {tmp_path/'ca'}\nstate_dir: {tmp_path/'state'}\n"
|
||||
"policy:\n enabled: false\n"
|
||||
)
|
||||
return cfg
|
||||
|
||||
|
|
@ -203,10 +202,11 @@ def _proxy_env(monkeypatch, tmp_path):
|
|||
monkeypatch.setenv("WARDEN_CONFIG", str(_warden_yaml(tmp_path)))
|
||||
|
||||
|
||||
def test_cli_proxy_refuses_without_policy_ack(monkeypatch, tmp_path):
|
||||
def test_cli_proxy_unknown_zone_fail_open_reaches_transport_guard(monkeypatch, tmp_path):
|
||||
_proxy_env(monkeypatch, tmp_path)
|
||||
monkeypatch.setenv("VAULT_TOKEN", "caller")
|
||||
# subprocess must never run if the gate blocks first.
|
||||
# The unknown-zone profile proceeds when no evaluator is configured, then
|
||||
# the independent safe-transport boundary still refuses captured stdout.
|
||||
monkeypatch.setattr(
|
||||
"warden.proxy.subprocess.run",
|
||||
lambda *a, **k: (_ for _ in ()).throw(AssertionError("fetch ran despite gate")),
|
||||
|
|
@ -216,8 +216,8 @@ def test_cli_proxy_refuses_without_policy_ack(monkeypatch, tmp_path):
|
|||
["access", "npm", "--domain", "coulomb_social", "--field", "NPM_AUTH_TOKEN",
|
||||
"--path", "platform/x/y/z", "--fetch"],
|
||||
)
|
||||
assert r.exit_code == 4
|
||||
assert "not enforced" in r.stdout or "not enforced" in str(r.output)
|
||||
assert r.exit_code == 6
|
||||
assert "unknown-zone fail_open" in r.output
|
||||
|
||||
|
||||
def test_cli_proxy_requires_caller_auth(monkeypatch, tmp_path):
|
||||
|
|
@ -228,11 +228,27 @@ def test_cli_proxy_requires_caller_auth(monkeypatch, tmp_path):
|
|||
r = runner.invoke(
|
||||
app,
|
||||
["access", "npm", "--domain", "coulomb_social", "--field", "NPM_AUTH_TOKEN",
|
||||
"--path", "platform/x/y/z", "--fetch", "--no-policy"],
|
||||
"--path", "platform/x/y/z", "--fetch"],
|
||||
)
|
||||
assert r.exit_code == 3
|
||||
|
||||
|
||||
def test_cli_proxy_rejects_retired_no_policy_bypass(monkeypatch, tmp_path):
|
||||
_proxy_env(monkeypatch, tmp_path)
|
||||
monkeypatch.setenv("VAULT_TOKEN", "caller")
|
||||
monkeypatch.setattr(
|
||||
"warden.proxy.subprocess.run",
|
||||
lambda *a, **k: (_ for _ in ()).throw(AssertionError("fetch ran despite retired flag")),
|
||||
)
|
||||
r = runner.invoke(
|
||||
app,
|
||||
["access", "npm", "--domain", "coulomb_social", "--field", "NPM_AUTH_TOKEN",
|
||||
"--path", "platform/x/y/z", "--fetch", "--no-policy"],
|
||||
)
|
||||
assert r.exit_code == 2
|
||||
assert "--no-policy is retired" in r.output
|
||||
|
||||
|
||||
# --- T4: login lane --------------------------------------------------------
|
||||
|
||||
def test_cli_login_lane_runs_without_token_or_policy_ack(monkeypatch, tmp_path):
|
||||
|
|
@ -281,6 +297,7 @@ def test_invalid_lane_rejected(tmp_path):
|
|||
id="x", title="t", need_keywords=["k"], owner_repo="o", subsystem="s",
|
||||
warden_executes=False, wiki_ref="w", canon_ref="c", reviewed="2026-06-27",
|
||||
status="active", lane="bogus",
|
||||
workload_ref={"applicability": "not-applicable", "reason": "fixture"},
|
||||
)
|
||||
p = tmp_path / "c.yaml"
|
||||
p.write_text(yaml.dump({"version": 1, "entries": [entry]}))
|
||||
|
|
@ -361,7 +378,7 @@ def test_access_fetch_to_nonterminal_stdout_is_refused(tmp_path, monkeypatch):
|
|||
lambda *a, **k: (_ for _ in ()).throw(AssertionError("fetch ran despite stdout guard")),
|
||||
)
|
||||
# CliRunner captures stdout (not a tty), so the guard trips without --unsafe-stdout.
|
||||
r = runner.invoke(app, ["access", "whynot-design-npm-publish", "--fetch", "--no-policy"])
|
||||
r = runner.invoke(app, ["access", "whynot-design-npm-publish", "--fetch"])
|
||||
assert r.exit_code == 6
|
||||
assert "sanctioned transport" in r.output.lower() or "refusing" in r.output.lower()
|
||||
|
||||
|
|
@ -378,7 +395,7 @@ def test_access_fingerprint_masks_and_bypasses_stdout_guard(monkeypatch, tmp_pat
|
|||
monkeypatch.setattr("warden.proxy.subprocess.run", lambda *a, **k: _Fake())
|
||||
r = runner.invoke(
|
||||
app,
|
||||
["access", "whynot-design-npm-publish", "--fingerprint", "--no-policy"],
|
||||
["access", "whynot-design-npm-publish", "--fingerprint"],
|
||||
)
|
||||
assert r.exit_code == 0
|
||||
assert "top-secret-token-value" not in r.output # value never shown
|
||||
|
|
@ -395,7 +412,7 @@ def test_access_agent_high_risk_raw_stream_refused(tmp_path, monkeypatch):
|
|||
app,
|
||||
[
|
||||
"access", "railiance-backup-offsite-lane",
|
||||
"--fetch", "--no-policy", "--unsafe-stdout",
|
||||
"--fetch", "--unsafe-stdout",
|
||||
],
|
||||
)
|
||||
assert r.exit_code == 7, r.output
|
||||
|
|
@ -415,7 +432,7 @@ def test_access_agent_high_risk_fingerprint_allowed(tmp_path, monkeypatch):
|
|||
monkeypatch.setattr("warden.proxy.subprocess.run", lambda *a, **k: _Fake())
|
||||
r = runner.invoke(
|
||||
app,
|
||||
["access", "railiance-backup-offsite-lane", "--fingerprint", "--no-policy"],
|
||||
["access", "railiance-backup-offsite-lane", "--fingerprint"],
|
||||
)
|
||||
assert r.exit_code == 0, r.output
|
||||
assert "should-not-appear" not in r.output
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ No test here requires a live subsystem — routing is a read-only pointer layer.
|
|||
"""
|
||||
import json
|
||||
import re
|
||||
from datetime import date
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
|
@ -11,10 +12,9 @@ import yaml
|
|||
from typer.testing import CliRunner
|
||||
|
||||
from warden.cli import app
|
||||
from datetime import date
|
||||
|
||||
from warden.routing import CatalogError, load_catalog
|
||||
from warden.routing.catalog import days_since_review, find_catalog_path, is_review_stale
|
||||
from warden.scorecard import check_catalog_rotation_coverage
|
||||
|
||||
runner = CliRunner()
|
||||
|
||||
|
|
@ -40,6 +40,10 @@ SSH_ENTRY = {
|
|||
"canon_ref": "net-kingdom/docs/x.md",
|
||||
"reviewed": "2026-06-18",
|
||||
"status": "active",
|
||||
"workload_ref": {
|
||||
"applicability": "not-applicable",
|
||||
"reason": "generic certificate action",
|
||||
},
|
||||
"cert_command": "warden sign <actor> --pubkey <path>",
|
||||
"steps": ["confirm inventory", "sign"],
|
||||
}
|
||||
|
|
@ -55,6 +59,10 @@ ROUTED_ENTRY = {
|
|||
"canon_ref": "net-kingdom/docs/x.md",
|
||||
"reviewed": "2026-06-18",
|
||||
"status": "active",
|
||||
"workload_ref": {
|
||||
"applicability": "not-applicable",
|
||||
"reason": "generic credential pattern",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -76,6 +84,45 @@ def test_real_catalog_has_one_executed_lane():
|
|||
assert [e.id for e in executed] == ["ssh-cert-host-access"]
|
||||
|
||||
|
||||
def test_every_catalog_lane_declares_workload_applicability():
|
||||
catalog = load_catalog(_repo_catalog())
|
||||
assert all(entry.workload_ref is not None for entry in catalog.entries)
|
||||
assert {entry.workload_ref.resolution for entry in catalog.entries} == {
|
||||
"resolved", "unknown", "not-applicable"
|
||||
}
|
||||
|
||||
|
||||
def test_managed_and_operational_workload_references_parse():
|
||||
catalog = load_catalog(_repo_catalog())
|
||||
managed = catalog.get("issue-core-ingestion-api-key").workload_ref
|
||||
assert managed.resolution == "resolved"
|
||||
assert (managed.rapp_id, managed.name, managed.deployable) == (
|
||||
"rapp-issue-core", "issue-core", "issue-core"
|
||||
)
|
||||
operational = catalog.get("ops-warden-warden-sign-token").workload_ref
|
||||
assert operational.resolution == "resolved"
|
||||
assert operational.rapp_id is None
|
||||
assert operational.name == "ops-warden"
|
||||
assert operational.declaration_ref == "tenancy.yaml"
|
||||
|
||||
|
||||
def test_workload_reference_rejects_ambiguous_absence(tmp_path):
|
||||
bad = dict(ROUTED_ENTRY)
|
||||
bad.pop("workload_ref")
|
||||
with pytest.raises(CatalogError, match="workload_ref"):
|
||||
load_catalog(_write_catalog(tmp_path, [bad]))
|
||||
|
||||
|
||||
def test_workload_reference_rejects_malformed_managed_target(tmp_path):
|
||||
bad = dict(ROUTED_ENTRY)
|
||||
bad["workload_ref"] = {
|
||||
"applicability": "applicable",
|
||||
"rapp_id": "rapp-issue-core",
|
||||
}
|
||||
with pytest.raises(CatalogError, match="requires name"):
|
||||
load_catalog(_write_catalog(tmp_path, [bad]))
|
||||
|
||||
|
||||
def test_ops_warden_warden_sign_lane_has_native_exec():
|
||||
"""RAILIANCE-WP-0005 T08 — broker lane routes to railiance-platform credential exec."""
|
||||
catalog = load_catalog(_repo_catalog())
|
||||
|
|
@ -454,9 +501,6 @@ def test_every_entry_has_reviewed_date():
|
|||
# Rotation / re-establishment guidance registry (WARDEN-WP-0026 T06)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
from warden.scorecard import check_catalog_rotation_coverage
|
||||
|
||||
|
||||
def test_every_active_vending_lane_has_rotation_guidance():
|
||||
"""Coverage gate: an active lane that vends a secret must say how to renew it."""
|
||||
catalog = load_catalog(_repo_catalog())
|
||||
|
|
@ -774,6 +818,32 @@ def test_unrecognised_grade_is_treated_as_high():
|
|||
assert entry.is_graded is False
|
||||
|
||||
|
||||
def test_ungraded_risk_uses_maturity_derived_zone_default():
|
||||
entry = _bare_entry()
|
||||
assert entry.risk_for_zone(
|
||||
effective_zone="z0-experimental",
|
||||
admission="satisfied",
|
||||
synthetic_only=True,
|
||||
) == "standard"
|
||||
assert entry.risk_for_zone(
|
||||
effective_zone="z0-experimental",
|
||||
admission="unknown",
|
||||
synthetic_only=True,
|
||||
) == "high"
|
||||
assert entry.risk_for_zone(
|
||||
effective_zone="z3-critical",
|
||||
admission="satisfied",
|
||||
) == "critical"
|
||||
assert entry.risk_for_zone(effective_zone="unknown") == "high"
|
||||
|
||||
|
||||
def test_explicit_risk_grade_always_wins_over_zone_default():
|
||||
entry = _bare_entry(risk="standard")
|
||||
assert entry.risk_for_zone(
|
||||
effective_zone="z3-critical", admission="satisfied"
|
||||
) == "standard"
|
||||
|
||||
|
||||
def test_low_risk_vocabulary_is_explicit():
|
||||
for grade in ("standard", "low", "accepted"):
|
||||
entry = _bare_entry(risk=grade)
|
||||
|
|
@ -870,6 +940,11 @@ def test_cli_route_gaps_fail_on_stale_exits_3(repo_catalog_env):
|
|||
assert result.exit_code == 3
|
||||
rows = json.loads(result.stdout)
|
||||
assert any(r["stale"] for r in rows)
|
||||
# A lane can be stale on age or on never having been verified; both must be
|
||||
# expressible, or asked-and-waiting silently passes the gate.
|
||||
assert any(r["stale"] and r["days_since_review"] == 0 for r in rows)
|
||||
# A freshly reviewed lane can still be stale because it was never verified;
|
||||
# asked-and-waiting must not silently pass the gate as the calendar moves.
|
||||
assert any(
|
||||
r["stale"]
|
||||
and r["days_since_review"] <= 1
|
||||
and r["verified"] == "asked-and-waiting"
|
||||
for r in rows
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,10 +1,6 @@
|
|||
"""Tests for EXPOSED taint convention (WARDEN-WP-0026 T05)."""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from typer.testing import CliRunner
|
||||
|
||||
from warden.cli import app
|
||||
|
|
|
|||
52
tests/test_workload_join.py
Normal file
52
tests/test_workload_join.py
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
"""Explicit lane-to-workload join tests (WARDEN-WP-0032 / RMGR-WP-0010-T06)."""
|
||||
from pathlib import Path
|
||||
|
||||
import yaml
|
||||
|
||||
from scripts.report_workload_join import build
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
|
||||
|
||||
def test_repo_catalog_uses_only_explicit_workload_references():
|
||||
report = build(ROOT / "registry/routing/catalog.yaml", Path.home())
|
||||
assert report["ok"] is True
|
||||
assert len(report["resolved"]) == 3
|
||||
assert len(report["unknown"]) == 17
|
||||
assert len(report["not_applicable"]) == 7
|
||||
assert {row["lane"] for row in report["resolved"]} == {
|
||||
"ops-warden-warden-sign-token",
|
||||
"issue-core-ingestion-api-key",
|
||||
"rapp-qonto-keycape-client",
|
||||
}
|
||||
|
||||
|
||||
def test_invalid_exact_deployable_resolves_unknown(tmp_path):
|
||||
rapp = tmp_path / "rapp-x" / "declarations"
|
||||
rapp.mkdir(parents=True)
|
||||
(rapp / "rapp.yaml").write_text(yaml.safe_dump({
|
||||
"rapp_id": "rapp-x",
|
||||
"workload_identity": {"name": "x"},
|
||||
"composition": {"member_repos": [{"deployables": ["api"]}]},
|
||||
}))
|
||||
catalog_dir = tmp_path / "ops-warden" / "registry" / "routing"
|
||||
catalog_dir.mkdir(parents=True)
|
||||
catalog = catalog_dir / "catalog.yaml"
|
||||
catalog.write_text(yaml.safe_dump({"entries": [{
|
||||
"id": "x",
|
||||
"workload_ref": {
|
||||
"applicability": "applicable",
|
||||
"rapp_id": "rapp-x",
|
||||
"name": "x",
|
||||
"deployable": "missing",
|
||||
},
|
||||
}]}))
|
||||
posture = catalog_dir.parent / "policy"
|
||||
posture.mkdir()
|
||||
(posture / "security-posture.yaml").write_text("dataclass_floor: {}\n")
|
||||
|
||||
report = build(catalog, tmp_path)
|
||||
assert not report["resolved"]
|
||||
assert report["unknown"][0]["lane"] == "x"
|
||||
assert "deployable" in report["unknown"][0]["reason"]
|
||||
Loading…
Add table
Add a link
Reference in a new issue