Align native proof with KeyCape Basic authentication and corrected image
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: 01a10780-6d41-7952-9718-dfbc1f41236f
This commit is contained in:
tegwick 2026-10-04 23:42:15 +02:00
parent 4db8563eff
commit 6f4b87d44e
5 changed files with 38 additions and 10 deletions

View file

@ -0,0 +1,14 @@
{
"complete": false,
"exact_identity": true,
"exact_path_projection_matches": true,
"exact_policy_and_ttl": true,
"negative_identity": false,
"parent_list_refused": true,
"phase": "requester_exchange",
"projection_mode": true,
"reader_revoked": true,
"revoked_lookup_refused": true,
"sibling_get_refused": true,
"wrong_audience_refused": true
}

View file

@ -0,0 +1,6 @@
{
"complete": true,
"negative_identity": true,
"phase": "wrong_identity_refused",
"wrong_identity_refused": true
}

View file

@ -0,0 +1,6 @@
{
"complete": true,
"negative_identity": true,
"phase": "wrong_identity_refused",
"wrong_identity_refused": true
}

File diff suppressed because one or more lines are too long

View file

@ -1,9 +1,10 @@
"""Temporary native proof. Emits only fixed phases and booleans; never raw failures."""
import base64
import json
import stat
import sys
from pathlib import Path
from urllib.parse import urlencode
from urllib.parse import urlencode, quote_plus
from urllib.request import Request, build_opener, ProxyHandler, HTTPRedirectHandler
from urllib.error import HTTPError
from informed_decision.requester import RequesterTokenProvider, CLIENT_ID
@ -17,9 +18,10 @@ SECRET = Path('/var/run/secrets/informed-decision/requester/client-secret')
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, *args, **kwargs): return None
def http(method, url, body=None, token=None, form=False):
def http(method, url, body=None, token=None, form=False, client_auth=None):
headers = {'Content-Type': 'application/x-www-form-urlencoded' if form else 'application/json'}
if token: headers['X-Vault-Token'] = token
if client_auth: headers['Authorization'] = 'Basic ' + client_auth
raw = body if form else (json.dumps(body).encode() if body is not None else None)
req = Request(url, data=raw, headers=headers, method=method)
try: response = build_opener(ProxyHandler({}), NoRedirect()).open(req, timeout=5)
@ -69,10 +71,10 @@ def run(negative=False):
receipt['phase'] = 'requester_exchange'
provider = RequesterTokenProvider(ISSUER, str(SECRET))
check('signed_create_only_exchange', bool(provider()))
credentials = base64.b64encode((quote_plus(CLIENT_ID)+':'+quote_plus(secret)).encode()).decode()
for scope in ('approval:approve', 'approval:read', 'approval:consume'):
status, result = http('POST', ISSUER+'/token', form=True, body=urlencode({
'grant_type': 'client_credentials', 'client_id': CLIENT_ID,
'client_secret': secret, 'scope': scope}).encode())
status, result = http('POST', ISSUER+'/token', form=True, client_auth=credentials, body=urlencode({
'grant_type': 'client_credentials', 'scope': scope}).encode())
check(scope.replace(':', '_')+'_refused', status in (400, 403) and 'access_token' not in result)
receipt['complete'] = True
except BaseException: