78 lines
3.8 KiB
Python
78 lines
3.8 KiB
Python
"""Read only known public scanner paths; suppress raw cluster errors."""
|
|
from pathlib import Path
|
|
import argparse
|
|
import json
|
|
import subprocess
|
|
|
|
HERE = Path(__file__).resolve().parent
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument('--attempt', required=True)
|
|
args = parser.parse_args()
|
|
assert args.attempt.isalnum()
|
|
remote = r'''
|
|
import json, subprocess
|
|
def call(args, stage='metadata'):
|
|
p = subprocess.run(args, capture_output=True, text=True, timeout=30)
|
|
if p.returncode:
|
|
print(json.dumps({'error':'metadata-command-refused', 'stage':stage}))
|
|
raise SystemExit(2)
|
|
return p.stdout
|
|
items=json.loads(call(['kubectl','get','nodes','-o','json']))['items']
|
|
nodes=[a['address'] for n in items for a in n['status']['addresses'] if a['type']=='InternalIP']
|
|
if len(items)!=1 or '92.205.62.239' not in nodes:
|
|
print(json.dumps({'error':'target-node-mismatch', 'node_count':len(items), 'internal_ips':nodes})); raise SystemExit(2)
|
|
pods=call(['kubectl','-n','forgejo','get','pods','-o','custom-columns=NAME:.metadata.name,UID:.metadata.uid,PHASE:.status.phase','--no-headers'])
|
|
running=[line.split() for line in pods.splitlines() if line.startswith('forgejo-gitea-') and line.split()[-1]=='Running']
|
|
if len(running)!=1:
|
|
raise RuntimeError('ambiguous-forgejo-pod')
|
|
pod,uid,_=running[0]
|
|
paths=[
|
|
'/data/security/receive-secret-scan/20261012-57a0642b6251/receive-secret-scan',
|
|
'/data/security/receive-secret-scan/20261012-57a0642b6251/gitleaks',
|
|
'/opt/forge-secret-template/hooks/pre-receive.d/10-custodian-secret-scan',
|
|
'/data/git/repositories/coulomb/the-custodian.git/hooks/pre-receive.d/10-custodian-secret-scan',
|
|
]
|
|
script='set -eu\nid -u\nuname -r\nstat -f -c %t /dev/shm\nstat -c "%a:%u:%g:%F" /dev/shm\n'
|
|
for path in paths:
|
|
script+='if test -f '+path+' && test ! -L '+path+'; then\nstat -c "%a:%u:%g:%F" '+path+'\nsha256sum '+path+'\nelse\necho unavailable\nfi\n'
|
|
script+="""
|
|
for base in /data/git/repositories /data/git/gitea-repositories /data/gitea/repositories; do
|
|
if test -d "$base"; then printf 'root=%s\\n' "$base"; fi
|
|
for path in "$base"/*/*.git/hooks/pre-receive.d/10-custodian-secret-scan; do
|
|
if test -f "$path" && test ! -L "$path"; then
|
|
printf 'hook=%s\\n' "$path"
|
|
stat -c "%a:%u:%g:%F" "$path"
|
|
sha256sum "$path"
|
|
fi
|
|
done
|
|
done
|
|
"""
|
|
output=call(['kubectl','-n','forgejo','exec',pod,'--','sh','-c',script], stage='public-file-metadata')
|
|
current=call(['kubectl','-n','forgejo','get','pod',pod,'-o','custom-columns=UID:.metadata.uid','--no-headers']).strip()
|
|
if current!=uid:
|
|
raise RuntimeError('pod-identity-changed')
|
|
print(json.dumps({'node_ip':'92.205.62.239', 'pod':pod, 'pod_uid':uid, 'read_only':True, 'public_scanner_metadata':output.splitlines()}))
|
|
'''
|
|
compile(remote, '<read-only-preflight>', 'exec')
|
|
result = subprocess.run(['ssh', '-o', 'BatchMode=yes', 'railiance01', 'python3', '-'],
|
|
input=remote, text=True, capture_output=True, timeout=150)
|
|
receipt = {'returncode': result.returncode, 'read_only': True, 'real_credentials_retrieved': False}
|
|
if result.returncode == 0:
|
|
receipt['result'] = json.loads(result.stdout)
|
|
else:
|
|
receipt['error'] = 'read-only-metadata-refused; raw output suppressed'
|
|
try:
|
|
detail=json.loads(result.stdout)
|
|
if detail.get('error') in {'metadata-command-refused', 'target-node-mismatch'}:
|
|
receipt['detail']=detail
|
|
except ValueError:
|
|
pass
|
|
path=HERE/('native-preflight-'+args.attempt+'.json')
|
|
with path.open('x') as f:
|
|
f.write(json.dumps(receipt, indent=2)+'\n')
|
|
summary={k:receipt[k] for k in ['returncode','read_only','error','detail'] if k in receipt}
|
|
if 'result' in receipt:
|
|
summary.update({k:receipt['result'][k] for k in ['node_ip','pod','pod_uid']})
|
|
summary['installed_hooks']=sum(line.startswith('hook=') for line in receipt['result']['public_scanner_metadata'])
|
|
print(json.dumps(summary))
|
|
raise SystemExit(result.returncode)
|