Documentation utilisateur

Installation, configuration, API publiques et dépannage.

Auton

Le projet Auton

Auton est un logiciel libre et gratuit d’exécution à distance. auton est le client CLI/TUI ; autond expose les commandes configurées au moyen d’une API HTTP authentifiée et d’une console web locale facultative. Il sert aux diagnostics des opérateurs, aux tâches CI/CD et aux outils distants tels qu’Ansible, curl ou Terraform.

Le client sélectionne les cibles et orchestre les scénarios. Chaque daemon applique ses propres permissions sur les endpoints, exécute les tâches et conserve leurs résultats. Aucun serveur central n’est nécessaire.

Démarrage rapide

Ce démarrage rapide utilise Auton 1.5.3, avec authentification SQLite, tâches persistantes et console Web. Récupérez cette version et utilisez Docker Compose :

git clone https://github.com/decryptus/auton.git
cd auton
git checkout v1.5.3
docker compose build
docker compose run --rm --no-deps --entrypoint autond-auth auton \
  -c /etc/auton/auton.yml user set -u operator -s read -s run -s maintenance
docker compose up -d

Choisissez un mot de passe à l’invite interactive, puis ouvrez http://127.0.0.1:8666/ui/ et connectez-vous comme operator. Sélectionnez l’endpoint hello et confirmez l’exécution : sa commande fixe affiche Hello from Auton!. Il n’existe aucun identifiant par défaut.

Compose lie le port publié à l’interface de boucle locale de l’hôte ; la configuration du conteneur écoute sur l’interface du conteneur. L’authentification et l’historique utilisent des fichiers SQLite distincts dans un volume nommé. docker compose down les conserve ; docker compose down -v les supprime. Les résultats expirent toujours selon la politique de conservation configurée.

Pour un accès distant, configurez HTTPS, définissez web_origin avec l’origine externe et gardez le backend privé (voir la console web). L’origine navigateur fournie accepte volontairement 127.0.0.1, et non localhost.

Exécuter le même message par HTTP ou depuis la CLI

Le démarrage rapide SQLite utilise votre mot de passe pour la connexion web et un jeton bearer à permissions limitées pour l’accès API/CLI. L’authentification HTTP Basic par mot de passe appartient à une configuration historique distincte ; elle ne permet pas de se connecter à SQLite.

Après docker compose up -d, créez un jeton valable une heure pour le même opérateur et copiez-le sur votre machine. Exécutez ces commandes depuis le répertoire auton cloné :

docker compose exec auton autond-auth -c /etc/auton/auton.yml \
  token create -u operator -s read -s run -t 3600 \
  -o /var/lib/autond/auth/quickstart.token
(umask 077; docker compose cp auton:/var/lib/autond/auth/quickstart.token ./quickstart.token)
chmod 600 ./quickstart.token

Le fichier de jeton est un secret d’accès : gardez-le privé et hors de Git. La création refuse d’écraser un fichier existant ; utilisez un nouveau nom dans toutes les commandes pour émettre un autre jeton. Le jeton expire après une heure. Conservez l’identifiant affiché par token create pour pouvoir le révoquer plus tôt.

Avec curl installé, soumettez l’opération fixe hello. Cet exemple utilise Bash et transmet l’en-tête d’autorisation par l’entrée standard afin de garder le jeton hors des arguments de commande :

job_id="$(python3 -c 'import uuid; print(uuid.uuid4())')"
sed 's/^/Authorization: Bearer /' ./quickstart.token | \
  curl --fail-with-body --silent --show-error --max-time 10 \
    --header @- --header 'Content-Type: application/json' --data '{}' \
    "http://127.0.0.1:8666/run/hello/$job_id"

# Read this job again until status is complete; do not submit it again.
sed 's/^/Authorization: Bearer /' ./quickstart.token | \
  curl --fail-with-body --silent --show-error --max-time 10 \
    --header @- "http://127.0.0.1:8666/jobs/hello/$job_id"

Une exécution réussie présente status: complete, return_code: 0 et Hello from Auton! dans stream. L’acceptation de la soumission ne prouve pas à elle seule la réussite de l’exécution. Si la soumission dépasse le délai, inspectez le même identifiant de tâche avant d’envisager une nouvelle soumission.

Pour la CLI, installez le client dans un environnement virtuel Python 3.10–3.13 et exécutez un autre message avec le même jeton :

python3 -m venv .venv
. .venv/bin/activate
python -m pip install auton==1.5.3
auton --uri http://127.0.0.1:8666 -k ./quickstart.token --endpoint hello

La CLI affiche Hello from Auton! et se termine avec le code zéro lorsque la commande réussit. Elle n’ouvre la TUI que si vous demandez explicitement --tui. Actualisez la console web en étant connecté comme operator pour voir aussi ces tâches : HTTP, CLI et web partagent la même identité et le même historique conservé.

Environnement d’exécution et fiabilité

Auton 1.0 cible Linux/Unix avec Python 3.10–3.13. Python 2 n’est plus pris en charge. Python 3.13 utilise legacycrypt et la dépendance de compatibilité legacy-cgi d’HTTPdis. Python 3.12 et suivants installent pyasyncore. Les versions Python plus récentes restent hors du périmètre testé.

L’image Docker installe désormais cette copie du dépôt, s’exécute sous l’utilisateur auton et Compose publie le port 8666 sur 127.0.0.1 uniquement. Le démarrage rapide impose l’authentification SQLite et les permissions des endpoints. Les configurations Basic existantes restent prises en charge ; utilisez HTTPS avant d’exposer l’un de ces modes à distance. Chaque identité authentifiée reste propre à sa requête.

Exécution et basculement

  • Le premier serveur qui accepte la tâche met fin aux essais sur les autres serveurs. Le basculement automatique se limite aux échecs d’établissement de connexion. Un délai de lecture dépassé ou une déconnexion après envoi est ambigu et ne provoque pas de nouveau POST. Utilisez --mode status --uid <original-id> pour inspecter la tâche. Il n’existe ni état partagé ni garantie d’exécution exactement une fois entre serveurs.

  • --http-timeout 30 limite chaque attente de connexion ou de lecture HTTP. Ce délai est distinct du timeout d’exécution de l’endpoint et ne constitue pas une durée maximale globale de la tâche.

  • Lorsque le délai d’exécution expire, le groupe de processus est arrêté et récupéré ; le client reçoit le code de sortie 124. L’arrêt du service interrompt la commande active avec le code 130. Les tâches doivent rester dans leur groupe de processus ; ce mécanisme n’est pas un bac à sable de conteneur.

  • stdout/stderr sont décodés en UTF-8 en remplaçant les séquences invalides. Les lignes partielles sont disponibles sans attendre un retour à la ligne. La réponse initiale est affichée.

  • Les arguments clients sont littéraux, y compris les accolades et le JSON. Seuls les arguments configurés par l’administrateur permettent l’interpolation de variables. Les noms de fichiers envoyés doivent être de simples noms de base ; les chemins absolus et les traversées de répertoires sont refusés.

Reprendre après un échec

Situation

Vérifications avant une nouvelle soumission

Connexion refusée avant son établissement

Vérifiez l’adresse et la disponibilité du daemon. Le basculement explicite ne peut essayer une autre adresse configurée que lorsque le transport sait que la soumission n’a pas été envoyée.

Connexion perdue ou délai de réponse dépassé après la soumission

La commande a pu s’exécuter. Conservez l’identifiant d’origine et interrogez son état sur le daemon d’origine avec la même identité ; un dépassement de délai ne signifie pas une annulation.

Jeton API expiré ou révoqué (401)

Obtenez un nouveau jeton pour le même compte. Si une requête précédente a été acceptée, inspectez cette tâche avec les accès renouvelés avant de la relancer. Une session web expirée nécessite une nouvelle connexion.

Échec de la commande

Inspectez stdout, stderr et le code de sortie conservés. Une terminaison avec un code non nul peut avoir des effets partiels ; aucune nouvelle tentative n’est automatique.

Délai d’exécution dépassé (124)

Le daemon arrête le groupe de processus de la commande. Inspectez les sorties partielles et les effets externes avant de décider d’une nouvelle tentative.

Daemon redémarré avec historique SQLite

Les résultats terminés restent disponibles jusqu’à expiration. Une tâche inachevée est marquée interrompue et n’est jamais rejouée automatiquement. L’issue d’une tâche auparavant en cours est inconnue ; vérifiez ses effets.

Tâche introuvable (404)

Vérifiez le daemon, l’endpoint et l’identifiant. L’expiration, l’éviction ou un stockage uniquement en mémoire peuvent supprimer les traces ; l’absence d’historique ne prouve pas que la commande ne s’est jamais exécutée.

Lire une tâche existante sans en soumettre une autre :

auton --mode status --uri https://autond.example \
  -k ./operator.token --endpoint diagnostic --uid ORIGINAL-JOB-ID

Utilisez l’identifiant exact de la requête initiale, sans créer de nouvel UUID. Gardez le même compte : la propriété de la tâche s’applique toujours après renouvellement du jeton. Pour les scripts ou cron, enregistrez un --uid explicite avant la soumission afin de ne pas dépendre de la sortie du terminal. La console web marque les tâches en cours interrompues Unknown outcome (issue inconnue). La lecture de l’état et l’actualisation de la console ne soumettent jamais à nouveau une commande.

Résultats et limites de ressources

Les nouveaux clients envoient X-Auton-Output-Offset dans les requêtes d’état et utilisent next_offset dans les réponses. Les offsets comptent les blocs de sortie, pas les octets. Répéter un offset renvoie le même préfixe et les sorties produites ensuite, sans consommer la lecture d’un autre client. Les anciens clients conservent leur curseur partagé. Une tâche terminée n’est plus supprimée à la première lecture de son état.

Limites dans general :

Paramètre

Valeur par défaut

Comportement

result_ttl

3600 secondes

Les résultats terminés expirent ; le nettoyage intervient lors des requêtes d’exécution ou d’état suivantes.

max_jobs_per_user

La moitié de max_jobs, arrondie à l’entier supérieur

Limite les jobs en attente et en cours par utilisateur, tous endpoints confondus. Les requêtes anonymes partagent un quota. Tout dépassement renvoie HTTP 429.

max_jobs

128

Limite l’ensemble des tâches en attente, en cours et conservées. Les résultats terminés les plus anciens sont évincés en premier ; si toutes les tâches sont actives, les nouvelles soumissions reçoivent 503.

max_output_bytes

1048576

Budget UTF-8 cumulé de stdout/stderr par tâche. Son dépassement arrête la commande avec le code 1. Un court diagnostic est conservé en supplément.

Chaque utilisateur dispose de ses propres identifiants de jobs sur chaque endpoint. Deux utilisateurs peuvent choisir le même identifiant, y compris avec un historique SQLite ou Redis. Un doublon pour un même utilisateur sur le même endpoint renvoie HTTP 409. Des arguments invalides renvoient HTTP 400. La lecture ou l’annulation d’un identifiant inconnu sur un endpoint autorisé renvoie HTTP 404. OIDC accepte une date d’émission en avance de 30 secondes au maximum. La date d’expiration reste stricte.

Par défaut, les résultats restent en mémoire et disparaissent au redémarrage. Le stockage SQLite facultatif conserve les résultats ; le démarrage rapide Docker l’active. Les identifiants ne sont réservés que pendant la conservation de leur tâche ; utilisez un nouvel UUID par opération. Après éviction ou expiration, les résultats ne peuvent plus être relus et les identifiants ne protègent plus contre une nouvelle exécution. L’accès à l’état est réservé à l’utilisateur authentifié ayant soumis la tâche, sous réserve des permissions actuelles de l’endpoint. Les tâches de démonstration non authentifiées n’ont pas d’identité utilisateur individuelle.

Découverte des endpoints

Les clients découvrent les endpoints autorisés par GET /endpoints authentifié (scope read en mode SQLite). La TUI et la console web utilisent déjà ce catalogue ; les adresses des cibles restent configurées côté client. La découverte ne soumet aucune tâche, ne diffuse rien vers les URI de secours et n’accorde aucun droit d’exécution.

Un endpoint peut publier explicitement une description facultative :

endpoints:
  hello:
    plugin: subproc
    discovery:
      description: Print a greeting to verify remote execution.
    users:
      operator: true
    config:
      prog: /usr/bin/printf
      args: ['Hello from Auton!\n']
      disallow-args: true
      timeout: 5

Seuls name et les métadonnées de découverte explicitement déclarées sont renvoyés, après contrôle des ACL actuelles. Sans description, la réponse existante {"name": "hello"} ne change pas. Une description est un texte imprimable sur une seule ligne, limité à 512 caractères ; les champs inconnus ou valeurs invalides empêchent le chargement avant l’initialisation des endpoints. Ce texte est visible par toute identité autorisée à découvrir l’endpoint : n’y placez aucun secret. Commandes, chemins, variables, accès, utilisateurs et activité de la file ne sont ni déduits ni exposés.

La TUI affiche les descriptions et permet de les rechercher ; la console web les affiche comme du texte, notamment dans le sélecteur d’endpoints. L’exécution exige toujours run et la permission de l’endpoint à l’admission et à l’exécution. Les configurations historiques ou anonymes conservent leur politique d’authentification ; la découverte ne la renforce pas implicitement. Auton 1.2.0 prend aussi en charge des schémas de paramètres explicites et des formulaires générés (voir ci-dessous). Aucun argument, contrainte ou défaut n’est déduit de la configuration privée de l’exécutable.

Visibilité du daemon local

Le daemon expose aussi ces routes en lecture seule :

Requête

Résultat

GET /jobs

jobs : métadonnées des tâches conservées de l’appelant, sans les sorties.

GET /jobs?endpoint=test&status=complete

Filtres exacts par endpoint et état. Les états sont new, processing et complete ; une tâche terminée n’a pas nécessairement un code de sortie zéro. Les filtres invalides renvoient 400.

GET /jobs/<endpoint>/<id>

Métadonnées et sorties conservées ; X-Auton-Output-Offset sélectionne les blocs stdout, à partir de zéro par défaut.

GET /endpoints

endpoints : noms autorisés par les ACL actuelles des endpoints.

GET /health

status: ok lorsque le service local de tâches est accessible ; cela ne vérifie ni les dépendances distantes ni la progression des workers.

GET /stats

stats : nombre de tâches visibles, totaux par état et nombre d’endpoints accessibles.

Listes, détails et statistiques appliquent les permissions actuelles des endpoints et la propriété des tâches. Les totaux excluent les tâches d’autres utilisateurs ; la profondeur des files partagées n’est pas exposée. Le détail renvoie HTTP 200 même si la commande a échoué : inspectez status, return_code et errors. Une tâche absente ou expirée renvoie 404, un refus d’accès 403 et un délai de verrouillage dépassé 503. Les listes, statistiques et détails nettoient aussi les résultats expirés. L’historique SQLite local facultatif survit au redémarrage (voir Tâches locales persistantes) ; la mémoire reste le mode par défaut.

Ces lectures ne font jamais avancer le curseur de sortie historique /status. Le détail conserve le format existant (stream pour stdout, errors pour stderr et les diagnostics). Les contrats /run et /status restent inchangés.

La configuration d’exemple utilise auth_mode: required : configurez les accès Basic ou SQLite avant de démarrer. Les ACL actuelles des endpoints et la propriété des tâches restent applicables. Utilisez HTTPS à distance. Conservez safe_init: true sur la route run lors de la migration des routes.

Exécution explicite sur plusieurs cibles

Exécuter une commande sur chaque daemon explicitement nommé :

auton --target web-01=https://autond-01.example.com \
      --target web-02=https://autond-02.example.com \
      --endpoint curl --operation-id deploy-42 --parallel 2 \
      -a https://example.com

Les cibles peuvent aussi être déclarées dans un inventaire YAML client explicite, distinct de la configuration serveur autond. Voir targets.yml.example :

targets:
  autond-01: https://autond-01.example.com
  autond-02: https://autond-02.example.com

Sélectionnez une ou plusieurs cibles configurées en répétant --target :

auton --config targets.yml --target autond-01 --target autond-02 \
      --endpoint curl -a https://example.com

Les noms configurés et les cibles ponctuelles peuvent être combinés :

auton --config targets.yml --target autond-01 \
      --target temporary=https://autond-03.example.com \
      --endpoint curl -a https://example.com

Le même inventaire permet la sélection en lecture seule dans la TUI :

auton --config targets.yml --tui --daemon autond-01 --daemon autond-02

Des groupes nommés peuvent sélectionner plusieurs cibles déclarées. Les noms des groupes et des cibles suivent [a-z0-9-]+ (1 à 32 caractères) ; leurs membres sont des noms exacts de cibles, sans groupes imbriqués.

targets:
  autond-01: https://autond-01.example.com
  autond-02: https://autond-02.example.com
groups:
  production: [autond-01, autond-02]
# Execute once on each target in the union of the selections.
auton -c targets.yml -t autond-01 -g production --endpoint curl -a https://example.com

# Open a read-only TUI restricted to the same group; no job is submitted.
auton --tui -c targets.yml -g production

-c, -t et -g sont les alias de --config, --target et --target-group. Répétez -g pour combiner des groupes. Les cibles explicites sont résolues d’abord, puis les groupes dans l’ordre des options et leurs membres dans l’ordre du fichier ; les membres communs ne s’exécutent qu’une fois. Répéter directement un nom --target reste une erreur. Des noms distincts pointant vers la même origine normalisée sont aussi refusés pour l’exécution. Les groupes ne changent jamais le basculement. Les sélecteurs de cibles et de groupes acceptent les motifs décrits ci-dessous ; les membres YAML restent des noms exacts.

Déclarer des cibles ne les sélectionne jamais automatiquement. --config exige une sélection explicite par --target, --target-group ou --daemon et ne se combine pas avec --uri. Il n’existe ni chemin d’inventaire implicite ni substitution de variables. Les noms inconnus, clés YAML dupliquées, noms ou URI invalides (même non sélectionnés), champs inconnus et URI non textuelles sont refusés avant toute requête. Un NAME=URI ponctuel ne peut pas masquer un nom configuré ; choisissez un autre alias.

L’inventaire accepte 1 à 128 cibles, au plus 128 groupes et 1 à 128 membres par groupe. Placez entre guillemets les noms uniquement numériques et les mots réservés YAML comme on. L’authentification reste dans les options CLI ou d’environnement existantes, pas dans ce fichier.

--target NAME et --target NAME=URI peuvent aussi sélectionner les connexions TUI en lecture seule. --daemon reste réservé à la TUI et ne se combine pas avec --target ; chacun peut être associé à --target-group. Pour l’exécution, les sélections de cibles ne peuvent pas utiliser --uid/AUTON_UID, --mode run/status ou --no-return-code. AUTON_URI est ignoré pour les sélections nommées explicites. Répéter --uri conserve le mode basculement.

Sélection par nom, motif glob et expression régulière

La CLI et la TUI utilisent la même convention que monit-docker :

# Globs match the entire name, case-sensitively.
auton --tui -c targets.yml -t 'web-*' -g 'prod-*'

# A leading ~ selects a regex; matching starts at the beginning of the name.
# Add $ to require an end match. Quote patterns to avoid shell expansion.
auton --tui -c targets.yml --daemon '~web-[0-9]{1,2}$'

--target/-t, --target-group/-g et --daemon dans la TUI acceptent des sélecteurs. Répétez les options pour les combiner ; les virgules appartiennent au motif et ne servent jamais de séparateur. Les motifs correspondent seulement aux noms déclarés dans l’inventaire, jamais aux URI. NAME=URI crée toujours une connexion ponctuelle explicite. Les groupes sont développés après correspondance de leurs noms ; les sélections communes gardent leur première position et s’exécutent une fois. Répéter directement un nom exact de cible reste une erreur.

Chaque sélecteur doit correspondre à au moins un nom. Les noms inconnus, expressions invalides, délais regex dépassés et correspondances vides annulent toute la sélection avant l’accès réseau ou le démarrage du terminal. Aucun repli vers toutes les cibles n’existe. Une sélection accepte jusqu’à 128 sélecteurs de 4096 caractères chacun, avec un budget total d’une seconde et au plus 50 ms par comparaison motif/nom. La syntaxe suit Python re, évaluée par le moteur borné regex VERSION0. Les noms déclarés gardent la validation distincte [a-z0-9-]+.

Imports de sections sur un seul niveau

Utilisez la convention DWho import_<section> dans le fichier client principal :

import_targets:
  - targets/production.yml
  - targets/staging.yml
import_groups: groups.yml

Un fichier de cibles importé contient directement la correspondance nom/URI, sans enveloppe targets:. Un fichier de groupes importé contient directement la correspondance groupe/liste de membres, sans enveloppe groups:. Les sections targets et groups du fichier principal peuvent ajouter d’autres noms.

Les chemins sont locaux et relatifs au répertoire du fichier principal ; les chemins locaux absolus sont aussi acceptés. Un seul niveau d’import est autorisé : les fichiers importés ne peuvent pas en importer d’autres. Les chemins dupliqués (y compris via liens symboliques), noms dupliqués entre fichiers ou sections, fichiers absents et sections mal formées sont des erreurs ; rien n’est remplacé silencieusement. L’entrée UTF-8 cumulée est limitée à 64 Kio et 16 fichiers importés. Les imports par URL, balises !include, clés de fusion YAML et groupes imbriqués ne sont pas pris en charge. Toutes les sections sont chargées et validées avant sélection ou accès réseau. Ces règles s’appliquent aussi à import_scenarios et import_scenario_groups décrits ci-dessous.

Les mêmes arguments préparés, fichiers d’arguments et variables d’environnement sont envoyés à chaque cible sélectionnée. Utilisez les profils d’accès liés aux origines pour des comptes indépendants. Un seul jeton -k ou une identité Basic historique s’applique à toutes les cibles explicites ; réservez ce mode aux origines qui font toutes confiance à ces accès. Utilisez HTTPS à distance. Toutes les origines sont validées avant le premier POST (nom d’hôte/IPv4/IPv6, port 1–65535, sans espace ni caractère de contrôle). Les redirections ne sont jamais suivies. Chaque daemon applique son authentification, ses ACL et la propriété des tâches. Les origines normalisées dupliquées sont refusées ; des alias DNS distincts du même daemon ne peuvent pas être détectés automatiquement.

Le client affiche un objet JSON final, adapté à l’enregistrement dans une CI :

{
  "operation_id": "deploy-42",
  "endpoint": "curl",
  "status": "completed",
  "targets": [{
    "target": "web-01",
    "uri": "https://autond-01.example.com",
    "job_id": "8c1438b0-df10-455c-83ba-73b5b1bcd2b0",
    "uid": "curl:8c1438b0-df10-455c-83ba-73b5b1bcd2b0",
    "status": "completed",
    "remote_status": "complete",
    "return_code": 0,
    "stdout": ["OK\n"],
    "stderr": [],
    "error": null,
    "output_truncated": false,
    "duration_ms": 125.0
  }]
}

L’exemple montre une seule cible ; chaque cible sélectionnée reçoit son entrée et un nouvel identifiant de tâche UUID. operation_id est un UUID par défaut et constitue une étiquette côté client, pas une clé d’idempotence. Répéter l’invocation, même avec la même étiquette, lance de nouvelles tâches. Enregistrez le résultat JSON pour conserver la correspondance opération/tâches ; les daemons ne disposent ni de persistance des opérations ni d’ordonnanceur central.

État de la cible

Signification

completed

Terminaison confirmée avec le code de sortie zéro

failed

Terminaison confirmée avec un code de sortie non nul

rejected

Soumission explicitement refusée, par exemple pour un échec d’authentification ou d’ACL

unknown

Résultat non confirmé ; la commande distante a pu s’exécuter ou peut encore être en cours

not_submitted

Observation arrêtée avant la soumission de cette cible en attente

L’état de l’opération vaut completed uniquement si toutes les cibles réussissent, incomplete si une cible est inconnue ou non soumise, sinon failed. Le code de sortie CLI vaut zéro uniquement pour une opération terminée avec succès ; --no-return-code n’est pas disponible ici. Les cibles indépendantes continuent lorsqu’une autre échoue ; aucun retour arrière n’est effectué.

--parallel vaut 4 par défaut (plage 1–32). --operation-timeout vaut 300 secondes et limite la fenêtre d’observation, y compris l’attente d’un worker. --http-timeout limite chaque attente de connexion ou de lecture ; une requête déjà lancée peut se terminer après la limite d’observation. Ctrl-C arrête l’observation et les soumissions en attente, attend les requêtes HTTP en cours, puis affiche les résultats disponibles. Aucun de ces mécanismes n’annule les tâches distantes.

Un POST potentiellement accepté n’est jamais rejoué automatiquement, même après un échec réseau. Pour unknown, inspectez le daemon et l’identifiant enregistrés dans la TUI ou avec GET /jobs/<endpoint>/<job_id> avant de décider de la suite. Les sorties restent séparées par cible, avec une limite cumulée de 1 Mio pour stdout/stderr et un indicateur explicite de troncature. Le tableau stderr contient aussi les diagnostics du daemon. La durée mesure l’observation côté client, pas seulement l’exécution du processus distant. Ce mode initial affiche le résultat à la fin ; les vues d’opération en direct restent un travail ultérieur.

Origines de secours ordonnées par cible

Une cible logique peut définir des daemons de remplacement ordonnés tout en conservant la forme existante name: URI :

targets:
  node-01: https://autond-01.example.com
  node-02: https://autond-02.example.com
  deployment:
    uris:
      - {target: node-01}
      - {target: node-02}
      - https://autond-03.example.com

auton -c client.yml -t deployment --endpoint deploy s’exécute sur une seule origine admissible. Sélectionner plusieurs cibles exécute toujours l’opération sur chaque cible distincte. Aucun nouveau drapeau ni diffusion implicite vers les origines de remplacement n’est ajouté.

Chaque liste uris contient 1 à 16 origines littérales ou références explicites {target: name}. Une référence peut résoudre la chaîne d’une autre cible jusqu’à 16 niveaux ; les cibles absentes et les cycles sont refusés. Les références aux groupes de cibles sont interdites. Les doublons normalisés d’une chaîne sont fusionnés dans l’ordre de première apparition ; l’expansion doit conserver au plus 16 origines. Des origines communes à des cibles d’exécution sélectionnées séparément sont refusées avant soumission pour éviter une double exécution. Tout l’inventaire est validé, même les définitions non sélectionnées. Les imports de fichiers restent distincts et limités à un niveau ; les références de cibles n’importent aucun fichier.

L’origine suivante n’est envisagée qu’après un refus pour maintenance, un contrôle de santé indisponible avant tout POST, ou un échec d’établissement de connexion prouvant que le POST n’a pas été accepté. Les erreurs de validation TLS, refus d’autorisation, réponses HTTP 503 génériques, POST ambigus et réponses perdues ou trop tardives n’autorisent aucune soumission de remplacement. Chaque tentative utilise le budget restant de l’opération.

Après admission, les lectures d’état et de sorties restent sur ce daemon. Dans un scénario, la première étape réussie fixe l’origine pour toutes les étapes et tous les scénarios restants de l’invocation. Si cette origine devient indisponible ou passe en maintenance, la cible s’arrête ; la séquence ne déplace jamais silencieusement l’état local du daemon. Un remplacement doit effectuer un travail équivalent avec les mêmes permissions et dépendances ; une autre machine ne remplace pas automatiquement une commande locale à un hôte.

Les résultats comprennent l’uri contactée ou ayant accepté la tâche et les attempts ordonnées, avec les états not_admitted, responded, admitted ou unknown et des raisons explicites. responded ne prouve pas l’admission : la tâche retournée doit être valide. L’état final de la cible ou de l’étape fait foi ; une issue inconnue exige une inspection manuelle avant toute nouvelle invocation.

L’aperçu d’exécution TUI montre la chaîne ordonnée et les résultats montrent les origines essayées. La supervision reste liée à l’origine principale de chaque cible, indiquée en pied de page lorsqu’il existe des chaînes de remplacement. Elle n’agrège pas les tâches des daemons de secours et ne bascule pas silencieusement entre eux. Sélectionnez séparément leurs noms physiques pour les inspecter, ou ouvrez explicitement l’origine réelle du résultat. Le résultat de l’opération contient déjà les sorties du daemon ayant accepté la tâche.

Maintenance locale du daemon

La maintenance suspend les nouvelles exécutions tout en laissant accessibles l’état de santé, les listes de tâches et les sorties. Configurez les administrateurs autorisés sur le daemon :

general:
  # Keep the existing general settings and enable HTTP authentication.
  maintenance_operators: [operator]
  maintenance: false
  maintenance_reason: ""

La nouvelle route dans etc/auton/modules/job.yml exige une authentification ; une liste d’opérateurs vide (valeur par défaut) n’autorise personne à modifier la maintenance. Le droit d’exécuter un endpoint n’accorde pas le droit de maintenance. Lors d’une mise à niveau, ajoutez POST /maintenance à la configuration des routes existante.

curl --user operator --header 'Content-Type: application/json' \
  --data '{"enabled":true,"reason":"Planned upgrade"}' \
  https://autond.example.com/maintenance
curl --user operator --header 'Content-Type: application/json' \
  --data '{"enabled":false}' https://autond.example.com/maintenance

Le booléen enabled est obligatoire ; reason est facultatif et limité à 512 caractères. La santé reste status: "ok", avec maintenance: {enabled, reason} et accepting_jobs. Le motif doit être adapté à toutes les personnes autorisées à lire l’état de santé. La TUI distingue maintenance et erreurs de connexion ou de santé.

  • Les tâches déjà en cours se terminent normalement.

  • Les tâches admises mais encore en attente restent new (en file), sans horodatage de début. Elles reprennent à la fin de la maintenance même si le client s’est déconnecté. L’autorisation de l’endpoint est vérifiée à nouveau avant le lancement du processus.

  • Les nouvelles soumissions reçoivent HTTP 503, le JSON message: "daemon_maintenance" et X-Auton-Admission: not-admitted. L’admission et le lancement du processus partagent un contrôle atomique avec les changements de maintenance ; vérifier seulement la santé ne suffit pas.

  • L’exécution moderne multi-cibles/scénarios/TUI vérifie la santé avant soumission et signale la maintenance comme un refus explicite. Les anciens daemons renvoyant 404 pour la santé restent compatibles. Un 503 générique ou un POST ambigu ne permet jamais de rejouer une commande. Les anciens clients sont protégés par le contrôle d’admission serveur même sans vérification préalable.

La maintenance et la file d’attente sont un état local en mémoire. Le redémarrage reprend la valeur initiale YAML de maintenance sans restaurer le travail en attente. La pause n’expire pas automatiquement et n’évince pas les tâches admises, qui occupent toujours la capacité. La limite d’observation du client peut expirer pendant l’attente et produire une issue inconnue ; inspectez l’identifiant enregistré avant de soumettre à nouveau. Les changements de maintenance sont journalisés comme daemon.maintenance si JSONL est configuré. Les origines de remplacement suivent les règles de refus sûr ci-dessus ; la maintenance n’autorise jamais à rejouer une tâche admise ou ambiguë.

Scénarios et groupes de scénarios côté client

Un scénario exécute des étapes ordonnées sur chaque cible explicitement sélectionnée. Chaque étape crée une tâche distante distincte. Déclarez les scénarios dans l’inventaire client :

targets:
  web-01: https://autond-01.example.com
  web-02: https://autond-02.example.com
groups:
  production: [web-01, web-02]
scenarios:
  deploy:
    version: 1
    description: Check, deploy and verify the application
    steps:
      - name: preflight
        endpoint: preflight
      - name: deploy
        endpoint: deploy
        args: ["release-42"]
        env: {DEPLOY_ENV: "production"}
      - name: verify
        endpoint: verify
scenario_groups:
  release: [deploy]

Les endpoints référencés doivent déjà être configurés et autorisés sur chaque daemon. Le YAML client ne peut ni installer des commandes ni modifier les ACL des endpoints.

auton -c client.yml -g production -s deploy
auton -c client.yml -t 'web-*' -S 'rel*' > operation.json
# Long aliases: --scenario and --scenario-group

Les sélecteurs de scénarios et de groupes utilisent la syntaxe glob/~regex et les limites des cibles. Chaque sélecteur doit correspondre ; une absence de correspondance invalide toute la sélection, même si les autres correspondent. Les scénarios directs sont sélectionnés d’abord, puis les groupes ; chaque catégorie conserve l’ordre des options, les motifs suivent l’ordre de déclaration et les groupes l’ordre de leurs membres. Les doublons sont supprimés à leur première occurrence. Les groupes contiennent des noms exacts de scénarios, jamais d’autres groupes.

Pour répartir l’inventaire, utilisez import_scenarios: scenarios/deploy.yml et import_scenario_groups: scenario-groups.yml dans le fichier principal. Les fichiers importés contiennent directement les entrées (par exemple deploy: {version: 1, steps: ...}), sans enveloppe de section. Les imports restent limités à un niveau. Voir le scénario d’exemple.

Les noms de scénarios, groupes et étapes suivent [a-z0-9-]+ sur 1 à 32 caractères. Chaque étape possède un name unique dans le scénario, un endpoint, éventuellement args (liste de chaînes) et env (table de chaînes). Placez entre guillemets les valeurs numériques ou réservées YAML. La version doit être l’entier 1. Les champs inconnus sont refusés. Limites : 128 scénarios et 128 groupes, 32 étapes par scénario et 128 étapes par invocation. La limite commune de 64 Kio inclut les imports. Toutes les définitions et références sont validées avant soumission.

Les étapes et scénarios s’exécutent séquentiellement par cible, avec --parallel workers répartis entre les cibles. Un échec, un refus explicite ou une issue inconnue arrête la séquence de cette cible ; les étapes et scénarios suivants sont marqués skipped sans identifiant de tâche. Les autres cibles continuent. Le délai d’observation concerne toute l’invocation ; son expiration ou l’interruption du client empêche la suite sans annuler une tâche distante en cours. Les tâches acceptées ne sont jamais retentées automatiquement ; aucun retour arrière ni reprise n’est effectué. Un POST ambigu n’est jamais rejoué.

Le JSON final contient kind: "scenario", operation_id, les scenarios sélectionnés, l’état global status et un tableau targets. Chaque cible contient les résultats ordonnés de ses scénarios, puis de leurs étapes : nom (step), endpoint, identifiant de tâche, état, code de sortie, stdout, stderr et durée. Les sorties conservées sont limitées à 1 Mio pour l’ensemble des étapes de chaque cible ; la troncature est explicite. Le code de sortie vaut zéro uniquement si chaque étape de chaque cible réussit. Conservez le JSON pour retrouver les tâches ; la progression nécessite que le client reste actif.

Les étapes possèdent leurs propres entrées : --endpoint (y compris AUTON_ENDPOINT), les options CLI d’arguments/environnement et les modes historiques run/status ne se combinent pas avec les scénarios. Avec --tui, les sélecteurs de scénarios limitent seulement le catalogue interactif. Les commandes simples et les invocations historiques de basculement restent disponibles.

Interface terminal de l’opérateur (client)

Le client Unix comprend les interfaces Textual et curses. Consultez le guide Textual pour l’interface moderne. Les raccourcis suivants concernent curses, avec supervision en lecture seule et écran explicite de préparation des opérations. Cette interface nécessite un terminal interactif prenant en charge Python curses et un daemon exposant l’API de visibilité ci-dessus.

auton --tui --uri https://autond.example.net --http-timeout 5

# Named daemons are selected explicitly; press a to aggregate their read-only state.
auton --tui --daemon prod=https://autond-01.example.net \
            --daemon staging=https://autond-02.example.net --refresh 2

L’authentification utilise -k / --token-file pour un jeton bearer, ou les options --auth-user / --auth-passwd et les variables AUTON_AUTH_USER / AUTON_AUTH_PASSWD existantes. Ces accès s’appliquent à tous les daemons explicitement listés ; sélectionnez uniquement des serveurs de confiance partageant cette identité, ou configurez les profils distincts liés aux origines ci-dessous. Les URI doivent être des origines HTTP(S), sans accès intégrés, chemin, requête ni fragment. Utilisez HTTPS à distance. Les redirections sont refusées et un échec ne provoque pas de tentative silencieuse sur un autre daemon.

--daemon est réservé à la TUI et remplace AUTON_URI ; il ne se combine pas avec --uri explicite. Une seule valeur --uri ou AUTON_URI est acceptée comme raccourci. Plusieurs --uri d’exécution restent un basculement, et non une sélection ou une diffusion. Ouvrir la TUI ne soumet aucune commande. L’exécution exige l’écran de préparation distinct et une confirmation explicite ; dans la version 1.2.0, l’annulation distante est une action CLI/web séparée, jamais un effet de la fermeture de la TUI.

Touche

Action

[ / ]

Sélectionner le daemon nommé précédent/suivant ou ALL.

a

Alterner entre un daemon et la vue agrégée ALL.

Tab

Passer entre les vues Jobs, Endpoints, Output et Daemons.

Up / Down or k / j

Sélectionner une ligne ; faire défiler Output.

Entrée

Ouvrir la sortie d’une tâche ; filtrer un endpoint avec son daemon ; ouvrir un daemon depuis la table Daemons.

/

Modifier la recherche littérale ; Entrée ou Échap termine la saisie.

s

Parcourir les états : tous, en attente, en cours, terminés.

c

Effacer les filtres de recherche, d’état et d’endpoint.

v

Alterner stdout et stderr/diagnostics.

Page précédente / Page suivante

Faire défiler dix lignes.

r / p

Actualiser immédiatement / suspendre l’actualisation automatique.

e

Ouvrir la préparation d’exécution sans soumettre de tâche.

Escape / q

Revenir aux tâches / quitter.

Préparer et exécuter interactivement

# Browse the inventory, then explicitly choose what and where to execute.
auton --tui -c client.yml
# Restrict the available targets and scenario catalogue before opening.
auton --tui -c client.yml -g 'prod-*' -S 'maintenance-*'

Appuyez sur e pour préparer une opération. Tab parcourt Targets, Target groups, Scenarios, Scenario groups et Endpoints. Espace sélectionne ou désélectionne une entrée ; l’ordre de sélection détermine celui des scénarios. Ouvrir l’écran ne sélectionne rien pour l’exécution. Les groupes dépassant le périmètre initial des cibles sont masqués, ainsi que les groupes de scénarios contenant des membres hors du catalogue filtré. Les filtres initiaux utilisent glob/~regex ; / dans le panneau effectue une recherche littérale de sous-chaîne sans changer la sélection.

Choisissez des scénarios/groupes ou un seul endpoint. Les endpoints proviennent du catalogue visible du daemon ; leur présence sur chaque cible n’est pas supposée et le daemon vérifie à nouveau les droits à la soumission. Pour un endpoint, appuyez sur i et saisissez un objet JSON tel que {"args": ["hello"], "env": {"LANG": "C"}} ; Entrée termine la saisie. Les scénarios gardent leurs entrées déclarées.

Entrée prépare un aperçu validé avec noms/origines des cibles, étapes ordonnées et entrées. Relisez-le avec j/k, puis y soumet exactement une fois ; n ou Échap revient sans soumettre. L’opération s’exécute en arrière-plan avec les mêmes services applicatifs et valeurs par défaut que la CLI. x arrête l’observation et les nouvelles soumissions, attend les requêtes en cours et affiche les résultats disponibles ; les tâches distantes actives ne sont pas annulées. Fermer le terminal arrête aussi la progression client sans annuler le travail accepté.

L’écran de résultat affiche les états par cible/étape, les identifiants, codes de sortie, stdout/stderr et la troncature. Utilisez j/k ou Page précédente/suivante, puis Échap pour revenir à la supervision. Pendant l’exécution, le panneau montre chaque cible/scénario/étape, son dernier état observé, son origine et son identifiant. pending signifie non encore soumis ; submitting ne prouve pas l’acceptation ; queued et running reflètent les réponses du daemon. Les étapes échouées ou inconnues arrêtent la séquence de la cible ; les suivantes sont skipped. La progression est locale à la session et échantillonnée via les lectures d’état existantes ; elle n’ajoute ni requêtes, ni rejeu, ni reprise persistante du scénario.

Sur l’écran de résultat, appuyez sur w, saisissez un nouveau chemin puis Entrée pour exporter le JSON complet (identifiants, origines, sorties, codes de sortie, troncature et issues inconnues/ignorées). Échap annule la demande de chemin. Les exports utilisent des permissions privées et refusent les fichiers ou liens symboliques existants. Les sorties peuvent contenir des données sensibles. L’export enregistre l’observation terminée même si l’issue distante est inconnue ; il ne soumet, ne reprend et n’annule aucune tâche.

Les captures ci-dessous montrent la version publiée sur le site. Elles sont régénérées depuis la révision fixée à chaque construction et partagées entre GitHub et le manuel web. La provenance des captures indique le commit source, la version et les empreintes des images.

Les captures ci-dessous montrent la véritable interface Textual avec des données synthétiques hors ligne ; aucune commande distante n’est exécutée :

Prepare targets and scenario groups Review the execution plan Inspect operation results

Les comptes et listes respectent la propriété des tâches et les ACL côté serveur. Une terminaison n’est pas nécessairement une réussite : inspectez le code de sortie et stderr. Les lectures relisent les données conservées sans consommer le curseur historique. Les erreurs API, y compris les 404 d’anciens daemons, sont explicites. L’affichage s’adapte au terminal (minimum 64 colonnes sur 12 lignes), filtre les caractères de contrôle distants et reste réactif pendant l’actualisation en arrière-plan. Un changement de daemon peut attendre l’actualisation bornée en cours ; q quitte immédiatement. --refresh vaut 2 secondes après chaque actualisation, avec un minimum de 0,2 seconde ; --http-timeout borne chaque GET. La sélection d’un daemon n’interroge que lui. Appuyez sur a ou ouvrez Daemons pour agréger les daemons nommés. Jusqu’à quatre lectures s’exécutent en parallèle ; les états reçus apparaissent pendant l’attente des plus lents. Chaque tâche et endpoint porte le nom de son daemon, ce qui distingue des identifiants identiques. Ouvrir une sortie contacte toujours le daemon d’origine.

La table Daemons montre l’état en attente/sain/erreur, les comptes de tâches visibles et les erreurs propres à chaque daemon. L’en-tête marque les résultats incomplets comme partiels et affiche la couverture, par exemple 2/3. Les comptes n’incluent que les tâches réellement reçues pendant l’actualisation ; les daemons en erreur ou en attente ne sont pas considérés silencieusement comme vides ni représentés par d’anciennes tâches. Un filtre d’endpoint dans ALL s’applique à cet endpoint sur son daemon d’origine. L’agrégation reste en lecture seule, entièrement côté client, sans historique central persistant ni changement du basculement d’exécution.

Captures de la TUI

Ces captures montrent l’interface Textual avec des données synthétiques signalées. Les noms des tâches et leurs sorties sont des exemples. Cliquez sur une capture pour l’ouvrir en taille réelle ; le site régénère les PNG partagés à partir des sources épinglées.

Tâches agrégées, avec commandes réussies et échouées :

Auton TUI: jobs from two daemons

État des daemons et nombre de tâches visibles :

Auton TUI: daemon status table

Sortie d’une tâche, liée à son daemon d’origine :

Auton TUI: retained stdout

Régénérez les captures avec python scripts/capture_tui.py depuis une copie de développement disposant des dépendances du daemon, de pyte, de Pillow et de la police DejaVu Sans Mono. Le script capture un véritable pseudo-terminal et rend ses cellules ; il ne construit pas de fausse interface et ne contacte pas les serveurs de production.

Journal JSONL local des tâches

Activer un journal facultatif sur chaque autond :

general:
  journal_path: /var/log/auton/jobs.jsonl
  journal_max_bytes: 10485760
  journal_backup_count: 5

Sans journal_path, aucun journal n’est créé. Le répertoire parent du chemin absolu doit déjà exister et être accessible en écriture à l’utilisateur du daemon. Utilisez un seul processus par fichier et un répertoire contrôlé par cet utilisateur. Les nouveaux fichiers sont créés en 0600 ; les permissions existantes sont conservées. Les liens symboliques et fichiers non ordinaires sont refusés. Les fichiers sont ouverts à la demande après réduction des privilèges.

Chaque ligne est un objet JSON contenant schema_version: 1, timestamp en UTC, event, job_id (endpoint:id), execution_id, endpoint, principal, return_code, duration_ms et reason. Un nouvel UUID d’exécution distingue les identifiants réutilisés après expiration. Les refus avant création d’objet n’ont pas d’UUID d’exécution. Les champs nuls signifient non applicable ou encore inconnu ; les durées utilisent une horloge monotone. Les identifiants sont limités à 256 caractères et les troncatures sont signalées dans truncated_fields.

Événement

Signification

job.admitted

Validation, autorisation et capacité vérifiées ; un objet est réservé avant insertion en file.

job.started

Le worker a passé le contrôle d’ACL à l’exécution et a démarré.

job.completed

Exécution terminée avec le code de sortie zéro.

job.failed

Échec de commande ou exception d’exécution.

job.timeout

L’adaptateur d’exécution a signalé un délai dépassé.

job.rejected

Refus à l’admission pour ACL/endpoint/capacité/doublon, échec de mise en file ou refus d’ACL à l’exécution.

Le journal contient uniquement les métadonnées du cycle de vie. Il ne contient ni arguments, variables d’environnement, fichiers envoyés, stdout/stderr, secrets d’accès ni messages d’exception. Il ne journalise pas les lectures ou interrogations répétées. Les échecs d’authentification HTTP et requêtes mal formées refusées avant admission restent hors de ce journal ; les journaux techniques continuent séparément.

La rotation intervient avant qu’un ajout dépasse journal_max_bytes (minimum 16384 octets). .1 est la sauvegarde la plus récente ; journal_backup_count sauvegardes au maximum (1 à 100, 5 par défaut) sont conservées en plus du fichier actif. Les écritures et la rotation sont sérialisées dans le daemon. Ne partagez pas ce chemin entre daemons et n’appliquez pas une règle de rotation externe au même fichier.

Les enregistrements sont vidés et fermés après chaque événement, sans fsync systématique. Ce journal d’exploitation fonctionne au mieux, sans persistance transactionnelle : un plantage peut laisser un historique incomplet. Les échecs d’écriture sont signalés dans les logs techniques au plus une fois par minute et par journal ; ils ne font ni échouer ni relancer une commande. Le journal ne restaure pas les tâches après redémarrage, ne rejoue pas les commandes et ne prolonge pas la conservation en mémoire des résultats de l’API.

Installation

autond côté serveur

pip install autond

auton côté client

pip install auton

Variables d’environnement

autond

Variable

Description

Valeur par défaut

AUTOND_CONFIG

Contenu du fichier de configuration
(par exemple export AUTOND_CONFIG="$(cat auton.yml)")

AUTOND_LOGFILE

Chemin du fichier de logs

/var/log/autond/daemon.log

AUTOND_PIDFILE

Chemin du fichier PID d’autond

/run/auton/autond.pid

AUTON_GROUP

Groupe d’auton

auton ou root

AUTON_USER

Utilisateur d’auton

auton ou root

auton

Variable

Description

Valeur par défaut

AUTON_AUTH_USER

Utilisateur pour l’authentification

AUTON_AUTH_PASSWD

Mot de passe pour l’authentification

AUTON_ENDPOINT

Nom du point d’entrée

AUTON_LOGFILE

Chemin du fichier de logs

/var/log/auton/auton.log

AUTON_NO_RETURN_CODE

Ne pas terminer avec le code de retour si cette variable est présente

False

AUTON_UID

UID de la tâche auton

UUID aléatoire

AUTON_URI

URI d’autond
(par exemple http://auton-01.example.org:8666,http://auton-02.example.org:8666)

Configuration d’Autond

Consultez l’exemple de configuration etc/auton/auton.yml.example

Points d’entrée

Cet exemple déclare trois points d’entrée : ansible-playbook-ssh, ansible-playbook-http et curl. Ils utilisent le plugin subproc.

endpoints:
  ansible-playbook-ssh:
    plugin: subproc
    config:
      prog: ansible-playbook
      timeout: 3600
      args:
        - '/etc/ansible/playbooks/ssh-install.yml'
        - '--tags'
        - 'sshd'
      become:
        enabled: true
      env:
        DISPLAY_SKIPPED_HOSTS: 'false'
  ansible-playbook-http:
    plugin: subproc
    config:
      prog: ansible-playbook
      timeout: 3600
      args:
        - '/etc/ansible/playbooks/http-install.yml'
        - '--tags'
        - 'httpd'
      become:
        enabled: true
      env:
        DISPLAY_SKIPPED_HOSTS: 'false'
  curl:
    plugin: subproc
    config:
      prog: curl
      timeout: 3600

Importer des catalogues de points d’entrée

Disponible depuis Auton 1.0.0. La configuration principale du daemon peut conserver des points d’entrée définis directement et en importer d’autres :

import_endpoints:
  - endpoints/diagnostics.yml

Un catalogue importé contient directement les noms des points d’entrée, sans enveloppe endpoints: :

python-check:
  plugin: subproc
  import_vars: python-vars.yml
  import_config: python-config.yml
  import_users: operators.yml
  config:
    timeout: 10

Consultez l’exemple complet de catalogue. Les chemins des catalogues sont relatifs à la configuration principale. Les chemins des composants sont relatifs au catalogue qui déclare le point d’entrée (au fichier réel en cas de lien symbolique), indépendamment du répertoire courant. Les chemins locaux absolus sont également acceptés. import_endpoints accepte un nom de fichier ou une liste.

Les catalogues d’endpoints ne peuvent pas importer d’autres catalogues. Leurs endpoints peuvent utiliser import_vars, import_config et import_users. Les variables et les utilisateurs sont des mappings terminaux. Une configuration importée peut charger les six blocs terminaux d’arguments et d’environnement décrits ci-dessous, mais pas une autre configuration. Plusieurs endpoints peuvent partager ces composants. L’ordre de traitement est vars, config, users ; les valeurs écrites en ligne dans chaque section remplacent les valeurs importées correspondantes.

Les catalogues sont en YAML simple. Les composants conservent les modèles Mako et l’accès à la configuration du point d’entrée, notamment aux variables déjà chargées. Les fichiers de configuration Mako sont du code d’administration de confiance, sans bac à sable. Ne les acceptez jamais de clients non fiables. Les imports ne modifient ni l’authentification du daemon ni les ACL des points d’entrée.

Les noms d’endpoints en double, les fichiers de catalogue répétés (y compris par lien symbolique), les clés YAML en double, les fichiers absents, les mappings invalides et les imports imbriqués interdits empêchent le démarrage. Les nouveaux fichiers importés n’acceptent ni clés de fusion YAML, ni balises d’inclusion personnalisées, ni URL distantes. Ces règles s’appliquent aux imports de configuration des endpoints définis en ligne comme importés. Limites : 32 catalogues, 1 Mio de sources cumulées et 1 024 endpoints importés ; chaque source de composant et son rendu sont limités à 1 Mio. Tous les composants sont préparés avant l’initialisation des instances d’endpoints.

Authentification

Les nouvelles installations peuvent utiliser l’authentification persistante SQLite. Installez autond[auth]==1.5.3, ou utilisez l’image Docker, qui inclut le module d’authentification. HTTPdis >= 0.6.31 et Sonicprobe >= 0.3.55 fournissent les implémentations partagées d’Argon2, des jetons et de SQLite.

general:
  listen_addr: 127.0.0.1
  auth_mode: required
  authentication:
    backend: sqlite
    path: /var/lib/autond/auth/auth.db
    timeout: 5
  maintenance_operators: [alice]

Le daemon contrôle la configuration et l’emplacement du stockage. Un chemin de base relatif est résolu à côté du YAML principal ; une configuration uniquement par environnement exige un chemin absolu. L’authentification et l’historique des tâches utilisent des stockages indépendants. La base est ouverte après le passage en daemon et la réduction des privilèges. Elle est locale à ce déploiement et ne constitue pas un serveur d’authentification partagé entre plusieurs nœuds.

Créez le répertoire et administrez les comptes avec l’utilisateur système du daemon. Les mots de passe sont demandés deux fois et ne sont jamais acceptés comme arguments de commande. Aucun compte par défaut ni point d’entrée public d’administration des comptes n’est fourni.

sudo install -d -m 0700 -o auton -g auton /var/lib/autond/auth
sudo -u auton autond-auth -c /etc/auton/auton.yml user set -u alice -s read -s run -s maintenance
sudo -u auton autond-auth -c /etc/auton/auton.yml user list
sudo -u auton autond-auth -c /etc/auton/auton.yml token create -u alice -s read -s run -t 3600 -o /var/lib/autond/auth/operator.token

La création d’un jeton écrit son secret uniquement dans un nouveau fichier de mode 0600 et affiche son identifiant ainsi que son expiration. Elle refuse d’écraser un fichier existant. Transférez ce fichier de manière sûre à l’opérateur ; il doit appartenir à l’utilisateur système du client, en mode 0600. Les jetons ont une durée de vie explicite (une heure par défaut, 30 jours au maximum) et un sous-ensemble des droits du compte. La création de comptes et de jetons n’accorde que read par défaut.

Portée

Actions API autorisées

read

Santé, statistiques, points d’entrée autorisés, tâches du propriétaire, détails et état

run

Soumettre des tâches aux points d’entrée autorisés par les ACL du compte

maintenance

Modifier la maintenance ; l’appartenance à maintenance_operators est également requise

Les portées n’accordent pas l’accès aux points d’entrée et ne contournent pas la propriété des tâches. Exécuter puis interroger une tâche exige run et read. Les modules personnalisés doivent appliquer leurs propres portées ; le mode required authentifie chaque route déclarée et conserve les listes d’utilisateurs autorisés. Seules les routes intégrées de tâches, de visibilité et de maintenance appliquent automatiquement le tableau ci-dessus.

auton --uri https://autond.example -k ~/.config/auton/operator.token --endpoint check
auton --tui --uri https://autond.example -k ~/.config/auton/operator.token
auton -c inventory.yml -t prod-01 -s diagnostics -k ~/.config/auton/operator.token
# AUTON_TOKEN_FILE can supply the same filename.
sudo -u auton autond-auth -c /etc/auton/auton.yml token revoke -i CREDENTIAL_ID
sudo -u auton autond-auth -c /etc/auton/auton.yml user disable -u alice

Audit des refus d’authentification (JSONL)

Activez un journal distinct appartenant au daemon ; le démarrage rapide Docker l’active dans son volume persistant. Les installations existantes restent inchangées sans configuration explicite :

general:
  auth_audit:
    path: /var/log/autond/auth.jsonl
    max_bytes: 10485760
    backup_count: 5
    max_events_per_minute: 60

Les chemins relatifs utilisent le répertoire de la configuration principale. Créez le répertoire parent avec l’utilisateur système du daemon ; aucun autre utilisateur ne doit pouvoir y écrire. Les fichiers sont ordinaires, privés (mode 0600 à la création), appartiennent au daemon et ne comportent ni lien symbolique ni lien physique. Le chemin d’audit doit être distinct des journaux de tâches et des bases SQLite. Réservez chaque chemin à un seul daemon et ses fichiers de rotation numérotés à ce journal. Une destination initiale invalide ou non sûre bloque le démarrage.

Chaque ligne contient uniquement schema_version, timestamp en UTC, event et count :

{"schema_version":1,"timestamp":"2026-09-29T16:00:00.000+00:00","event":"auth.denied","count":1}

Événement

Signification

auth.denied

HTTP 401, y compris identifiants absents, mal formés, expirés ou refusés.

auth.forbidden

HTTP 403, y compris permissions des routes et points d’entrée, portées et politique d’origine du navigateur.

auth.unavailable

Le fournisseur d’authentification ou la connexion/déconnexion du navigateur a renvoyé 503 ; les réponses 503 de capacité des tâches ou de maintenance sont exclues.

auth.login_throttled

HTTPdis a explicitement limité une tentative de connexion. Sa réponse HTTP 401 produit un événement auth.denied distinct.

auth.audit_suppressed

Nombre d’événements supprimés pendant la fenêtre d’audit précédente (plafonné à 2147483647).

Aucune identité, adresse client, URL, en-tête, cookie, jeton, mot de passe, charge utile ou message d’exception n’est sérialisé. Cet audit porte sur les refus et la disponibilité, pas sur une investigation par utilisateur ni sur l’administration des comptes. La classification HTTP s’applique aussi au mode Basic historique explicite ; les signaux de limitation de connexion proviennent du service d’authentification SQLite d’HTTPdis.

La rotation conserve le fichier actif et backup_count archives. Les écritures sont limitées à max_events_per_minute (2 à 10000, 60 par défaut) dans des fenêtres monotones fixes de 60 secondes, résumé des suppressions compris. Ce résumé est émis au prochain événement d’une fenêtre ultérieure ; aucun vidage ne tourne en arrière-plan et les compteurs en attente sont perdus au redémarrage. Les refus répétés ne peuvent donc provoquer une consommation disque ou mémoire illimitée. Un échec d’écriture en cours d’exécution est compté et signalé au plus une fois par minute, sans texte d’exception. Il ne modifie pas la décision d’authentification ; des événements peuvent manquer. L’authentification continue de refuser l’accès si son propre stockage échoue.

Profils d’identifiants clients liés aux origines

Des bases de daemon indépendantes émettent des jetons indépendants. Déclarez des profils nommés dans l’inventaire client pour lier des fichiers de jetons privés à des origines explicites :

targets:
  primary: https://autond-01.example.net
  backup: https://autond-02.example.net
  deployment:
    uris:
      - {target: primary}
      - {target: backup}
credentials:
  primary-operator:
    origins: [https://autond-01.example.net]
    token_file: tokens/primary.token
  backup-operator:
    origins: [https://autond-02.example.net]
    token_file: tokens/backup.token
auton -c inventory.yml -t deployment --endpoint check
auton -c inventory.yml -t primary -t backup -s diagnostics
auton --tui -c inventory.yml -t primary -t backup

Les noms de profils suivent la syntaxe existante [a-z0-9-]+ (1 à 32 caractères). Chaque profil accepte uniquement origins (1 à 16 origines HTTP(S)) et token_file ; 128 profils au maximum sont autorisés. Les jetons exigent HTTPS, sauf pour les adresses IP littérales de boucle locale. Les origines suivent la normalisation partagée des URI, ports par défaut, IDNA et IPv6 compris. Les origines équivalentes en double sont refusées, même entre profils. Aucun motif de nom d’hôte, développement de groupe de cibles ou identifiant par défaut n’est prévu.

Toutes les origines sélectionnées, y compris chaque candidat de basculement, doivent disposer d’un profil avant toute requête de tâche ou de surveillance. Une association absente ou un fichier de jeton sélectionné illisible fait échouer la sélection ; aucun repli vers un autre jeton, Basic ou l’accès anonyme n’a lieu. Seuls les fichiers sélectionnés sont lus. Les protections existantes de propriétaire, mode, fichier ordinaire et lien symbolique s’appliquent. Un profil peut volontairement partager un jeton entre plusieurs origines explicitement listées ; il ne synchronise pas les comptes.

import_credentials: auth/profiles.yml suit les mêmes règles d’import plates et bornées que les autres sections de l’inventaire. Le fichier importé contient la correspondance des profils, sans enveloppe credentials. Les chemins des jetons sont relatifs au fichier déclarant le profil ; les chemins absolus sont aussi acceptés. Ne placez jamais le contenu des jetons dans le YAML.

Les profils ne peuvent pas être combinés avec -k, AUTON_TOKEN_FILE ou les options et variables d’environnement Basic. Sans profil, l’usage existant de -k reste disponible : le jeton est lié aux origines explicitement sélectionnées, candidats de basculement compris. CLI, TUI, RemoteClient, adaptateur de visibilité, opérations et scénarios appliquent la même liaison. Les redirections restent désactivées ; un refus d’authentification ne déclenche pas de basculement et un POST ambigu n’est jamais rejoué. Le comportement Basic historique est inchangé.

La révocation, la désactivation et le remplacement du mot de passe prennent effet sur les requêtes suivantes, sans redémarrage. Ils n’annulent pas les tâches déjà acceptées. Comptes, sessions, jetons et révocations survivent au redémarrage. Les tâches survivent également si leur stockage SQLite optionnel est activé, comme dans le démarrage rapide Docker. Aucun rejeu automatique n’est introduit. Jeton et mot de passe sont des modes clients mutuellement exclusifs ; le mode SQLite ne se replie jamais sur Basic. Le client refuse les jetons Bearer sur HTTP, sauf vers une IP littérale de boucle locale ; la vérification TLS reste active. Utilisez HTTPS au niveau du proxy et gardez le backend privé. Ne placez pas de jetons dans les URI, inventaires YAML, arguments du shell ou logs.

Gardez la base locale et ses sauvegardes privées : les identifiants sont hachés, mais la base n’est pas chiffrée. Son parent doit appartenir au daemon et ne pas être accessible en écriture aux autres utilisateurs ; la base doit être un fichier ordinaire privé. Les schémas incompatibles, permissions non sûres et erreurs du stockage entraînent un refus d’accès. Ne remplacez jamais le fichier sous un daemon actif. Arrêtez tous les processus d’écriture avant de copier une sauvegarde. L’historique Redis est disponible depuis 1.2.0 ; l’authentification reste sur SQLite. Une console navigateur optionnelle est disponible avec l’authentification SQLite, voir ci-dessous. Les configurations Bearer seules et Basic historiques explicites restent utilisables sans console. Cette version ne fournit ni TOTP ni SSO.

Authentification Basic existante

L’authentification Basic reste prise en charge avec une politique appliquée centralement :

general:
  listen_addr: 127.0.0.1
  auth_mode: required
  auth_basic: Restricted
  auth_basic_file: /etc/auton/auton.passwd

required protège chaque route de module déclarée, y compris la santé et les futures routes, même si son YAML indique auth: false. Les listes explicites d’utilisateurs autorisés sont conservées. Un fichier de mots de passe absent, vide, mal formé ou contenant des utilisateurs en double bloque le démarrage. Créez un fichier bcrypt de manière interactive, sans mot de passe sur la ligne de commande :

htpasswd -c -B /etc/auton/auton.passwd alice
# For subsequent accounts, omit -c to preserve existing users.
htpasswd -B /etc/auton/auton.passwd automation

Rendez le fichier lisible par le compte du démon et inaccessible aux autres utilisateurs (par exemple, propriétaire et groupe adaptés au déploiement, mode 0640). Traitez-le comme un secret et ne le commitez pas. Les identifiants sont chargés au démarrage : redémarrez le démon après rotation ou révocation. La vérification bcrypt est testée sur la matrice Linux/Python prise en charge. Les anciennes entrées SHA-1 restent lisibles pour la migration, mais les nouveaux identifiants doivent utiliser bcrypt. La matrice CI couvre Python 3.10 à 3.13.

Utilisez HTTPS pour l’accès distant, généralement via un reverse proxy, avec le daemon sur la boucle locale ou une interface privée isolée. Basic ne chiffre pas les identifiants. La vérification TLS du client reste activée. N’exposez pas publiquement le backend non chiffré et n’utilisez pas les en-têtes d’identité transmis comme authentification.

Pour le développement local jetable uniquement, auth_mode: anonymous est disponible avec une adresse d’écoute IP littérale de boucle locale et sans fichier de mots de passe. Il conserve les exigences propres aux routes (la maintenance reste protégée), mais les appels locaux partagent sinon une identité anonyme et la visibilité des tâches. La boucle locale ne protège ni des autres utilisateurs locaux ni d’un reverse proxy : ne publiez pas ce mode derrière un proxy.

Migration de l’authentification de 0.3.2 vers 1.0

La version 1.0 introduit des politiques d’authentification explicites. Consultez le guide de mise à niveau 1.0 avant de remplacer une installation. Le mode anonyme vérifie l’adresse d’écoute effective, y compris lorsqu’elle est définie avec --listen-addr.

Les configurations sans auth_mode conservent le comportement historique par route et consignent un avertissement. Le mode auth_mode: legacy rend ce choix explicite. Dans ce mode, auth_basic_file seul ne protège pas les routes. Définissez auth: true sur chaque route protégée avant de migrer vers required.

L’exemple fourni écoute désormais sur la boucle locale et sélectionne required. Le démarrage rapide Docker crée donc un compte avant de lancer son daemon authentifié avec une configuration distincte. Il ne lance plus de daemon d’exemple accessible anonymement. Pour un reverse proxy en conteneur, choisissez explicitement l’adresse d’écoute interne et ne publiez pas les ports du backend sur Internet. Les configurations montées existantes ne sont pas réécrites. Commandes CLI, ACL des points d’entrée et propriété des tâches restent inchangées.

Utilisez la section users pour indiquer les utilisateurs autorisés par point d’entrée :

ansible-playbook-ssh:
  plugin: subproc
  users:
    maintainer: true
    bob: true
  config:
    prog: ansible-playbook
    timeout: 3600
    args:
      - '/etc/ansible/playbooks/ssh-install.yml'
      - '--tags'
      - 'sshd'
    become:
      enabled: true
    env:
      DISPLAY_SKIPPED_HOSTS: 'false'

Plugin subproc

Le plugin subproc exécute des programmes avec subprocess de Python.

Variables d’environnement AUTON prédéfinies pendant l’exécution :

Variable

Description

AUTON

Indique que la tâche s’exécute dans un environnement AUTON

AUTON_JOB_TIME

Heure actuelle dans le fuseau local

AUTON_JOB_GMTIME

Heure actuelle en GMT

AUTON_JOB_UID

UID de la tâche courante transmis par le client

AUTON_JOB_UUID

Identifiant unique de la tâche courante

Utilisez prog pour indiquer le chemin du programme :

endpoints:
  curl:
    plugin: subproc
    config:
      prog: curl

Utilisez workdir pour changer le répertoire de travail :

endpoints:
  curl:
    plugin: subproc
    config:
      prog: curl
      workdir: somedir/

Utilisez search_paths pour indiquer les chemins où chercher prog :

endpoints:
  curl:
    plugin: subproc
    config:
      prog: curl
      search_paths:
        - /usr/local/bin
        - /usr/bin
        - /bin

Utilisez la section become pour exécuter sous un autre utilisateur :

endpoints:
  curl:
    plugin: subproc
    config:
      prog: curl
      become:
        enabled: true
        user: foo

Utilisez timeout pour lever une exception après n secondes (60 secondes par défaut) :

endpoints:
  curl:
    plugin: subproc
    config:
      prog: curl
      timeout: 3600

Utilisez la section args pour définir les arguments toujours présents :

endpoints:
  curl:
    plugin: subproc
    config:
      prog: curl
      args:
        - '-s'
        - '-4'

Les ajouts du client peuvent être contrôlés pour chaque opération avec allow-args, allow-env, allow-argfiles et allow-envfiles. Utilisez true pour autoriser une catégorie, une liste de noms pour un accès sélectif, ou des règles par argument ou variable pour contrôler les valeurs. Les règles explicites disallow-* sont prioritaires. Consultez le guide des règles d’entrée client et de migration pour les options répétées, les expressions régulières, le fonctionnement des fichiers et le changement de comportement entre 1.x et 2.0.

Pour les cibles de type subprocess, un champ client non vide interdit par une option disallow-* provoque un refus HTTP 400 avant la mise en file. Les champs vides restent acceptés.

Utilisez disallow-args pour interdire les arguments du client :

endpoints:
  curl:
    plugin: subproc
    config:
      prog: curl
      args:
        - '-vvv'
        - 'https://example.com'
      disallow-args: true

Utilisez la section argfiles pour définir les fichiers d’arguments toujours présents :

endpoints:
  curl:
    plugin: subproc
    config:
      prog: curl
      argfiles:
        - arg: '--key'
          filepath: /tmp/private_key
        - arg: '-d@'
          filepath: /tmp/data

Utilisez disallow-argfiles pour interdire les fichiers d’arguments du client :

endpoints:
  curl:
    plugin: subproc
    config:
      prog: curl
      argfiles:
        - arg: '--key'
          filepath: /tmp/private_key
        - arg: '-d@'
          filepath: /tmp/data
      disallow-argfiles: true

Utilisez la section env pour définir les variables d’environnement toujours présentes :

endpoints:
  curl:
    plugin: subproc
    config:
      prog: curl
      env:
        HTTP_PROXY: http://proxy.example.com:3128/
        HTTPS_PROXY: http://proxy.example.com:3128/

Utilisez disallow-env pour interdire les variables d’environnement du client :

endpoints:
  curl:
    plugin: subproc
    config:
      prog: curl
      env:
        HTTP_PROXY: http://proxy.example.com:3128/
        HTTPS_PROXY: http://proxy.example.com:3128/
      disallow-env: true

Utilisez la section envfiles pour définir les fichiers d’environnement toujours présents :

endpoints:
  curl:
    plugin: subproc
    config:
      prog: curl
      envfiles:
        - somedir/foo.env
        - somedir/bar.env

Utilisez disallow-envfiles pour interdire les fichiers d’environnement du client :

endpoints:
  curl:
    plugin: subproc
    config:
      prog: curl
      envfiles:
        - somedir/foo.env
        - somedir/bar.env
      disallow-envfiles: true

Lignes de commande Auton

Exécuter curl

L’endpoint curl fourni affiche la version de curl. Appelez-le sans argument client.

auton --endpoint curl --uri http://localhost:8666

Ces exemples de syntaxe CLI supposent que l’administrateur a configuré un autre endpoint curl qui autorise les entrées indiquées.

Récupérer l’URL https://example.com :

auton --endpoint curl --uri http://localhost:8666 -a 'https://example.com'

Récupérer l’URL https://example.com avec l’authentification auton :

auton --endpoint curl --uri http://localhost:8666 --auth-user foo --auth-passwd bar -a 'https://example.com'

Ajouter la variable d’environnement HTTP_PROXY :

auton --endpoint curl --uri http://localhost:8666 -a 'https://example.com' -e 'HTTP_PROXY=http://proxy.example.com:3128/'

Importer une variable d’environnement déjà déclarée avec –imp-env :

HTTPS_PROXY=http://proxy.example.com:3128/ auton --endpoint curl --uri http://localhost:8666 -a 'https://example.com' --imp-env HTTPS_PROXY

Charger les variables d’environnement depuis des fichiers locaux :

auton --endpoint curl --uri http://localhost:8666 -a 'https://example.com' --load-envfile foo.env

Demander à autond de charger les fichiers d’environnement de son propre système de fichiers :

auton --endpoint curl --uri http://localhost:8666 -a 'https://example.com' --envfile /etc/auton/auton.env

Ajouter plusieurs URI autond pour la haute disponibilité :

auton --endpoint curl --uri http://localhost:8666 --uri http://localhost:8667 -a 'https://example.com'

Ajouter des fichiers d’arguments pour envoyer des fichiers locaux :

auton --endpoint curl --uri http://localhost:8666 -A '--cacert=cacert.pem' -a 'https://example.com'

Ajouter plusieurs arguments :

auton --endpoint curl --uri http://localhost:8666 --multi-args '-vvv -u foo:bar https://example.com' --multi-argsfiles '-d@=somedir/foo.txt -d@=bar.txt --cacert=cacert.pem'

Lire le contenu d’un fichier depuis l’entrée standard avec - :

cat foo.txt | auton --endpoint curl --uri http://localhost:8666 --multi-args '-vvv -u foo:bar sftp://example.com' --multi-argsfiles '--key=private_key.pem --pubkey=public_key.pem -T=-'

Client distant Python

La distribution cliente auton fournit désormais auton_client.RemoteClient :

from auton_client import RemoteClient

client = RemoteClient(
    uris=['https://autond.example'],
    endpoint='backup',
    uid='backup-123',
    payload={'args': ['--verify']},
    auth=('alice', 'password'),
    http_timeout=30,
)
for result in client.iter_results(delay=0.5):
    consume(result)  # Your application decides how to present/store the result.

Le client accepte une session compatible avec requests et une fonction sleep optionnelles. Il ne lit jamais l’entrée standard, n’affiche rien et ne choisit pas le code de sortie du processus. Chaque lot produit fait avancer le curseur de sortie ; une requête d’état reprend à ce curseur. do_run() et do_status() restent disponibles pour les opérations ponctuelles. Un échec ambigu de POST n’est jamais rejoué sur un autre daemon. Options de commande, préparation des fichiers et de l’environnement, affichage terminal et code de sortie restent dans bin/auton. Installez la distribution auton pour utiliser le client distant ; autond fournit toujours le daemon séparément.

L’expiration des tâches reste déclenchée par les opérations du service ; ce changement n’ajoute ni thread d’expiration en arrière-plan ni échéance globale d’interrogation du client. Le stockage local durable est disponible séparément avec general.job_storage.

Tâches locales persistantes

Activez cette option indépendamment de l’authentification, dans la configuration du daemon :

general:
  job_storage:
    backend: sqlite
    path: /var/lib/autond/jobs/jobs.db
    timeout: 5
  result_ttl: 3600
  max_jobs: 128
  max_output_bytes: 1048576

Créez le répertoire parent sous le compte du daemon avant de démarrer Autond (par exemple install -d -m 0700 -o auton -g auton /var/lib/autond/jobs). Les chemins relatifs sont résolus depuis le répertoire de la configuration principale. Le fichier est créé en mode 0600 ; son parent doit appartenir à l’utilisateur du daemon et ne pas être accessible en écriture au groupe ou aux autres utilisateurs. Les fichiers existants doivent être privés, ordinaires et appartenir à cet utilisateur. Utilisez un système de fichiers local compatible avec SQLite et les verrous de fichiers. Chaque historique appartient à un seul daemon ; un second daemon qui l’utilise refuse de démarrer. L’image Docker fournit /var/lib/autond/jobs ; montez-y un stockage persistant avec les bons droits si l’historique doit survivre au remplacement du conteneur.

L’adaptateur SQLite réutilise Sonicprobe AnySQL avec reconnexion et rejeu automatiques désactivés. Authentification et historique exigent des fichiers de base distincts ; Basic fonctionne également avec les tâches SQLite. Sans section job_storage, le comportement historique en mémoire reste inchangé. Auton 1.2.0 accepte aussi un historique Redis via DWho (voir ci-dessous), indépendamment de l’authentification SQLite.

Les tâches sont enregistrées à l’admission, avant exécution et à la fin. Les blocs stdout/stderr finaux, codes de retour, horodatages, identité d’exécution et propriétaire survivent au redémarrage. Les charges utiles, fichiers envoyés et variables d’environnement ne sont pas persistés. La sortie elle-même peut contenir des données sensibles. La sortie en cours reste en mémoire jusqu’à la fin ; elle n’est pas sauvegardée ligne par ligne.

Après redémarrage, les tâches inachevées ne sont jamais remises en file ni rejouées :

Dernier état persistant

Résultat restauré

new

complete, code de retour 130, outcome: job.interrupted, outcome_reason: restart_before_launch, execution_uncertain: false. La commande n’a pas démarré.

processing

complete, code de retour 130, outcome: job.interrupted, outcome_reason: daemon_restart, execution_uncertain: true. Son résultat réel est inconnu.

complete

Résultat et sortie d’origine conservés.

L’instantané avant lancement est conservateur : un plantage peut survenir avant la création du processus ou après l’exécution mais avant l’enregistrement final. La mort brutale du daemon peut aussi laisser un processus déjà lancé actif. La récupération ne se rattache pas à ce processus et ne le tue pas à partir de son PID enregistré. Vérifiez ses effets avant de relancer manuellement. L’état existant complete évite que les anciens clients interrogent indéfiniment des tâches interrompues ; cet état ne signifie pas réussite. Les ACL actuelles et la propriété des tâches s’appliquent aux résultats restaurés, y compris aux points d’entrée retirés de la configuration.

Un échec du stockage désactive les nouvelles admissions et indique status: degraded avec storage.available: false dans /health. Un échec d’enregistrement à l’admission ou avant lancement empêche le démarrage. Un échec d’enregistrement final laisse le worker actif mais les lectures du résultat renvoient 503 ; les listes de tâches indiquent storage_error: true. Aucun repli silencieux en mémoire ni nouvelle tentative automatique n’a lieu. Réparez le stockage puis redémarrez le daemon. Les requêtes déjà acceptées restent soumises au même contrôle de persistance avant lancement.

La conservation suit les règles existantes de TTL et de capacité, en mémoire comme sur disque. Le nettoyage intervient à la récupération et aux lectures/admissions ; aucun thread d’expiration ne tourne en arrière-plan. Les tâches terminées sont évincées en premier pendant une admission normale. Réduire la capacité au redémarrage ne conserve que les instantanés les plus récents. Les fichiers SQLite peuvent garder leur taille allouée après suppression ; il s’agit d’un historique borné, pas d’une archive d’audit illimitée. Le mode durable accepte au maximum 10000 tâches et 16 Mio de sortie configurée par tâche. Réduire la limite de sortie sous le volume déjà conservé peut empêcher la récupération : gardez l’ancienne limite jusqu’à expiration de ces résultats. Sauvegardez la base avec le daemon arrêté.

Le journal JSONL optionnel reste un log de métadonnées distinct. Il ne restaure pas les tâches et ne garantit pas un accord transactionnel avec l’historique SQLite.

Console Web Autond

La console est désactivée par défaut. Activez-la après avoir créé les comptes SQLite avec autond-auth (voir l’authentification). Un opérateur a généralement besoin de read et run ; la maintenance exige aussi la portée maintenance et l’appartenance à general.maintenance_operators.

general:
  auth_mode: required
  authentication:
    backend: sqlite
    path: /var/lib/autond/auth/auth.db
    timeout: 5
  web_enabled: true
  web_origin: https://autond.example.net
  maintenance_operators: [operator]

Exposez le daemon via HTTPS et ouvrez https://autond.example.net/ui/. web_origin est l’origine publique sans chemin ni barre oblique finale. Réservez un nom d’hôte à ce daemon ; n’y hébergez pas d’applications sans rapport, même sur d’autres ports. Pour le développement local uniquement, http://127.0.0.1:8666 ou une origine IPv6 littérale de boucle locale est acceptée. Les noms d’hôte HTTP comme localhost sont refusés. La console exige l’authentification SQLite ; elle ne propose pas de mode navigateur Basic mis en cache. Les clients CLI/TUI Bearer continuent d’utiliser la même API.

Un reverse proxy terminant TLS doit préserver le Host configuré et servir /ui/ ainsi que l’API à la racine de cette origine. Gardez le backend non chiffré privé. Par exemple, dans un serveur nginx HTTPS dont le certificat est configuré :

location / {
    proxy_pass http://127.0.0.1:8666;
    proxy_set_header Host autond.example.net;
}

L’origine configurée fait autorité ; les en-têtes Forwarded/X-Forwarded ne la déterminent jamais. La limitation des connexions voit le pair TCP direct, proxy compris. Les limites globales et par pair restent actives, mais les utilisateurs derrière un proxy partagent la limite de ce pair. Seuls les fichiers fixes HTML/CSS/JS/logo et /ui/auth/login sont publics. Les données des tâches, la maintenance et les routes d’exécution restent authentifiées. L’espace de routes /ui est réservé ; les chevauchements sont refusés au démarrage.

L’authentification du navigateur réutilise le service de comptes/sessions et le stockage SQLite d’HTTPdis :

  • Une session opaque réside dans un cookie HttpOnly, SameSite=Strict, également Secure et préfixé __Host- sous HTTPS. Elle expire au plus tard après 8 heures ou après 30 minutes sans activité authentifiée. L’actualisation automatique compte comme activité.

  • La connexion exige une requête JSON de même origine et renouvelle toute session existante. Chaque mutation, déconnexion comprise, exige une Origin exacte et un en-tête CSRF.

  • Seule la valeur CSRF est conservée dans le stockage local du navigateur pour permettre rechargements et onglets. Les mots de passe et identifiants de session/Bearer n’y sont jamais placés. Si ce stockage est indisponible, la page courante fonctionne mais un rechargement exige une nouvelle connexion.

  • Désactiver un compte ou renouveler ses identifiants révoque ses sessions et ses jetons. La déconnexion révoque la session courante côté serveur. CORS et les requêtes préalables ne sont pas activés.

  • Les réponses, erreurs applicatives comprises, ne sont pas mises en cache ; l’intégration dans un cadre est interdite et une CSP restrictive n’autorise que les ressources locales fournies. HTTPS envoie HSTS. La sortie des tâches est affichée comme texte, jamais interprétée comme HTML.

La console adaptative affiche la disponibilité et la maintenance du daemon, les points d’entrée autorisés, les tâches de l’appelant, la recherche et les filtres d’état, les durées et les flux de sortie séparés. La tâche sélectionnée et la liste sont actualisées toutes les 5 secondes quand l’onglet est visible ; cette actualisation peut être désactivée. États et compteurs sont limités à l’utilisateur connecté. La version installée du daemon apparaît après connexion. Les tâches interrompues ou au résultat inconnu restent visuellement distinctes des réussites.

Run endpoint soumet une tâche à ce daemon après confirmation explicite. Les arguments sont littéraux, un par ligne ; aucune syntaxe de guillemets du shell n’est interprétée. Un formulaire vide signifie aucun argument ; une ligne vide dans un formulaire non vide constitue un argument vide. Cette première interface ne fournit ni envoi de fichiers/environnement, ni administration des comptes, ni cibles/groupes, ni scénarios ou orchestration multi-daemons ; ces rôles restent à la CLI et au TUI. Les contrôles de portée de l’interface facilitent l’usage ; les services continuent d’imposer portées, ACL, propriété et politique opérateur.

Une réponse de soumission ambiguë est affichée avec l’identifiant de tâche et n’est jamais retentée. Actualisez la liste et vérifiez la tâche et ses effets avant de réexécuter. L’affichage est limité à 200000 caractères par flux ; utilisez la CLI/API pour récupérer tout le résultat conservé dans la limite configurée du daemon. Les comptes en lecture seule ne peuvent ni exécuter ni modifier la maintenance ; les comptes sans read sont informés que la console l’exige.

Les tests navigateur de la CI utilisent un vrai daemon jetable et des points d’entrée Python locaux inoffensifs : injection dans la sortie, débordement mobile, restauration de session, accès en lecture seule et réponse POST perdue sont couverts. Pour les reproduire avec Node 24 et Playwright 1.62.1, lancez node scripts/check_web_console.cjs depuis le dépôt avec PYTHON pointant vers l’environnement Python configuré du daemon. Définissez AUTON_BROWSER_EXECUTABLE pour une installation système de Chromium/Chrome. Ce script crée les captures de documentation ; il ne s’agit pas d’une démo publique d’exécution.

Autond sign-in Autond jobs and output Autond mobile maintenance view

Réconcilier un rapport d’opération enregistré

Une observation JSON enregistrée peut être vérifiée à nouveau sans soumettre de tâches ni reprendre les étapes ignorées. La sélection explicite des cibles définit la frontière de confiance : chaque origine contactée doit appartenir à la cible sélectionnée dans l’inventaire actuel. Les identifiants proviennent de la configuration actuelle, jamais du rapport.

umask 077
auton -c targets.yml -t production --reconcile observation.json > observation-current.json

Le JSON d’entrée est limité à 16 Mio, avec au maximum 8 Mio de sortie actualisée conservée dans l’instantané. Les exports plus grands doivent être séparés par opération/cible avant réconciliation ; cette limite est vérifiée avant tout accès réseau.

Cette opération produit un instantané borné, en lecture seule. Une tâche absente, expirée ou inaccessible reste inconnue ; son rejeu n’est jamais considéré comme sûr. Les étapes déjà ignorées, refusées ou non soumises restent inchangées. Les sorties sont actualisées depuis le même daemon et la même identité de tâche ; les durées d’observation enregistrées sont conservées et identifiées comme telles dans le TUI. Le rapport d’origine n’est pas modifié. Ne redirigez pas la sortie vers le rapport d’entrée. Le code de sortie vaut zéro uniquement si tout le travail observé s’est terminé avec succès. --operation-timeout borne le budget global entre requêtes et --http-timeout borne chaque requête HTTP.

Dans l’écran de préparation du TUI (e), sélectionnez les cibles/groupes de confiance, appuyez sur r et saisissez le chemin du rapport. Cette lecture des tâches existantes ne demande ni confirmation d’exécution ni soumission. Utilisez w sur l’observation obtenue pour enregistrer un nouveau JSON privé. L’enregistrement est explicite ; un client fermé avant export ne dispose d’aucun rapport automatiquement récupérable.

Surveillance des origines de remplacement

Le TUI lit chaque origine des chaînes de cibles explicitement sélectionnées. deploy désigne l’origine principale et deploy@2 la seconde, puis les rangs suivent l’ordre de l’inventaire. Les lectures des détails/sorties restent attachées à l’origine physique sélectionnée. Au maximum 128 origines sont sélectionnables, avec quatre workers de lecture simultanés. La préparation de l’exécution utilise toujours les noms logiques : cette vue ne transforme pas une chaîne de basculement en exécution diffusée. Des alias partageant une origine physique l’affichent séparément ; les totaux comptent les connexions affichées.

Poursuite explicite après une étape en échec

Une étape de scénario peut définir continue_on_error: true. La valeur par défaut reste false. La poursuite s’applique uniquement à un échec final confirmé, conserve cet échec dans le résultat final et fixe les étapes suivantes au même daemon. Les résultats inconnus, refus et délais d’observation dépassés arrêtent toujours la séquence de la cible. Cette option ne relance aucune tâche, n’annule aucun effet et ne transforme pas un échec en réussite.

Paramètres positionnels publiés

Un point d’entrée peut publier explicitement un contrat d’arguments borné. Seules ces métadonnées publiques sont renvoyées par /endpoints, après autorisation. Aucune configuration privée du plugin n’est publiée.

discovery:
  description: Check one service
  parameters:
    version: 1
    args:
      - name: service
        choices: [web, database]
      - name: attempts
        type: integer
        required: false

Chaque champ est un argument positionnel littéral. Types acceptés : string (par défaut), integer et boolean (texte true/false). Les champs peuvent définir description, choices, max_length (1 à 4096) et required (true par défaut). Les champs facultatifs doivent être à la fin ; 64 champs au maximum sont autorisés. Le daemon refuse les arguments absents, supplémentaires ou invalides avant admission et les valide à nouveau dans le worker. Les points d’entrée sans schéma conservent leur comportement existant. Ce schéma décrit seulement les arguments positionnels, pas les variables d’environnement ou les fichiers envoyés.

La console Web construit un formulaire. Dans la préparation TUI, sélectionnez un point d’entrée puis p pour la saisie guidée ; Échap conserve la saisie précédente. Le formulaire guidé du TUI remplace les arguments et efface l’environnement. Des schémas publiés incompatibles ne peuvent pas être combinés. L’exécution exige toujours l’aperçu et la confirmation habituels. Les arguments CLI bruts restent disponibles et reçoivent la même validation serveur.

Annulation explicite d’une tâche

Le propriétaire authentifié d’une tâche peut demander son annulation avec la nouvelle portée cancel ; cette permission n’est pas ajoutée silencieusement aux jetons existants. Avec Basic, le propriétaire authentifié et l’ACL du point d’entrée sont vérifiés. L’adaptateur fourni subproc prend en charge l’annulation ; les autres doivent la prendre en charge explicitement.

auton --mode cancel --uri https://node.example.com --endpoint backup \
  --uid 00000000-0000-0000-0000-000000000001 -k operator.token

La requête est fixée à un daemon et n’est jamais retentée automatiquement. Une tâche en file est empêchée de démarrer, même pendant la maintenance. Un sous-processus actif et son groupe sont arrêtés avant le signalement de l’état final. La réponse peut indiquer cancel_requested: true pendant le nettoyage ; inspectez la tâche pour confirmer outcome: job.cancelled. L’annulation ne peut pas défaire les effets déjà produits ; une tâche terminée avant elle conserve son résultat réel.

Le détail Web d’une tâche propose une confirmation distincte pour l’annulation. Arrêter l’observation dans la CLI/TUI n’annule toujours pas la tâche. Les installations existantes doivent ajouter la route POST /cancel/<endpoint>/<id> depuis le YAML du module fourni.

Scénarios sans surveillance sur un hôte de contrôle

auton -c targets.yml -g production -s maintenance \
  --operation-timeout 3600 --detach-dir /private/new-operation

--detach-dir lance explicitement un worker Unix détaché sur l’hôte de contrôle courant. La commande au premier plan rend la main après le détachement ; fermer son terminal n’arrête pas la séquence. Le worker exécute le même service applicatif validé, avec les identifiants existants en mémoire. Aucun ordonnanceur permanent ni daemon central n’est requis. Gardez l’hôte de contrôle actif : ce mode ne déplace pas l’exécution sur une autre machine et ne redémarre pas automatiquement le worker après une panne de l’hôte.

Le répertoire doit être nouveau ; il est créé en mode 0700. observation.json est remplacé atomiquement par des points de contrôle privés en 0600, puis par le résultat final. Ils contiennent les références et états des tâches, pas les identifiants ni les charges utiles d’entrée. Un point de contrôle est écrit avant chaque soumission ; une réponse interrompue ou perdue reste incertaine. Si la persistance échoue, les soumissions suivantes s’arrêtent. Un point de contrôle partiel omet la sortie des commandes jusqu’au résultat final ; utilisez --reconcile avec l’inventaire actuel de confiance pour lire la sortie conservée par le daemon. Aucun rejeu ni reprise automatique n’a lieu après un plantage du worker.

Historique Redis optionnel via DWho

Installez autond[redis] et configurez explicitement un espace Redis par daemon :

general:
  job_storage:
    backend: redis
    url: redis://127.0.0.1:6379/0
    namespace: autond-one
    timeout: 3

Les connexions sont fournies par dwho.adapters.redis.DWhoAdapterRedis. Auton fournit uniquement sa politique d’instantanés, de conservation et de récupération des tâches. Un bail de propriété renouvelable et des écritures atomiques protégées empêchent plusieurs daemons d’écrire simultanément dans un espace. Les délais de connexion/lecture sont bornés, les nouvelles tentatives du client sont désactivées et la perte du stockage/bail bloque les persistances et admissions suivantes. Perdre un bail ne prouve pas qu’une commande externe s’est arrêtée : les tâches inachevées sont restaurées comme interrompues/incertaines et ne sont jamais rejouées.

Utilisez un service Redis privé, un espace unique, des ACL adaptées et rediss:// pour chiffrer l’accès distant. Persistance, sauvegardes et politique d’éviction Redis restent à la charge de l’opérateur ; n’utilisez pas un cache avec éviction pour un historique durable. L’historique est facultatif ; la mémoire reste le défaut et SQLite reste pris en charge. L’authentification reste configurée séparément avec son stockage SQLite existant.

TLS mutuel (depuis 1.2.0)

Le HTTPS natif peut exiger un certificat client en plus de l’identité applicative existante. Activez l’authentification obligatoire et fournissez les fichiers de certificats :

general:
  auth_mode: required
  tls:
    certificate: server-chain.pem
    private_key: server.key
    client_ca: client-ca.pem

Les chemins sont relatifs au fichier de configuration du daemon. Le serveur exige TLS 1.2 ou supérieur et une chaîne cliente approuvée par client_ca. Les noms des certificats ne donnent aucun droit sur les points d’entrée : les identifiants Basic ou un jeton/session applicatif restent requis. Protégez les clés privées avec des permissions privées. Les identifiants sont chargés avant réduction des privilèges ; leur renouvellement exige un redémarrage contrôlé.

Les connexions CLI/TUI acceptent --ca-file CA.pem --client-cert client.pem --client-key client.key. Ces réglages s’appliquent aussi au basculement, aux workers détachés, à la réconciliation et à l’annulation. Chaque origine sélectionnée doit utiliser HTTPS. La vérification du certificat serveur ne peut pas être désactivée. Pour le navigateur, installez le certificat client dans celui-ci ou utilisez une entrée TLS sécurisée séparément.

SSO navigateur avec OIDC (depuis 1.2.0)

Installez autond[oidc] (inclus dans l’image Docker). Configurez d’abord les comptes SQLite existants et la console Web HTTPS, puis ajoutez explicitement un fournisseur OIDC. Les valeurs ci-dessous sont des exemples à remplacer, pas un fournisseur fonctionnel :

general:
  oidc:
    issuer: https://identity.example/tenant
    authorization_endpoint: https://identity.example/tenant/authorize
    token_endpoint: https://identity.example/tenant/token
    client_id: auton-console
    client_secret_file: oidc-client.secret  # omit for a public PKCE client
    jwks_file: oidc-public-keys.json
    subjects:
      opaque-provider-subject: operator

Enregistrez exactement https://YOUR-AUTON-ORIGIN/oidc/callback chez le fournisseur. Utilisez le flux authorization code avec PKCE S256 et des jetons d’identité RS256. Le fichier secret doit avoir des droits privés (0600) ; il est lu au démarrage. L’opérateur fournit les clés publiques RSA de signature de l’émetteur dans un fichier JWKS. Conservez des clés qui se chevauchent pendant la rotation, mettez le fichier à jour puis redémarrez : aucune découverte ni récupération distante automatique n’a lieu. Aucune URL des en-têtes de jetons n’est récupérée. Les URL de l’émetteur et des points d’entrée doivent être en HTTPS ; les échanges de jetons ont des délais bornés, sans nouvelle tentative ni redirection. Les clients publics et les clients confidentiels client_secret_basic sont pris en charge ; les autres méthodes d’authentification de jetons ne le sont pas.

La console affiche Sign in with SSO uniquement si cette option est configurée. L’état à usage unique, le cookie HttpOnly lié au navigateur, le nonce, l’émetteur, l’audience, la signature et l’expiration sont vérifiés. Un sujet doit correspondre explicitement à un compte local existant et actif. Auton revérifie ce compte à chaque requête, révision et permissions actuelles comprises. Les rôles du fournisseur n’accordent jamais de permissions locales et le SSO ne crée jamais de comptes. Définissez un mot de passe local aléatoire robuste pour un compte normalement utilisé en SSO ; la connexion par mot de passe local reste disponible indépendamment.

Les sessions SSO restent dans la mémoire bornée du daemon (1024 sessions maximum, 128 connexions en attente de cinq minutes, quatre échanges de jetons simultanés). Elles expirent à la première échéance entre expiration du jeton d’identité et une heure, avec 15 minutes d’inactivité maximum. Redémarrer le daemon déconnecte les utilisateurs SSO. La déconnexion termine la session locale, pas celle du fournisseur d’identité. Aucun jeton de renouvellement, propagation de déconnexion, flux device ou connexion CLI automatique n’est prévu. CLI/cron continue d’utiliser des jetons Bearer locaux explicites ou Basic, éventuellement avec mTLS.

Conservation des résultats pendant l’inactivité

Le daemon supprime désormais les résultats finaux expirés même sans lectures API entrantes. Il préserve les tâches en file/actives, supprime les instantanés persistants sous le même verrou de service que l’admission et dégrade la santé/admission si cette suppression échoue. Un passage intervient au plus tard toutes les 60 secondes (plus tôt si le TTL configuré est inférieur), avec au maximum 16 suppressions et un budget d’une seconde vérifié entre opérations de stockage. Un gros arriéré peut donc demander plusieurs passages. Cette conservation n’efface pas sûrement les sauvegardes et ne garantit pas une suppression à des fins d’investigation.

Auton 1.2.0 prend en charge Python 3.10 à 3.13.

Les échecs inattendus de soumission ou de lecture d’état renvoient HTTP 503 avec job_service_unavailable, sans détails d’exception internes. Cette réponse ne prouve pas que la soumission a été refusée : réconciliez l’identifiant de tâche avant de réessayer.

Consultez la validation de la configuration pour la couverture des schémas YAML et la compatibilité.

Documentation

Interface terminal Textual

Installez la dépendance facultative et sélectionnez explicitement l’interface moderne :

python -m pip install 'auton[textual]'
auton --tui --tui-ui textual -c inventory.yml

Consultez le guide Textual pour la navigation et les opérations prises en charge. L’interface curses existante reste disponible. Les captures utilisent des données synthétiques.

Importer des blocs d’arguments et d’environnement

Auton 1.5.0 et 2.0.0rc3 ajoutent import_args, import_env, import_allow_args, import_disallow_args, import_allow_env et import_disallow_env. Déclarez-les sur un endpoint, dans son config ou dans son fichier import_config. Plusieurs imports de blocs différents peuvent coexister. Chacun accepte un nom de fichier YAML local. Consultez le guide complet et l’exemple réutilisable.

endpoints:
  report:
    plugin: subproc
    import_config: imports/report.yml
# imports/report.yml
prog: /opt/scripts/report.sh
import_args: args.yml
import_env: env.yml
import_allow_args: allow-args.yml
import_disallow_args: disallow-args.yml
import_allow_env: allow-env.yml
import_disallow_env: disallow-env.yml

Seuls les imports descendants sont autorisés : configuration → blocs terminaux. Une configuration ne peut pas importer une autre configuration, et un bloc ne peut contenir aucun nouvel import. Les chemins sont relatifs au fichier qui déclare chaque import. Les valeurs en ligne remplacent le bloc importé entier ; les listes ne sont pas concaténées et les listes d’autorisations ne sont pas combinées.

Documentation des contributeurs

Vous modifiez le projet ? Utilisez le guide distinct Documentation des contributeurs.

Pour les contributeurs

Clients HTTP lents

Le démon accorde dix secondes par requête pour recevoir la ligne de requête et tous les en-têtes HTTP. En mTLS natif, ce délai commence après la négociation TLS. L’envoi d’octets isolés ne le prolonge pas. À son expiration, le serveur ferme la connexion et le worker peut prendre une autre requête. Ce délai ne couvre ni le corps de la requête ni l’exécution de la tâche.

La lecture du corps HTTP dispose de son propre délai absolu. Il est de dix secondes plus une seconde par tranche de 32 Kio de taille déclarée, avec un plafond de deux minutes. Un corps de 1 Mio dispose par exemple de 42 secondes. À expiration, le démon renvoie HTTP 408 et ferme la connexion avant l’exécution de la cible. Les limites de taille existantes restent applicables. Le délai prend fin dès que le corps a été lu et ne limite pas l’exécution de la tâche.