secrets-engine/src/secrets_engine/execution_contract.py
tegwick 4dd004a225
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Verify normalized task approval facts and preserve signed source types
Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a140c4-354a-7823-8f0d-8f717397f786
2026-10-16 17:28:03 +02:00

188 lines
7.9 KiB
Python

"""Closed, immutable metadata descriptor; shape is never execution authority.
This source-only compiler input cannot grant an action, authenticate a principal,
prove owner source authenticity or open a backend. Those integration gates remain
outside this type. Existing actions cannot borrow the new descriptor.
"""
from __future__ import annotations
import copy
import hashlib
import json
import re
from dataclasses import dataclass
from datetime import datetime
from pathlib import PurePosixPath
from urllib.parse import urlsplit
from uuid import UUID
from secrets_engine.errors import DecisionError
VERSION = "SECRETS-EXEC-20261011-v1"
HASH = re.compile(r"^sha256:[0-9a-f]{64}$")
KEYS = {
"contract_version", "operation_id", "operation", "execution_actor", "ccr_id",
"ccr_immutable_sha256", "execution_grant_ccr_id", "grant_immutable_sha256",
"catalog_sha256", "source_bundle", "backend_origin", "cluster_uid",
"operations", "operation_deadline", "backend_budget", "expected_before",
"expected_after",
}
SOURCE_ROLES = {"engine_dispatcher", "platform_mediator", "typed_ccr", "policy_auth"}
def _refuse() -> None:
# Do not interpolate untrusted descriptors into messages/evidence.
raise DecisionError("invalid execution_contract descriptor")
def _closed(value, keys):
if type(value) is not dict or set(value) != set(keys):
_refuse()
return value
def _text(value):
if type(value) is not str or not value or len(value) > 4096 or any(ord(c) < 32 for c in value):
_refuse()
return value
def _hash(value):
if type(value) is not str or not HASH.fullmatch(value):
_refuse()
def _path(value, *, absolute=False):
_text(value)
if (value.startswith("/") != absolute or "\\" in value or "%" in value
or "?" in value or "#" in value or ":" in value
or any(p in {"", ".", ".."} for p in value.lstrip("/").split("/"))
or str(PurePosixPath(value)) != value):
_refuse()
def _validated(value):
value = copy.deepcopy(_closed(value, KEYS))
if value['contract_version'] != VERSION or value['operation'] != 'metadata-apply-ccr' or value['execution_actor'] != 'service:secrets-engine':
_refuse()
try:
if str(UUID(_text(value['operation_id']))) != value['operation_id']:
_refuse()
except (ValueError, AttributeError):
_refuse()
for key in ['ccr_id', 'execution_grant_ccr_id', 'cluster_uid']:
_text(value[key])
if value['ccr_id'] == value['execution_grant_ccr_id']:
_refuse()
for key in ['ccr_immutable_sha256', 'grant_immutable_sha256', 'catalog_sha256', 'expected_before', 'expected_after']:
_hash(value[key])
sources = _closed(value['source_bundle'], SOURCE_ROLES)
for source in sources.values():
_closed(source, {'path', 'sha256'})
_path(source['path'], absolute=True)
_hash(source['sha256'])
try:
origin = urlsplit(_text(value['backend_origin']))
if (origin.scheme not in {'http', 'https'} or not origin.hostname
or origin.username is not None or origin.password is not None
or origin.path or origin.query or origin.fragment or origin.port is None):
_refuse()
except ValueError:
_refuse()
try:
deadline = datetime.fromisoformat(_text(value['operation_deadline']).replace('Z', '+00:00'))
if deadline.tzinfo is None:
_refuse()
except ValueError:
_refuse()
budget = _closed(value['backend_budget'], {'ttl_seconds', 'uses'})
if (type(budget['ttl_seconds']) is not int or not 30 <= budget['ttl_seconds'] <= 120
or type(budget['uses']) is not int or not 1 <= budget['uses'] <= 12):
_refuse()
operations = value['operations']
if type(operations) is not list or not 1 <= len(operations) < budget['uses']:
_refuse() # Reserve at least one cleanup use; no silent retries.
for operation in operations:
_closed(operation, {'method', 'path', 'payload_sha256'})
if type(operation['method']) is not str or operation['method'] not in {'GET', 'PUT'}:
_refuse()
_path(operation['path'])
# Only metadata pilot endpoint shapes, never KV/mount/token/secretid.
if not re.fullmatch(r'(sys/policies/acl/[A-Za-z0-9_-]+|auth/[A-Za-z0-9_-]+/role/[A-Za-z0-9_-]+)', operation['path']):
_refuse()
_hash(operation['payload_sha256'])
return value
def catalog_target_digest(target: dict) -> str:
"""Descriptor-local sorted JSON fingerprint, distinct from PDP digest."""
encoded = json.dumps(target, sort_keys=True, ensure_ascii=False, allow_nan=False,
separators=(',', ':')).encode('utf-8')
return 'sha256:' + hashlib.sha256(encoded).hexdigest()
@dataclass(frozen=True)
class ExecutionContract:
_serialized: str
@classmethod
def parse(cls, descriptor: dict) -> 'ExecutionContract':
validated = _validated(descriptor)
return cls(json.dumps(validated, sort_keys=True, separators=(',', ':'), allow_nan=False))
def as_dict(self) -> dict:
# Revalidate even a directly constructed instance: no trusted label bypass.
try:
return _validated(json.loads(self._serialized))
except (ValueError, TypeError, RecursionError):
_refuse()
def attach_execution_contract(request: dict, contract: ExecutionContract | None) -> None:
action = request['action']
if action != 'execute-ccr':
if contract is not None:
raise DecisionError('execution_contract requires execute-ccr action')
return
if type(contract) is not ExecutionContract:
raise DecisionError('execute-ccr requires typed execution_contract')
value = contract.as_dict()
if request['resource']['attributes']['stage'] != 'prod':
raise DecisionError('execute-ccr requires prod stage')
if request['tenant'] != 'tenant:platform':
raise DecisionError('execute-ccr requires platform tenant')
if value['catalog_sha256'] != catalog_target_digest(request['context']['catalog_target']):
raise DecisionError('execution_contract catalog target does not match')
if request['subject'] != {'id':'secrets-engine','type':'service'}:
raise DecisionError('execute-ccr requires secrets-engine service subject')
# Match the producer's fixed tenant normalization before approval issue.
request['subject']['tenant'] = 'tenant:platform'
request['resource']['tenant'] = 'tenant:platform'
# Public declaration from Access ServicePilotInputs.DeclaredServiceBinding;
# bound before approval issuance, never an authentication assertion.
request['context']['service_actor_binding'] = {
'version':'proposed-service-task-caller/v1',
'transport_principal':'system:serviceaccount:secrets-engine:secrets-engine',
'subject_id':'secrets-engine','subject_type':'service','tenant':'tenant:platform',
}
request['context']['execution_contract'] = value
request['context']['human_control'] = True
def require_execution_deadline(request: dict, *, time_window=None, bounds=()) -> None:
"""Check trusted-time freshness and served upper bounds before CAS binding."""
contract = request.get('context', {}).get('execution_contract')
if contract is None:
return
from secrets_engine.application_time import validity_bounds
deadline = datetime.fromisoformat(contract['operation_deadline'].replace('Z', '+00:00'))
_, upper = validity_bounds(None, time_window)
if upper >= deadline:
raise DecisionError('execution_contract deadline has expired')
for bound in bounds:
try:
limit = datetime.fromisoformat(bound.replace('Z', '+00:00'))
if limit.tzinfo is None or deadline > limit:
raise DecisionError('execution_contract deadline exceeds served authority')
except (ValueError, TypeError, AttributeError):
raise DecisionError('execution_contract requires served deadline') from None