conductor/scripts/fixtures/slice12/check-backup-rejection.py

26 lines
1.8 KiB
Python

import pathlib,json,hashlib,tarfile,io,subprocess,sys,tempfile
archive,fqdn=sys.argv[1:]
stack=pathlib.Path('/opt/skeletonworks/conductor')/fqdn
def fingerprint():return {p.name:hashlib.sha256(p.read_bytes()).hexdigest() for p in stack.iterdir() if p.is_file()}
before=fingerprint()
with tempfile.TemporaryDirectory() as directory:
directory=pathlib.Path(directory)
with tarfile.open(archive) as source:
original=[(m,source.extractfile(m).read() if m.isfile() else b'') for m in source.getmembers()]
for kind in ['checksum','symlink','traversal','missing-applications']:
target=directory/(kind+'.tar.gz')
with tarfile.open(target,'w:gz') as output:
for member,data in original:
if kind=='missing-applications' and (member.name=='applications' or member.name.startswith('applications/')):continue
if kind=='checksum' and member.name=='manifest.json':data=data+b' '
member.size=len(data) if member.isfile() else 0
output.addfile(member,io.BytesIO(data) if member.isfile() else None)
if kind in ['symlink','traversal']:
member=tarfile.TarInfo('unsafe' if kind=='symlink' else '../unsafe')
if kind=='symlink':member.type=tarfile.SYMTYPE;member.linkname='/etc/passwd'
output.addfile(member)
result=subprocess.run(['/opt/skeletonworks/scripts/restore-conductor.sh','--fqdn',fqdn,'--backup-file',str(target),'--force','--skip-safety-backup'],capture_output=True,text=True)
assert result.returncode!=0,kind
assert fingerprint()==before,kind+' changed configuration before rejecting the archive'
print('PASS: corrupted, linked, traversing and incomplete-app backups rejected without configuration changes.')