This repository has been archived on 2020-06-17. You can view files and clone it, but cannot push or open issues or pull requests.
autonomic/autonomic/command/coophost.py

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))