remote_users_fact

Rôle Ansible qui gère un local fact comptant les sessions distantes par protocole (SSH, Citrix, Horizon) et évaluant la fiabilité en comparant avec who.

Gestion du state

Le rôle est piloté par la variable remote_users_fact_state :

State Comportement
noop (défaut) Aucune action — le rôle ne touche à rien
present Déploie le fact, valide le JSON, affiche le résumé
absent Supprime le fact, purge ansible_local, nettoie le répertoire si vide

Le state peut être défini à tout niveau (all, groupe, hôte, extra-vars). noop par défaut garantit qu'un hôte ajouté à l'inventaire sans configuration explicite ne sera pas impacté.

flowchart LR
    A[assert.yml] --> B{remote_users_fact_state}
    B -->|noop| C[Aucune action]
    B -->|present| D[present.yml]
    B -->|absent| E[absent.yml]
    D --> F{validate ?}
    F -->|oui| G[validate.yml]
    F -->|non| H{summary ?}
    G --> H
    H -->|oui| I[summary.yml]
    H -->|non| J[Fin]
    I --> J
    E --> J
    C --> J

Arborescence

├── site.yml                          # Playbook principal
├── inventories/
│   └── hosts.yml                     # Inventaire exemple
└── roles/
    └── remote_users_fact/
        ├── defaults/main.yml         # Variables (dont state)
        ├── files/remote_users.fact   # Script fact
        ├── handlers/main.yml         # Rechargement facts
        ├── meta/main.yml             # Métadonnées Galaxy
        └── tasks/
            ├── main.yml              # Assertions → routage par state
            ├── assert.yml            # Validation stricte du paramétrage
            ├── present.yml           # Déploiement (state=present)
            ├── absent.yml            # Suppression (state=absent)
            ├── validate.yml          # Exécution + assert structure JSON
            └── summary.yml           # Affichage matrice + alertes

Usage

# Appliquer le state défini dans l'inventaire
ansible-playbook -i inventories/hosts.yml site.yml

# Forcer le déploiement partout (override)
ansible-playbook -i inventories/hosts.yml site.yml -e remote_users_fact_state=present

# Supprimer partout
ansible-playbook -i inventories/hosts.yml site.yml -e remote_users_fact_state=absent

# Sur un groupe spécifique
ansible-playbook -i inventories/hosts.yml site.yml -l citrix_servers

# Tags disponibles
ansible-playbook ... --tags assert           # Assertions seules
ansible-playbook ... --tags present,deploy   # Déploiement seul
ansible-playbook ... --tags validate         # Validation seule
ansible-playbook ... --tags summary          # Résumé seul
ansible-playbook ... --tags absent,remove    # Suppression seule

Variables

Variable Défaut Description
remote_users_fact_state noop present / absent / noop
remote_users_fact_dir /etc/ansible/facts.d Répertoire de destination
remote_users_fact_name remote_users.fact Nom du script
remote_users_fact_owner root Propriétaire
remote_users_fact_group root Groupe
remote_users_fact_validate true Activer la validation post-deploy
remote_users_fact_display_summary true Afficher le résumé
remote_users_fact_warn_verdicts voir defaults Verdicts déclenchant un warning

Assertions

Le rôle valide le paramétrage avant toute action :

  • remote_users_fact_state est défini et vaut present, absent ou noop
  • remote_users_fact_dir est un chemin absolu (si state != noop)
  • remote_users_fact_name respecte le pattern *.fact (si state != noop)
  • remote_users_fact_owner et group sont définis (si state == present)
  • remote_users_fact_validate et display_summary sont des booléens
  • remote_users_fact_warn_verdicts est une liste de verdicts valides

En cas de state present, la validation post-déploiement vérifie aussi :

  • Le script s'exécute sans erreur (rc == 0)
  • La sortie est du JSON parsable
  • Toutes les clés obligatoires sont présentes
  • Les compteurs sont >= 0
  • total_by_protocol == ssh + citrix + horizon
  • Le verdict est dans la liste des verdicts connus
  • Le fact est chargé dans ansible_local

Fact déployé

Accessible via ansible_local.remote_users :

{
  "timestamp": "2026-04-13T10:30:00Z",
  "sessions": {
    "ssh": 3,
    "citrix": 12,
    "horizon": 0,
    "total_by_protocol": 15,
    "who_remote": 14
  },
  "users_remote": "alice,bob,charlie",
  "reliability": {
    "ratio_who_over_total": 0.93,
    "verdict": "WHO_INF_TOTAL",
    "detail": "who manque 1 session(s) sans TTY"
  },
  "detection": {
    "citrix_vda_installed": true,
    "horizon_agent_installed": false,
    "ssh_method": "sshd_process_and_ss",
    "citrix_method": "ctxquery",
    "horizon_method": "fallback_ports"
  }
}

Verdicts

Verdict Signification
FIABLE who == total → compteurs alignés
OK Écart <= 1 → tolérable
WHO_SUP_TOTAL who > total → protocole non surveillé
WHO_INF_TOTAL who < total → sessions headless sans TTY
WHO_SEUL total == 0 → protocoles non détectés
PROTO_SEUL who == 0 → sessions sans allocation TTY
NEUTRE 0 == 0 → aucune session

Exemple d'inventaire avec states

all:
  vars:
    remote_users_fact_state: present    # Défaut global

  children:
    prod_servers:
      hosts:
        srv-01: {}
        srv-02: {}

    # Hôte exclu
    dev_servers:
      hosts:
        dev-01:
          remote_users_fact_state: noop

    # Groupe en décommission
    legacy:
      vars:
        remote_users_fact_state: absent

CI / Tests

Le rôle est testé automatiquement sur toutes les distributions déclarées dans meta/main.yml via Docker.

flowchart LR
    A[meta/main.yml] --> B[build_matrix.py]
    B --> C[JSON matrix]
    C --> D{Makefile}
    D --> E[Dockerfile.el]
    D --> F[Dockerfile.debian]
    E --> G[docker build + run]
    F --> G
    G --> H[test_playbook.yml]
    H --> I[role: assert + present + validate + summary]

Commandes Make

make help          # Affiche les cibles disponibles
make matrix        # Affiche la matrice JSON des distros
make lint          # yamllint + ansible-lint
make test          # Teste toutes les distros
make test-el9      # Teste une seule distro
make clean         # Supprime les images Docker de test

Registry privée

Par défaut les images sont tirées depuis Docker Hub. Pour utiliser une registry privée (Artifactory, Harbor, etc.), définir les variables d'environnement :

Variable Défaut Exemple
DOCKER_REGISTRY (vide = Docker Hub) registry.nuevolia.dev
DOCKER_REGISTRY_PREFIX (vide) library/
# Artifactory
DOCKER_REGISTRY=registry.nuevolia.dev DOCKER_REGISTRY_PREFIX=library/ make test

# Harbor
DOCKER_REGISTRY=harbor.local DOCKER_REGISTRY_PREFIX=proxy/ make test

Pipelines CI

Trois configurations sont fournies :

Fichier Système Stratégie
.gitea/workflows/ci.yml Gitea Actions Matrix dynamique parallèle
.gitlab-ci.yml GitLab CI Séquentiel
Jenkinsfile Jenkins Stages parallèles

Les variables DOCKER_REGISTRY et DOCKER_REGISTRY_PREFIX peuvent être définies dans les secrets/variables de chaque CI.

Utilisation dans d'autres playbooks

- hosts: all
  gather_facts: true
  tasks:
    - name: Bloquer un déploiement si trop de sessions
      ansible.builtin.fail:
        msg: "{{ ansible_local.remote_users.sessions.total_by_protocol }} sessions actives"
      when:
        - ansible_local.remote_users is defined
        - ansible_local.remote_users.sessions.total_by_protocol | int > 10
S
Description
No description provided
Readme 66 KiB
Languages
Shell 48%
Python 25.9%
Makefile 23%
Emacs Lisp 3.1%