fix(auth): authenticate producer-signed decisions before authorization
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-astra
Assistant-Session: 01a140c4-354a-7823-8f0d-8f717397f786
This commit is contained in:
tegwick 2026-10-16 07:51:44 +02:00
parent 6bd7129eac
commit c80a944105
30 changed files with 2059 additions and 32 deletions

View file

@ -22,7 +22,8 @@ from secrets_engine.approval_auth import approval_auth_configured, approval_toke
from secrets_engine.execution_contract import ExecutionContract, require_execution_deadline
from secrets_engine.approval_claim import observe_pdp_approval_claim, validate_approval_claim
from secrets_engine.catalog import human_control_required
from secrets_engine.decision_check import check_decision
from secrets_engine.decision_check import check_decision, require_supported_pdp_address
from secrets_engine.decision_signature import load_trust
from secrets_engine.authorization import (
build_action_request,
validate_decision_envelope,
@ -300,6 +301,16 @@ def authorize_action(
configured at all, which leaves production fail-closed. A configured but
failing path raises: a partial deployment must not read as an absent one.
"""
serving = (getattr(cfg, "approval_url", "") and approval_auth_configured(cfg)
and _authorization_id(entry, decision))
if serving or (getattr(cfg, "pdp_url", "") and getattr(cfg, "pdp_token_file", None)):
if not getattr(cfg, "pdp_url", "") or not getattr(cfg, "pdp_token_file", None):
raise DecisionError("production action requires configured access-engine URL/token and responder trust")
require_supported_pdp_address(str(cfg.pdp_url))
load_trust(getattr(cfg, "pdp_trust_file", None))
verifier = getattr(cfg, "pdp_verifier", None)
if verifier is None or not Path(verifier).is_absolute() or not Path(verifier).is_file():
raise DecisionError("access-engine signature verifier is not installed")
observation = resolve_approval_observation(
cfg, entry, action, decision,
fields=fields,
@ -333,6 +344,8 @@ def authorize_action(
token_file=Path(pdp_token),
request=expected_request,
opener=pdp_opener,
trust_file=getattr(cfg, "pdp_trust_file", None),
verifier=getattr(cfg, "pdp_verifier", None),
)
if not getattr(cfg, "clock_trust_file", None):
wait_for_decision_start(envelope)