From 6cceb3f3b2f2017907a8db8efafd92c9c06aa8dd Mon Sep 17 00:00:00 2001 From: Florian Date: Sat, 5 Sep 2026 07:50:24 +0200 Subject: [PATCH] README : couvrir les 14 phases precedentes, mettre en avant la confidentialite Le README ne decrivait encore que les toutes premieres fonctionnalites (sessions, tunnels -L/-R, SFTP, terminaux locaux, cles, known_hosts) : rien sur ~/.ssh/config, ProxyJump, le SOCKS dynamique, le keepalive/reconnexion automatique, le terminal divise, les workspaces, les snippets, les tags/ groupes, le coffre-fort d'identifiants ni l'assistant IA. Reecriture complete en gardant le ton et la structure d'origine (description concrete, raccourcis clavier, "pourquoi" plutot que juste "quoi") : - Nouveau chapeau explicite : aucun compte cloud, aucune telemetrie, les identifiants restent locaux, l'IA est entierement optionnelle. - Fonctionnalites reorganisees par theme (terminal / connexion et auth / organisation / SFTP / cles et secrets / assistant IA), chaque nouvelle fonctionnalite decrite avec le menu ou bouton exact pour y acceder - verifie contre le code plutot que suppose. - "Structure du projet" reecrite pour refleter l'arborescence actuelle (controllers/, ui/, services/, storage/, security/, ai/, openssh/...). - "Tests" et nouvelle section "Qualite" mis a jour pour pytest/ruff/pyright/ CI (Phases 13-14), en gardant la possibilite de lancer un script seul. - "Limites connues" mise a jour avec les limites reelles actuelles (ProxyJump a un seul rebond, coffre-fort Windows uniquement, socle de typage pyright non resorbe) plutot que celles, resolues depuis, de la version initiale. Co-Authored-By: Claude Sonnet 5 --- README.md | 250 +++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 190 insertions(+), 60 deletions(-) diff --git a/README.md b/README.md index 67bdb22..7b18671 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,17 @@ # PySSH Client -Client SSH/SFTP personnel (type MobaXterm/Termius/Bitvise), 100% local, sans compte ni service tiers. +Client SSH/SFTP personnel (type MobaXterm/Termius/Bitvise), **100% local**. + +**Aucun compte requis, aucun service cloud, aucune telemetrie.** Sessions, cles, mots de passe +memorises et snippets restent dans des fichiers locaux (ou le trousseau securise de Windows) — +rien n'est jamais envoye a un serveur tiers. La seule fonctionnalite qui communique vers +l'exterieur est l'**assistant IA**, entierement optionnel, desactive par defaut, et qui n'envoie +quoi que ce soit qu'au fournisseur que *vous* configurez avec *votre propre* cle API (voir plus bas). ## Fonctionnalites +### Terminal SSH + - Sessions SSH multiples dans des onglets, avec terminal ANSI colore et trois themes - Copier-coller **a la souris, comme dans un terminal Unix** : selectionner copie aussitot (double-clic pour un mot), et le clic droit colle directement — ni menu, ni raccourci. @@ -12,41 +20,114 @@ Client SSH/SFTP personnel (type MobaXterm/Termius/Bitvise), 100% local, sans com - Confort d'affichage : zoom `Ctrl+molette` ou `Ctrl+ +/-` (`Ctrl+0` remet a zero, la taille est memorisee), barre de defilement de l'historique, `Maj+PagePrec/Suiv`, `Ctrl+Fin` pour revenir en direct, et recherche dans l'historique avec `Ctrl+F` -- Onglets renommables (double-clic sur l'onglet, ou clic droit) et deplaçables ; - le clic droit permet aussi de fermer les autres onglets -- Panneau des sessions redimensionnable en attrapant le separateur, et masquable entierement - (`F9`, menu Affichage, ou la croix du panneau) pour donner tout l'ecran au terminal -- **Tunnels SSH** (redirection de ports) : bouton "Tunnels" dans la barre d'un onglet SSH. - Redirection locale (`-L`) pour atteindre depuis votre poste un service qui n'ecoute que sur la - boucle locale du serveur, et redirection distante (`-R`) dans l'autre sens -- **Envoi simultane** : le bouton "⇉ Multi" du panneau lateral diffuse ce que vous tapez vers tous - les onglets terminal ouverts, pour piloter plusieurs serveurs d'un coup -- Journalisation de session dans un fichier (bouton "Journal"), sequences ANSI retirees pour rester lisible -- Reconnexion en un clic quand une session tombe (bouton dans la barre de l'onglet) : pratique - avec des serveurs de test qui redemarrent souvent -- Les hotes deja approuves par votre commande `ssh` (`~/.ssh/known_hosts`) sont reconnus : pas de - double confirmation d'empreinte. Les nouvelles cles vont dans le fichier propre a l'application -- Terminaux locaux accessibles en un clic, **sans session enregistree**. L'application detecte les - shells presents sur le poste et les propose tous : PowerShell, cmd, et surtout les **shells Unix** - s'ils sont installes (Bash de Git for Windows, MSYS2, Cygwin, WSL, ou un busybox pose a cote de - l'application). Comme le terminal local de MobaXterm, on retrouve alors `ls`, `grep`, `sed`, `awk`, - `vi`, `scp`... sous Windows. **Un shell Unix est choisi par defaut** quand il y en a un ; - sinon PowerShell. Rien n'est embarque : l'application reutilise ce qui est deja installe -- Carnet d'adresses de serveurs (JSON local, `data/sessions.json`) organise par dossiers, connexion en un clic -- Gestion des cles SSH : generation **Ed25519, ECDSA (courbes NIST P-256 / P-384 / P-521) et RSA**, - import de cles existantes, export (cle publique/privee), protection par passphrase -- Client SFTP integre facon WinSCP : double panneau local/distant avec colonnes triables (nom, taille, date, droits), - glisser-deposer entre les panneaux, renommage (F2), suppression (Suppr), creation de dossier, permissions distantes - (chmod), et file de transferts avec progression. **Aucun favori n'est necessaire pour l'utiliser** — voir ci-dessous -- **SFTP sur la connexion en cours** : depuis n'importe quel terminal ou vous avez tape `ssh user@hote` a la main, le - bouton "📁 SFTP sur cette connexion" lit l'hote, l'utilisateur et le port dans la commande saisie et ouvre le - gestionnaire de fichiers dessus. Pense pour les serveurs de test en DHCP, qu'on n'a aucune envie d'enregistrer -- **Authentification automatique** (mode par defaut) : comme la commande `ssh`, l'application utilise l'agent SSH et les - cles de `~/.ssh` sans que vous ayez a designer quoi que ce soit, et ne demande un mot de passe qu'en dernier recours -- Verification des empreintes de cles d'hote (TOFU) avant premiere connexion, comme un client SSH classique -- Gestionnaire des hotes connus (menu "Hotes connus" ou bouton "⚙" du panneau lateral) : si une adresse en DHCP change de machine, la cle d'hote presentee ne correspond plus a celle enregistree — l'application le detecte et propose de remplacer l'ancienne entree directement au moment de la connexion, sans avoir a vider le fichier `known_hosts` a la main. Le gestionnaire permet aussi un nettoyage manuel (par hote ou en une fois). +- Onglets renommables (double-clic, ou clic droit) et deplaçables ; le clic droit permet + aussi de les diviser en **2 ou 4 panneaux** (cote a cote, empiles, ou grille), de deplacer un + autre onglet ouvert dans un panneau, ou de fermer les autres onglets +- **Keepalive et reconnexion automatique** configurables par session (intervalle, nombre de + tentatives, delai avec recul progressif) : une coupure reseau n'oblige plus a rouvrir + la session et ressaisir les identifiants +- Journalisation de session dans un fichier (bouton "Journal"), sequences ANSI retirees pour + rester lisible +- Reconnexion manuelle en un clic (bouton dans la barre de l'onglet) -Aucun mot de passe n'est stocke sur le disque : l'authentification par mot de passe est demandee a chaque connexion, et les passphrases de cles sont demandees uniquement en memoire au moment de la connexion. +### Connexion et authentification + +- **Authentification automatique** (mode par defaut) : comme la commande `ssh`, l'application + utilise l'agent SSH et les cles de `~/.ssh` sans que vous ayez a designer quoi que ce soit, et + ne demande un mot de passe qu'en dernier recours +- **Import de votre `~/.ssh/config`** : les `Host` deja definis (HostName, User, Port, + IdentityFile, ProxyJump, ForwardAgent...) apparaissent directement dans le panneau lateral + (section "⚙ Configuration OpenSSH"), utilisables sans les ressaisir, ou importables comme + session PySSH en un clic +- **Bastion / ProxyJump** : une session peut passer par un rebond SSH, choisi parmi vos sessions + existantes, un `Host` de `~/.ssh/config`, ou une configuration manuelle. Un groupe de sessions + peut aussi heriter d'un bastion commun (voir Groupes ci-dessous) +- **Tunnels SSH** (bouton "🔀 Tunnels" dans la barre d'un onglet SSH) : redirection locale + (`-L`, atteindre depuis votre poste un service qui n'ecoute que sur la boucle locale du + serveur), distante (`-R`), et **proxy SOCKS dynamique** (`-D`, pour faire transiter tout le + trafic d'une application par le tunnel) +- Verification des empreintes de cles d'hote (TOFU) avant premiere connexion, comme un client + SSH classique. Les hotes deja approuves par votre commande `ssh` (`~/.ssh/known_hosts`) sont + reconnus : pas de double confirmation d'empreinte +- Gestionnaire des hotes connus (menu "Hotes connus") : si une adresse en DHCP change de + machine, la cle d'hote presentee ne correspond plus a celle enregistree — l'application le + detecte et propose de remplacer l'ancienne entree directement au moment de la connexion + +### Organisation + +- Carnet d'adresses de serveurs (JSON local, `data/sessions.json`) organise par dossiers, + connexion en un clic +- **Tags** (plusieurs par session) avec filtre/recherche dans le panneau lateral +- **Groupes** : un dossier de sessions peut porter des parametres par defaut (utilisateur, port, + cle SSH, bastion, keepalive) via clic droit > "Parametres du groupe...". Le bouton + "↓ Heriter du groupe" du formulaire de session les reprend en pre-remplissage, sans empecher + de les modifier au cas par cas pour une session donnee +- **Workspaces** : sauvegardent l'etat complet d'une disposition de travail — onglets ouverts, + ordre, divisions et tailles de panneaux, sessions associees — et la restaurent en un clic + (menu "Workspaces", `Ctrl+Shift+W`). Une case optionnelle restaure le dernier workspace au + demarrage. **Aucun mot de passe n'est jamais stocke dans un workspace** +- **Recherche rapide** (`Ctrl+K`) : palette façon lanceur d'applications, recherche floue parmi + sessions, hotes OpenSSH, workspaces, snippets et actions, entierement au clavier +- **Snippets** : commandes enregistrees par categorie (des exemples Linux/Docker/Proxmox sont + fournis au premier lancement), gerables (creer/modifier/supprimer/rechercher) depuis le menu + "Snippets" ou le bouton "📋 Snippets" de chaque onglet. Un snippet peut etre **insere** (le + texte est ecrit, jamais valide automatiquement), **execute**, ou **execute sur tous les + onglets a la fois** via Multi-Send +- **Envoi simultane** : le bouton "⇉ Multi" du panneau lateral diffuse ce que vous tapez vers + tous les onglets terminal ouverts (y compris dans les panneaux divises), pour piloter + plusieurs serveurs d'un coup + +### SFTP + +- Client SFTP integre facon WinSCP : double panneau local/distant avec colonnes triables (nom, + taille, date, droits), glisser-deposer entre les panneaux, renommage (F2), suppression + (Suppr), creation de dossier, permissions distantes (chmod), et file de transferts avec + progression — le tout en arriere-plan, sans jamais geler l'interface +- **Aucun favori n'est necessaire pour l'utiliser** — trois façons d'y arriver : + - *Vous avez tape `ssh user@hote` dans un terminal* : bouton "📁 SFTP sur cette connexion" + dans la barre de l'onglet. L'hote et l'utilisateur sont deduits de la commande tapee + - *Connexion ponctuelle* : bouton "📁 SFTP" du panneau lateral, ou `Ctrl+Shift+F` + - *Session enregistree* : le panneau de fichiers est deja affiche a cote du terminal des + l'ouverture, comme dans MobaXterm ; ou clic droit > "Ouvrir en SFTP" pour un onglet dedie + +### Cles et secrets + +- Gestion des cles SSH : generation **Ed25519, ECDSA (courbes NIST P-256/P-384/P-521) et RSA**, + import de cles existantes, export, protection par passphrase. Sous Windows, les cles privees + generees ou importees reçoivent des permissions NTFS restreintes (ACL), equivalent du + `chmod 600` Unix +- **Coffre-fort de mots de passe optionnel** : a la creation d'une session par mot de passe, une + case "Memoriser de maniere securisee" permet de ne plus le ressaisir a chaque connexion. Le + mot de passe est alors stocke dans le **Gestionnaire d'identifiants Windows** (chiffre par + DPAPI), **jamais en clair dans un fichier de PySSH**. Sans cette case cochee (comportement par + defaut), rien n'est memorise : le mot de passe est redemande a chaque connexion, comme + aujourd'hui + +### Assistant IA (optionnel, desactive par defaut) + +Une aide ponctuelle pour l'administration systeme, pas un pilote automatique : **aucune commande +n'est jamais executee automatiquement**. + +- **Desactive par defaut**, et sans le moindre fournisseur impose : compatible avec toute API de + type OpenAI (OpenAI, OpenRouter, un proxy interne, ou un modele local exposant la meme API) — + vous indiquez l'URL et le modele, il n'y a pas de liste figee. Se configure depuis le menu + "Assistant IA > Parametres...", avec un bouton "Tester la connexion" +- Depuis un onglet terminal, le bouton "🤖 Assistant IA" permet, sur la selection courante : + **Expliquer cette sortie**, **Diagnostiquer cette erreur**, **Proposer une solution**, ou + **Poser une question** en y ajoutant la selection comme contexte. Les reponses s'affichent + dans un panneau lateral (conversation en memoire uniquement, jamais journalisee ni ecrite sur + le disque) +- **Generer une commande** (a partir d'une description en langage naturel, sans selection + necessaire) affiche toujours la commande proposee avant tout usage, avec trois choix : la + **copier**, l'**inserer dans le terminal** (le texte est ecrit, jamais valide automatiquement), + ou **annuler**. Une commande correspondant a un motif reconnu comme destructeur (`rm -rf`, + `mkfs`, `dd`, un `DROP DATABASE`...) est signalee par un avertissement explicite +- **Avant tout envoi** au fournisseur configure : un avis de principe s'affiche une seule fois, + et chaque envoi est verifie localement a la recherche de secrets evidents (mot de passe, cle + privee, jeton d'authentification) — si quelque chose est detecte, vous choisissez de le + masquer automatiquement, de l'envoyer tel quel, ou d'annuler l'envoi +- **La cle API** passe exclusivement par le meme coffre-fort securise que les mots de passe de + session (Gestionnaire d'identifiants Windows) : jamais dans `settings.json`, jamais journalisee ## Installation (Windows) @@ -56,7 +137,15 @@ Necessite Python 3.10+ installe sur le poste (verifiable avec `py -3 --version`) setup.bat ``` -Ce script cree un environnement virtuel local (`venv/`) et y installe les dependances (PySide6, paramiko, pyte, cryptography, pywinpty) — rien n'est installe globalement sur le poste. +Ce script cree un environnement virtuel local (`venv/`) et y installe les dependances (PySide6, +paramiko, pyte, cryptography, pywinpty) — rien n'est installe globalement sur le poste. + +Pour contribuer au code (tests, lint, verification de types), installez plutot les dependances +de developpement : + +```bash +venv\Scripts\pip install -r requirements-dev.txt +``` ## Lancement @@ -109,8 +198,8 @@ automatiquement sur `%APPDATA%\PySSHClient\`. ## Premiers pas -1. **Terminal local immediat** : bouton "💻 Terminal" dans le panneau lateral (ou `Ctrl+Shift+T`), ou double-clic sur "PowerShell"/"Invite de commandes" dans la section "Terminaux locaux" de l'arborescence — aucune session a creer. -2. **Nouvelle session SSH** (bouton "+ Session" ou `Ctrl+N`) : renseignez l'hote, le port, l'utilisateur et le mode d'authentification. +1. **Terminal local immediat** : bouton "💻 Terminal" dans le panneau lateral (ou `Ctrl+Shift+T`), ou double-clic sur "PowerShell"/"Invite de commandes" dans la section "💻 Terminaux locaux" de l'arborescence — aucune session a creer. +2. **Nouvelle session SSH** (bouton "+ Session" ou `Ctrl+N`) : renseignez l'hote, le port, l'utilisateur et le mode d'authentification. Vous avez deja un `~/.ssh/config` ? Ses `Host` apparaissent tout seuls dans la section "⚙ Configuration OpenSSH", inutile de les ressaisir. 3. **Cles SSH** (menu "Cles SSH > Gestionnaire de cles") : generez une nouvelle paire de cles ou importez-en une existante, puis selectionnez-la dans le formulaire de session. 4. Double-cliquez sur une session dans l'arborescence pour ouvrir un onglet terminal SSH. 5. **SFTP — trois facons d'y arriver**, selon la situation : @@ -123,46 +212,87 @@ automatiquement sur `%APPDATA%\PySSHClient\`. Dans tous les cas : glisser-deposer entre les deux panneaux, F2 renomme, Suppr supprime, F5 actualise, et le clic droit sur le panneau distant donne acces aux permissions (chmod). +6. **Aller plus vite** : `Ctrl+K` ouvre une recherche rapide parmi tout ce que vous avez deja ouvert ou enregistre. +7. **Retrouver une disposition de travail** : une fois plusieurs onglets/panneaux organises a votre gout, menu + "Workspaces > Gestionnaire de workspaces..." (`Ctrl+Shift+W`) pour l'enregistrer et la rouvrir en un clic. +8. **Assistant IA** (facultatif) : menu "Assistant IA > Parametres..." pour indiquer l'URL, le modele et la cle API + d'un fournisseur compatible OpenAI. Tant que cette etape n'est pas faite, l'assistant reste inactif et + n'envoie jamais rien nulle part. ## Structure du projet ``` -main.py point d'entree +main.py point d'entree app/ - theme.py feuille de style "bleu nuit" + icone d'application - session_manager.py base de sessions (JSON) - key_manager.py generation/import/export de cles SSH - ssh_connection.py connexion SSH en arriere-plan (paramiko + QThread) - known_hosts_manager.py gestion du fichier known_hosts (lister/retirer/remplacer une cle d'hote) - local_terminal.py terminal local Windows (PowerShell/cmd via pywinpty) - terminal_widget.py emulateur de terminal ANSI (pyte + QPainter) - sftp_panel.py client SFTP a deux panneaux - main_window.py fenetre principale (arbre de sessions + onglets) - tunnels.py tunnels SSH (redirection de ports -L / -R) - dialogs/ boites de dialogue (session, cles, hotes, tunnels, connexion) + main_window.py fenetre principale : assemble panneau lateral, onglets, menus + session_manager.py base de sessions (JSON), tags, parametres de bastion/keepalive/reconnexion + key_manager.py generation/import/export de cles SSH, empreintes + known_hosts_manager.py gestion du fichier known_hosts (lister/retirer/remplacer une cle d'hote) + ssh_connection.py connexion SSH en arriere-plan (paramiko + QThread), bastion, keepalive + local_terminal.py terminal local Windows (PowerShell/cmd via pywinpty) + terminal_widget.py emulateur de terminal ANSI (pyte + QPainter) + sftp_panel.py client SFTP a deux panneaux, transferts en arriere-plan + tunnels.py tunnels SSH : redirection -L / -R et proxy SOCKS dynamique -D + bastion.py resolution d'un ProxyJump (session / Host OpenSSH / manuel) + credentials.py coffre-fort optionnel (Gestionnaire d'identifiants Windows) + workspace.py, snippets.py, persistance des workspaces, snippets et parametres de groupe + groups.py, app_settings.py + theme.py feuille de style "bleu nuit" + icone d'application + ai/ assistant IA : fournisseur, redaction de secrets, detection de + commandes dangereuses, parametres, execution en arriere-plan + controllers/ logique d'assemblage : cycle de vie des onglets, panneau des + sessions, diffusion Multi-Send, restauration des workspaces + ui/ widgets d'onglet (SSH/local/SFTP), terminal divise, panneau IA + dialogs/ boites de dialogue (session, cles, hotes, tunnels, snippets, + workspaces, groupes, recherche rapide, parametres IA...) + openssh/ lecture de ~/.ssh/config + security/ protection des cles privees (ACL NTFS sous Windows) + storage/ ecriture atomique de fichiers JSON, migration de schema + services/ logique pure sans dependance Qt (detection ~cible SSH, recherche + floue, calcul du delai de reconnexion) resources/ - theme.qss feuille de style Qt "bleu nuit" + theme.qss feuille de style Qt "bleu nuit" data/ - sessions.json vos serveurs enregistres (non versionne) - keys.json registre des cles connues (non versionne) - keys/ cles generees par l'application (non versionne) - known_hosts empreintes d'hotes approuvees (non versionne) + sessions.json, keys.json, vos donnees locales (non versionnees) - voir .gitignore + workspaces.json, snippets.json, + groups.json, known_hosts, keys/ +tests/ suite de tests (voir "Tests" ci-dessous) ``` ## Tests ```bash -tests\run_all.bat +pytest ``` +(necessite `pip install -r requirements-dev.txt`). Chaque fichier `tests/test_*.py` reste aussi +executable individuellement (`python tests/test_xxx.py`), pratique pour rejouer un seul scenario +pendant le developpement. + Les tests construisent de vraies fenetres Qt sans les afficher (`QT_QPA_PLATFORM=offscreen`) et -couvrent : le copier-coller et les raccourcis du terminal, la detection de l'hote dans une commande -`ssh` tapee a la main, la logique SFTP (transferts, renommage, tri, suppression recursive) avec un -serveur simule, et la construction complete de l'application. +couvrent, entre autres : le copier-coller et les raccourcis du terminal, la detection de l'hote +dans une commande `ssh` tapee a la main, la logique SFTP (transferts, renommage, tri, suppression +recursive) avec un serveur simule, le stockage atomique et la migration de schema, la lecture de +`~/.ssh/config`, la resolution de ProxyJump, le coffre-fort d'identifiants, la detection de +secrets et de commandes dangereuses, et l'ensemble de l'assistant IA (fournisseur HTTP, panneau, +integration dans les onglets) — sans jamais faire d'appel reseau reel. + +## Qualite + +```bash +ruff check app main.py tests # style et erreurs courantes +pyright # verification de types (mode progressif, voir pyproject.toml) +``` + +Une CI Gitea Actions (`.gitea/workflows/ci.yml`) execute le lint et les tests a chaque push, et +construit la version portable sur la branche principale. ## Limites connues / pistes d'amelioration - L'emulation de terminal couvre les usages courants (bash, vim, htop...) mais n'est pas un xterm parfaitement complet. - Le terminal local repose sur `pywinpty` (pseudo-console Windows). Si un onglet local reste bloque sur un ecran vide, tapez une touche : le rafraichissement de la console Windows peut etre paresseux dans certains contextes (notamment les sessions Windows non interactives) et se declenche a la premiere frappe. - Le SFTP ne propose pas encore l'edition de fichier distant en place (telecharger / modifier / renvoyer a la main). -- Pas encore d'export/import global du carnet de sessions (le fichier `data/sessions.json` peut etre copie manuellement). +- Le ProxyJump ne gere qu'un seul rebond pour l'instant (pas de chainage de plusieurs bastions). +- Le coffre-fort d'identifiants (mots de passe de session, cle API IA) repose sur le Gestionnaire d'identifiants Windows : pas d'equivalent sur Linux/macOS pour l'instant, l'application fonctionne mais sans memorisation securisee sur ces systemes. +- L'application est concue et testee pour Windows uniquement (pywinpty, ACL NTFS, Gestionnaire d'identifiants). +- La verification de types (`pyright`) est volontairement en mode progressif : un socle de signalements existe encore dans `app/ui/tabs.py` et `app/ssh_connection.py` (voir `pyproject.toml`), a resorber au fil du temps plutot que d'un bloc.