"""Provide the exact C01 execution profile for disposable backend tests only.""" from contextlib import contextmanager import hashlib import json from pathlib import Path import subprocess import sys def inventory(): return json.loads(subprocess.check_output(['sudo', '-n', 'aa-status', '--json'], timeout=15)) def parser(action, policy): result = subprocess.run(['sudo', '-n', '/usr/sbin/apparmor_parser', action, '--skip-cache'], input=policy, capture_output=True, timeout=15) if result.returncode: raise RuntimeError(f'Execution-profile fixture {action} failed (exit {result.returncode}): ' + result.stderr.decode(errors='replace')) @contextmanager def loaded_profile(repo): template = (Path(repo) / 'image-recipe/configs/archipelago-manager-exec.profile.in').read_bytes() name = 'archipelago-manager-exec-' + hashlib.sha256(template).hexdigest() policy = template.replace(b'@PROFILE@', name.encode()) before = inventory() if name in before['profiles']: if before['profiles'][name] != 'enforce': raise RuntimeError('Existing execution profile is not enforcing; refusing to replace it') # An installed policy belongs to its existing owner. Never replace/remove it. yield name return parser('-a', policy) try: if inventory()['profiles'].get(name) != 'enforce': raise RuntimeError('Fixture execution profile was not loaded in enforce mode') yield name finally: current = inventory() if any(item['profile'] == name for rows in current['processes'].values() for item in rows): raise RuntimeError('Execution-profile fixture still has bound processes; retaining policy') parser('-R', policy) after = inventory() if name in after['profiles'] or after['profiles'] != before['profiles']: raise RuntimeError('Execution-profile cleanup did not preserve the original policy set') print('PASS temporary C01 execution profile removed; original policy set preserved', flush=True) def main(): if len(sys.argv) < 4 or sys.argv[2] != '--': raise SystemExit('usage: with_exec_profile.py SOURCE_ROOT -- COMMAND [ARG...]') with loaded_profile(sys.argv[1]): result = subprocess.run(sys.argv[3:]) return result.returncode if __name__ == '__main__': raise SystemExit(main())