#!/usr/bin/env python3 """Provision a password for Alfred's local admin pages (never in shell history).""" import getpass import json import os import secrets from pathlib import Path from werkzeug.security import generate_password_hash ROOT = Path(__file__).resolve().parents[1] AUTH_FILE = ROOT / 'config' / 'admin_auth.json' SECRET_FILE = ROOT / 'config' / 'admin_secret.key' def atomic_bytes(path, content): path.parent.mkdir(parents=True, exist_ok=True) temp = path.with_name(path.name + '.tmp') fd = os.open(temp, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600) try: with os.fdopen(fd, 'wb') as stream: stream.write(content) stream.flush() os.fsync(stream.fileno()) os.replace(temp, path) os.chmod(path, 0o600) finally: temp.unlink(missing_ok=True) def main(): if not SECRET_FILE.exists(): atomic_bytes(SECRET_FILE, secrets.token_bytes(32)) password = getpass.getpass('Nouveau mot de passe administrateur Alfred : ') confirm = getpass.getpass('Confirmer le mot de passe : ') if password != confirm or len(password) < 12: raise SystemExit('Mot de passe non confirmé ou inférieur à 12 caractères.') encoded = json.dumps({'password_hash': generate_password_hash(password, method='scrypt')}).encode('utf-8') atomic_bytes(AUTH_FILE, encoded) print('Mot de passe administrateur enregistré. Les anciennes sessions sont invalidées.') if __name__ == '__main__': main()