restapi-client.linux-arm 0.5.2-build.20260813.1

Build Information

Provenance Azure DevOps Pipeline
Owner kntera (Yan Boivin)
Date de compilation 2026-08-14 02:26:03 UTC
Version 0.5.2.20260813.1
SHA256 178b4aa5f76e084a8fe1f0dfcf6057fa28f90d78

restapi-client

Outil en ligne de commande qui invoque des API REST sous le contrôle d'une politique d'autorisation (allow / deny / redact). Conçu pour permettre à des agents d'appeler des services HTTP en gardant l'humain aux commandes sur tout appel non couvert par la politique — même modèle de sécurité que ssh-client.


Contexte

Plutôt que d'exposer curl brut à un agent, restapi-client s'intercale comme garde-fou : chaque appel (combinaison service + méthode REST + chemin d'URL) est évalué contre une liste allow et une liste deny avant d'être envoyé. Un appel refusé n'ouvre même pas de connexion ; un appel inconnu signale à l'appelant qu'une décision humaine est requise. Une liste redact complémentaire permet d'autoriser un appel tout en caviardant sa réponse (corps jamais affiché ni journalisé). Chaque invocation (y compris les refus) est journalisée dans une session.

Spécifications complètes : doc/spec/** (A01 portée, E01 CLI, E02 services, E03 politique, E04 invocation, E05 sessions).


Utilisation

restapi-client invoke --service <nom> --method <GET|POST|…> --path <chemin>
                      [--query clé=valeur]… [--header "Nom: valeur"]…
                      [--body <json> | --body-file <chemin> | --body-stdin]
                      [--timeout <sec>] [--json] [--once]
restapi-client policy check <service> <méthode> <chemin>
restapi-client policy allow  <service> <méthodes> <motif-chemin>
restapi-client policy deny   <service> <méthodes> <motif-chemin>
restapi-client policy redact <service> <méthodes> <motif-chemin> [--mask <champ>[:<regex>]]…
restapi-client policy remove <service> <méthodes> <motif-chemin>
restapi-client policy list [--json]
restapi-client service add <nom> --base-url <url> [--base-path <chemin>] [--auth none]
restapi-client service add <nom> --base-url <url> --auth basic --user <u> --password-stdin
restapi-client service add <nom> --base-url <url> --auth bearer --token-stdin
restapi-client service add <nom> --base-url <url> --auth api-key --token-stdin [--api-key-header <nom>]
restapi-client service remove <nom>
restapi-client service list [--json]
restapi-client service test <nom> [--path <chemin>]
restapi-client session start [<id>]
restapi-client session end [<id>]
restapi-client session current [--json]
restapi-client session list [--json]
restapi-client --version | --help

Option globale : --config-dir <chemin> (sinon RESTAPICLIENT_HOME, puis ./.restapi-client s'il existe, puis ~/.restapi-client). --session <id> cible une session précise (créée si absente). --no-sessions désactive l'inscription locale des sessions (équivaut à RESTAPICLIENT_NO_SESSIONS=1). --no-debug-log désactive le journal de debug HTTP (équivaut à RESTAPICLIENT_NO_DEBUG_LOG=1).


Services

Les API cibles sont déclarées par nom dans config.json : URL de base, chemin de base optionnel, méthode d'authentification et en-têtes par défaut. Les secrets (mot de passe, jeton, clé d'api) sont stockés à part dans credentials.json (durci), jamais dans config.json, et se fournissent sur l'entrée standard.

# Sans authentification
restapi-client service add httpbin --base-url https://httpbin.org

# Bearer (le jeton est lu sur stdin)
printf '%s' 'le-jeton' | restapi-client service add github --base-url https://api.github.com --auth bearer --token-stdin

# Basic
printf '%s' 'le-mot-de-passe' | restapi-client service add jira --base-url https://jira.example.com --base-path /rest/api/2 --auth basic --user bot --password-stdin

# Clé d'api dans un en-tête dédié
printf '%s' 'la-clé' | restapi-client service add interne --base-url https://api.interne.local --auth api-key --token-stdin --api-key-header X-Api-Key

restapi-client service test github --path /rate_limit   # GET réel, rapporte le statut http
restapi-client service list

L'URL effective d'un appel est base-url + base-path + path. service add et service list affichent le préfixe tel que les appels le construiront, ce qui permet de vérifier la déclaration sur-le-champ.


⚠️ Chemins d'URL depuis Git Bash (MSYS)

Git Bash réécrit tout argument ressemblant à un chemin POSIX absolu en chemin Windows, avant que l'outil ne le reçoive : --base-path /client/v4 arrive comme C:/Program Files/Git/client/v4. Rien en aval ne peut distinguer cette valeur d'une valeur voulue.

L'outil refuse donc (code 252) tout chemin qui est un chemin Windows absolu (C:/…, C:\…) — forme qu'un chemin d'URL ne prend jamais — sur invoke --path, service add --base-path, service test --path, policy check et les motifs de policy allow / deny / redact. Le message nomme la cause et les contournements :

MSYS_NO_PATHCONV=1 restapi-client service add cloudflare --base-url https://api.cloudflare.com --base-path /client/v4
restapi-client service add cloudflare --base-url https://api.cloudflare.com --base-path //client/v4

Les guillemets ne protègent pas : "/client/v4" et '/client/v4' sont convertis comme la forme nue — le shell les retire avant que MSYS n'intervienne. Ce que MSYS convertit :

Valeur Convertie
/admin, /client/v4, "/client/v4" oui
/admin/*, /admin?x=1 non — un * ou un ? inhibe la conversion
//admin non — la barre oblique doublée est l'échappement MSYS

Un motif glob (/admin/*) échappe donc à la conversion : c'est le motif exact (/admin), celui d'une règle deny précise, qui était exposé — une règle réécrite figure dans policy list sans ne plus rien couvrir. D'où le refus plutôt qu'un avertissement. policy remove en est exempté, pour que les règles déjà enregistrées sous cette forme restent supprimables.

Depuis PowerShell ou un shell POSIX, aucune conversion n'a lieu et le contrôle ne se déclenche pas.


Politique d'autorisation (allow / deny / redact)

Une règle est la combinaison de trois éléments :

  1. service — nom du service déclaré (* accepté) ;
  2. méthodes — GET, liste GET,POST, ou * ;
  3. motif de chemin — glob simple sur le chemin d'URL (* seul métacaractère), évalué sans la query string.
restapi-client policy check github GET /repos/kntera/x     # décision sans invoquer
restapi-client policy allow github GET "/repos/*"          # autoriser
restapi-client policy deny  "*"    DELETE "*"               # interdire DELETE partout
restapi-client policy redact vault "*" "/secrets/*"        # cacher tout l'appel
restapi-client policy redact github GET "/user/keys*" --mask "payload-response:\"key\":\s*\"[^\"]*\""
restapi-client policy list
  • La liste deny est prioritaire ; le défaut est fermé : un appel non couvert n'est jamais envoyé silencieusement (code 253, décision humaine requise).
  • Un motif de chemin doit pouvoir correspondre au chemin comparé, qui commence toujours par / : un motif ne commençant ni par / ni par * est refusé (code 252) plutôt qu'enregistré sans jamais rien couvrir. Depuis Git Bash, voir aussi l'avertissement sur la conversion des chemins ci-dessus.
  • La liste redact est indépendante : elle ne rend pas un appel 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é (URL, en-têtes, corps requête et réponse → [REDACTED] ; seuls service, méthode, chemin, statut 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. Champs : url, payload-query (corps de la requête), payload-response (corps de la réponse), header-<clé> (ex. header-authorization, côté requête et réponse).
    • toutes les règles redact couvrant l'appel s'appliquent : leurs masques se cumulent et une seule règle sans --mask cache tout l'appel.
  • Masquage automatique en plus de la politique : l'en-tête d'authentification et toute occurrence littérale ou percent-encodée d'un secret du service (jeton, mot de passe, blob base64 du basic — même renvoyés par le serveur) sont toujours remplacés par [REDACTED] dans la sortie et le journal. L'en-tête d'authentification conserve le schéma (Basic/Bearer) et, pour bearer/api-key, un aperçu de la clé — préfixe de type jusqu'au dernier séparateur (-/_/+) des 8 premiers caractères et/ou 5 premiers caractères du secret selon la longueur (ex. Bearer sk-ant-api03[REDACTED], pk_live_[REDACTED]) ; en basic, seul le schéma est visible.
code Signification
0 Réponse HTTP 2xx.
3 / 4 / 5 Classe du statut HTTP final (3xx / 4xx / 5xx) ; statut exact via --json (statusCode) et le diagnostic stderr. Un 3xx final = redirection non suivie.
250 Erreur de configuration (service inconnu, identifiants absents, fichier de politique invalide).
251 Délai dépassé (défaut 30 s, --timeout 0 = illimité).
252 Erreur d'usage.
253 Appel inconnu — autorisation utilisateur requise (rien envoyé).
254 Refusé par une règle deny (rien envoyé).
255 Erreur de connexion HTTP (réseau, DNS, TLS).

L'ajout d'une règle allow, deny ou redact est une décision explicite de l'utilisateur : présenter l'appel inconnu, recueillir la décision, puis seulement policy allow / policy deny (ou invoke --once pour 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 <service> <méthode> "<motif>" puis relancer invoke.
Autoriser une seule fois Relancer invoke avec --once ; aucune persistance.
Refuser toujours policy deny <service> <méthode> "<motif>" ; ne pas invoquer.
Refuser cette fois-ci Ne rien persister, ne pas invoquer.

Ne jamais généraliser un motif au-delà de ce que l'utilisateur a approuvé ; ne jamais proposer de motif large pour une méthode mutative (POST, PUT, PATCH, DELETE).


Invocation

restapi-client invoke --service github --method GET --path "/repos/kntera/x/issues" --query "state=open"
restapi-client invoke --service jira --method POST --path "/issue" --body '{"fields":{...}}'
cat payload.json | restapi-client invoke --service jira --method POST --path "/issue" --body-stdin
  • Le corps est envoyé en application/json par défaut ; un --header "Content-Type: …" le remplace. Les en-têtes d'appel priment sur les en-têtes par défaut du service.
  • Redirections : suivies (5 max par défaut), mais chaque saut est réévalué contre la politique et journalisé individuellement. Un saut deny → 254 ; un saut non couvert → 253 (décision humaine) ; une cible hors des services déclarés n'est pas suivie (la réponse 3xx est retournée).
  • En mode texte, le corps de la réponse finale est écrit sur stdout ; le statut, l'URL et la durée sont des diagnostics stderr (préfixés restapi-client:).
  • --json produit un unique objet structuré sur stdout : service, méthode, chemin, URL, décision, règle, statusCode, contentType, responseHeaders, body, redacted, redirectCount, durationMs, timedOut.

Sessions

Une session regroupe les invoke d'une période de travail et journalise intégralement chaque requête HTTP (y compris refusée, chaque saut de redirection et le GET de service test) dans sessions/<AAAAMMJJhhmmss>-<id>.jsonl (à côté de l'exécutable) : URL, en-têtes requête et réponse, corps requête et réponse (plafonnés à 64 KiB chacun), décision, statut, 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 requête réellement envoyée est tracée dans un journal de debug HTTP quotidien, restapi-debug-AAAA-MM-JJ.log (à côté de l'exécutable) : même vue caviardée, mais corps intégraux (non plafonnés). Ce journal n'est pas affecté par --no-sessions ; il se désactive par --no-debug-log ou RESTAPICLIENT_NO_DEBUG_LOG=1. Le fichier est durci à sa création (600 sous POSIX ; avertissement ACL sous Windows).

restapi-client session start maintenance-1
restapi-client session current
restapi-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 invoke en crée une automatiquement.


Sécurité

  • Deny prioritaire et défaut fermé : un appel non couvert n'est jamais envoyé silencieusement — y compris les cibles de redirection, réévaluées saut par saut.
  • Secrets isolés dans credentials.json (permissions propriétaire seul sous POSIX), jamais affichés ni journalisés en clair — l'en-tête d'authentification et toute occurrence littérale ou percent-encodée d'un secret sont automatiquement remplacés par [REDACTED] (l'en-tête garde le schéma et, pour bearer/api-key, un court aperçu de la clé pour l'identifier).
  • 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 requête (décision, URL, en-têtes et corps requête/réponse) dans la session.

Le modèle est coopératif : restapi-client structure et trace les appels d'un agent ; il se combine à l'allowlist du harnais (n'autoriser que restapi-client, jamais curl brut, ni l'édition directe des fichiers de politique et d'identifiants).

No packages depend on restapi-client.linux-arm.

This package has no dependencies.

Version Downloads Last updated
0.5.2-build.20260813.1 16 08/14/2026