Bind wrapped issuance to native metadata and preserve immutable recipient attempts
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-6.1-sol
Assistant-Session: 01a126e1-76f8-7643-8cf3-e93336539ade
This commit is contained in:
tegwick 2026-10-12 00:11:49 +02:00
parent 58129de8f1
commit 0db6adef69
8 changed files with 288 additions and 46 deletions

View file

@ -65,13 +65,17 @@ def test_wrap_kv_writes_0600_file_and_omits_token_from_result(tmp_path):
assert WRAP_ACCESSOR not in result.wrap_handle
def test_wrap_rejects_repo_paths():
def test_wrap_rejects_repo_paths(tmp_path):
import subprocess
repository = tmp_path / "repository"
repository.mkdir()
subprocess.run(["git", "init", str(repository)], check=True, capture_output=True)
entry = validate_entry(copy.deepcopy(VALID))
with pytest.raises(ProvisioningError, match="Git worktree"):
write_wrapped_handoff(
FakeWrapClient(),
entry,
out_file=__import__("pathlib").Path("wrap.token"),
out_file=repository / "wrap.token",
ttl="15m",
)
@ -96,6 +100,7 @@ def test_parse_wrap_accepts_wrap_info_only():
"token": WRAP_TOKEN,
"accessor": WRAP_ACCESSOR,
"ttl": 900,
"creation_path": "secret/x",
}
}
)
@ -116,7 +121,7 @@ def test_wrap_kv_get_uses_wrap_ttl_flag(monkeypatch):
return SimpleNamespace(
returncode=0,
stdout=json.dumps(
{"wrap_info": {"token": WRAP_TOKEN, "accessor": WRAP_ACCESSOR}}
{"wrap_info": {"token": WRAP_TOKEN, "accessor": WRAP_ACCESSOR, "ttl": 900, "creation_path": "secret/data/test/team/thing"}}
),
stderr="",
)
@ -158,3 +163,93 @@ def test_production_wrap_fails_closed(tmp_path, monkeypatch):
)
with pytest.raises(DecisionError, match="production action 'wrap'"):
cli.cmd_wrap(cfg, args)
@pytest.mark.parametrize('change', [
{'creation_path':'secret/data/other-recipient'}, {'creation_path':None},
{'ttl':901}, {'ttl':60}, {'ttl':True}, {'ttl':None},
{'token':42}, {'token':'value with whitespace'}, {'accessor':None},
])
def test_native_wrap_binding_cannot_be_inferred_from_request(change):
client=OpenBaoClient(addr='http://example.invalid',token='t',bao_bin='bao')
value={'token':WRAP_TOKEN,'accessor':WRAP_ACCESSOR,'ttl':900,'creation_path':'secret/data/test/team/thing'}
value.update(change)
with pytest.raises(BackendError) as raised:
client._parse_wrap_response(json.dumps({'wrap_info':value}),ttl='15m',creation_path='secret/data/test/team/thing')
assert WRAP_TOKEN not in str(raised.value)
def test_valid_wrap_info_cannot_mask_unwrapped_payload():
client=OpenBaoClient(addr='http://example.invalid',token='t',bao_bin='bao')
value={'wrap_info':{'token':WRAP_TOKEN,'accessor':WRAP_ACCESSOR,'ttl':900,'creation_path':'secret/x'},'data':{'secret':'NEVER-LOG-ME'}}
with pytest.raises(BackendError) as raised:
client._parse_wrap_response(json.dumps(value),ttl='15m',creation_path='secret/x')
assert 'NEVER-LOG-ME' not in str(raised.value)
def test_existing_output_prevents_mint_and_preserves_original(tmp_path):
out=tmp_path/'wrap.token';out.write_text('previous trial');out.chmod(0o600)
client=FakeWrapClient()
with pytest.raises(ProvisioningError,match='already exists'):
write_wrapped_handoff(client,validate_entry(copy.deepcopy(VALID)),out_file=out,ttl='60s')
assert client.calls==[] and out.read_text()=='previous trial'
def test_leaf_and_parent_symlink_cannot_redirect_handoff(tmp_path):
from pathlib import Path
target=tmp_path/'retained';target.write_text('private existing');target.chmod(0o600)
out=tmp_path/'wrap.token';out.symlink_to(target)
client=FakeWrapClient();entry=validate_entry(copy.deepcopy(VALID))
with pytest.raises(ProvisioningError):write_wrapped_handoff(client,entry,out_file=out,ttl='60s')
folder=tmp_path/'private';folder.mkdir(mode=0o700)
parent=tmp_path/'redirect';parent.symlink_to(folder,target_is_directory=True)
with pytest.raises(ProvisioningError):write_wrapped_handoff(client,entry,out_file=parent/'wrap.token',ttl='60s')
assert client.calls==[] and target.read_text()=='private existing'
def test_backend_failure_retains_private_reservation_and_prevents_remint(tmp_path):
class Failed(FakeWrapClient):
def wrap_kv_get(self,*args,**kwargs):
self.calls.append('attempt');raise BackendError('unverified native mint')
client=Failed();out=tmp_path/'wrap.token';entry=validate_entry(copy.deepcopy(VALID))
with pytest.raises(BackendError):write_wrapped_handoff(client,entry,out_file=out,ttl='60s')
assert out.exists() and out.read_bytes()==b'' and out.stat().st_mode&0o077==0
with pytest.raises(ProvisioningError):write_wrapped_handoff(client,entry,out_file=out,ttl='60s')
assert client.calls==['attempt']
def test_shared_output_directory_refuses_before_backend(tmp_path):
parent=tmp_path/'shared';parent.mkdir(mode=0o755);client=FakeWrapClient()
with pytest.raises(ProvisioningError,match='owned and private'):
write_wrapped_handoff(client,validate_entry(copy.deepcopy(VALID)),out_file=parent/'wrap.token',ttl='60s')
assert client.calls==[]
def test_concurrent_handoff_reserves_before_only_one_backend_mint(tmp_path):
from concurrent.futures import ThreadPoolExecutor
import threading
entered,release=threading.Event(),threading.Event()
class Paused(FakeWrapClient):
def wrap_kv_get(self,*args,**kwargs):
entered.set();assert release.wait(5)
return super().wrap_kv_get(*args,**kwargs)
client=Paused();entry=validate_entry(copy.deepcopy(VALID));out=tmp_path/'wrap.token'
with ThreadPoolExecutor(max_workers=2) as pool:
first=pool.submit(write_wrapped_handoff,client,entry,out_file=out,ttl='60s')
assert entered.wait(5)
try:
with pytest.raises(ProvisioningError):write_wrapped_handoff(client,entry,out_file=out,ttl='60s')
finally:release.set()
first.result()
assert len(client.calls)==1 and out.read_text().strip()==WRAP_TOKEN
def test_output_replacement_during_backend_call_does_not_overwrite_other_recipient(tmp_path):
out=tmp_path/'wrap.token';other=tmp_path/'other';other.write_text('retained recipient')
class Replaced(FakeWrapClient):
def wrap_kv_get(self,*args,**kwargs):
out.unlink();out.symlink_to(other)
return super().wrap_kv_get(*args,**kwargs)
client=Replaced()
with pytest.raises(ProvisioningError,match='reservation changed'):
write_wrapped_handoff(client,validate_entry(copy.deepcopy(VALID)),out_file=out,ttl='60s')
assert other.read_text()=='retained recipient' and len(client.calls)==1

View file

@ -0,0 +1,24 @@
"""Real wrapping semantics in a disposable local OpenBao, not estate authority."""
import json
import re
from secrets_engine.openbao import OpenBaoClient
from tests.test_integration_bao import bao_dev, pytestmark # noqa: F401
def test_native_wrap_path_ttl_and_one_time_unwrap(bao_dev):
written=bao_dev._run(['kv','put','-format=json','secret/d3-wrap-fixture',
'marker=synthetic-wrapped-integration-value'])
assert written.returncode==0
wrapped=bao_dev.wrap_kv_get('secret','d3-wrap-fixture',ttl='60s')
assert wrapped.creation_path=='secret/data/d3-wrap-fixture'
assert wrapped.ttl=='60'
assert wrapped.wrap_token not in repr(wrapped) and wrapped.wrap_token not in json.dumps(wrapped.evidence())
recipient=OpenBaoClient(addr=bao_dev.addr,token=wrapped.wrap_token,bao_bin=bao_dev.bao_bin)
first=recipient._run(['unwrap','-format=json'])
assert first.returncode==0
assert json.loads(first.stdout)['data']['data']['marker']=='synthetic-wrapped-integration-value'
replay=recipient._run(['unwrap','-format=json'])
assert replay.returncode==2 and not replay.stdout.strip()
assert re.search(r'Code:\s*400\b',replay.stderr)
assert '* wrapping token is not valid or does not exist' in replay.stderr