## ────────────────────────────────────────────── ## WGSecure (WGS) — Makefile ## Compilation Linux & Windows via PyInstaller ## ────────────────────────────────────────────── APP := wgsecure VERSION := 0.4.0 VENV := .venv PYTHON := $(VENV)/bin/python3 PIP := $(VENV)/bin/pip SRC := main.py DIST := dist BUILD := build ICON := /tmp/wgsecure_icon_build.png # Options PyInstaller communes aux deux plateformes PI_OPTS := \ --noconfirm \ --clean \ --name $(APP) \ --hidden-import pyotp \ --hidden-import qrcode \ --hidden-import qrcode.image.pil \ --hidden-import PIL \ --hidden-import PIL.Image \ --hidden-import cryptography \ --hidden-import cryptography.hazmat.primitives.asymmetric.x25519 \ --collect-submodules PyQt6 .PHONY: all linux windows release install install-gnome uninstall-gnome run run-admin icon reset-password setup-sudoers clean clean-all help venv # ── Cible par défaut ──────────────────────────────────────────────────────── all: linux # ── Environnement virtuel ──────────────────────────────────────────────────── venv: $(VENV)/bin/python3 $(VENV)/bin/python3: python3 -m venv $(VENV) $(PIP) install --upgrade pip --quiet # ── Génération de l'icône PNG (utilisée par PyInstaller) ──────────────────── icon: @$(PYTHON) -c "\ import sys; sys.path.insert(0,'.');\ from PyQt6.QtWidgets import QApplication; app=QApplication(sys.argv);\ from app.ui.icons import icon_app;\ pix=icon_app().pixmap(256,256); pix.save('$(ICON)','PNG');\ print(' Icône générée →', '$(ICON)')" 2>/dev/null @test -f $(ICON) || (echo " ❌ Génération icône échouée"; exit 1) # ── Binaire Linux ──────────────────────────────────────────────────────────── linux: install icon @echo "" @echo " 🐧 Compilation Linux (PyInstaller onefile)…" @echo "" $(PYTHON) -m PyInstaller $(PI_OPTS) \ --onefile \ --icon=$(ICON) \ $(SRC) @echo "" @echo " ✅ Binaire Linux → $(DIST)/$(APP)" @echo "" # ── Binaire Windows (via Wine + Python Windows) ────────────────────────────── windows: icon @echo "" @echo " 🪟 Compilation Windows (Wine + PyInstaller)…" @echo "" @which wine > /dev/null 2>&1 \ || (echo " ❌ Wine non installé → sudo apt install wine"; exit 1) @wine $(WINE_PYTHON) -m PyInstaller $(PI_OPTS) \ --onefile \ --windowed \ --icon=$(ICON) \ $(SRC) \ || (echo ""; \ echo " ❌ Échec : Python Windows introuvable dans Wine."; \ echo " → Installez-le avec : make setup-wine"; \ echo ""; exit 1) @echo "" @echo " ✅ Binaire Windows → $(DIST)/$(APP).exe" @echo "" # ── Installation de Python dans Wine ───────────────────────────────────────── WINE_PY_VER := 3.11.9 WINE_PY_URL := https://www.python.org/ftp/python/$(WINE_PY_VER)/python-$(WINE_PY_VER)-amd64.exe WINE_PY_EXE := /tmp/python-$(WINE_PY_VER)-amd64.exe WINE_PYTHON := $(HOME)/.wine/drive_c/users/$(USER)/AppData/Local/Programs/Python/Python311/python.exe setup-wine: @echo " 📦 Installation Python $(WINE_PY_VER) Windows dans Wine…" @which wine > /dev/null 2>&1 \ || (echo " ❌ wine non installé → sudo apt install wine"; exit 1) @test -f $(WINE_PY_EXE) \ || (echo " ⬇️ Téléchargement Python Windows…" \ && curl -L -o $(WINE_PY_EXE) $(WINE_PY_URL)) @echo " 🔧 Installation silencieuse…" wine $(WINE_PY_EXE) /quiet InstallAllUsers=0 PrependPath=1 @echo " 📦 Installation des dépendances…" wine $(WINE_PYTHON) -m pip install --upgrade pip wine $(WINE_PYTHON) -m pip install -r requirements.txt wine $(WINE_PYTHON) -m pip install pyinstaller @echo " ✅ Python Windows prêt dans Wine" # ── Release (Linux renommé avec version) ───────────────────────────────────── release: clean linux @mv $(DIST)/$(APP) $(DIST)/$(APP)-$(VERSION)-linux-x86_64 @echo " 📦 Release → $(DIST)/$(APP)-$(VERSION)-linux-x86_64" # ── Installation GNOME (utilisateur local, sans sudo) ──────────────────────── INSTALL_BIN := $(HOME)/.local/bin INSTALL_ICON := $(HOME)/.local/share/icons/hicolor/256x256/apps INSTALL_APPS := $(HOME)/.local/share/applications install-gnome: linux @echo "" @echo " 🐧 Installation de WGSecure pour GNOME…" @mkdir -p $(INSTALL_BIN) $(INSTALL_ICON) $(INSTALL_APPS) @cp $(DIST)/$(APP) $(INSTALL_BIN)/$(APP) @chmod +x $(INSTALL_BIN)/$(APP) @echo " ✅ Binaire → $(INSTALL_BIN)/$(APP)" @cp $(ICON) $(INSTALL_ICON)/$(APP).png @echo " ✅ Icône → $(INSTALL_ICON)/$(APP).png" @printf '[Desktop Entry]\nType=Application\nName=WGSecure\nComment=WireGuard GUI avec MFA TOTP\nExec=%s\nIcon=%s\nCategories=Network;Security;\nStartupWMClass=wgsecure\nTerminal=false\n' \ "$(INSTALL_BIN)/$(APP)" "$(APP)" \ > $(INSTALL_APPS)/$(APP).desktop @echo " ✅ Lanceur → $(INSTALL_APPS)/$(APP).desktop" @gtk-update-icon-cache -f -t $(HOME)/.local/share/icons/hicolor 2>/dev/null || true @update-desktop-database $(INSTALL_APPS) 2>/dev/null || true @echo "" @echo " 🎉 Installation terminée. WGSecure est disponible dans le menu GNOME." @echo "" uninstall-gnome: @echo " 🗑️ Désinstallation de WGSecure…" @rm -f $(INSTALL_BIN)/$(APP) @rm -f $(INSTALL_ICON)/$(APP).png @rm -f $(INSTALL_APPS)/$(APP).desktop @gtk-update-icon-cache -f -t $(HOME)/.local/share/icons/hicolor 2>/dev/null || true @update-desktop-database $(INSTALL_APPS) 2>/dev/null || true @echo " ✅ WGSecure désinstallé" # ── Dépendances Python ──────────────────────────────────────────────────────── install: venv $(PIP) install -r requirements.txt $(PIP) install pyinstaller @echo " ✅ Dépendances installées dans $(VENV)" # ── Droits sudo wg-quick sans dialogue de mot de passe ─────────────────────── setup-sudoers: @echo "" @echo " 🔧 Configuration sudoers pour wg-quick (sans mot de passe)…" @$(PYTHON) -c "\ import os, subprocess; \ user = os.environ.get('USER', os.path.basename(os.path.expanduser('~'))); \ rule = user + ' ALL=(ALL) NOPASSWD: /usr/bin/wg-quick\n'; \ tmp = '/tmp/wgsecure_sudoers_tmp'; \ open(tmp, 'w').write(rule); \ r = subprocess.run(['pkexec', 'bash', '-c', 'cp ' + tmp + ' /etc/sudoers.d/wgsecure && chmod 440 /etc/sudoers.d/wgsecure']); \ os.unlink(tmp); \ print(' ✅ /etc/sudoers.d/wgsecure configuré — WGSecure n\\'a plus besoin de dialogue admin.' if r.returncode == 0 else ' ❌ Échec. Exécutez manuellement : sudo bash -c \"echo ' + user + ' ALL=(ALL) NOPASSWD: /usr/bin/wg-quick > /etc/sudoers.d/wgsecure && chmod 440 /etc/sudoers.d/wgsecure\"')" @echo "" # ── Réinitialisation du mot de passe administrateur ────────────────────────── reset-password: @echo "" @echo " ⚠️ Réinitialisation du mot de passe administrateur WGSecure…" @$(PYTHON) -c "\ import sys; sys.path.insert(0,'.');\ from app.core.config import Config;\ cfg = Config();\ cfg.set_admin_password('');\ print(' ✅ Mot de passe supprimé — accès admin sans restriction au prochain démarrage.')" @echo "" # ── Lancer l'application ───────────────────────────────────────────────────── run: venv DISPLAY=:0 $(PYTHON) $(SRC) run-admin: venv DISPLAY=:0 $(PYTHON) $(SRC) --admin # ── Nettoyage ──────────────────────────────────────────────────────────────── clean: @echo " 🧹 Nettoyage…" @rm -rf $(BUILD) $(DIST) *.spec @find . -name "__pycache__" -type d -exec rm -rf {} + 2>/dev/null; true @find . -name "*.pyc" -delete 2>/dev/null; true @echo " ✅ Artefacts supprimés" clean-all: clean @rm -rf $(VENV) @echo " ✅ Venv supprimé" # ── Aide ───────────────────────────────────────────────────────────────────── help: @echo "" @echo " ╔══════════════════════════════════════════════╗" @echo " ║ 🛡️ WGSecure v$(VERSION) — Makefile ║" @echo " ╠══════════════════════════════════════════════╣" @echo " ║ make install Installe les dépendances ║" @echo " ║ make linux Binaire Linux (onefile) ║" @echo " ║ make windows Binaire Windows (Wine) ║" @echo " ║ make release Linux + nommage release ║" @echo " ║ make setup-wine Python Windows dans Wine ║" @echo " ║ make install-gnome Installe dans GNOME ║" @echo " ║ make uninstall-gnome Désinstalle de GNOME ║" @echo " ║ make setup-sudoers wg-quick sans sudo ║" @echo " ║ make reset-password Supprime le MDP admin ║" @echo " ║ make run Lance l'application ║" @echo " ║ make run-admin Lance en mode admin ║" @echo " ║ make clean Supprime les artefacts ║" @echo " ╚══════════════════════════════════════════════╝" @echo ""