Remove the image build and consolidate operational code under scripts
This commit is contained in:
77 files changed
+586
-260607
No files matched your search
@@ -0,0 +1,76 @@
|
||||
"""Install an immutable watchdog bundle from the operator's checkout."""
|
||||
import hashlib
|
||||
import io
|
||||
import os
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
import stat
|
||||
import tarfile
|
||||
import tempfile
|
||||
|
||||
|
||||
def _bundle_from_source(root):
|
||||
root = Path(root).resolve()
|
||||
files = [root / 'provisioning' / name for name in ('__init__.py', 'access.py', 'state.py')]
|
||||
output = io.BytesIO()
|
||||
with tarfile.open(fileobj=output, mode='w') as archive:
|
||||
for path in files:
|
||||
if (not path.is_file() or '__pycache__' in path.parts
|
||||
or any(part.is_symlink() for part in (path, *path.parents))):
|
||||
raise RuntimeError('Provisioning bundle contains an unsafe source path')
|
||||
data = path.read_bytes()
|
||||
info = tarfile.TarInfo(path.relative_to(root).as_posix())
|
||||
info.size, info.mode, info.mtime = len(data), 0o644, 0
|
||||
info.uid = info.gid = 0
|
||||
archive.addfile(info, io.BytesIO(data))
|
||||
data = output.getvalue()
|
||||
return data, hashlib.sha256(data).hexdigest()
|
||||
|
||||
|
||||
def _trusted(path):
|
||||
info = path.lstat()
|
||||
if not stat.S_ISDIR(info.st_mode) or info.st_uid != os.geteuid() or info.st_mode & 0o022:
|
||||
raise RuntimeError(f"Untrusted provisioning directory: {path}")
|
||||
|
||||
|
||||
def install(root=Path('/')):
|
||||
source = Path(__file__).resolve().parents[1]
|
||||
data, digest = _bundle_from_source(source)
|
||||
# All ancestors from the filesystem root must be protected before publishing code.
|
||||
parent = root
|
||||
_trusted(parent)
|
||||
for component in ('usr', 'local', 'lib', 'apex-provisioner'):
|
||||
parent = parent / component
|
||||
parent.mkdir(mode=0o755, exist_ok=True)
|
||||
_trusted(parent)
|
||||
destination = parent / digest
|
||||
with tempfile.TemporaryDirectory(prefix='.install-', dir=parent) as temporary:
|
||||
stage = Path(temporary) / 'bundle'
|
||||
stage.mkdir(mode=0o755)
|
||||
with tarfile.open(fileobj=io.BytesIO(data)) as archive:
|
||||
for member in archive:
|
||||
if not member.isfile() or '..' in Path(member.name).parts or Path(member.name).is_absolute():
|
||||
raise RuntimeError('Invalid provisioning bundle member')
|
||||
target = stage / member.name
|
||||
target.parent.mkdir(mode=0o755, parents=True, exist_ok=True)
|
||||
with archive.extractfile(member) as source_file, target.open('xb') as output:
|
||||
shutil.copyfileobj(source_file, output)
|
||||
target.chmod(member.mode)
|
||||
try:
|
||||
os.rename(stage, destination)
|
||||
except OSError:
|
||||
_trusted(destination)
|
||||
installed, existing_digest = _bundle_from_source(destination)
|
||||
if existing_digest != digest or installed != data:
|
||||
raise RuntimeError('Installed provisioning bundle differs from the checkout') from None
|
||||
for path in destination.rglob('*'):
|
||||
info = path.lstat()
|
||||
if info.st_uid != os.geteuid() or info.st_mode & 0o022 or path.is_symlink():
|
||||
raise RuntimeError(f'Untrusted installed provisioning file: {path}') from None
|
||||
return destination
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if os.geteuid() != 0:
|
||||
raise SystemExit('Run bundle installation as root.')
|
||||
print(install())
|
||||
Reference in new issue
Block a user