diff options
Diffstat (limited to 'scripts/docker/files/bin/setup-test-env.py')
| -rwxr-xr-x | scripts/docker/files/bin/setup-test-env.py | 647 | 
1 files changed, 0 insertions, 647 deletions
diff --git a/scripts/docker/files/bin/setup-test-env.py b/scripts/docker/files/bin/setup-test-env.py deleted file mode 100755 index bbf5267c..00000000 --- a/scripts/docker/files/bin/setup-test-env.py +++ /dev/null @@ -1,647 +0,0 @@ -#!/usr/bin/env python - - -""" -This script knows how to build a minimum environment for Soledad Server, which -includes the following: - -  - Couch server startup -  - Token and shared database initialization -  - Soledad Server startup - -Options can be passed for configuring the different environments, so this may -be used by other programs to setup different environments for arbitrary tests. -Use the --help option to get information on usage. - -For some commands you will need an environment with Soledad python packages -available, thus you might want to explicitly call python and not rely in the -shebang line. -""" - - -import time -import os -import signal -import tempfile -import psutil -from argparse import ArgumentParser -from subprocess import call -from couchdb import Server -from couchdb.http import PreconditionFailed -from couchdb.http import ResourceConflict -from couchdb.http import ResourceNotFound -from hashlib import sha512 - -from leap.soledad.common.l2db.errors import DatabaseDoesNotExist - - -# -# Utilities -# - -def get_pid(pidfile): -    if not os.path.isfile(pidfile): -        return 0 -    try: -        with open(pidfile) as f: -            return int(f.read()) -    except IOError: -        return 0 - - -def pid_is_running(pid): -    try: -        psutil.Process(pid) -        return True -    except psutil.NoSuchProcess: -        return False - - -def pidfile_is_running(pidfile): -    try: -        pid = get_pid(pidfile) -        psutil.Process(pid) -        return pid -    except psutil.NoSuchProcess: -        return False - - -def status_from_pidfile(args, default_basedir, name): -    basedir = _get_basedir(args, default_basedir) -    pidfile = os.path.join(basedir, args.pidfile) -    try: -        pid = get_pid(pidfile) -        psutil.Process(pid) -        print "[+] %s is running with pid %d" % (name, pid) -    except (IOError, psutil.NoSuchProcess): -        print "[-] %s stopped" % name - - -def kill_all_executables(args): -    basename = os.path.basename(args.executable) -    pids = [int(pid) for pid in os.listdir('/proc') if pid.isdigit()] -    for pid in pids: -        try: -            p = psutil.Process(pid) -            if p.name() == basename: -                print '[!] killing - pid: %d' % pid -                os.kill(pid, signal.SIGKILL) -        except: -            pass - - -# -# Couch Server control -# - -COUCH_EXECUTABLE = '/usr/bin/couchdb' -ERLANG_EXECUTABLE = 'beam.smp' -COUCH_TEMPLATE = os.path.join( -    os.path.dirname(os.path.realpath(__file__)), -    './conf/couchdb_default.ini') -COUCH_TEMPLATE -COUCH_PIDFILE = 'couchdb.pid' -COUCH_LOGFILE = 'couchdb.log' -COUCH_PORT = 5984 -COUCH_HOST = '127.0.0.1' -COUCH_BASEDIR = '/tmp/couch_test' - - -def _get_basedir(args, default): -    basedir = args.basedir -    if not basedir: -        basedir = default -    if not os.path.isdir(basedir): -        os.mkdir(basedir) -    return basedir - - -def couch_server_start(args): -    basedir = _get_basedir(args, COUCH_BASEDIR) -    pidfile = os.path.join(basedir, args.pidfile) -    logfile = os.path.join(basedir, args.logfile) - -    # check if already running -    pid = get_pid(pidfile) -    if pid_is_running(pid): -        print '[*] error: already running - pid: %d' % pid -        exit(1) -    if os.path.isfile(pidfile): -        os.unlink(pidfile) - -    # generate a config file from template if needed -    config_file = args.config_file -    if not config_file: -        config_file = tempfile.mktemp(prefix='couch_config_', dir=basedir) -        lines = [] -        with open(args.template) as f: -            lines = f.readlines() -            lines = map(lambda l: l.replace('BASEDIR', basedir), lines) -        with open(config_file, 'w') as f: -            f.writelines(lines) - -    # start couch server -    try: -        call([ -            args.executable, -            '-n',  # reset configuration file chain (including system default) -            '-a %s' % config_file,       # add configuration FILE to chain -            '-b',  # spawn as a background process -            '-p %s' % pidfile,   # set the background PID FILE -            '-o %s' % logfile,   # redirect background stdout to FILE -            '-e %s' % logfile])  # redirect background stderr to FILE -    except Exception as e: -        print '[*] error: could not start couch server - %s' % str(e) -        exit(1) - -    # couch may take a bit to store the pid in the pidfile, so we just wait -    # until it does -    pid = None -    while not pid: -        try: -            pid = get_pid(pidfile) -            break -        except: -            time.sleep(0.1) - -    print '[+] couch is running with pid: %d' % pid - - -def couch_server_stop(args): -    basedir = _get_basedir(args, COUCH_BASEDIR) -    pidfile = os.path.join(basedir, args.pidfile) -    pid = get_pid(pidfile) -    if not pid_is_running(pid): -        print '[*] error: no running server found' -        exit(1) -    call([ -        args.executable, -        '-p %s' % pidfile,  # set the background PID FILE -        '-k'])  # kill the background process, will respawn if needed -    print '[-] stopped couch server with pid %d ' % pid - - -def couch_status_from_pidfile(args): -    status_from_pidfile(args, COUCH_BASEDIR, 'couch') - - -# -# User DB maintenance                                                        # -# - -def user_db_create(args): -    from leap.soledad.common.couch import CouchDatabase -    url = 'http://localhost:%d/user-%s' % (args.port, args.uuid) -    try: -        CouchDatabase.open_database( -            url=url, create=False, replica_uid=None) -        print '[*] error: database "user-%s" already exists' % args.uuid -        exit(1) -    except DatabaseDoesNotExist: -        CouchDatabase.open_database( -            url=url, create=True, replica_uid=None) -        print '[+] database created: user-%s' % args.uuid - - -def user_db_delete(args): -    s = _couch_get_server(args) -    try: -        dbname = 'user-%s' % args.uuid -        s.delete(dbname) -        print '[-] database deleted: %s' % dbname -    except ResourceNotFound: -        print '[*] error: database "%s" does not exist' % dbname -        exit(1) - - -# -# Soledad Server control -# - -TWISTD_EXECUTABLE = 'twistd'  # use whatever is available on path - -SOLEDAD_SERVER_BASEDIR = '/tmp/soledad_server_test' -SOLEDAD_SERVER_CONFIG_FILE = './conf/soledad_default.ini' -SOLEDAD_SERVER_PIDFILE = 'soledad.pid' -SOLEDAD_SERVER_LOGFILE = 'soledad.log' -SOLEDAD_SERVER_PRIVKEY = 'soledad_privkey.pem' -SOLEDAD_SERVER_CERTKEY = 'soledad_certkey.pem' -SOLEDAD_SERVER_PORT = 2424 -SOLEDAD_SERVER_AUTH_TOKEN = 'an-auth-token' -SOLEDAD_SERVER_URL = 'https://localhost:2424' - -SOLEDAD_CLIENT_PASS = '12345678' -SOLEDAD_CLIENT_BASEDIR = '/tmp/soledad_client_test' -SOLEDAD_CLIENT_UUID = '1234567890abcdef' - - -def soledad_server_start(args): -    basedir = _get_basedir(args, SOLEDAD_SERVER_BASEDIR) -    pidfile = os.path.join(basedir, args.pidfile) -    logfile = os.path.join(basedir, args.logfile) -    private_key = os.path.join(basedir, args.private_key) -    cert_key = os.path.join(basedir, args.cert_key) - -    pid = get_pid(pidfile) -    if pid_is_running(pid): -        pid = get_pid(pidfile) -        print "[*] error: already running - pid: %d" % pid -        exit(1) - -    port = args.port -    if args.tls: -        port = 'ssl:%d:privateKey=%s:certKey=%s:sslmethod=SSLv23_METHOD' \ -               % (args.port, private_key, cert_key) -    params = [ -        '--logfile=%s' % logfile, -        '--pidfile=%s' % pidfile, -        'web', -        '--wsgi=leap.soledad.server.application.wsgi_application', -        '--port=%s' % port -    ] -    if args.no_daemonize: -        params.insert(0, '--nodaemon') - -    call([args.executable] + params) - -    pid = get_pid(pidfile) -    print '[+] soledad-server is running with pid %d' % pid - - -def soledad_server_stop(args): -    basedir = _get_basedir(args, SOLEDAD_SERVER_BASEDIR) -    pidfile = os.path.join(basedir, args.pidfile) -    pid = get_pid(pidfile) -    if not pid_is_running(pid): -        print '[*] error: no running server found' -        exit(1) -    os.kill(pid, signal.SIGKILL) -    print '[-] stopped - pid: %d' % pid - - -def soledad_server_status_from_pidfile(args): -    status_from_pidfile(args, SOLEDAD_SERVER_BASEDIR, 'soledad-server') - - -# couch helpers - -def _couch_get_server(args): -    url = 'http://%s:%d/' % (args.host, args.port) -    return Server(url=url) - - -def _couch_create_db(args, dbname): -    s = _couch_get_server(args) -    # maybe create the database -    try: -        s.create(dbname) -        print '[+] database created: %s' % dbname -    except PreconditionFailed as e: -        error_code, _ = e.message -        if error_code == 'file_exists': -            print '[*] error: "%s" database already exists' % dbname -            exit(1) -    return s - - -def _couch_delete_db(args, dbname): -    s = _couch_get_server(args) -    # maybe create the database -    try: -        s.delete(dbname) -        print '[-] database deleted: %s' % dbname -    except ResourceNotFound: -        print '[*] error: "%s" database does not exist' % dbname -        exit(1) - - -def _token_dbname(): -    dbname = 'tokens_' + \ -        str(int(time.time() / (30 * 24 * 3600))) -    return dbname - - -def token_db_create(args): -    dbname = _token_dbname() -    _couch_create_db(args, dbname) - - -def token_db_insert_token(args): -    s = _couch_get_server(args) -    try: -        dbname = _token_dbname() -        db = s[dbname] -        token = sha512(args.auth_token).hexdigest() -        db[token] = { -            'type': 'Token', -            'user_id': args.uuid, -        } -        print '[+] token for uuid "%s" created in tokens database' % args.uuid -    except ResourceConflict: -        print '[*] error: token for uuid "%s" already exists in tokens database' \ -              % args.uuid -        exit(1) - - -def token_db_delete(args): -    dbname = _token_dbname() -    _couch_delete_db(args, dbname) - - -# -# Shared DB creation -# - -def shared_db_create(args): -    _couch_create_db(args, 'shared') - - -def shared_db_delete(args): -    _couch_delete_db(args, 'shared') - - -# -# Certificate creation -# - -CERT_CONFIG_FILE = os.path.join( -    os.path.dirname(os.path.realpath(__file__)), -    './conf/cert_default.conf') - - -def cert_create(args): -    private_key = os.path.join(args.basedir, args.private_key) -    cert_key = os.path.join(args.basedir, args.cert_key) -    try: -        os.mkdir(args.basedir) -    except OSError: -        pass -    call([ -        'openssl', -        'req', -        '-x509', -        '-sha256', -        '-nodes', -        '-days', '365', -        '-newkey', 'rsa:2048', -        '-config', args.config_file, -        '-keyout', private_key, -        '-out', cert_key]) - - -def cert_delete(args): -    private_key = os.path.join(args.basedir, args.private_key) -    cert_key = os.path.join(args.basedir, args.cert_key) -    try: -        os.unlink(private_key) -        os.unlink(cert_key) -    except OSError: -        pass - - -# -# Soledad Client Control -# - -def soledad_client_test(args): - -    # maybe infer missing parameters -    basedir = args.basedir -    if not basedir: -        basedir = tempfile.mkdtemp() -    server_url = args.server_url -    if not server_url: -        server_url = 'http://127.0.0.1:%d' % args.port - -    # get a soledad instance -    from client_side_db import _get_soledad_instance -    _get_soledad_instance( -        args.uuid, -        unicode(args.passphrase), -        basedir, -        server_url, -        args.cert_key, -        args.auth_token) - - -# -# Command Line Interface -# - -class Command(object): - -    def __init__(self, parser=ArgumentParser()): -        self.commands = [] -        self.parser = parser -        self.subparsers = None - -    def add_command(self, *args, **kwargs): -        # pop out the func parameter to use later -        func = None -        if 'func' in kwargs.keys(): -            func = kwargs.pop('func') -        # eventually create a subparser -        if not self.subparsers: -            self.subparsers = self.parser.add_subparsers() -        # create command and associate a function with it -        command = Command(self.subparsers.add_parser(*args, **kwargs)) -        if func: -            command.parser.set_defaults(func=func) -        self.commands.append(command) -        return command - -    def set_func(self, func): -        self.parser.set_defaults(func=func) - -    def add_argument(self, *args, **kwargs): -        self.parser.add_argument(*args, **kwargs) - -    def add_arguments(self, arglist): -        for args, kwargs in arglist: -            self.add_argument(*args, **kwargs) - -    def parse_args(self): -        return self.parser.parse_args() - - -# -# Command Line Interface -# - -def run_cli(): -    cli = Command() - -    # couch command with subcommands -    cmd_couch = cli.add_command('couch', help="manage couch server") - -    cmd_couch_start = cmd_couch.add_command('start', func=couch_server_start) -    cmd_couch_start.add_arguments([ -        (['--executable', '-e'], {'default': COUCH_EXECUTABLE}), -        (['--basedir', '-b'], {}), -        (['--config-file', '-c'], {}), -        (['--template', '-t'], {'default': COUCH_TEMPLATE}), -        (['--pidfile', '-p'], {'default': COUCH_PIDFILE}), -        (['--logfile', '-l'], {'default': COUCH_LOGFILE}) -    ]) - -    cmd_couch_stop = cmd_couch.add_command('stop', func=couch_server_stop) -    cmd_couch_stop.add_arguments([ -        (['--executable', '-e'], {'default': COUCH_EXECUTABLE}), -        (['--basedir', '-b'], {}), -        (['--pidfile', '-p'], {'default': COUCH_PIDFILE}), -    ]) - -    cmd_couch_status = cmd_couch.add_command( -        'status', func=couch_status_from_pidfile) -    cmd_couch_status.add_arguments([ -        (['--basedir', '-b'], {}), -        (['--pidfile', '-p'], {'default': COUCH_PIDFILE})]) - -    cmd_couch_kill = cmd_couch.add_command('kill', func=kill_all_executables) -    cmd_couch_kill.add_argument( -        '--executable', '-e', default=ERLANG_EXECUTABLE) - -    # user database maintenance -    cmd_user_db = cli.add_command('user-db') - -    cmd_user_db_create = cmd_user_db.add_command('create', func=user_db_create) -    cmd_user_db_create.add_arguments([ -        (['--host', '-H'], {'default': COUCH_HOST}), -        (['--port', '-P'], {'type': int, 'default': COUCH_PORT}), -        (['--uuid', '-u'], {'default': SOLEDAD_CLIENT_UUID}), -    ]) - -    cmd_user_db_create = cmd_user_db.add_command( -        'delete', func=user_db_delete) -    cmd_user_db_create.add_arguments([ -        (['--host', '-H'], {'default': COUCH_HOST}), -        (['--port', '-P'], {'type': int, 'default': COUCH_PORT}), -        (['--uuid', '-u'], {'default': SOLEDAD_CLIENT_UUID}) -    ]) - -    # soledad server command with subcommands -    cmd_sol_server = cli.add_command( -        'soledad-server', help="manage soledad server") - -    cmd_sol_server_start = cmd_sol_server.add_command( -        'start', func=soledad_server_start) -    cmd_sol_server_start.add_arguments([ -        (['--executable', '-e'], {'default': TWISTD_EXECUTABLE}), -        (['--config-file', '-c'], {'default': SOLEDAD_SERVER_CONFIG_FILE}), -        (['--pidfile', '-p'], {'default': SOLEDAD_SERVER_PIDFILE}), -        (['--logfile', '-l'], {'default': SOLEDAD_SERVER_LOGFILE}), -        (['--port', '-P'], {'type': int, 'default': SOLEDAD_SERVER_PORT}), -        (['--tls', '-t'], {'action': 'store_true'}), -        (['--private-key', '-K'], {'default': SOLEDAD_SERVER_PRIVKEY}), -        (['--cert-key', '-C'], {'default': SOLEDAD_SERVER_CERTKEY}), -        (['--no-daemonize', '-n'], {'action': 'store_true'}), -        (['--basedir', '-b'], {'default': SOLEDAD_SERVER_BASEDIR}), -    ]) - -    cmd_sol_server_stop = cmd_sol_server.add_command( -        'stop', func=soledad_server_stop) -    cmd_sol_server_stop.add_arguments([ -        (['--basedir', '-b'], {'default': SOLEDAD_SERVER_BASEDIR}), -        (['--pidfile', '-p'], {'default': SOLEDAD_SERVER_PIDFILE}), -    ]) - -    cmd_sol_server_status = cmd_sol_server.add_command( -        'status', func=soledad_server_status_from_pidfile) -    cmd_sol_server_status.add_arguments([ -        (['--basedir', '-b'], {'default': SOLEDAD_SERVER_BASEDIR}), -        (['--pidfile', '-p'], {'default': SOLEDAD_SERVER_PIDFILE}), -    ]) - -    cmd_sol_server_kill = cmd_sol_server.add_command( -        'kill', func=kill_all_executables) -    cmd_sol_server_kill.add_argument( -        '--executable', '-e', default=TWISTD_EXECUTABLE) - -    # token db maintenance -    cmd_token_db = cli.add_command('token-db') -    cmd_token_db_create = cmd_token_db.add_command( -        'create', func=token_db_create) -    cmd_token_db_create.add_arguments([ -        (['--host', '-H'], {'default': COUCH_HOST}), -        (['--uuid', '-u'], {'default': SOLEDAD_CLIENT_UUID}), -        (['--port', '-P'], {'type': int, 'default': COUCH_PORT}), -    ]) - -    cmd_token_db_insert_token = cmd_token_db.add_command( -        'insert-token', func=token_db_insert_token) -    cmd_token_db_insert_token.add_arguments([ -        (['--host', '-H'], {'default': COUCH_HOST}), -        (['--uuid', '-u'], {'default': SOLEDAD_CLIENT_UUID}), -        (['--port', '-P'], {'type': int, 'default': COUCH_PORT}), -        (['--auth-token', '-a'], {'default': SOLEDAD_SERVER_AUTH_TOKEN}), -    ]) - -    cmd_token_db_delete = cmd_token_db.add_command( -        'delete', func=token_db_delete) -    cmd_token_db_delete.add_arguments([ -        (['--host', '-H'], {'default': COUCH_HOST}), -        (['--uuid', '-u'], {'default': SOLEDAD_CLIENT_UUID}), -        (['--port', '-P'], {'type': int, 'default': COUCH_PORT}), -    ]) - -    # shared db creation -    cmd_shared_db = cli.add_command('shared-db') - -    cmd_shared_db_create = cmd_shared_db.add_command( -        'create', func=shared_db_create) -    cmd_shared_db_create.add_arguments([ -        (['--host', '-H'], {'default': COUCH_HOST}), -        (['--port', '-P'], {'type': int, 'default': COUCH_PORT}), -    ]) - -    cmd_shared_db_delete = cmd_shared_db.add_command( -        'delete', func=shared_db_delete) -    cmd_shared_db_delete.add_arguments([ -        (['--host', '-H'], {'default': COUCH_HOST}), -        (['--port', '-P'], {'type': int, 'default': COUCH_PORT}), -    ]) - -    # certificate generation -    cmd_cert = cli.add_command('cert', help="create tls certificates") - -    cmd_cert_create = cmd_cert.add_command('create', func=cert_create) -    cmd_cert_create.add_arguments([ -        (['--basedir', '-b'], {'default': SOLEDAD_SERVER_BASEDIR}), -        (['--config-file', '-c'], {'default': CERT_CONFIG_FILE}), -        (['--private-key', '-K'], {'default': SOLEDAD_SERVER_PRIVKEY}), -        (['--cert-key', '-C'], {'default': SOLEDAD_SERVER_CERTKEY}), -    ]) - -    cmd_cert_create = cmd_cert.add_command('delete', func=cert_delete) -    cmd_cert_create.add_arguments([ -        (['--basedir', '-b'], {'default': SOLEDAD_SERVER_BASEDIR}), -        (['--private-key', '-K'], {'default': SOLEDAD_SERVER_PRIVKEY}), -        (['--cert-key', '-C'], {'default': SOLEDAD_SERVER_CERTKEY}), -    ]) - -    # soledad client command with subcommands -    cmd_sol_client = cli.add_command( -        'soledad-client', help="manage soledad client") - -    cmd_sol_client_test = cmd_sol_client.add_command( -        'test', func=soledad_client_test) -    cmd_sol_client_test.add_arguments([ -        (['--port', '-P'], {'type': int, 'default': SOLEDAD_SERVER_PORT}), -        (['--tls', '-t'], {'action': 'store_true'}), -        (['--uuid', '-u'], {'default': SOLEDAD_CLIENT_UUID}), -        (['--passphrase', '-k'], {'default': SOLEDAD_CLIENT_PASS}), -        (['--basedir', '-b'], {'default': SOLEDAD_CLIENT_BASEDIR}), -        (['--server-url', '-s'], {'default': SOLEDAD_SERVER_URL}), -        (['--cert-key', '-C'], {'default': os.path.join( -            SOLEDAD_SERVER_BASEDIR, -            SOLEDAD_SERVER_CERTKEY)}), -        (['--auth-token', '-a'], {'default': SOLEDAD_SERVER_AUTH_TOKEN}), -    ]) - -    # parse and run cli -    args = cli.parse_args() -    args.func(args) - - -if __name__ == '__main__': -    run_cli()  | 
