Keep ambient tokens out of the service-JWT OpenBao login
The anonymous JWT login inherited BAO_TOKEN/VAULT_TOKEN and the bao CLI token helper, so it presented an env/operator token alongside the JWT. Run that login with no env token and a token helper that returns none, proven against the real bao CLI. This closes secrets-engine's part of the CCR-2026-0038 no-fallback check. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 544698@bnt-lap001 Assistant-Session: 279b8520-335f-4041-ba2a-9491335473db
This commit is contained in:
parent
1732c419d2
commit
9ec4e0bea5
4 changed files with 112 additions and 19 deletions
|
|
@ -105,7 +105,8 @@ def test_login_jwt_keeps_jwt_out_of_argv_and_revokes(monkeypatch):
|
|||
client = OpenBaoClient(addr="http://example.invalid", token="", bao_bin="bao")
|
||||
captured = {}
|
||||
|
||||
def fake_json_call(args, payload):
|
||||
def fake_json_call(args, payload, *, anonymous=False):
|
||||
captured["anonymous"] = anonymous
|
||||
captured["args"] = list(args)
|
||||
captured["payload"] = dict(payload)
|
||||
return '{"auth":{"client_token":"jwt-child-token","accessor":"jwt-accessor"}}'
|
||||
|
|
@ -114,6 +115,7 @@ def test_login_jwt_keeps_jwt_out_of_argv_and_revokes(monkeypatch):
|
|||
session = client.login_jwt("jwt", "secrets-engine", "header.payload.sig")
|
||||
assert "header.payload.sig" not in " ".join(captured["args"])
|
||||
assert captured["payload"]["jwt"] == "header.payload.sig"
|
||||
assert captured["anonymous"] is True
|
||||
assert "jwt-accessor" not in session.accessor_fingerprint
|
||||
revoke = []
|
||||
monkeypatch.setattr(
|
||||
|
|
@ -151,3 +153,27 @@ def test_provision_jwt_auth_never_reaches_openbao_on_missing_contract(
|
|||
cfg = _cfg(tmp_path)
|
||||
with pytest.raises(BackendError, match="JWT mount/role contract is not published"):
|
||||
cli.cmd_provision(cfg, args)
|
||||
|
||||
|
||||
def test_login_jwt_presents_no_ambient_env_or_helper_token(monkeypatch):
|
||||
monkeypatch.setenv("BAO_TOKEN", "env-token-must-not-be-sent")
|
||||
monkeypatch.setenv("VAULT_TOKEN", "env-token-must-not-be-sent")
|
||||
seen = {}
|
||||
|
||||
def fake_run(argv, **kwargs):
|
||||
env = kwargs["env"]
|
||||
seen["env"] = dict(env)
|
||||
seen["helper_config"] = open(env["BAO_CONFIG_PATH"], encoding="utf-8").read()
|
||||
return SimpleNamespace(
|
||||
returncode=0,
|
||||
stdout='{"auth":{"client_token":"jwt-child-token","accessor":"jwt-accessor"}}',
|
||||
stderr="",
|
||||
)
|
||||
|
||||
monkeypatch.setattr("secrets_engine.openbao.subprocess.run", fake_run)
|
||||
client = OpenBaoClient(addr="http://example.invalid", token="", bao_bin="bao")
|
||||
client.login_jwt("jwt", "secrets-engine", "header.payload.sig")
|
||||
assert "BAO_TOKEN" not in seen["env"]
|
||||
assert "VAULT_TOKEN" not in seen["env"]
|
||||
assert seen["env"]["VAULT_CONFIG_PATH"] == seen["env"]["BAO_CONFIG_PATH"]
|
||||
assert seen["helper_config"].startswith('token_helper = "')
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue