modules/crypto.py (57 lines of code) (raw):

import json import os from cryptography.fernet import Fernet def get_key(): return os.environ.get("SVC_ACCT_DECRYPT").encode() def encrypt(source_file: str, target_file="", overwrite=False) -> str: """Encrypt an existing file, place in data/secrets""" if not target_file: target_file = os.path.splitext(source_file)[0] if not source_file.endswith(".json"): raise OSError("We only encrypt json files") target_loc = os.path.join("data", "secrets", f"{target_file}.json") if os.path.exists(target_loc) and not overwrite: raise OSError("Cannot overwrite existing file, set overwrite=True to ignore.") with open(source_file) as fh: secret = json.load(fh) token = encrypt_ends(secret) with open(target_loc, "w") as fh: json.dump(token, fh, indent=2) return target_loc def encrypt_ends(secret: dict) -> dict: encrypter = Fernet(get_key()) encrypts = [] for key, value in secret.items(): if isinstance(value, dict): encrypts.append((key, encrypt_ends(value))) elif isinstance(value, str): encrypts.append((key, encrypter.encrypt(value.encode()).decode())) for enc in encrypts: (key, value) = enc if isinstance(value, str): secret[key] = "[enc]||" + value else: secret[key] = value return secret def decrypt(filename: str) -> dict: """Decrypt a file from data/secrets, return the secrets""" if not filename.endswith(".json"): filename = filename + ".json" if not os.path.exists(os.path.dirname(filename)): filename = os.path.join("data", "secrets", filename) if not os.path.exists(filename): raise OSError(f"File {filename} does not exist.") with open(filename) as fh: token = json.load(fh) return decrypt_ends(token) def decrypt_ends(token: dict) -> dict: decrypter = Fernet(get_key()) decrypts = [] for key, value in token.items(): if isinstance(value, dict): decrypts.append((key, decrypt_ends(value))) elif isinstance(value, str) and value.startswith("[enc]||"): secret = value.split("||")[1] decrypts.append((key, decrypter.decrypt(secret.encode()).decode())) for dec in decrypts: (key, value) = dec token[key] = value return token