runv-server

server tooling for runv.club
Log | Files | Refs | README

close_entre.py (4250B)


      1 #!/usr/bin/env python3
      2 """
      3 Script para fechar temporariamente os registros do terminal `entre`.
      4 Ele edita o ficheiro de drop-in do SSH para usar `closed_app.py` em vez de `entre_app.py`.
      5 
      6 Executar como root no servidor Debian.
      7 """
      8 import os
      9 import sys
     10 import subprocess
     11 import argparse
     12 from pathlib import Path
     13 
     14 ADMIN_DIR = Path(__file__).resolve().parent.parent / "scripts" / "admin"
     15 if str(ADMIN_DIR) not in sys.path:
     16     sys.path.insert(0, str(ADMIN_DIR))
     17 
     18 from admin_guard import ensure_admin_cli
     19 
     20 def eprint(msg: str) -> None:
     21     print(msg, file=sys.stderr)
     22 
     23 def require_root() -> None:
     24     if os.geteuid() != 0:
     25         eprint("Execute como root (sudo).")
     26         raise SystemExit(1)
     27 
     28 def run(cmd: list[str]) -> None:
     29     r = subprocess.run(cmd, capture_output=True, text=True, timeout=60)
     30     if r.returncode != 0:
     31         err = (r.stderr or r.stdout or "").strip()
     32         raise RuntimeError(f"Falhou: {' '.join(cmd)}\n{err}")
     33 
     34 def main() -> int:
     35     parser = argparse.ArgumentParser(
     36         description="Fecha temporariamente os registros do terminal entre.",
     37     )
     38     parser.add_argument(
     39         "--dry-run",
     40         action="store_true",
     41         help="mostra o que seria alterado sem gravar nem recarregar o SSH",
     42     )
     43     parser.add_argument(
     44         "--auth-mode",
     45         default="empty-password",
     46         help="opção compatível com setup_entre.py; mantida por simetria operacional",
     47     )
     48     parser.add_argument(
     49         "--install-pam-empty-password-rule",
     50         action="store_true",
     51         help="opção compatível com setup_entre.py; close_entre.py não altera PAM",
     52     )
     53     parser.add_argument(
     54         "--skip-pam-empty-password-rule",
     55         action="store_true",
     56         help="opção compatível com setup_entre.py; close_entre.py não altera PAM",
     57     )
     58     args = parser.parse_args()
     59 
     60     ensure_admin_cli(
     61         script_name=Path(__file__).name,
     62         dry_run=bool(args.dry_run),
     63     )
     64     require_root()
     65     
     66     dropin_path = Path("/etc/ssh/sshd_config.d/runv-entre.conf")
     67     if not dropin_path.is_file():
     68         eprint(f"Erro: o ficheiro de configuração SSH {dropin_path} não foi encontrado.")
     69         eprint("Parece que o setup do terminal `entre` ainda não foi executado ou está corrompido.")
     70         return 1
     71 
     72     content = dropin_path.read_text(encoding="utf-8")
     73     
     74     if "closed_app.py" in content:
     75         print("Os registros já parecem estar fechados (closed_app.py detetado na config).")
     76         return 0
     77 
     78     if "entre_app.py" not in content:
     79         eprint("Aviso: 'entre_app.py' não encontrado na configuração. Modificação ignorada por segurança.")
     80         return 1
     81 
     82     # Substitui a app principal pela fechada
     83     new_content = content.replace("entre_app.py", "closed_app.py")
     84     
     85     if args.dry_run:
     86         print(f"[dry-run] modificaria {dropin_path.name}: entre_app.py -> closed_app.py")
     87         print("[dry-run] correria sshd -t e systemctl reload ssh")
     88         return 0
     89 
     90     # Grava novamente
     91     dropin_path.write_text(new_content, encoding="utf-8")
     92     print(f"Modificado {dropin_path.name}: entre_app.py -> closed_app.py")
     93 
     94     # Testa as confiugrações do ssh
     95     print("Testando a configuração com 'sshd -t'...")
     96     try:
     97         run(["sshd", "-t"])
     98     except RuntimeError as e:
     99         # Tenta reverter
    100         eprint(f"Erro de sshd detectado: {e}")
    101         eprint("Revertendo as mudanças.")
    102         dropin_path.write_text(content, encoding="utf-8")
    103         return 1
    104 
    105     print("sshd -t: OK.")
    106 
    107     # Recarrega o SSH
    108     try:
    109         run(["systemctl", "reload", "ssh"])
    110         print("Serviço SSH recarregado (reload).")
    111     except RuntimeError:
    112         try:
    113             run(["systemctl", "reload", "sshd"])
    114             print("Serviço SSH recarregado (reload).")
    115         except RuntimeError as e:
    116             eprint(f"Aviso: Não foi possível fazer o recarregamento do SSH de forma automática: {e}")
    117             eprint("Por favor recarregue manualmente: systemctl reload ssh")
    118             
    119     print("\n[+] Fechado com sucesso! Agora as ligações serão encaminhadas para o ecrã CLOSED.")
    120     print("Para reabrir os registros no futuro, basta correr 'sudo ./setup_entre.py' novamente.")
    121 
    122     return 0
    123 
    124 if __name__ == "__main__":
    125     sys.exit(main())