137 lines
3.5 KiB
Python
137 lines
3.5 KiB
Python
"""CoopHost module."""
|
|
|
|
from os import chdir, mkdir
|
|
from os.path import basename, exists
|
|
from pathlib import Path
|
|
from socket import gethostname
|
|
|
|
import click
|
|
|
|
from autonomic.config import CONFIG_YAML, INFRA_DIR
|
|
from autonomic.logger import log
|
|
from autonomic.settings import add, get
|
|
from autonomic.utils import (
|
|
ensure_config_dir,
|
|
ensure_deploy_d_dir,
|
|
exit,
|
|
input_ask,
|
|
pass_ask,
|
|
question_ask,
|
|
run,
|
|
yaml_dump,
|
|
yaml_load,
|
|
)
|
|
|
|
hostname = gethostname()
|
|
|
|
|
|
@click.command()
|
|
@click.pass_context
|
|
def coophost(ctx):
|
|
"""Manage CoopHost resources."""
|
|
ensure_config_dir()
|
|
ensure_deploy_d_dir()
|
|
|
|
app_dir = Path(".").absolute()
|
|
app = basename(app_dir)
|
|
log.info("Auto-detected the {} application".format(app))
|
|
|
|
choices = ["encrypt", "decrypt"]
|
|
operation = question_ask("operation", "Which operation?", choices)
|
|
|
|
if operation == "encrypt":
|
|
encrypt(app, app_dir)
|
|
elif operation == "decrypt":
|
|
decrypt(app, app_dir)
|
|
|
|
|
|
def get_vault_pass(app):
|
|
"""Retrieve or set the app vault password."""
|
|
app_settings = get(app)
|
|
|
|
if app_settings is not None and "vault-password" in app_settings:
|
|
log.info("Using app vault password stored in {}".format(CONFIG_YAML))
|
|
return app_settings["vault-password"]
|
|
|
|
log.info("No app vault password configured")
|
|
vault_password = pass_ask("Vault password?")
|
|
|
|
log.info("App vault password stored in {}".format(CONFIG_YAML))
|
|
add({app: {"vault-password": vault_password}})
|
|
|
|
return vault_password
|
|
|
|
|
|
def decrypt(app, app_dir):
|
|
"""Decrypt a secret."""
|
|
vault_password = get_vault_pass(app)
|
|
name = input_ask("Which variable do you want to decrypt?")
|
|
|
|
vault_path = (Path(".") / "deploy.d" / "vault").absolute()
|
|
var_path = (vault_path / "{}.yml".format(name)).absolute()
|
|
|
|
if not exists(var_path):
|
|
exit("{}.yml is missing?".format(name))
|
|
|
|
cmd = [
|
|
".venv/bin/ansible",
|
|
hostname,
|
|
"--inventory",
|
|
"{},".format(hostname),
|
|
"-m",
|
|
"debug",
|
|
"-a",
|
|
"var='{}'".format(name),
|
|
"-e @{}".format(var_path),
|
|
"--ask-vault-pass",
|
|
"-e",
|
|
"ansible_user={}".format(get("username")),
|
|
]
|
|
|
|
decrypted = run(
|
|
cmd,
|
|
cwd=INFRA_DIR,
|
|
output=True,
|
|
pexpect=True,
|
|
pexpected={"(?i)vault password:": vault_password},
|
|
)
|
|
|
|
log.info(decrypted)
|
|
|
|
|
|
def encrypt(app, app_dir):
|
|
"""Encrypt a secret for a CoopHost package."""
|
|
vault_password = get_vault_pass(app)
|
|
name = input_ask("Which variable do you want to encrypt?")
|
|
value = pass_ask("Variable value to encrypt?")
|
|
|
|
cmd = [".venv/bin/ansible-vault", "encrypt_string", "--name", name, value]
|
|
encrypted = run(
|
|
cmd,
|
|
cwd=INFRA_DIR,
|
|
pexpect=True,
|
|
pexpected={
|
|
"(?i)new vault password:": vault_password,
|
|
"(?i)confirm new vault password:": vault_password,
|
|
},
|
|
)
|
|
encrypted = (
|
|
encrypted.strip()
|
|
.replace("\r", "")
|
|
.replace("\nEncryption successful", "")
|
|
)
|
|
|
|
chdir(app_dir)
|
|
log.info("Changed directory back to {}".format(app_dir))
|
|
|
|
vault_path = (Path(".") / "deploy.d" / "vault").absolute()
|
|
if not exists(vault_path):
|
|
log.info("Creating {}".format(vault_path))
|
|
mkdir(vault_path)
|
|
|
|
var_path = (vault_path / "{}.yml".format(name)).absolute()
|
|
with open(var_path, "w"):
|
|
loaded = yaml_load(encrypted, text=True)
|
|
yaml_dump(var_path, loaded)
|
|
log.success("Encrypted and saved {} in {}".format(name, var_path))
|