Advance blocked assurance and operator callback work
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: 01a06ecb-456a-71c2-b41e-0755d336e883
This commit is contained in:
codex 2026-09-06 14:16:49 +02:00
parent a3ca4b708f
commit 445f1361dc
16 changed files with 505 additions and 144 deletions

View file

@ -14,6 +14,7 @@ import sys
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT / 'scripts'))
from service_assurance import read_contract, admission
from recovery_evidence import recovery_signals
def query(args, allowed_codes=(0,)):
@ -94,7 +95,8 @@ def capture():
add('eso.ready', 'unavailable')
add('eso.refresh', 'unavailable')
# No token, Secret, application data/logs or seal/unseal mutation.
# Native restore and offsite receipts remain separate attended evidence.
# Receipt timestamps are preserved; reads never renew recovery evidence.
signals.update(recovery_signals(datetime.now(timezone.utc)))
return {'schema': 'railiance-platform.observation.v1', 'cluster_uid': uid,
'captured_at': datetime.now(timezone.utc).isoformat(), 'signals': signals}

View file

@ -1,63 +1,4 @@
#!/usr/bin/env bash
# Silent owner command for the governed openbao-platform-admin-login lane.
# Warden rejects any child output and self-revokes the attended session after
# this command exits. The role payload contains no secret values.
# Silent child for the governed attended login; no role or token output.
set -euo pipefail
ROLE_PATH="auth/netkingdom/role/platform-admin"
CALLBACK_URI="http://127.0.0.1:18200/ui/vault/auth/netkingdom/oidc/callback"
PAYLOAD="$(mktemp "${TMPDIR:-/tmp}/openbao-platform-admin-role.XXXXXX.json")"
READBACK="$(mktemp "${TMPDIR:-/tmp}/openbao-platform-admin-readback.XXXXXX.json")"
cleanup() {
rm -f "$PAYLOAD" "$READBACK"
}
trap cleanup EXIT INT TERM
chmod 0600 "$PAYLOAD" "$READBACK"
command -v bao >/dev/null 2>&1
command -v python3 >/dev/null 2>&1
cat >"$PAYLOAD" <<'ROLE_JSON'
{
"role_type": "oidc",
"user_claim": "sub",
"groups_claim": "groups",
"oidc_scopes": ["openid", "profile", "email", "groups"],
"allowed_redirect_uris": [
"http://localhost:8250/oidc/callback",
"http://127.0.0.1:8250/oidc/callback",
"http://127.0.0.1:18200/ui/vault/auth/netkingdom/oidc/callback",
"https://bao.coulomb.social/ui/vault/auth/netkingdom/oidc/callback",
"https://bao.coulomb.social/ui/vault/auth/keycape/oidc/callback"
],
"bound_claims": {
"groups": ["net-kingdom-admins"]
},
"claim_mappings": {
"email": "email",
"preferred_username": "username"
},
"policies": ["platform-admin"],
"ttl": "1h"
}
ROLE_JSON
bao write "$ROLE_PATH" @"$PAYLOAD" >/dev/null 2>&1
bao read -format=json "$ROLE_PATH" >"$READBACK" 2>/dev/null
python3 - "$READBACK" "$CALLBACK_URI" <<'PY' >/dev/null 2>&1
import json
import sys
path, callback = sys.argv[1:]
with open(path, encoding="utf-8") as handle:
role = json.load(handle).get("data") or {}
if callback not in role.get("allowed_redirect_uris", []):
raise SystemExit(1)
if role.get("role_type") != "oidc":
raise SystemExit(1)
if "platform-admin" not in role.get("token_policies", role.get("policies", [])):
raise SystemExit(1)
PY
exec python3 "$(dirname "$0")/openbao_operator_loopback_callback.py" "$@" >/dev/null 2>&1

View file

@ -0,0 +1,49 @@
#!/usr/bin/env python3
"""Silent contained callback update; preserve the existing administrator role."""
import json
import subprocess
import sys
ROLE = 'auth/netkingdom/role/platform-admin'
CALLBACK = 'http://127.0.0.1:18200/ui/vault/auth/netkingdom/oidc/callback'
def read_role():
result = subprocess.run(['bao', 'read', '-format=json', ROLE],
capture_output=True, check=True, timeout=30)
role = json.loads(result.stdout)['data']
if (role.get('role_type') != 'oidc'
or 'platform-admin' not in role.get('token_policies', role.get('policies', []))
or not isinstance(role.get('allowed_redirect_uris'), list)
or not all(isinstance(uri, str) for uri in role['allowed_redirect_uris'])):
raise ValueError('unexpected role')
return role
def update(read=read_role, write=None):
original = read()
if CALLBACK in original['allowed_redirect_uris']:
return False
desired = dict(original, allowed_redirect_uris=original['allowed_redirect_uris'] + [CALLBACK])
if read() != original:
raise ValueError('role changed before write')
# The endpoint has no CAS: this detects observed drift, not an atomic lock.
if write is None:
subprocess.run(['bao', 'write', ROLE, '-'], input=json.dumps(desired).encode(),
capture_output=True, check=True, timeout=30)
else:
write(desired)
if read() != desired:
raise ValueError('role readback differs')
return True
if __name__ == '__main__':
try:
if sys.argv[1:] == ['--check-only']:
sys.exit(0 if CALLBACK in read_role()['allowed_redirect_uris'] else 3)
if sys.argv[1:]:
sys.exit(2)
update()
except Exception:
sys.exit(1)

View file

@ -0,0 +1,44 @@
"""Hash-pinned native recovery receipts, with original completion timestamps."""
import hashlib
import json
from pathlib import Path
from service_assurance import timestamp
ROOT = Path(__file__).resolve().parents[1]
def recovery_signals(now, root=ROOT):
index = json.loads((root / 'assurance/recovery-evidence.json').read_text())
if index['schema'] != 'railiance-platform.recovery-evidence.v1':
raise ValueError('unknown recovery index')
signals = {}
for entry in index['receipts']:
signal = entry['signal']
if signal in signals or signal not in ('apps-pg.restore', 'forgejo-db.restore'):
raise ValueError('unexpected recovery signal')
sample = {'result': 'unavailable', 'observed_at': now.isoformat()}
try:
path = (root / entry['path']).resolve()
if not path.is_relative_to((root / 'docs/evidence').resolve()):
raise ValueError('receipt outside evidence directory')
raw = path.read_bytes()
if hashlib.sha256(raw).hexdigest() != entry['sha256']:
raise ValueError('receipt drift')
receipt = json.loads(raw)
cell = signal.removesuffix('.restore')
if (receipt['schema'] != 'platform.scaleway-primary-restore.v1'
or receipt['primary_destination'] != f's3://railiance-platform-pg-backup/platform-pg/{cell}/'
or receipt['source'] != 'Scaleway Barman base backup and WAL'
or receipt['stage'] != 'database_acceptance'
or receipt['status'] != 'verified'
or receipt['cleanup'] is not True
or receipt['production_ready'] is not True):
raise ValueError('receipt not accepted')
completed = timestamp(receipt['finished_at'])
if not timestamp(receipt['started_at']) <= completed <= now:
raise ValueError('invalid receipt chronology')
sample = {'result': 'pass', 'observed_at': receipt['finished_at']}
except (OSError, ValueError, KeyError, TypeError):
pass
signals[signal] = sample
return signals