#!/usr/bin/python3 # # Copyright (C) 2015 Codethink Limited # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; version 2 of the License. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . '''Commandline 'run things in a sandbox' tool.''' import argparse import logging import sys import sandboxlib def info(message, *args): # FIXME: disable by default, add --verbose flag print(message % args) logging.info(message % args) def parse_args(): parser = argparse.ArgumentParser(description="Run something in a sandbox.") parser.add_argument( 'sandbox', metavar='PATH', type=str, help="path to sandbox (image file, or directory tree)") parser.add_argument( 'command', metavar='COMMAND', type=str, nargs='?', help="command to run in sandbox") parser.add_argument( '--cwd', type=str, required=False, help="current working directory for COMMAND") parser.add_argument( '--executor', '-e', choices=['chroot', 'linux_user_chroot', 'linux-user-chroot', 'bubblewrap'], type=str, default='chroot', help="which sandboxing backend to use") return parser.parse_args() def run(): args = parse_args() executor = sandboxlib.get_executor(args.executor) if sandboxlib.load.appc.is_app_container_image(args.sandbox): info("%s is an App Container image." % args.sandbox) context = sandboxlib.load.appc.unpack_app_container_image( args.sandbox) with context as (rootfs_path, manifest): if args.command is None: command = manifest['app']['exec'] else: command = args.command cwd = None if args.cwd is not None: cwd = args.cwd elif 'workingDirectory' in manifest['app']: cwd = manifest['app']['workingDirectory'] env = sandboxlib.load.appc.BASE_ENVIRONMENT.copy() if 'environment' in manifest['app']: for item in manifest['app']['environment']: env[item['name']] = item['value'] env['AC_APP_NAME'] = manifest['name'] sharing_config = executor.maximum_possible_isolation() extra_mounts = [ (None, '/proc', 'proc', None) ] exit, out, err = executor.run_sandbox( rootfs_path, command, cwd=cwd, env=env, extra_mounts=extra_mounts, **sharing_config) # We'll take a punt on the output being valid UTF-8. print(out.decode('utf-8')) print(err.decode('utf-8')) else: # We should at minimum handle filesystem trees as well. raise RuntimeError( "Only App Container images are supported right now.") try: run() except RuntimeError as e: print("ERROR: %s" % e)