claria.tools.sql-client 1.0.0-build.20260819.1
Build Information
| Provenance | Azure DevOps Pipeline |
| Owner | kntera (Yan Boivin) |
| Date de compilation | 2026-08-20 03:29:31 UTC |
| Version | 1.0.0.20260819.1 |
| SHA256 | c459994b8934484f497073c13eb1e289a1d66b28 |
sql-client
Outil en ligne de commande qui exécute des requêtes SQL sur des bases
SQL Server, MySQL et PostgreSQL, sous le contrôle d'une politique
d'autorisation (allow / deny / redact). Conçu pour permettre à des
agents d'opérer des bases de données en gardant l'humain aux commandes sur
tout énoncé non couvert par la politique — même modèle de sécurité que
restapi-client et ssh-client.
Contexte
Plutôt que d'exposer un client SQL brut (sqlcmd, mysql, psql) à un agent,
sql-client s'intercale comme garde-fou : chaque script est analysé
(découpage en énoncés, type et objets référencés de chacun), puis chaque énoncé
— la combinaison base + type d'énoncé (SELECT, UPDATE, DELETE, …) + objet
(table, vue, procédure) — est évalué contre une liste allow et une liste
deny avant tout envoi. Le type d'énoncé joue le rôle de la méthode REST
de restapi-client ; l'objet, celui du chemin d'URL. Un script refusé
n'ouvre même pas de connexion ; un énoncé inconnu signale à l'appelant qu'une
décision humaine est requise. Une liste redact complémentaire permet
d'autoriser une requête tout en caviardant sa vue (SQL et résultats jamais
affichés ni journalisés). 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 bases,
E03 politique, E04 exécution, E05 sessions).
Utilisation
sql-client exec --database <nom> (--sql <texte> | --sql-file <chemin> | --sql-stdin)
[--timeout <sec>] [--max-rows <n>] [--json] [--once] [--transaction]
sql-client policy check <base> <type> <objet>
sql-client policy check <base> --sql <texte>
sql-client policy allow <base> <types> <motif-objet>
sql-client policy deny <base> <types> <motif-objet>
sql-client policy redact <base> <types> <motif-objet> [--mask <champ>[:<regex>]]…
sql-client policy remove <base> <types> <motif-objet>
sql-client policy list [--json]
sql-client database add <nom> --provider <sqlserver|mysql|postgresql>
--host <fqdn|ip> [--port <n>] --dbname <base>
--user <utilisateur> --password-stdin
[--no-encrypt] [--trust-server-certificate]
sql-client database remove <nom>
sql-client database list [--json]
sql-client database test <nom>
sql-client session start [<id>]
sql-client session end [<id>]
sql-client session current [--json]
sql-client session list [--json]
sql-client --version | --readme | --help
Option globale : --config-dir <chemin> (sinon SQLCLIENT_HOME, sinon
./.sql-client — local au projet, créé au besoin ; en lecture seule,
repli sur les fichiers livrés à côté du binaire ; les journaux — sessions et
debug — vont dans .log/sql-client/ du répertoire de travail). --session <id> cible une
session précise (créée si absente). --no-sessions désactive l'inscription
locale des sessions (équivaut à SQLCLIENT_NO_SESSIONS=1).
Bases de données
Les bases cibles sont déclarées par nom dans config.json : fournisseur,
hôte, port, base et options TLS. Les secrets (mot de passe) sont stockés à part
dans credentials.json (durci), jamais dans config.json, et se fournissent
sur l'entrée standard.
# SQL Server
printf '%s' 'le-mot-de-passe' | sql-client database add appdb --provider sqlserver --host db01.example.com --dbname app --user agent --password-stdin
# MySQL (TLS sans validation du certificat)
printf '%s' 'le-mot-de-passe' | sql-client database add inventaire --provider mysql --host mysql.interne.local --dbname inventaire --user bot --password-stdin --trust-server-certificate
# PostgreSQL (sans TLS, réseau interne)
printf '%s' 'le-mot-de-passe' | sql-client database add telemetrie --provider postgresql --host 10.0.0.12 --dbname telemetrie --user agent --password-stdin --no-encrypt
sql-client database test appdb # connexion réelle, sonde SELECT 1, version du serveur
sql-client database list
Seule l'authentification utilisateur + mot de passe est supportée (auth intégrée Windows / Kerberos / Azure AD hors portée). Ports par défaut : 1433 (sqlserver), 3306 (mysql), 5432 (postgresql).
Politique d'autorisation (allow / deny / redact)
Une règle est la combinaison de trois éléments — le modèle de
restapi-client, où le type d'énoncé remplace la méthode REST :
- base — nom de la base déclarée (
*accepté) ; - types —
SELECT, listeSELECT,UPDATE, ou*(EXEC,EXECUTEetCALLsont normalisés enEXEC) ; - motif d'objet — glob simple sur le nom d'objet (
*seul métacaractère), insensible à la casse, comparé à chaque table/vue/procédure référencée par l'énoncé (jointures comprises).
sql-client policy check appdb SELECT users # décision sans exécuter
sql-client policy check appdb --sql "SELECT * FROM users u JOIN commandes c ON c.userId = u.id"
sql-client policy allow appdb SELECT "users*" # autoriser
sql-client policy allow appdb SELECT,UPDATE "commandes"
sql-client policy deny "*" DROP,TRUNCATE "*" # interdire le DDL destructeur partout
sql-client policy redact vault "*" "secrets*" # cacher tout l'appel
sql-client policy redact appdb SELECT "jetons_api" --mask "column-jeton"
sql-client policy list
- Un script de plusieurs énoncés est évalué énoncé par énoncé, chaque énoncé sur chacun de ses objets ; le pire cas gagne (deny > unknown > allow) et rien n'est envoyé tant que tout n'est pas autorisé — aucune exécution partielle.
- La liste
denyest prioritaire ; le défaut est fermé : un énoncé non couvert n'est jamais envoyé silencieusement (code 253, décision humaine requise). L'analyse échoue fermé elle aussi (énoncé sans objet reconnu → seul un motif*le couvre). - La liste
redactest indépendante : elle ne rend pas un énoncé autorisé — elle caviarde ce que l'appel expose, à la fois dans la sortie et dans le journal de session :- sans
--mask: tout l'appel est caché (texte SQL, colonnes et lignes →[REDACTED]; seuls base, analyse, nombres de lignes et durée restent visibles) ; - avec
--mask <champ>[:<regex>](répétable) : seuls les champs désignés sont masqués — champ entier sans regex, ou uniquement les parties correspondant à la regex (valeurs texte). Champs :sql(texte du script),rows(toutes les valeurs),column-<nom>(une colonne des résultats, ex.column-mot_de_passe).
- sans
- Masquage automatique en plus de la politique : toute occurrence littérale
du mot de passe de la base (dans le SQL ou les résultats) est toujours
remplacée par
[REDACTED]dans la sortie et le journal.
| code | Signification |
|---|---|
0 |
Script exécuté sans erreur SQL. |
1 |
Erreur SQL rapportée par le serveur (syntaxe, contrainte, privilège) ; détail via --json (error) et le diagnostic stderr. |
250 |
Erreur de configuration (base inconnue, identifiants absents). |
251 |
Délai dépassé (défaut 30 s, --timeout 0 = illimité). |
252 |
Erreur d'usage (arguments invalides, script vide). |
253 |
Énoncé inconnu — autorisation utilisateur requise (rien envoyé). |
254 |
Refusé par une règle deny (rien envoyé). |
255 |
Erreur de connexion (réseau, authentification, TLS). |
L'ajout d'une règle
allow,denyouredactest une décision explicite de l'utilisateur : présenter l'énoncé inconnu, recueillir la décision, puis seulementpolicy allow/policy deny(ouexec --oncepour une autorisation ponctuelle).
Face à un code 253, les quatre décisions possibles de l'utilisateur :
| Décision | Action de l'agent |
|---|---|
| Autoriser toujours | policy allow <base> <type> "<motif>" (une règle par énoncé approuvé) puis relancer exec. |
| Autoriser une seule fois | Relancer exec avec --once ; aucune persistance. |
| Refuser toujours | policy deny <base> <type> "<motif>" ; ne pas exécuter. |
| Refuser cette fois-ci | Ne rien persister, ne pas exécuter. |
Ne jamais généraliser un motif au-delà de ce que l'utilisateur a approuvé ; ne
jamais proposer de motif large pour un type mutatif (INSERT, UPDATE,
DELETE, MERGE, DDL, EXEC).
Exécution
sql-client exec --database appdb --sql "SELECT TOP 10 * FROM users ORDER BY createdAt DESC"
sql-client exec --database appdb --sql-file ./scripts/maj-stocks.sql
sql-client exec --database appdb --sql-file ./scripts/procedures.sql --transaction
cat requete.sql | sql-client exec --database telemetrie --sql-stdin --json
- Chaque opération SQL est autorisée séparément (jamais « ligne par
ligne ») ; une définition
CREATE PROCEDURE/FUNCTION/TRIGGERcompte comme une seule opération sur le nom de la routine. - Le script est découpé en lots selon le fournisseur (lignes
GOpour SQL Server, directiveDELIMITERpour MySQL) puis envoyé, dans l'ordre, sur une même connexion ; un script sans séparateur part en une seule commande, tel quel (variables, tables temporaires et transactions explicites conservent leur sémantique). --transactionenveloppe le script dans une transaction client unique (commitau succès,rollbackà la première erreur ou au délai dépassé) ; sinon le script gère sa propre transaction ou l'autocommit s'applique.- Chaque jeu de résultats est plafonné à
--max-rowslignes (1000 par défaut,0= illimité) ; au-delà, le jeu est marquétruncated. - En mode texte, les lignes de chaque jeu sont écrites sur stdout en JSON
(tableau d'objets
colonne: valeur) ; le résumé (énoncés, jeux, lignes, durée) est un diagnostic stderr (préfixésql-client:). --jsonproduit un unique objet structuré sur stdout : base, fournisseur, décision, règle, analyse des énoncés (statements),resultSets,rowsAffected,error,redacted,durationMs,timedOut,transaction,rolledBack.- Valeurs :
NULL→null, nombres/booléens natifs, dates ISO 8601, binaires en Base64.
Sessions
Une session regroupe les exec d'une période de travail et journalise
intégralement chaque exécution (y compris refusée et la sonde de
database test) dans .log/sql-client/sessions/<id>.jsonl (dans le
répertoire de travail) : analyse
des énoncés, décision, texte SQL et résultats (plafonnés à 64 KiB
chacun), lignes affectées, erreur, durée. Les valeurs journalisées sont la vue
caviardée : une donnée masquée (règle redact ou secret) n'est jamais
persistée.
En complément, chaque script réellement envoyé est tracé dans un journal
de debug SQL quotidien, sql-debug-AAAA-MM-JJ.log (dans .log/sql-client/
du répertoire de travail) :
même vue caviardée, mais résultats intégraux (non plafonnés). Ce journal
n'est pas affecté par --no-sessions.
sql-client session start maintenance-1
sql-client session current
sql-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.
Sécurité
- Deny prioritaire et défaut fermé : un énoncé non couvert n'est jamais envoyé silencieusement — l'analyse échoue fermé, et un script partiellement couvert n'est pas envoyé du tout.
- Secrets isolés dans
credentials.json(permissions propriétaire seul sous POSIX), jamais affichés ni journalisés — toute occurrence littérale du mot de passe est automatiquement remplacée par[REDACTED]. - Caviardage : les données sensibles (liste
redact, masques par champ et regex) ne transitent ni par la sortie de l'agent ni par les journaux. - Journalisation intégrale de chaque exécution (décision, analyse, SQL, résultats) dans la session.
- Moindre privilège côté serveur : le compte SQL déclaré ne devrait détenir que les privilèges nécessaires — la politique est un garde-fou, pas une barrière.
Le modèle est coopératif : sql-client structure et trace les requêtes d'un
agent ; il se combine à l'allowlist du harnais (n'autoriser que sql-client,
jamais un client SQL brut, ni l'édition directe des fichiers de politique et
d'identifiants).
No packages depend on claria.tools.sql-client.
| Version | Downloads | Last updated |
|---|---|---|
| 1.0.0-build.20260819.1 | 8 | 08/20/2026 |