Fix contained OpenBao login handoff
Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a058f3-8ba0-7692-a042-9a870fc3d663
This commit is contained in:
parent
4e267179db
commit
b4c1d3900a
3 changed files with 81 additions and 6 deletions
|
|
@ -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;
|
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
|
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
|
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
|
an isolated helper session, never returns that output, requires successful
|
||||||
records are metadata only.
|
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
|
* **G3 — policy gate before fetch.** The CLI runs ``check_fetch_policy`` before
|
||||||
calling anything here; this module refuses to run an unresolved command template.
|
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.
|
"""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,
|
The default home is proven writable before the OIDC client starts. Login,
|
||||||
child, and revocation output are captured and discarded. Any non-empty output,
|
child, and revocation output are captured and discarded. A successful login
|
||||||
persistence defect, or non-zero result fails closed; any possibly issued token
|
may return client output only after the private helper has been populated;
|
||||||
is revoked before the isolated helper directory is removed.
|
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:
|
if not child_argv:
|
||||||
raise ProxyError(
|
raise ProxyError(
|
||||||
|
|
@ -428,7 +431,7 @@ def proxy_attended_login_exec(
|
||||||
except (OSError, ProxyError):
|
except (OSError, ProxyError):
|
||||||
helper_valid = False
|
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(
|
revoked = _revoke_contained(
|
||||||
resolved.argv[0], env=env, possible_output=login_output
|
resolved.argv[0], env=env, possible_output=login_output
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -391,6 +391,42 @@ def test_attended_login_unexpected_output_is_contained_revoked_and_cleaned(
|
||||||
assert not (tmp_path / ".warden-attended-login").exists()
|
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():
|
def test_real_catalog_login_entry_is_login_lane():
|
||||||
from warden.routing import load_catalog
|
from warden.routing import load_catalog
|
||||||
e = load_catalog(_repo_catalog()).get("key-cape-oidc-login")
|
e = load_catalog(_repo_catalog()).get("key-cape-oidc-login")
|
||||||
|
|
|
||||||
36
workplans/WARDEN-WP-0034-attended-login-openbao-output.md
Normal file
36
workplans/WARDEN-WP-0034-attended-login-openbao-output.md
Normal 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.
|
||||||
Loading…
Add table
Add a link
Reference in a new issue