#!/usr/bin/env python3 """User-run migration: decrypt in memory, reshape, encrypt for both machine keys.""" import argparse import json import os from pathlib import Path import subprocess from urllib.parse import quote parser = argparse.ArgumentParser(description=__doc__) parser.add_argument('source', type=Path) parser.add_argument('destination', type=Path) parser.add_argument('--age', required=True, help='Comma-separated public age recipients for both machines') args = parser.parse_args() if args.destination.exists(): parser.error('Destination exists; refusing to overwrite it') def url(scheme, database): authority = quote(database['username'], safe='') + ':' + quote(database['password'], safe='') authority += '@' + database['host'] if database.get('port'): authority += ':' + str(database['port']) return scheme + '://' + authority try: old = json.loads(subprocess.check_output( ['sops', 'decrypt', '--output-type', 'json', str(args.source)], stderr=subprocess.DEVNULL)) new = { 'email': old['company_login']['email'], 'password': old['company_login']['password'], 'YOOKR_MYSQL_LIVE_DATABASE_URL': url('mariadb', old['databases']['mysql']['live']) + '?ssl-verify-server-cert=0', 'YOOKR_MONGODB_LIVE_DATABASE_URL': url('mongodb+srv', old['databases']['mongodb']['live']), 'leafcloud': old['leafcloud'], } encrypted = subprocess.check_output( ['sops', 'encrypt', '--input-type', 'json', '--output-type', 'yaml', '--age', args.age, '/dev/stdin'], input=json.dumps(new).encode(), stderr=subprocess.DEVNULL) os.umask(0o077) with args.destination.open('xb') as output: output.write(encrypted) except (subprocess.CalledProcessError, KeyError, ValueError, OSError): raise SystemExit('Migration failed; no plaintext was written. Check source schema, keys and recipients.') print('Encrypted company document created. Original credentials were preserved.')