60 lines
2.4 KiB
Python
60 lines
2.4 KiB
Python
"""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())
|