57 lines
4.1 KiB
Python
57 lines
4.1 KiB
Python
"""Founder-run read-only scanner preflight; prints only selected public evidence."""
|
|
import subprocess,json,hashlib,pathlib,sys
|
|
NS='forgejo';NAME='forge';POD='forge-79c7fb84db-k5wtm'
|
|
EXPECTED_UID='1faefb26-cccd-4d0e-b509-70a7eb0b4f4d'
|
|
POD_UID='2c9f911a-403e-4183-a027-2b8d48742348'
|
|
BASE='/data/security/receive-secret-scan/20261027-b735d052a49f'
|
|
ADAPTER='b735d052a49fc8e9cca14cddee074c5429352ad71841eb6548459294f15683a2'
|
|
SCANNER='88f91962aa2f93ac6ab281d553b9e125f5197bbbce38f9f2437f7299c32e5509'
|
|
def k(*args):
|
|
q=subprocess.run(['kubectl',*args],capture_output=True,timeout=60)
|
|
if q.returncode:raise RuntimeError('read-only-command-failed; raw diagnostics withheld')
|
|
return q.stdout
|
|
|
|
def main():
|
|
d=json.loads(k('-n',NS,'get','deployment',NAME,'-o','json'))
|
|
if d['metadata']['uid']!=EXPECTED_UID:raise RuntimeError('deployment-identity-drift')
|
|
uid=k('-n',NS,'get','pod',POD,'-o','jsonpath={.metadata.uid}').decode()
|
|
if uid!=POD_UID:raise RuntimeError('pod-identity-drift')
|
|
spec=d['spec']['template']['spec'];inits=spec.get('initContainers',[])
|
|
candidates=[c['name'] for c in spec['containers'] if c.get('image')=='code.forgejo.org/forgejo/forgejo:11.0.3-rootless']
|
|
if len(candidates)!=1:raise RuntimeError('forge-container-ambiguous')
|
|
container=candidates[0]
|
|
guards=[(i,x) for i,x in enumerate(inits) if x['name']=='verify-secret-scanner']
|
|
if len(guards)!=1:raise RuntimeError('scanner-guard-ambiguous')
|
|
index,guard=guards[0]
|
|
volumes=spec.get('volumes',[]);selected=[(i,x) for i,x in enumerate(volumes) if x['name']=='secret-scan-template']
|
|
if len(selected)!=1:raise RuntimeError('scanner-volume-ambiguous')
|
|
vindex,volume=selected[0];cmname=volume['configMap']['name']
|
|
if cmname!='forgejo-secret-template-d1df801be39f':raise RuntimeError('template-configmap-drift')
|
|
# This exact public ConfigMap contains only the receiver hook, per owner source.
|
|
hook=k('-n',NS,'get','configmap',cmname,'-o','jsonpath={.data.hook}')
|
|
expected=('#!/bin/sh\nset +vx\nset -eu\nexec '+BASE+'/receive-secret-scan --scanner '+BASE+'/gitleaks\n').encode()
|
|
if hook!=expected:raise RuntimeError('mounted-hook-source-drift')
|
|
metadata=k('-n',NS,'exec',POD,'-c',container,'--','sh','-c',
|
|
'set -eu; test -f "$1" && test ! -L "$1"; test -f "$2" && test ! -L "$2"; sha256sum "$1" "$2"',
|
|
'sh',BASE+'/receive-secret-scan',BASE+'/gitleaks').decode().splitlines()
|
|
hashes=[s.split()[0] for s in metadata]
|
|
if hashes!=[ADAPTER,SCANNER]:raise RuntimeError('installed-scanner-artifact-drift')
|
|
nodes=json.loads(k('get','nodes','-o','json'))['items']
|
|
if len(nodes)!=1 or not any(a['address']=='92.205.62.239' for a in nodes[0]['status']['addresses']):raise RuntimeError('node-target-drift')
|
|
description=k('describe','node',nodes[0]['metadata']['name']).decode()
|
|
allocation=description.split('Allocated resources:',1)[1].split('Events:',1)[0].strip() if 'Allocated resources:' in description else None
|
|
if allocation is None:raise RuntimeError('node-headroom-unavailable')
|
|
receipt=dict(read_only=True,deployment_uid=EXPECTED_UID,pod=POD,pod_uid=POD_UID,
|
|
deployment_name=NAME,container=container,node_uid=nodes[0]['metadata']['uid'],node_name=nodes[0]['metadata']['name'],
|
|
guard_index=index,guard_command=guard.get('command'),guard_args=guard.get('args'),volume_index=vindex,
|
|
volume=volume,strategy=d['spec'].get('strategy'),resources=[dict(name=c['name'],resources=c.get('resources')) for c in spec['containers']],
|
|
old_configmap=cmname,old_hook_sha256=hashlib.sha256(hook).hexdigest(),old_adapter_sha256=ADAPTER,scanner_sha256=SCANNER,
|
|
allocated_resources=allocation)
|
|
pathlib.Path('/tmp/forge-scanner-preflight-receipt.json').write_text(json.dumps(receipt,indent=2)+'\n')
|
|
# Keep long public shell commands in the local receipt; return concise checks.
|
|
print(json.dumps({k:receipt[k] for k in ['read_only','deployment_name','deployment_uid','pod_uid','node_uid','old_configmap','old_adapter_sha256','strategy','allocated_resources']},indent=2))
|
|
print('receipt: /tmp/forge-scanner-preflight-receipt.json')
|
|
try:main()
|
|
except Exception as exc:
|
|
print('preflight refused:',str(exc) if isinstance(exc,RuntimeError) else type(exc).__name__)
|
|
sys.exit(1)
|