Fix contained OpenBao login handoff
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s

Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a058f3-8ba0-7692-a042-9a870fc3d663
This commit is contained in:
tegwick 2026-09-01 00:13:26 +02:00
parent 4e267179db
commit b4c1d3900a
3 changed files with 81 additions and 6 deletions

View file

@ -12,8 +12,9 @@ intact. Three guardrails are enforced here in code:
the tool with inherited stdout/stderr so the value never enters warden's memory;
sanctioned exec/file transports hold it only for their bounded handoff. The
high-risk attended-login lane is stricter: it captures every client byte inside
an isolated helper session, permits no output, self-revokes, and cleans up. Audit
records are metadata only.
an isolated helper session, never returns that output, requires successful
persistence to a private token helper, self-revokes, and cleans up. Audit records
are metadata only.
* **G3 policy gate before fetch.** The CLI runs ``check_fetch_policy`` before
calling anything here; this module refuses to run an unresolved command template.
@ -380,9 +381,11 @@ def proxy_attended_login_exec(
"""Run an attended login and one silent child inside a private helper home.
The default home is proven writable before the OIDC client starts. Login,
child, and revocation output are captured and discarded. Any non-empty output,
persistence defect, or non-zero result fails closed; any possibly issued token
is revoked before the isolated helper directory is removed.
child, and revocation output are captured and discarded. A successful login
may return client output only after the private helper has been populated;
persistence defects and non-zero results fail closed. The reviewed child must
remain silent. Any possibly issued token is revoked before the isolated helper
directory is removed.
"""
if not child_argv:
raise ProxyError(
@ -428,7 +431,7 @@ def proxy_attended_login_exec(
except (OSError, ProxyError):
helper_valid = False
if login.returncode != 0 or login_output.strip() or not helper_valid:
if login.returncode != 0 or not helper_valid:
revoked = _revoke_contained(
resolved.argv[0], env=env, possible_output=login_output
)

View file

@ -391,6 +391,42 @@ def test_attended_login_unexpected_output_is_contained_revoked_and_cleaned(
assert not (tmp_path / ".warden-attended-login").exists()
def test_attended_login_contained_success_output_never_escapes(monkeypatch, tmp_path, capsys):
monkeypatch.setattr(Path, "home", lambda: tmp_path)
sentinel = "hvs.NONPRODUCTION_CONTAINED_LOGIN"
child_ran = False
def fake_run(argv, **kw):
nonlocal child_ran
helper = Path(kw["env"]["HOME"]) / ".vault-token"
if argv[:2] == ["bao", "login"]:
helper.write_text(sentinel)
helper.chmod(0o600)
return subprocess.CompletedProcess(
argv,
0,
stdout=json.dumps({"auth": {"client_token": sentinel}}).encode(),
stderr=b"",
)
if argv == ["reviewed-child"]:
child_ran = True
return subprocess.CompletedProcess(argv, 0, stdout=b"", stderr=b"")
if argv[:3] == ["bao", "token", "revoke"]:
return subprocess.CompletedProcess(argv, 0, stdout=b"", stderr=b"")
raise AssertionError(argv)
monkeypatch.setattr("warden.proxy.subprocess.run", fake_run)
assert proxy_attended_login_exec(
ResolvedFetch(argv=["bao", "login", "-no-print"]),
child_argv=["reviewed-child"],
) == 0
captured = capsys.readouterr()
assert child_ran is True
assert sentinel not in captured.out
assert sentinel not in captured.err
assert not (tmp_path / ".warden-attended-login").exists()
def test_real_catalog_login_entry_is_login_lane():
from warden.routing import load_catalog
e = load_catalog(_repo_catalog()).get("key-cape-oidc-login")

View file

@ -0,0 +1,36 @@
---
id: WARDEN-WP-0034
type: workplan
title: "Accept contained OpenBao login output only after helper persistence"
domain: infotech
repo: ops-warden
status: active
owner: codex
topic_slug: attended-login-openbao-output
created: "2026-09-01"
updated: "2026-09-01"
---
## Repair attended-login handoff
```task
id: WARDEN-WP-0034-T01
status: done
priority: high
```
Allow a successful OpenBao login to proceed when its output is fully contained
and the private mode-0600 token helper is populated. Continue failing closed on
non-zero login, missing persistence, child output, revocation failure, or cleanup
failure.
## Verify live contained operation
```task
id: WARDEN-WP-0034-T02
status: progress
priority: high
```
Run the proxy regression suite, reinstall the CLI, and complete one governed
OpenBao platform-admin operation with deterministic self-revocation.