secrets-engine/tests/test_guards.py
tegwick a852d3f1ff feat(mvp): working secrets-engine CLI for the whynot-design npm publish lane
Implements SECRETS-WP-0002 end to end as a uv-managed Python package:

- catalog: non-secret lane registry + strict validator (build/test/prod)
- stage roles + OpenBao ACL policies; guards refuse wildcards, sys/, identity/,
  admin names, and cross-stage paths before any backend call
- plan/apply: dry-run-first, idempotent policy + approle apply, decision-gated
- decisions: State Hub lookup with local-fixture fallback; non-secret evidence
  to JSONL + hub progress, scrubbed of any value
- provision/verify: mode-0600 file import + generated test values; positive/
  negative checks that never print the value
- exec delivery: `exec --catalog ... -- npm publish` injects the token via a
  temp .npmrc for the child only, cleaned up on exit/failure/interrupt
- ops-warden routing contract + hardening backlog docs
- 34 tests incl. live OpenBao integration; scripts/demo-e2e.sh runs the full
  chain against a throwaway bao dev server

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 12:28:45 +02:00

67 lines
2 KiB
Python

"""Negative checks: a plan that would grant broad power must fail closed."""
import pytest
from secrets_engine.catalog import validate_entry
from secrets_engine.errors import PolicyGuardError
from secrets_engine.plan import build_plan
from secrets_engine.roles import assert_path_in_stage, assert_policy_safe
from tests.test_catalog import VALID
def _entry(**over):
d = dict(VALID)
d.update(over)
return validate_entry(d)
def test_wildcard_policy_path_refused():
with pytest.raises(PolicyGuardError):
assert_policy_safe("se-test-x", {"secret/*": ["read"]})
def test_sys_path_refused():
with pytest.raises(PolicyGuardError):
assert_policy_safe("se-test-x", {"sys/policies/acl/x": ["read"]})
def test_identity_path_refused():
with pytest.raises(PolicyGuardError):
assert_policy_safe("se-test-x", {"identity/entity/x": ["read"]})
def test_admin_policy_name_refused():
with pytest.raises(PolicyGuardError):
assert_policy_safe("platform-admin", {"secret/data/x": ["read"]})
def test_broad_capability_refused():
with pytest.raises(PolicyGuardError):
assert_policy_safe("se-test-x", {"secret/data/x": ["sudo"]})
def test_out_of_stage_path_refused():
# a 'test' lane pointing into the build prefix is rejected
e = _entry(stage="test", path="build/sneaky/thing")
with pytest.raises(PolicyGuardError):
assert_path_in_stage(e)
def test_build_lane_must_use_build_prefix():
e = _entry(stage="build", path="random/thing")
with pytest.raises(PolicyGuardError):
assert_path_in_stage(e)
def test_stage_mismatch_in_plan_refused():
e = _entry(stage="test", path="test/team/thing")
with pytest.raises(PolicyGuardError):
build_plan(e, "prod")
def test_valid_plan_builds():
e = _entry(stage="test", path="test/team/thing")
plan = build_plan(e, "test", decision_id="d1")
assert plan.policy_name == "se-test-test-lane"
assert any(a.kind == "approle" for a in plan.actions)
assert "secret/data/test/team/thing" in plan.policy_hcl