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


#!/usr/bin/env python3

import argparse
import base64
import os
from pathlib import Path

import hvac
from jinja2 import Environment, FileSystemLoader

def log(msg):
    print(f"[ОК] {msg}")


# ============================================================
# VAULT LOGIN
# ============================================================

def vault_login():
    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")

    return client


# ============================================================
# VAULT READ
# ============================================================

def read_secret(client, path):
    response = client.secrets.kv.v2.read_secret_version(
        mount_point=os.environ["VAULT_MOUNT"],
        path=path,
        raise_on_deleted_version=True
    )
    return response["data"]["data"]


# ============================================================
# WRITE HELPERS
# ============================================================

def write_text(path: Path, content: str):
    path.parent.mkdir(parents=True, exist_ok=True)
    if not content:
        raise ValueError(f"Пустой текст: {path}")
    path.write_text(content)


def write_binary(path: Path, content: bytes):
    path.parent.mkdir(parents=True, exist_ok=True)
    if not content:
        raise ValueError(f"Пустой бинарный файл: {path}")
    path.write_bytes(content)


# ============================================================
# RENDER TEMPLATE (исправленная версия)
# ============================================================

def render_template(root: Path, template_name: str, output_path: Path, **context):
    """Рендерит шаблон относительно папки templates в APP_PATH"""
    templates_dir = root / "templates"
    
    print(f"[DEBUG] Рендерим шаблон {template_name} из {templates_dir}")

    if not templates_dir.exists():
        raise RuntimeError(f"Папка templates не найдена по пути: {templates_dir}")

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

    template = jinja.get_template(template_name)
    rendered = template.render(**context)

    write_text(output_path, rendered)
    log(f"Шаблон {template_name} успешно сгенерирован")


# ============================================================
# KERBEROS
# ============================================================

def build_kerberos(root: Path, k5: dict):
    keytab_b64 = k5.get("mailarchive.keytab")
    if not keytab_b64:
        raise RuntimeError("Нет keytab в Vault")

    # ---------------- KEYTAB ----------------
    write_binary(
        root / "kerberos-ma" / "mailarchive.keytab",
        base64.b64decode(keytab_b64)
    )
    log("Kerberos keytab сохранён")

    # ---------------- ENTRYPOINT ----------------
    principal = k5.get("KRB_PRINCIPAL")
    if not principal:
        raise RuntimeError("Нет KRB_PRINCIPAL в Vault")

    render_template(
        root,
        "entrypoint.sh.j2",
        root / "kerberos-ma" / "entrypoint.sh",
        KRB_PRINCIPAL=principal
    )


# ============================================================
# MAIN
# ============================================================

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--env", choices=["dev", "stage", "prod"], required=True)
    args = parser.parse_args()

    env = args.env

    # ==================== DEBUG (можно потом убрать) ====================
    print("=== DEBUG INFO ===")
    print("cwd:", os.getcwd())
    print("APP_PATH:", os.environ.get("APP_PATH"))
    root = Path(os.environ["APP_PATH"])
    print("root exists:", root.exists())
    print("templates exists:", (root / "templates").exists())
    # =================================================================

    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")
    db = read_secret(client, f"{base}/db")

    root = Path(os.environ["APP_PATH"])

    # ============================================================
    # DJANGO
    # ============================================================
    write_text(
        root / "django-ma/src/.env",
        django.get(".env")
    )
    log("Django .env создан")

    # ============================================================
    # KERBEROS
    # ============================================================
    build_kerberos(root, k5)

    # ============================================================
    # DB
    # ============================================================
    write_text(
        root / "django-ma/pg_service.conf",
        db.get("pg_service.conf")
    )
    log("DB конфиг создан")

    # ============================================================
    # WEBSERVER
    # ============================================================
    wd = root

    apache_ssl_dir = wd / "apache-ma/ssl"
    apache_keytab_dir = wd / "apache-ma/keytab"
    apache_conf_dir = wd / "apache-ma/conf/sites-enabled"

    # ---------------- CERTS ----------------
    if webserver.get("tls.crt"):
        write_text(apache_ssl_dir / "tls.crt", webserver["tls.crt"])
    if webserver.get("tls.key"):
        write_text(apache_ssl_dir / "tls.key", webserver["tls.key"])
    log("Apache TLS сертификаты сохранены")

    # ---------------- KEYTAB ----------------
    keytab = webserver.get("infradev.keytab")
    if keytab:
        write_binary(
            apache_keytab_dir / "infradev.keytab",
            base64.b64decode(keytab)
        )
    log("Apache keytab сохранён")

    # ---------------- CONFIG ----------------
    render_template(
        root,
        "mailarchive.conf.j2",
        apache_conf_dir / "mailarchive.conf",
        **webserver
    )

    # ============================================================
    # DONE
    # ============================================================
    log(f"Секреты получены для окружения: {env}")


if __name__ == "__main__":
    main()