Skip to content

Commit

Permalink
Initial commit of SOPS encryption logic
Browse files Browse the repository at this point in the history
  • Loading branch information
A.J. Herbert committed Apr 27, 2018
1 parent 4ddab2e commit a7da708
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 0 deletions.
17 changes: 17 additions & 0 deletions forge/cli.py
Expand Up @@ -31,6 +31,7 @@
from . import __version__
from .core import Forge
from .kubernetes import Kubernetes
from .sops import edit_secret, view_secret
from collections import OrderedDict

ENV = find_dotenv(usecwd=True)
Expand Down Expand Up @@ -163,6 +164,22 @@ def manifests(forge):
"""
forge.execute(forge.manifest)

@forge.command()
@click.argument("file_path", required=True, type=click.Path(exists=True))
def edit(file_path):
"""
Edit a secret file.
"""
edit_secret(file_path)

@forge.command()
@click.argument("file_path", required=True, type=click.Path(exists=True))
def view(file_path):
"""
View a secret file.
"""
view_secret(file_path)

@forge.command()
@click.pass_obj
@click.option('-n', '--namespace', envvar='K8S_NAMESPACE', type=click.STRING)
Expand Down
9 changes: 9 additions & 0 deletions forge/jinja2.py
Expand Up @@ -14,6 +14,7 @@

from __future__ import absolute_import

from .sops import decrypt, decrypt_cleanup
from .tasks import task, TaskError
from jinja2 import Environment, FileSystemLoader, Template, TemplateError, TemplateNotFound, Undefined, UndefinedError
import os, shutil
Expand Down Expand Up @@ -99,6 +100,8 @@ def render(source, target, predicate, **variables):
for path, dirs, files in os.walk(source):
for name in files:
if not predicate(name): continue
if name.endswith("-enc.yaml"):
decrypt(path, name)
relpath = os.path.join(os.path.relpath(path, start=source), name)
rendered = _do_render(env, root, relpath, variables)
outfile = os.path.join(target, relpath)
Expand All @@ -107,10 +110,16 @@ def render(source, target, predicate, **variables):
os.makedirs(outdir)
with open(outfile, "write") as f:
f.write(rendered)
if name.endswith("-enc.yaml"):
decrypt_cleanup(path, name)
else:
if name.endswith("-enc.yaml"):
decrypt(path, name)
rendered = _do_render(env, root, os.path.basename(source), variables)
with open(target, "write") as f:
f.write(rendered)
if name.endswith("-enc.yaml"):
decrypt_cleanup(path, name)

@task()
def renders(name, source, **variables):
Expand Down
30 changes: 30 additions & 0 deletions forge/sops.py
@@ -0,0 +1,30 @@
import os
import subprocess
import sys


def key_check():
if not os.getenv('SOPS_KMS_ARN'):
sys.exit("You must obtain the master key and export it in the 'SOPS_KMS_ARN' environment variable")

def decrypt(secret_file_dir, secret_file_name):
key_check()
secret_file_path = os.path.join(secret_file_dir, secret_file_name)
temp_secret_file_path = os.path.join(secret_file_dir, "tmp-" + secret_file_name)
os.rename(secret_file_path, temp_secret_file_path)
with open(secret_file_path, "w") as decrypted_file:
subprocess.call(["sops", "-d", temp_secret_file_path], stdout=decrypted_file)

def decrypt_cleanup(secret_file_dir, secret_file_name):
secret_file_path = os.path.join(secret_file_dir, secret_file_name)
temp_secret_file_path = os.path.join(secret_file_dir, "tmp-" + secret_file_name)
os.remove(secret_file_path)
os.rename(temp_secret_file_path, secret_file_path)

def edit_secret(secret_file_path):
key_check()
subprocess.call(["sops", secret_file_path])

def view_secret(secret_file_path):
key_check()
subprocess.call(["sops", "-d", secret_file_path])

0 comments on commit a7da708

Please sign in to comment.