Загрузка данных


#!/usr/bin/env python3

import argparse
import base64
import os
import hvac

from dotenv import load_dotenv
from pathlib import Path
from jinja2 import Environment, FileSystemLoader
from pathlib import Path

VAULT_MOUNT = "it-infradev"

def vault_login():
    """
    LDAP login в Vault.
    """

    client = hvac.Client(
        url=os.environ["VAULT_ADDR"]
    )

    login = client.auth.ldap.login(
        username=os.environ["VAULT_USERNAME"],
        password=os.environ["VAULT_PASSWORD"]
    )

    client.token = login["auth"]["client_token"]

    if not client.is_authenticated():
        raise RuntimeError(
            "Vault authentication failed"
        )

    return client


def read_secret(client, path):

    response = (
        client.secrets.kv.v2.read_secret_version(
            mount_point=VAULT_MOUNT,
            path=path
        )
    )

    return response["data"]["data"]


def write_text(path, content):

    path.parent.mkdir(
        parents=True,
        exist_ok=True
    )

    with open(path, "w") as f:
        f.write(content)


def write_binary(path, content):

    path.parent.mkdir(
        parents=True,
        exist_ok=True
    )

    with open(path, "wb") as f:
        f.write(content)


def main():

    load_dotenv()

    parser = argparse.ArgumentParser()

    parser.add_argument(
        "--env",
        choices=["dev", "stage", "prod"],
        required=True
    )

    args = parser.parse_args()

    env = args.env

    client = vault_login()

    base = f"projects/mailarchive/{env}"


    django = read_secret(
        client,
        f"{base}/django"
    )

    webserver = read_secret(
        client,
        f"{base}/webserver"
    )

    k5 = read_secret(
        client,
        f"{base}/k5-ma-client"
    )

    k5 = read_secret(
        client,
        f"{base}/db"
    )


    build_dir = Path("build")

    ####################################################################
    # DJANGO
    ####################################################################

    #
    # Предполагается что в Vault лежит поле:
    #
    # env
    #

    write_text(
        build_dir /
        "django-ma/src" /
        ".env",
        django["env"]
    )

    ####################################################################
    # K5 CLIENT
    ####################################################################

    #
    # Предполагается:
    #
    # principal
    # keytab
    #

    write_text(
        build_dir /
        "kerberos-ma" /
        "KRB_PRINCIPAL",
        k5["mailarchive.keytab"]
    )

    write_binary(
        build_dir /
        "k5-ma-client" /
        "mailarchive.keytab",
        base64.b64decode(
            k5["mailarchive.keytab"]
        )
    )

def prepare_webserver(repo_dir, webserver: dict):
    """
    Webserver build assets:

    Vault структура:
    - ssl_cert (PEM text)
    - ssl_key (PEM text)
    - ssl_ca (PEM text, optional)

    - ldap_keytab (base64)
    - gssapi_keytab (base64, optional)

    - все остальные поля = для vhost.j2
    """

    build_dir = Path(repo_dir) / ".build" / "webserver"
    build_dir.mkdir(parents=True, exist_ok=True)

    ####################################################################
    # 1. CERTS 
    ####################################################################

    if webserver.get("tls.crt"):
        (build_dir / "tls.crt").write_text(
            webserver["tls.crt"]
        )

    if webserver.get("tls.key"):
        (build_dir / "tls.key").write_text(
            webserver["tls.key"]
        )

    if webserver.get("ssl_ca"):
        (build_dir / "ca-bundle.pem").write_text(
            webserver["ssl_ca"]
        )

    ####################################################################
    # 2. KEYTAB
    ####################################################################

    if webserver.get("infradev.keytab"):
        (build_dir / "infradev.keytab").write_bytes(
            base64.b64decode(webserver["infradev.keytab"])
        )

    ####################################################################
    # 3. VHOST TEMPLATE RENDER
    ####################################################################

    templates_dir = Path(repo_dir) / "templates"

    env = Environment(
        loader=FileSystemLoader(str(templates_dir)),
        autoescape=False
    )

    template = env.get_template("vhost.conf.j2")

    rendered = template.render(**webserver)

    (build_dir / "vhost.conf").write_text(rendered)

    ####################################################################
    # 4. DEBUG 
    ####################################################################

    print("\n[webserver] vault keys:")
    for k in webserver.keys():
        print(" -", k)

    print(f"\n[webserver] build output: {build_dir}")


    print()
    print("Secrets downloaded successfully")
    print(f"Environment: {env}")
    print(f"Output dir: {build_dir.resolve()}")


if __name__ == "__main__":
    main()