Package protected review runtime and prepare deployment admission
Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a07ff8-19d0-7820-b4d0-1353833cb7fc
This commit is contained in:
parent
bb5b607bbd
commit
bda9381f07
20 changed files with 3534 additions and 7 deletions
114
informed_decision/container.py
Normal file
114
informed_decision/container.py
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
"""Container boundary: private runtime config, local evidence and one writer.
|
||||
|
||||
Kubernetes projected configuration is root-owned and symlinked. Copy its bounded
|
||||
non-secret JSON into an owned ephemeral file; do not weaken Runtime's private
|
||||
file checks or copy projected bearer credentials into persistent storage.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
from contextlib import contextmanager
|
||||
import fcntl
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import sqlite3
|
||||
import signal
|
||||
import stat
|
||||
import tempfile
|
||||
|
||||
from .store import Store
|
||||
|
||||
|
||||
def private_directory(path):
|
||||
path = Path(path)
|
||||
if not path.is_absolute():
|
||||
raise ValueError("absolute private directory required")
|
||||
path.mkdir(mode=0o700, exist_ok=True)
|
||||
info = path.lstat()
|
||||
if (not stat.S_ISDIR(info.st_mode) or info.st_uid != os.getuid()
|
||||
or stat.S_IMODE(info.st_mode) != 0o700):
|
||||
raise ValueError("private directory has unsafe ownership or mode")
|
||||
return path
|
||||
|
||||
|
||||
def prepare_configuration(source, *, data_root=Path('/data'), run_root=Path('/run/informed-decision')):
|
||||
with Path(source).open('rb') as handle:
|
||||
if not stat.S_ISREG(os.fstat(handle.fileno()).st_mode):
|
||||
raise ValueError('configuration must be a regular projected file')
|
||||
raw = handle.read(16385)
|
||||
if len(raw) > 16384:
|
||||
raise ValueError('configuration too large')
|
||||
data = json.loads(raw)
|
||||
evidence = Path(data_root) / 'private'
|
||||
if not isinstance(data, dict) or data.get('evidence_db') != str(evidence / 'review.sqlite'):
|
||||
raise ValueError('container evidence must use its private persistent volume')
|
||||
private_directory(evidence)
|
||||
destination = private_directory(Path(run_root) / 'private') / 'runtime.json'
|
||||
fd, temporary = tempfile.mkstemp(prefix='.runtime-', dir=destination.parent)
|
||||
try:
|
||||
with os.fdopen(fd, 'wb') as handle:
|
||||
handle.write(raw); handle.flush(); os.fsync(handle.fileno())
|
||||
os.replace(temporary, destination)
|
||||
finally:
|
||||
if os.path.exists(temporary):
|
||||
os.unlink(temporary)
|
||||
return destination, evidence
|
||||
|
||||
|
||||
@contextmanager
|
||||
def single_writer(evidence):
|
||||
directory = private_directory(evidence)
|
||||
fd = os.open(directory / 'serve.lock', os.O_CREAT | os.O_RDWR | os.O_NOFOLLOW, 0o600)
|
||||
try:
|
||||
info = os.fstat(fd)
|
||||
if (not stat.S_ISREG(info.st_mode) or info.st_uid != os.getuid()
|
||||
or info.st_nlink != 1 or stat.S_IMODE(info.st_mode) != 0o600):
|
||||
raise ValueError('unsafe service lock')
|
||||
try:
|
||||
fcntl.flock(fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
|
||||
except BlockingIOError:
|
||||
raise ValueError('another review service holds this evidence volume') from None
|
||||
yield
|
||||
finally:
|
||||
os.close(fd)
|
||||
|
||||
|
||||
def main():
|
||||
from .web import main as serve
|
||||
def terminate(signum, frame):
|
||||
# PID 1 does not get ordinary default signal behavior. Let Waitress
|
||||
# drain its dispatcher and web.main stop the audit pump on SIGTERM.
|
||||
raise SystemExit(0)
|
||||
signal.signal(signal.SIGTERM, terminate)
|
||||
try:
|
||||
config, evidence = prepare_configuration(os.environ.get('INFD_CONTAINER_CONFIG', '/configuration/runtime.json'))
|
||||
with single_writer(evidence):
|
||||
os.environ['INFD_REVIEW_CONFIG'] = str(config)
|
||||
os.environ['INFD_LISTEN_HOST'] = '0.0.0.0'
|
||||
serve()
|
||||
except (OSError, ValueError, sqlite3.Error):
|
||||
# Configuration can be supplied by an operator. Do not echo its values
|
||||
# or an upstream response on startup failure.
|
||||
raise SystemExit('Container runtime could not start; inspect configuration and private volume admission.') from None
|
||||
|
||||
|
||||
def admin():
|
||||
parser = argparse.ArgumentParser(description='Local custody operations; no network or approval mutation.')
|
||||
commands = parser.add_subparsers(dest='command', required=True)
|
||||
backup = commands.add_parser('backup', help='SQLite-consistent backup to a new private file')
|
||||
backup.add_argument('--db', type=Path, required=True)
|
||||
backup.add_argument('--output', type=Path, required=True)
|
||||
inspect = commands.add_parser('inspect', help='Report delivery/submission counts, never private content')
|
||||
inspect.add_argument('--db', type=Path, required=True)
|
||||
args = parser.parse_args()
|
||||
if not args.db.is_file():
|
||||
parser.error('existing evidence database required')
|
||||
store = Store(args.db)
|
||||
if args.command == 'backup':
|
||||
store.backup(args.output)
|
||||
print(json.dumps({'status': 'backed_up', 'consistent_snapshot': True}))
|
||||
else:
|
||||
with store._connection() as db:
|
||||
print(json.dumps({'schema_version': db.execute('PRAGMA user_version').fetchone()[0],
|
||||
'outbox': {r[0]: r[1] for r in db.execute('SELECT state,COUNT(*) FROM outbox GROUP BY state')},
|
||||
'submissions': {r[0]: r[1] for r in db.execute('SELECT state,COUNT(*) FROM submissions GROUP BY state')}}))
|
||||
|
|
@ -213,6 +213,9 @@ class App:
|
|||
|
||||
def main():
|
||||
from waitress import serve
|
||||
host = os.environ.get("INFD_LISTEN_HOST", "127.0.0.1")
|
||||
if host not in ("127.0.0.1", "0.0.0.0"):
|
||||
raise ValueError("unsupported listener address")
|
||||
# Waitress does not log request targets; a proxy must also omit callback
|
||||
# query strings and cookies. No debug traceback middleware belongs here.
|
||||
login = KeyCapeLogin(os.environ["INFD_KEYCAPE_ISSUER"])
|
||||
|
|
@ -224,7 +227,7 @@ def main():
|
|||
app = App(login, runtime.controller if runtime else None,
|
||||
readiness=runtime.pump.ready if runtime else lambda: False)
|
||||
try:
|
||||
serve(app, host="127.0.0.1", port=8080, threads=4)
|
||||
serve(app, host=host, port=8080, threads=4)
|
||||
finally:
|
||||
if runtime:
|
||||
runtime.pump.stop()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue