Beispiel #1
0
def rbac(ctx, schema, object_filter, action, role, all_schemata):
    """[GROUP] Role based access control"""

    database = ctx.obj["db"]

    if schema is None:
        if all_schemata is False:
            log("No schema given. Read the RBAC group help", lvl=warn)
            sys.exit()
        else:
            schemata = database.objectmodels.keys()
    else:
        schemata = [schema]

    things = []

    if object_filter is None:
        parsed_filter = {}
    else:
        parsed_filter = json.loads(object_filter)

    for schema in schemata:
        for obj in database.objectmodels[schema].find(parsed_filter):
            things.append(obj)

    if len(things) == 0:
        log("No objects matched the criteria.", lvl=warn)
        sys.exit()

    ctx.obj["objects"] = things
    ctx.obj["action"] = action
    ctx.obj["role"] = role
Beispiel #2
0
def check_environment(ctx, dev):
    """General fitness tests of the built environment"""

    if _check_environment(ctx, dev=dev):
        log("Environment seems healthy")

    finish(ctx)
Beispiel #3
0
def modules(wip):
    """Install the plugin modules"""

    # TODO: Remove altogether, this should be done via instance/environment only

    install_modules(wip)
    log("Done: Install Modules")
Beispiel #4
0
def modify(ctx, schema, uuid, object_filter, field, value):
    """Modify field values of objects"""
    database = ctx.obj["db"]

    model = database.objectmodels[schema]
    obj = None

    if uuid:
        obj = model.find_one({"uuid": uuid})
    elif object_filter:
        obj = model.find_one(literal_eval(object_filter))
    else:
        log("No object uuid or filter specified.", lvl=error)

    if obj is None:
        log("No object found", lvl=error)
        return

    log("Object found, modifying", lvl=debug)
    try:
        new_value = literal_eval(value)
    except ValueError:
        log("Interpreting value as string")
        new_value = str(value)

    obj._fields[field] = new_value
    obj.validate()
    log("Changed object validated", lvl=debug)
    obj.save()
    finish(ctx)
Beispiel #5
0
def browser(ctx):
    """Tries to start or point a browser towards this instance's frontend"""
    instance_configuration = ctx.obj["instance_configuration"]

    server = instance_configuration.get("webserver", "internal")
    protocol = "http"

    if server != "internal":
        protocol += "s"

    host = instance_configuration.get(
        "web_hostname",
        instance_configuration.get("web", {}).get("address", "127.0.0.1"))
    port = instance_configuration.get("web", {}).get("port", None)

    if port is None:
        url = "%s://%s" % (protocol, host)
    else:
        url = "%s://%s:%i" % (protocol, host, port)

    log("Opening browser to:", url)
    log("If this is empty or unreachable, check your instance with:\n"
        "   iso instance info\n"
        "Also try the health checks:\n"
        "   iso instance check")

    webbrowser.open(url)
Beispiel #6
0
def view(ctx, schema, uuid, object_filter):
    """Show stored objects"""

    database = ctx.obj["db"]

    if schema is None:
        log("No schema given. Read the help", lvl=warn)
        return

    model = database.objectmodels[schema]

    if uuid:
        obj = model.find({"uuid": uuid})
    elif object_filter:
        obj = model.find(literal_eval(object_filter))
    else:
        obj = model.find()

    if obj is None or model.count() == 0:
        log("No objects found.", lvl=warn)

    for item in obj:
        pprint(item._fields)

    finish(ctx)
Beispiel #7
0
def install(ctx, **kwargs):
    """Install a new environment of an instance"""

    log("Installing instance")

    env = ctx.obj["instance_configuration"]["environments"]

    green = env["green"]["installed"]
    blue = env["blue"]["installed"]

    if green or blue:
        log(
            "At least one environment is installed or in a non-clear state.\n"
            "Please use 'iso instance upgrade' to upgrade an instance.",
            lvl=warn,
        )
        abort(50081)

    _clear_instance(ctx, force=kwargs["force"], clear=False, no_archive=True)

    _install_environment(ctx, **kwargs)

    ctx.obj["instance_configuration"]["source"] = kwargs["source"]
    ctx.obj["instance_configuration"]["url"] = kwargs["url"]

    write_instance(ctx.obj["instance_configuration"])

    _turnover(ctx, force=kwargs["force"])

    finish(ctx)
Beispiel #8
0
def validate(ctx, schema, all_schemata):
    """Validates all objects or all objects of a given schema."""

    database = ctx.obj["db"]

    if schema is None:
        if all_schemata is False:
            log("No schema given. Read the help", lvl=warn)
            return
        else:
            schemata = database.objectmodels.keys()
    else:
        schemata = [schema]

    for schema in schemata:
        try:
            things = database.objectmodels[schema]
            with click.progressbar(
                things.find(), length=things.count(), label="Validating %15s" % schema
            ) as object_bar:
                for obj in object_bar:
                    obj.validate()
        except Exception as e:

            log(
                "Exception while validating:",
                schema,
                e,
                type(e),
                "\n\nFix this object and rerun validation!",
                emitter="MANAGE",
                lvl=error,
            )

    finish(ctx)
Beispiel #9
0
def info(ctx):
    """Shows information about the selected remote"""

    if ctx.obj["host_config"]["login"]["password"] != "":
        ctx.obj["host_config"]["login"]["password"] = "******"

    log("Remote %s:" % ctx.obj["remote"], ctx.obj["host_config"], pretty=True)
Beispiel #10
0
        def gpio_switch_toggle():
            """Check by inspection of a GPIO pin for a closed switch"""

            log("Checking for override GPIO switch on channel ",
                RPI_GPIO_CHANNEL,
                lvl=debug)

            if platform != "rpi":
                log(
                    "Environment toggle: "
                    "GPIO switch can only be handled on Raspberry Pi!",
                    lvl=critical)
                return False
            else:
                try:
                    import RPi.GPIO as GPIO
                except ImportError:
                    log(
                        "RPi Python module not found. "
                        "This only works on a Raspberry Pi!",
                        lvl=critical)
                    return False

                GPIO.setmode(GPIO.BOARD)
                GPIO.setup(RPI_GPIO_CHANNEL, GPIO.IN)

                state = GPIO.input(RPI_GPIO_CHANNEL) is True

                if state:
                    log("Environment override switch active!", lvl=warn)
                else:
                    log("Environment override switch not active", lvl=debug)

                return state
Beispiel #11
0
def list_all(ctx):
    """List all available Mongo Databases on the configured database host."""
    from pymongo import MongoClient

    client = MongoClient(ctx.obj["dbhost"])
    log(client.list_database_names())

    finish(ctx)
Beispiel #12
0
def _install_backend(ctx):
    """Installs the backend into an environment"""

    instance_name = ctx.obj["instance"]
    env = get_next_environment(ctx)

    set_instance(instance_name, env)

    log("Installing backend on", env, lvl=debug)

    env_path = get_path("lib", "")
    user = ctx.obj["instance_configuration"]["user"]

    success, result = run_process(
        os.path.join(env_path, "repository"),
        [
            os.path.join(env_path, "venv", "bin", "python3"), "setup.py",
            "develop"
        ],
        sudo=user,
    )
    if not success:
        output = str(result)

        if "was unable to detect version" in output:
            log(
                "Installing from dirty repository. This might result in dependency "
                "version problems!",
                lvl=hilight,
            )
        else:
            log(
                "Something unexpected happened during backend installation:\n",
                result,
                lvl=hilight,
            )

        # TODO: Another fault might be an unclean package path.
        #  But i forgot the log message to check for.
        # log('This might be a problem due to unclean installations of Python'
        #     ' libraries. Please check your path.')

    log("Installing requirements")
    success, result = run_process(
        os.path.join(env_path, "repository"),
        [
            os.path.join(env_path, "venv", "bin", "pip3"),
            "install",
            "-r",
            "requirements.txt",
        ],
        sudo=user,
    )
    if not success:
        log(format_result(result), lvl=error)

    return True
Beispiel #13
0
def remove_instance(instance_configuration):
    """Remove the configuration file for an instance"""

    filename = os.path.join(get_etc_instance_path(), instance_configuration + ".conf")
    if os.path.exists(filename):
        log("Removing instance", instance_configuration)
        os.remove(filename)
    else:
        log("Instance not found.")
Beispiel #14
0
def versions(ctx, source, url, fetch):
    """Check instance sources for installable versions"""

    releases = _get_versions(ctx, source, url, fetch)

    releases_keys = sorted_alphanumerical(releases.keys())

    log("Available Isomer releases:", releases_keys, pretty=True)
    log("Latest:", releases_keys[-1])
Beispiel #15
0
def load_instance(instance):
    """Read a single instance configuration"""

    file = os.path.join(get_etc_instance_path(), instance + ".conf")
    with open(file) as f:
        config = loads(f.read())
        log("Instance configuration'", instance, "'loaded.", lvl=debug)

    return config
Beispiel #16
0
def create_user(ctx):
    """Creates a new local user"""

    try:
        new_user = _create_user(ctx)

        new_user.save()
        finish(ctx)
    except KeyError:
        log("User already exists", lvl=warn)
Beispiel #17
0
def archive(ctx, force, dynamic):
    """Archive the specified or non-active environment"""

    result = _archive(ctx, force, dynamic)
    if result:
        log("Archived to '%s'" % result)
        finish(ctx)
    else:
        log("Could not archive.", lvl=error)
        abort(50060)
Beispiel #18
0
def test(ctx):
    """Run and return info command on a remote"""

    shell = ctx.obj["shell"]
    username = ctx.obj["host_config"]["login"]["username"]

    success, result = run_process(get_remote_home(username),
                                  ["iso", "-nc", "version"],
                                  shell=shell)
    log(success, "\n", format_result(result), pretty=True)
Beispiel #19
0
def create_admin(ctx):
    """Creates a new local user and assigns admin role"""

    try:
        admin = _create_user(ctx)
        admin.roles.append("admin")

        admin.save()
        finish(ctx)
    except KeyError:
        log("User already exists", lvl=warn)
Beispiel #20
0
def load_remotes():
    """Read the remote system configurations"""

    config = {}

    for root, _, files in os.walk(get_etc_remote_path()):
        for file in files:
            with open(os.path.join(root, file)) as f:
                config[file.rstrip(".conf")] = loads(f.read())
                log("Remote configuration loaded.", lvl=debug)

    return config
Beispiel #21
0
def enable(ctx):
    """Enable an existing user"""

    if ctx.obj["username"] is None:
        log('Specify the username with "iso db user --username ..."')
        return

    change_user = (ctx.obj["db"].objectmodels["user"].find_one(
        {"name": ctx.obj["username"]}))

    change_user.active = True
    change_user.save()
    finish(ctx)
Beispiel #22
0
def dependencies(ctx):
    """Install Isomer platform dependencies"""

    log("Installing platform dependencies")

    install_isomer(
        ctx.obj["platform"],
        ctx.obj["use_sudo"],
        show=ctx.obj["log_actions"],
        omit_platform=ctx.obj['platform'],
        omit_common=True,
    )

    finish(ctx)
Beispiel #23
0
def remote(ctx, name, install, platform, source, url, existing):
    """Remote instance control (Work in Progress!)"""

    ctx.obj["remote"] = name
    ctx.obj["platform"] = platform
    ctx.obj["source"] = source
    ctx.obj["url"] = url
    ctx.obj["existing"] = existing

    if ctx.invoked_subcommand == "add":
        return

    remotes = ctx.obj["remotes"] = load_remotes()

    if ctx.invoked_subcommand == "list":
        return

    # log('Remote configurations:', remotes, pretty=True)

    host_config = remotes.get(name, None)

    if host_config is None:
        log("Cannot proceed, remote unknown", lvl=error)
        abort(5000)

    ctx.obj["host_config"] = host_config

    if platform is None:
        platform = ctx.obj["host_config"].get("platform", "debian")
    ctx.obj["platform"] = platform

    spur_config = dict(host_config["login"])

    if spur_config["private_key_file"] == "":
        spur_config.pop("private_key_file")

    if spur_config["port"] != 22:
        log(
            "Warning! Using any port other than 22 is not supported right now.",
            lvl=warn,
        )

    spur_config.pop("port")

    shell = spur.SshShell(**spur_config)

    if install:
        success, result = run_process("/", ["iso", "info"], shell)
        if success:
            log("Isomer version on remote:", format_result(result))
        else:
            log('Use "remote install" for now')
            # if existing is None:
            #     get_isomer(source, url, '/root', shell=shell)
            #     destination = '/' + host_config['login']['username'] + '/repository'
            # else:
            #     destination = existing
            # install_isomer(platform, host_config.get('use_sudo', True), shell, cwd=destination)

    ctx.obj["shell"] = shell
Beispiel #24
0
def write_remote(remote):
    """Write a new or updated remote"""

    filename = os.path.join(get_etc_remote_path(), remote["name"] + ".conf")
    try:
        with open(filename, "w") as f:
            f.write(dumps(remote))
        log("Instance configuration stored.", lvl=debug)
    except PermissionError:
        log(
            "PermissionError: Could not write instance management configuration file",
            lvl=error,
        )
        abort(EXIT_NO_PERMISSION)
Beispiel #25
0
def remove(ctx, clear, no_archive):
    """Irrevocably remove a whole instance"""

    if clear:
        log("Destructively removing instance:", ctx.obj["instance"], lvl=warn)

    if not ask("Are you sure", default=False, data_type="bool"):
        abort(EXIT_USER_BAILED_OUT)

    if clear:
        _clear_instance(ctx, force=True, clear=clear, no_archive=no_archive)

    remove_instance(ctx.obj["instance"])
    finish(ctx)
Beispiel #26
0
def load_configuration():
    """Read the main system configuration"""

    filename = os.path.join(get_etc_path(), "isomer.conf")

    try:
        with open(filename, "r") as f:
            config = loads(f.read())
            log("Isomer configuration loaded.", lvl=debug)
    except FileNotFoundError:
        log("Configuration not found.", lvl=warn)
        return None

    return config
Beispiel #27
0
def _add_system_user(use_sudo=False):
    """instance Isomer system user (isomer.isomer)"""

    command = [
        "/usr/sbin/adduser",
        "--system",
        "--quiet",
        "--home",
        "/var/run/isomer",
        "--group",
        "--disabled-password",
        "--disabled-login",
        "isomer",
    ]

    success, output = run_process("/", command, sudo=use_sudo)
    if success is False:
        log("Error adding system user:"******"/usr/sbin/adduser", "isomer", "dialout"]

    success, output = run_process("/", command, sudo=use_sudo)
    if success is False:
        log("Error adding system user to dialout group:", lvl=error)
        log(output, lvl=error)

    time.sleep(2)
Beispiel #28
0
def write_instance(instance_configuration):
    """Write a new or updated instance"""

    instance_name = instance_configuration["name"]

    instance_file = os.path.join(
        get_etc_instance_path(), instance_name + ".conf"
    )
    instance_directory = os.path.join(get_etc_instance_path(), instance_name)
    try:
        log("Configuration:", instance_configuration, pretty=True, lvl=debug)
        with open(instance_file, "w") as f:
            f.write(dumps(instance_configuration))
        log("Instance configuration stored.", lvl=debug)

        if not os.path.exists(instance_directory):
            os.mkdir(instance_directory)
            log("Instance configuration directory created.", lvl=debug)
    except PermissionError:
        log(
            "PermissionError: Could not write instance management configuration "
            "file or create instance configuration directory.",
            lvl=error,
        )
        abort(EXIT_NO_PERMISSION)
Beispiel #29
0
def format_template(template, content):
    """Render a given pystache template
    with given content"""

    import pystache

    result = u""
    try:
        result = pystache.render(template, content, string_encoding="utf-8")
    except (ValueError, KeyError) as e:
        log("Templating error:", e, type(e), exc=True, lvl=error)

    # pprint(result)
    return result
Beispiel #30
0
def events():
    """List all known authorized and anonymous events"""

    from isomer.events.system import (
        get_anonymous_events,
        get_user_events,
        populate_user_events,
    )

    populate_user_events()

    event_list = {**get_user_events(), **get_anonymous_events()}

    log("Events:\n", event_list, pretty=True)