예제 #1
0
파일: etc.py 프로젝트: isomeric/isomer
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)
예제 #2
0
파일: etc.py 프로젝트: isomeric/isomer
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.")
예제 #3
0
파일: etc.py 프로젝트: isomeric/isomer
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
예제 #4
0
파일: etc.py 프로젝트: isomeric/isomer
def load_instances():
    """Read the instance configurations"""

    config = {}

    pattern = get_etc_instance_path() + "/*.conf"
    log("Loading all instance configuration files:", pattern, lvl=debug)

    for name in glob.glob(pattern):

        with open(name) as f:
            instance_name = os.path.basename(name).split(".")[0]
            config[instance_name] = loads(f.read())
            log("Instance configuration '", instance_name, "'loaded.", lvl=debug)

    return config
예제 #5
0
def create_configuration(ctx):
    """Creates an initial configuration"""
    log("Creating new configuration from template", lvl=verbose)

    if not os.path.exists(get_etc_path()):
        try:
            os.makedirs(get_etc_path())
            os.makedirs(get_etc_instance_path())
            os.makedirs(get_etc_remote_path())
            os.makedirs(get_etc_remote_keys_path())
        except PermissionError:
            log(
                'PermissionError: Could not create configuration directory "%s"'
                % get_etc_path(),
                lvl=warn,
            )
            warn_error(EXIT_NO_PERMISSION)

    ctx.obj["config"] = configuration_template

    return ctx
예제 #6
0
def _instance_selfsigned(instance_configuration):
    """Generates a snakeoil certificate that has only been self signed"""

    log("Generating self signed certificate/key combination")

    try:
        os.mkdir("/etc/ssl/certs/isomer")
    except FileExistsError:
        pass
    except PermissionError:
        log("Need root (e.g. via sudo) to generate ssl certificate")
        abort(1)

    try:
        from OpenSSL import crypto
    except ImportError:
        log("Need python3-openssl to do this.")
        abort(1)
        return

    def create_self_signed_cert(target):
        """Create a simple self signed SSL certificate"""

        key_file = os.path.join(target, "selfsigned.key")
        cert_file = os.path.join(target, "selfsigned.crt")
        combined_file = os.path.join(target, "selfsigned.pem")

        web_section = instance_configuration['web']

        cert_conf = {
            k: v
            for k, v in web_section.items() if k.startswith("certificate")
        }

        log("Certificate data:", cert_conf, pretty=True)

        hostname = instance_configuration.get("web",
                                              {}).get("hostnames",
                                                      gethostname())
        if isinstance(hostname, list):
            hostname = hostname[0]

        # create a key pair
        k = crypto.PKey()
        k.generate_key(crypto.TYPE_RSA, 2048)

        if os.path.exists(cert_file):
            try:
                certificate = open(cert_file, "rb").read()
                old_cert = crypto.load_certificate(crypto.FILETYPE_PEM,
                                                   certificate)
                serial = old_cert.get_serial_number() + 1
            except (crypto.Error, OSError) as e:
                log(
                    "Could not read old certificate to increment serial:",
                    type(e),
                    e,
                    exc=True,
                    lvl=warn,
                )
                serial = 1
        else:
            serial = 1

        # create a self-signed certificate
        certificate = crypto.X509()
        certificate.get_subject().C = cert_conf.get("certificate_country",
                                                    "EU")
        certificate.get_subject().ST = cert_conf.get("certificate_state",
                                                     "Sol")
        certificate.get_subject().L = cert_conf.get("certificate_location",
                                                    "Earth")
        # noinspection PyPep8
        certificate.get_subject().O = cert_conf.get("certificate_issuer",
                                                    "Unknown")
        certificate.get_subject().OU = cert_conf.get("certificate_unit",
                                                     "Unknown")
        certificate.get_subject().CN = hostname
        certificate.set_serial_number(serial)
        certificate.gmtime_adj_notBefore(0)
        certificate.gmtime_adj_notAfter(10 * 365 * 24 * 60 * 60)
        certificate.set_issuer(certificate.get_subject())
        certificate.set_pubkey(k)
        certificate.sign(k, "sha512")

        open(key_file, "wt").write(
            str(crypto.dump_privatekey(crypto.FILETYPE_PEM, k),
                encoding="ASCII"))

        open(cert_file, "wt").write(
            str(
                crypto.dump_certificate(crypto.FILETYPE_PEM, certificate),
                encoding="ASCII",
            ))

        open(combined_file, "wt").write(
            str(
                crypto.dump_certificate(crypto.FILETYPE_PEM, certificate),
                encoding="ASCII",
            ) + str(crypto.dump_privatekey(crypto.FILETYPE_PEM, k),
                    encoding="ASCII"))

    location = os.path.join(get_etc_instance_path(),
                            instance_configuration.get("name"))

    create_self_signed_cert(location)

    instance_configuration["web"]["key"] = os.path.join(
        location, "selfsigned.key")
    instance_configuration["web"]["certificate"] = os.path.join(
        location, "selfsigned.crt")

    write_instance(instance_configuration)
예제 #7
0
def _archive(ctx, force=False, dynamic=False):
    instance_configuration = ctx.obj["instance_configuration"]

    next_environment = get_next_environment(ctx)

    env = instance_configuration["environments"][next_environment]

    log("Instance info:",
        instance_configuration,
        next_environment,
        pretty=True,
        lvl=debug)
    log("Installed:", env["installed"], "Tested:", env["tested"], lvl=debug)

    if (not env["installed"] or not env["tested"]) and not force:
        log("Environment has not been installed - not archiving.", lvl=warn)
        return False

    log("Archiving environment:", next_environment)
    set_instance(ctx.obj["instance"], next_environment)

    timestamp = std_now().replace(":", "-").replace(".", "-")

    temp_path = mkdtemp(prefix="isomer_backup")

    log("Archiving database")
    if not dump(
            instance_configuration["database_host"],
            instance_configuration["database_port"],
            env["database"],
            os.path.join(temp_path, "db_" + timestamp + ".json"),
    ):
        if not force:
            log("Could not archive database.")
            return False

    archive_filename = os.path.join(
        "/var/backups/isomer/",
        "%s_%s_%s.tgz" % (ctx.obj["instance"], next_environment, timestamp),
    )

    try:
        shutil.copy(
            os.path.join(get_etc_instance_path(),
                         ctx.obj["instance"] + ".conf"),
            temp_path,
        )

        with tarfile.open(archive_filename, "w:gz") as f:
            if not dynamic:
                for item in locations:
                    path = get_path(item, "")
                    log("Archiving [%s]: %s" % (item, path))
                    f.add(path)
            f.add(temp_path, "db_etc")
    except (PermissionError, FileNotFoundError) as e:
        log("Could not archive environment:", e, lvl=error)
        if not force:
            return False
    finally:
        log("Clearing temporary backup target")
        shutil.rmtree(temp_path)

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

    log(ctx.obj["instance_configuration"])

    return archive_filename