tools/subrep_key.py (2140 bytes)
1 """Make the licence key of Subrep Pro on the server, once. 2 3 python tools/subrep_key.py 4 5 It writes SUBPLZ_WEB_SUBREP_LICENSE_KEY into .env and never shows it. It 6 prints the public key: build that into the Subrep desktop app (PUBLIC_KEY_B64 7 in subrep/licensing.py). When .env has the key already, it prints the public 8 key of that key and changes nothing. Every licence of every customer depends 9 on the key, so this tool never replaces it. 10 11 After the first run: systemctl restart subplz-web 12 """ 13 from __future__ import annotations 14 15 import base64 16 import os 17 import sys 18 from pathlib import Path 19 20 from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey 21 22 NAME = "SUBPLZ_WEB_SUBREP_LICENSE_KEY" 23 ROOT = Path(__file__).resolve().parent.parent 24 ENV = ROOT / ".env" 25 26 27 def b64e(raw: bytes) -> str: 28 return base64.urlsafe_b64encode(raw).rstrip(b"=").decode("ascii") 29 30 31 def b64d(text: str) -> bytes: 32 return base64.urlsafe_b64decode(text + "=" * (-len(text) % 4)) 33 34 35 def main() -> int: 36 text = ENV.read_text(encoding="utf-8") if ENV.exists() else "" 37 found = [line.split("=", 1)[1].strip() for line in text.splitlines() 38 if line.startswith(NAME + "=")] 39 if found and found[-1]: 40 key = Ed25519PrivateKey.from_private_bytes(b64d(found[-1])) 41 print(f"{NAME} is set already. It stays as it is.", file=sys.stderr) 42 else: 43 key = Ed25519PrivateKey.generate() 44 with ENV.open("a", encoding="utf-8") as f: 45 if text and not text.endswith("\n"): 46 f.write("\n") 47 f.write(f"{NAME}={b64e(key.private_bytes_raw())}\n") 48 # As tools/set-secret.sh: the service does not run as root. The file 49 # belongs to the owner of the checkout, and nobody else may read it. 50 if hasattr(os, "chown"): 51 owner = ROOT.stat() 52 os.chown(ENV, owner.st_uid, owner.st_gid) 53 os.chmod(ENV, 0o600) 54 print(f"{NAME} saved in {ENV}. Apply it with: systemctl restart subplz-web", 55 file=sys.stderr) 56 print(b64e(key.public_key().public_bytes_raw())) 57 return 0 58 59 60 if __name__ == "__main__": 61 sys.exit(main())