#!/usr/bin/env python3 """ Simple script to add a key to the emergency access server Takes an existing key file, copies it to the configured directory, and adds it to config """ import json import os import sys import shutil import secrets import hashlib import argparse from pathlib import Path def generate_password_hash(password: str, iterations: int = 100000) -> str: """Generate password hash using PBKDF2 with SHA-256 in canonical format""" salt = secrets.token_hex(16) derived = hashlib.pbkdf2_hmac( "sha256", password.encode(), salt.encode(), iterations ) # Return canonical format including algorithm and iteration count return f"pbkdf2_sha256${iterations}${salt}${derived.hex()}" def generate_secure_password(length: int = 32) -> str: """Generate a secure password""" import string alphabet = string.ascii_letters + string.digits + "!@#$%^&*" return "".join(secrets.choice(alphabet) for _ in range(length)) def load_config(config_path: str): """Load configuration file""" with open(config_path, "r") as f: return json.load(f) def save_config(config, config_path: str): """Save configuration file""" with open(config_path, "w") as f: json.dump(config, f, indent=2) def copy_key_file(source_path: str, dest_path: str): """Copy key file to destination with proper permissions""" # Create destination directory if needed dest_dir = os.path.dirname(dest_path) os.makedirs(dest_dir, exist_ok=True) # Copy file shutil.copy2(source_path, dest_path) # Set secure permissions os.chmod(dest_path, 0o600) # Try to set ownership to emergency-access user if running as root if os.geteuid() == 0: # Running as root try: import pwd, grp user = pwd.getpwnam("emergency-access") group = grp.getgrnam("emergency-access") os.chown(dest_path, user.pw_uid, group.gr_gid) print(f"✅ Copied key file with emergency-access ownership: {dest_path}") except (KeyError, OSError): print(f"✅ Copied key file: {dest_path}") print(f"⚠️ Run: sudo chown emergency-access:emergency-access {dest_path}") else: print(f"✅ Copied key file: {dest_path}") print(f"⚠️ Run: sudo chown emergency-access:emergency-access {dest_path}") def main(): parser = argparse.ArgumentParser(description="Add a key to emergency access server") parser.add_argument("key_id", help="Key identifier (e.g., backup, master)") parser.add_argument("key_file", help="Path to existing key file") parser.add_argument("backends", help="Comma-separated notification backends") parser.add_argument("--config", default="config.json", help="Config file path") parser.add_argument( "--dest-dir", default="/etc/emergency-access", help="Destination directory" ) parser.add_argument("--password", help="Password (generated if not provided)") parser.add_argument("--message", help="Custom notification message") args = parser.parse_args() # Check if source key file exists if not os.path.exists(args.key_file): print(f"❌ Key file not found: {args.key_file}") sys.exit(1) # Load config try: config = load_config(args.config) except FileNotFoundError: print(f"❌ Config file not found: {args.config}") sys.exit(1) # Check if key already exists if args.key_id in config.get("keys", {}): print(f"❌ Key '{args.key_id}' already exists") sys.exit(1) # Generate password if not provided if args.password: password = args.password else: password = generate_secure_password() print(f"🔑 Generated password: {password}") # Set up paths and config dest_file = os.path.join(args.dest_dir, f"{args.key_id}-key.txt") route = f"/emergency-key-{args.key_id}" username = f"emergency_{args.key_id}" password_hash = generate_password_hash(password) backends = [b.strip() for b in args.backends.split(",")] message = args.message or f"🚨 EMERGENCY: Key {args.key_id} accessed from server" # Copy key file copy_key_file(args.key_file, dest_file) # Add to config if "keys" not in config: config["keys"] = {} config["keys"][args.key_id] = { "route": route, "file": dest_file, "username": username, "password_hash": password_hash, "backends": backends, "message": message, } # Save config save_config(config, args.config) print(f"✅ Added key '{args.key_id}' to configuration") print(f" Route: {route}") print(f" Username: {username}") print(f" Password: {password}") print(f" Backends: {', '.join(backends)}") if __name__ == "__main__": main()