claria.tools.ssh-client 2.0.0-build.20260819.1
Build Information
| Provenance | Azure DevOps Pipeline |
| Owner | kntera (Yan Boivin) |
| Date de compilation | 2026-08-20 03:22:20 UTC |
| Version | 2.0.0.20260819.1 |
| SHA256 | c459994b8934484f497073c13eb1e289a1d66b28 |
ssh-client
Outil en ligne de commande qui exécute des commandes sur un serveur distant via
SSH, sous le contrôle d'une politique d'autorisation (allow / deny).
Conçu pour permettre à des agents d'installer et de maintenir des serveurs
en gardant l'humain aux commandes sur toute opération non couverte par la
politique.
Contexte
Plutôt que d'exposer ssh brut à un agent, ssh-client s'intercale comme
garde-fou : chaque commande est évaluée contre une liste allow et une liste
deny avant d'être exécutée. Une commande refusée n'ouvre même pas de
connexion ; une commande inconnue signale à l'appelant qu'une décision
humaine est requise. Chaque exécution (y compris les refus) est journalisée
dans une session.
Spécifications complètes : doc/spec/** (A01 portée, E01 CLI, E02 connexions,
E03 politique, E04 exécution, E05 sessions, E06 transferts, E07 espaces de
configuration).
Utilisation
ssh-client exec --host <alias> [--timeout <sec>] [--json] [--once] -- <commande…>
ssh-client upload --host <alias> [--json] <chemin-local> <chemin-distant>
ssh-client download --host <alias> [--json] <chemin-distant> <chemin-local>
ssh-client policy check [--namespace <espace>] <commande>
ssh-client policy allow [--namespace <espace>] <motif>
ssh-client policy deny [--namespace <espace>] <motif>
ssh-client policy allow-upload [--namespace <espace>] <motif-distant>
ssh-client policy allow-download [--namespace <espace>] <motif-distant>
ssh-client policy remove [--namespace <espace>] <motif>
ssh-client policy list [--json]
ssh-client host add <alias> --host <fqdn|ip> --user <utilisateur> --key <chemin> [--passphrase-stdin] [--port <n>]
ssh-client host add <alias> --host <fqdn|ip> --user <utilisateur> --password-stdin [--port <n>]
ssh-client host add <alias> --lxd-host <alias-hôte> --vm <nom-vm>
ssh-client host remove <alias>
ssh-client host list [--json]
ssh-client host test <alias>
ssh-client session start [<id>]
ssh-client session end [<id>]
ssh-client session current [--json]
ssh-client session list [--json]
ssh-client --version | --readme | --help
Option globale : --config-dir <chemin> fixe la racine de configuration
(sinon SSHCLIENT_HOME, sinon ./.conf/ssh-client s'il existe, sinon
~/.conf/ssh-client s'il existe, sinon ./.conf/ssh-client créé à la première
écriture — voir « Espaces de configuration »). --session <id> cible une
session précise (créée si absente). --no-sessions désactive l'inscription
locale des sessions (équivaut à SSHCLIENT_NO_SESSIONS=1).
Espaces de configuration (.conf/)
La configuration est lue par agrégation de sous-répertoires, comme les
conf.d/ de nginx. La racine .conf/ssh-client/ contient un sous-répertoire
par espace de configuration, chacun autonome (ses hôtes et leurs defaults
dans config.json, ses secrets dans credentials.json, sa politique —
commandes et transferts — dans policies.json) ; les journaux — sessions et
debug — vont dans .log/ssh-client/ du répertoire de travail :
.conf/ssh-client/
├── default/ config.json, credentials.json, policies.json ← espace par défaut
├── prod/ config.json, credentials.json, policies.json ← autre espace
└── lab/ config.json
.log/ssh-client/
├── sessions/ index.json, <date>-<id>.jsonl
└── ssh-debug-AAAA-MM-JJ.log
- Racine :
--config-dir, sinonSSHCLIENT_HOME, sinon le./.conf/ssh-clientlocal s'il existe, sinon celui du profil (~/.conf/ssh-client) s'il existe, sinon le local (créé à la première écriture). Une seule racine sert aux lectures et aux écritures d'une invocation ;host listla rappelle sur stderr. - Référence d'hôte :
<espace>/<alias>(exacte) ou<alias>seul → l'unique espace qui le déclare, sinon l'espacedefault, sinon erreur 250 (« hôte ambigu » : préciserprod/web01oulab/web01). Un alias ne contient pas de/. - Déclaration :
host add prod/web01 …écrit dansprod/(créé au besoin) ;host add web01 …remplace l'hôte là où il existe, sinon va dansdefault/. Un hôte LXD est déclaré dans l'espace de son hôte parent. - Politique par espace : les listes d'un
policies.jsonne gouvernent que les hôtes de leur espace. Les commandespolicyvisent l'espace de--namespace <espace>; sans l'option : l'unique espace, sinondefault, sinon 250.policy listgroupe par espace. Les suggestions émises pour une commande ou un transfert inconnu portent déjà le--namespacevoulu. defaultspar espace :timeoutSeconds,connectTimeoutSecondss'appliquent aux hôtes de l'espace ;sessionInactivityMinutes(global) vient dedefault, sinon de l'unique espace, sinon 10 min.- L'ancien
./.ssh-client/n'est plus lu : un diagnostic invite à déplacer ses fichiers dans./.conf/ssh-client/default/.
Connexions
Les serveurs sont déclarés par alias dans un espace de configuration
(référence <alias> ou <espace>/<alias>, voir « Espaces de configuration »).
L'authentification se fait par clé SSH importée ou par mot de passe.
Les secrets (contenu de clé, passphrase, mot de passe) sont stockés à part dans
credentials.json (durci), jamais dans config.json, et se fournissent sur
l'entrée standard.
# Par clé (le contenu de la clé est importé, pas le chemin) — espace default
ssh-client host add web01 --host web01.example.com --user admin --key ~/.ssh/id_ed25519
# Dans un espace de configuration dédié (.conf/ssh-client/prod/) — référence prod/web01
ssh-client host add prod/web01 --host web01.example.com --user admin --key ~/.ssh/id_ed25519
# Par mot de passe
printf '%s' 'le-mot-de-passe' | ssh-client host add db01 --host db01.example.com --user dba --password-stdin
ssh-client host test web01 # vérifie connexion, auth, empreinte d'hôte
ssh-client host list
L'empreinte de la clé d'hôte est capturée à la première connexion (TOFU) ; un changement ultérieur fait échouer la connexion (code 255).
Hôte LXD (VM via un hôte parent)
Une VM LXD hébergée par un hôte déjà déclaré se cible comme un hôte à part
entière : la connexion se paramètre avec l'alias de l'hôte parent puis le nom
de la VM. Les commandes qui ciblent la VM sont exécutées sur le LXD de
l'hôte parent (lxc exec <vm> -- sh -c '…'), avec les identifiants du
parent — l'hôte LXD n'a aucun secret propre.
ssh-client host add vm01 --lxd-host web01 --vm app-vm
ssh-client exec --host vm01 -- systemctl status nginx # → lxc exec app-vm … sur web01
La politique d'autorisation s'évalue sur la commande destinée à la VM (pas
sur la forme lxc exec enveloppée). Les transferts upload/download sont
supportés : le fichier transite par l'hôte parent (SFTP + lxc file push/pull, fichier temporaire supprimé ensuite), et la liste d'autorisation
s'évalue sur le chemin dans la VM.
ssh-client upload --host vm01 ./app.tar.gz /srv/app/app.tar.gz # SFTP → web01, puis lxc file push
ssh-client download --host vm01 /var/log/app.log ./app.log # lxc file pull, puis SFTP → local
Sessions
Une session regroupe les exec d'une période de travail et journalise chaque
commande (y compris refusée) avec son résultat dans
.log/ssh-client/sessions/<AAAAMMJJhhmmss>-<id>.jsonl (dans le répertoire de
travail, commun à tous les espaces).
ssh-client session start maintenance-1
ssh-client session current
ssh-client session end maintenance-1
La session active est la dernière session non terminée et non expirée
(expiration : 10 min d'inactivité par défaut). Sans session active, un exec
en crée une automatiquement.
Exécution et politique d'autorisation
ssh-client policy check systemctl status nginx # décision sans exécuter (espace default ou unique)
ssh-client policy check --namespace prod systemctl status nginx # politique de l'espace prod
ssh-client exec --host web01 -- systemctl status nginx
ssh-client exec --host prod/web01 -- systemctl status nginx # évalué contre prod/policies.json
La liste deny est prioritaire. Les commandes composées (;, &&, |…) sont
découpées en segments évalués individuellement.
| code | Signification |
|---|---|
0–249 |
Exécutée ; code de sortie distant propagé. |
250 |
Erreur de configuration (hôte inconnu ou ambigu entre plusieurs espaces, identifiants absents). |
251 |
Délai d'inactivité dépassé (aucune sortie ; défaut 300 s, --timeout 0 = illimité). |
252 |
Erreur d'usage. |
253 |
Commande inconnue — autorisation utilisateur requise (rien exécuté). |
254 |
Refusée par une règle deny (rien exécuté). |
255 |
Erreur de connexion SSH (réseau, auth, empreinte). |
L'ajout d'un motif à
allowoudenyest une décision explicite de l'utilisateur : présenter la commande inconnue, recueillir la décision, puis seulementpolicy allow/policy deny(ouexec --oncepour une autorisation ponctuelle).
Transfert de fichiers (upload / download)
Copie de fichiers entre la machine locale et le serveur via SFTP, sous une
liste d'autorisation dédiée dans policies.json (sections upload et
download, motifs glob sur le chemin distant, * accepté).
ssh-client policy allow-upload "/srv/app/*" # décision explicite de l'utilisateur (--namespace <espace> au besoin)
ssh-client upload --host web01 ./app.tar.gz /srv/app/app.tar.gz
ssh-client download --host web01 /var/log/app.log ./app.log
uploadprend<chemin-local> <chemin-distant>;downloadprend<chemin-distant> <chemin-local>. Une destination répertoire conserve le nom du fichier source.- Un chemin distant non couvert par la liste → code 253 (autorisation
utilisateur requise) ; l'agent demande, puis
policy allow-upload/allow-downloadsur décision explicite. - Chaque transfert (y compris refusé) est journalisé dans la session et le journal de debug avec les métadonnées du fichier : nom, SHA-256, date et taille.
Codes de sortie : 0 succès · 250 config/fichier introuvable · 252 usage ·
253 non autorisé · 255 erreur SFTP.
Sécurité
- Deny prioritaire et défaut fermé : une commande non couverte n'est jamais exécutée silencieusement.
- Secrets isolés dans
credentials.json(permissions propriétaire seul sous POSIX), jamais affichés ni journalisés. - Journalisation de chaque décision et de son résultat dans la session.
Le modèle est coopératif : ssh-client structure et trace les actions d'un
agent ; il se combine à l'allowlist du harnais (n'autoriser que ssh-client,
jamais ssh brut, ni l'édition directe des fichiers de politique).
No packages depend on claria.tools.ssh-client.
| Version | Downloads | Last updated |
|---|---|---|
| 2.0.0-build.20260819.1 | 15 | 08/20/2026 |