Files
archy/tests/regression/yaya-container-declarations.py
T

53 lines
3.6 KiB
Python

"""Exercise Yaya's 38 public data-mount/user declarations with synthetic payloads.
No original image command, environment, credential, key, wallet or host mount is
executed. Each declaration is tied to its captured hash; private data sources are
mapped to fresh synthetic directories and exercised by the inert /bin/true image.
"""
import hashlib
import json
import os
from pathlib import Path
def seed(c,appointment,runtime):
records=[];root=Path(runtime['runtime_data_dir'])/'yaya-declaration-mounts'
root.mkdir(mode=0o755);os.chown(root,1000,1000)
def podman(index,*args):
return c['run']('runuser','-u','archipelago','--','env','XDG_RUNTIME_DIR=/run/user/1000',
'systemd-run','--user','--wait','--pipe','--collect','--unit=c01-yaya-declaration-'+str(index),
'/usr/bin/podman',*args).stdout
assert len(appointment['container_declarations'])==38
stopped=[]
for index,item in enumerate(appointment['container_declarations']):
assert item['uidMappings']==[] and item['gidMappings']==[], 'new explicit mapping needs separate review'
user=item['process_user'];name='yaya-declaration-'+str(index);stopped.append(name)
args=['create','--name',name,'--network=none','--security-opt=seccomp=unconfined',
'--user',str(user['uid'])+':'+str(user['gid'])]
for group in user.get('additionalGids',[]):args+=['--group-add',str(group)]
volumes=[]
for mount in item['mounts']:
if mount['type']!='bind' or not mount['source'].startswith('/var/lib/archipelago/') or mount['destination']=='/dev/shm':continue
source=root/hashlib.sha256(mount['source'].encode()).hexdigest()
if not source.exists():
# The synthetic mount is a directory even for a captured config
# file; the declaration and this scope difference are recorded.
source.mkdir(mode=0o755);os.chown(source,1000,1000)
marker=source/'retained-metadata';c['write'](marker,b'synthetic preserved '+mount['source'].encode(),0o644)
os.chown(marker,1000,1000)
options=['ro' if 'ro' in mount['options'] else 'rw','rprivate']
args+=['--volume',str(source)+':'+mount['destination']+':'+','.join(options)]
volumes.append({'original':mount,'synthetic_source':str(source),'identity':c['policy'].identity(source.stat()),
'marker_sha256':c['sha'](source/'retained-metadata')})
args+=['localhost/c01-prerequisite:fixture','/bin/true']
identifier=podman(str(index)+'-create',*args).decode().strip();assert len(identifier)==64
podman(str(index)+'-execute','start','--attach',name)
observed=json.loads(podman(str(index)+'-inspect','inspect',name))[0]
assert observed['State']['ExitCode']==0 and observed['State']['Status']=='exited'
records.append({'name':name,'id':identifier,'source_declaration_sha256':item['source_declaration_sha256'],
'container_user':user,'uidMappings':item['uidMappings'],'gidMappings':item['gidMappings'],
'retained_mounts':volumes,'execution_exit':0,'last_started':observed['State']['StartedAt']})
c['dump'](c['EVIDENCE']/'yaya-container-declarations.json',{'passed':True,'count':38,'records':records,
'scope':'inert real rootless containers with synthetic data-mount projections and original numeric process users/groups; not original application workload UAT',
'original_host_network_and_pseudofs':'not reproduced as physical host access; owned isolated runtime networking qualified separately'})
return stopped