#!/usr/bin/env python3 """Pass one private bootstrap credential to the admitted pod over stdin.""" import json import os from pathlib import Path import re import stat import subprocess import sys class Refused(Exception): pass def private(info, directory=False): kind = stat.S_ISDIR if directory else stat.S_ISREG if not kind(info.st_mode) or info.st_uid != os.getuid() or info.st_mode & 0o077: raise Refused() if not directory and info.st_nlink != 1: raise Refused() def read_password(root): root = Path(os.path.abspath(root)) for ancestor in (root, *root.parents): if ancestor.is_symlink(): raise Refused() descriptors = [] try: flags = os.O_RDONLY | os.O_DIRECTORY | os.O_NOFOLLOW root_fd = os.open(root, flags); descriptors.append(root_fd) private(os.fstat(root_fd), True) parent_fd = os.open('privacyidea', flags, dir_fd=root_fd); descriptors.append(parent_fd) private(os.fstat(parent_fd), True) fd = os.open('secrets.env', os.O_RDONLY | os.O_NOFOLLOW | os.O_NONBLOCK, dir_fd=parent_fd) descriptors.append(fd); private(os.fstat(fd)) raw = os.read(fd, 65537) if len(raw) > 65536: raise Refused() values = [line.split('=', 1)[1] for line in raw.decode().splitlines() if line.startswith('PI_ADMIN_PASSWORD=')] # This entry point consumes gen-secrets.sh's format, never shell code. if len(values) != 1 or not re.fullmatch(r'[A-Za-z0-9]{32,128}', values[0]): raise Refused() return values[0] finally: for fd in reversed(descriptors): os.close(fd) def run(args, payload=None): completed = subprocess.run(args, input=payload, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, timeout=60, check=False) if completed.returncode or len(completed.stdout) > 4096: raise Refused() return completed.stdout def main(): if len(sys.argv) > 2: raise Refused() here = Path(__file__).resolve().parent password = read_password(sys.argv[1] if len(sys.argv) == 2 else here / '../../bootstrap/secrets') pod = run(['kubectl', 'get', 'pod', '-n', 'mfa', '-l', 'app.kubernetes.io/name=privacyidea', '--field-selector=status.phase=Running', '-o', 'jsonpath={.items[*].metadata.name}']).decode().strip() if not re.fullmatch(r'[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?', pod): raise Refused() script = (here / 'bootstrap-admin-remote.py').read_text() response = run(['kubectl', 'exec', '-i', '-n', 'mfa', pod, '--', 'python3', '-c', script], json.dumps({'password': password}).encode()) receipt = json.loads(response) if (not isinstance(receipt, dict) or set(receipt) != {'result', 'mfa_verified'} or receipt['result'] not in ('created', 'verified') or receipt['mfa_verified'] is not False): raise Refused() print('pi-admin bootstrap credential and scoped bootstrap policy verified.') print('MFA enrollment, effective-policy review and a fresh sign-in remain required; this is not MFA acceptance.') print('Use the approved custody entry for pi-admin; no credential is printed or exported.') print('Legacy trigger accounts and Secrets require a separate inventory/revocation review.') if __name__ == '__main__': try: main() except (Refused, OSError, ValueError, TypeError, subprocess.SubprocessError): print('ERROR: admin bootstrap refused or failed; use approved metadata-only diagnostics. No credential was printed.', file=sys.stderr) sys.exit(1)