Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a09cbb-87c6-7900-a145-4ce53ba9f1a6
53 lines
3.1 KiB
Python
53 lines
3.1 KiB
Python
from datetime import datetime, timezone, timedelta
|
|
from types import SimpleNamespace
|
|
import pytest
|
|
from railiance_clock.core import Window, unix_ns
|
|
from secrets_engine.application_time import read_window, validity_bounds, recheck_binding
|
|
from secrets_engine.approval_claim import validate_approval_claim
|
|
from secrets_engine.authorization import validate_decision_envelope
|
|
from secrets_engine.approval_consume import ConsumeBinding
|
|
from secrets_engine.errors import DecisionError
|
|
from tests.test_approval_claim import _claim, _binding, APPROVAL_ID, claim_binding_digest
|
|
from tests.test_decision_replay import pair
|
|
|
|
|
|
def window(lower, upper):
|
|
return Window(unix_ns(lower),unix_ns(upper),'test-authority','epoch','test-policy','sample')
|
|
|
|
|
|
def test_claim_uses_interval_not_workstation_time():
|
|
claim=_claim();start=datetime(2030,1,1,tzinfo=timezone.utc)
|
|
claim['validity']={'not_before':start.isoformat(),'expires_at':(start+timedelta(seconds=30)).isoformat()}
|
|
claim['freshness']['not_after']=(start+timedelta(seconds=10)).isoformat()
|
|
kw=dict(approval_id=APPROVAL_ID,expected_binding_digest=claim_binding_digest(**_binding()))
|
|
validate_approval_claim(claim,time_window=window(start+timedelta(seconds=1),start+timedelta(seconds=2)),**kw)
|
|
with pytest.raises(DecisionError):validate_approval_claim(claim,time_window=window(start-timedelta(seconds=1),start+timedelta(seconds=1)),**kw)
|
|
with pytest.raises(DecisionError):validate_approval_claim(claim,time_window=window(start+timedelta(seconds=9),start+timedelta(seconds=10)),**kw)
|
|
|
|
|
|
def test_producer_decision_interval_boundary():
|
|
request,decision=pair('rotate')
|
|
start=datetime.fromisoformat(decision['lifetime']['not_before'].replace('Z','+00:00'))
|
|
end=datetime.fromisoformat(decision['lifetime']['expires_at'].replace('Z','+00:00'))
|
|
kw=dict(accepted_policy_packages={'secrets-engine.catalog-lane.lifecycle'},accepted_policy_versions={'v2'})
|
|
validate_decision_envelope(decision,request,time_window=window(start,start+timedelta(seconds=1)),**kw)
|
|
with pytest.raises(DecisionError):validate_decision_envelope(decision,request,time_window=window(start-timedelta(microseconds=1),start+timedelta(seconds=1)),**kw)
|
|
with pytest.raises(DecisionError):validate_decision_envelope(decision,request,time_window=window(end-timedelta(seconds=1),end),**kw)
|
|
|
|
|
|
def test_configured_missing_trust_never_falls_back(tmp_path):
|
|
with pytest.raises(DecisionError):read_window(SimpleNamespace(clock_trust_file=tmp_path/'missing.json'))
|
|
assert read_window(SimpleNamespace(clock_trust_file=None)) is None
|
|
|
|
|
|
def test_no_mixing_shifted_now_and_interval():
|
|
now=datetime.now(timezone.utc)
|
|
with pytest.raises(DecisionError):validity_bounds(now,window(now,now))
|
|
|
|
|
|
def test_consume_rechecks_expiry(monkeypatch):
|
|
now=datetime.now(timezone.utc)
|
|
cfg=SimpleNamespace(clock_trust_file='configured')
|
|
binding=ConsumeBinding('approval','sha256:'+'a'*64,decision_expires_at=now.isoformat())
|
|
monkeypatch.setattr('secrets_engine.application_time.read_window',lambda cfg:window(now,now+timedelta(seconds=1)))
|
|
with pytest.raises(DecisionError):recheck_binding(cfg,binding)
|