feat(ansible-role-remote_users_fact) first commit

This commit is contained in:
2026-04-13 23:25:51 +02:00
commit 51f19b678f
11 changed files with 478 additions and 0 deletions
+27
View File
@@ -0,0 +1,27 @@
---
# =============================================================================
# defaults/main.yml — Variables par défaut du rôle remote_users_fact
# =============================================================================
# Répertoire de destination des local facts
remote_users_fact_dir: /etc/ansible/facts.d
# Nom du script fact
remote_users_fact_name: remote_users.fact
# Propriétaire et groupe du fichier
remote_users_fact_owner: root
remote_users_fact_group: root
# Activer la validation post-déploiement (exécution + parsing JSON)
remote_users_fact_validate: true
# Activer l'affichage du résumé après déploiement
remote_users_fact_display_summary: true
# Verdicts considérés comme anormaux (déclenchent un warning)
remote_users_fact_warn_verdicts:
- WHO_SUP_TOTAL
- WHO_INF_TOTAL
- WHO_SEUL
- PROTO_SEUL
@@ -0,0 +1,116 @@
#!/bin/bash
# =============================================================================
# remote_users.fact
# Ansible local fact — /etc/ansible/facts.d/remote_users.fact
# Retourne un JSON avec le comptage des sessions distantes par protocole
# et l'analyse de fiabilité who vs total
# =============================================================================
set -euo pipefail
# --- Comptage SSH ---
ssh_by_ss=0
if command -v ss &>/dev/null; then
ssh_by_ss=$(ss -tnp state established 2>/dev/null | grep -c "sshd" || echo 0)
fi
ssh_by_proc=$(pgrep -c -f "sshd:.*@" 2>/dev/null || echo 0)
ssh_count=$(( ssh_by_ss > ssh_by_proc ? ssh_by_ss : ssh_by_proc ))
# --- Comptage Citrix ---
citrix_count=0
ctxquery="/opt/Citrix/VDA/bin/ctxquery"
if [[ -x "$ctxquery" ]]; then
citrix_count=$("$ctxquery" -f all 2>/dev/null | grep -ci "active" || echo 0)
else
citrix_count=$(pgrep -c -f "ctxhdx|ctxgfx|wfica" 2>/dev/null || echo 0)
if [[ $citrix_count -eq 0 ]] && command -v ss &>/dev/null; then
citrix_count=$(ss -tnp state established 2>/dev/null \
| grep -cE ":(1494|2598)\b" || echo 0)
fi
fi
# --- Comptage Horizon ---
blast=$(pgrep -c -f "vmware-blast" 2>/dev/null || echo 0)
pcoip=$(pgrep -c -f "pcoip-server" 2>/dev/null || echo 0)
horizon_count=$(( blast + pcoip ))
if [[ $horizon_count -eq 0 ]] && command -v ss &>/dev/null; then
horizon_count=$(ss -tnp state established 2>/dev/null \
| grep -cE ":(8443|22443)\b" || echo 0)
fi
# --- Comptage who (distant) ---
who_count=$(who 2>/dev/null | grep -v '(:0' | grep -c '(.*[a-zA-Z0-9])' || echo 0)
# --- Liste utilisateurs distants (who) ---
who_users=$(who 2>/dev/null | grep -v '(:0' | grep '(.*[a-zA-Z0-9])' \
| awk '{print $1}' | sort -u | paste -sd ',' || echo "")
# --- Total protocoles ---
total=$(( ssh_count + citrix_count + horizon_count ))
# --- Analyse fiabilité ---
if [[ $total -eq 0 && $who_count -eq 0 ]]; then
ratio="null"
verdict="NEUTRE"
detail="Aucune session detectee"
elif [[ $total -eq 0 ]]; then
ratio="null"
verdict="WHO_SEUL"
detail="who detecte ${who_count} session(s) non classifiee(s) par protocole"
elif [[ $who_count -eq 0 ]]; then
ratio="0"
verdict="PROTO_SEUL"
detail="Sessions detectees par protocole mais invisibles dans who"
else
ratio=$(awk "BEGIN { printf \"%.2f\", ($who_count / $total) }")
diff=$(( who_count - total ))
abs_diff=${diff#-}
if [[ $abs_diff -eq 0 ]]; then
verdict="FIABLE"
detail="who == total protocoles, compteurs alignes"
elif [[ $abs_diff -le 1 ]]; then
verdict="OK"
detail="Ecart de ${abs_diff} session(s), tolerable"
elif [[ $who_count -gt $total ]]; then
verdict="WHO_SUP_TOTAL"
detail="who voit +${abs_diff} session(s) non classifiee(s)"
else
verdict="WHO_INF_TOTAL"
detail="who manque ${abs_diff} session(s) sans TTY"
fi
fi
# --- Détection des composants installés ---
has_citrix_vda=false
[[ -x "$ctxquery" ]] && has_citrix_vda=true
has_horizon_agent=false
[[ -f /usr/lib/vmware/viewagent/bin/vmware-viewagent ]] && has_horizon_agent=true
# --- Sortie JSON ---
cat <<EOF
{
"timestamp": "$(date -u '+%Y-%m-%dT%H:%M:%SZ')",
"sessions": {
"ssh": ${ssh_count},
"citrix": ${citrix_count},
"horizon": ${horizon_count},
"total_by_protocol": ${total},
"who_remote": ${who_count}
},
"users_remote": "${who_users}",
"reliability": {
"ratio_who_over_total": ${ratio:-null},
"verdict": "${verdict}",
"detail": "${detail}"
},
"detection": {
"citrix_vda_installed": ${has_citrix_vda},
"horizon_agent_installed": ${has_horizon_agent},
"ssh_method": "sshd_process_and_ss",
"citrix_method": "$( [[ -x "$ctxquery" ]] && echo "ctxquery" || echo "fallback_process_ports" )",
"horizon_method": "$( [[ $blast -gt 0 || $pcoip -gt 0 ]] && echo "blast_pcoip_process" || echo "fallback_ports" )"
}
}
EOF
@@ -0,0 +1,8 @@
---
# =============================================================================
# handlers/main.yml — Handlers du rôle remote_users_fact
# =============================================================================
- name: Recharger les local facts
ansible.builtin.setup:
filter: ansible_local
+40
View File
@@ -0,0 +1,40 @@
---
# =============================================================================
# meta/main.yml — Métadonnées du rôle remote_users_fact
# =============================================================================
galaxy_info:
role_name: remote_users_fact
author: infra-team
description: >
Déploie un local fact Ansible qui compte les sessions distantes
par protocole (SSH, Citrix, Horizon) et compare avec who
pour évaluer la fiabilité des compteurs.
license: MIT
min_ansible_version: "2.12"
platforms:
- name: EL
versions:
- "8"
- "9"
- name: Debian
versions:
- bullseye
- bookworm
- name: Ubuntu
versions:
- focal
- jammy
- noble
galaxy_tags:
- monitoring
- facts
- security
- ssh
- citrix
- horizon
- audit
dependencies: []
+23
View File
@@ -0,0 +1,23 @@
---
# =============================================================================
# tasks/deploy.yml — Création du répertoire et copie du fact
# =============================================================================
- name: Créer le répertoire facts.d
ansible.builtin.file:
path: "{{ remote_users_fact_dir }}"
state: directory
owner: "{{ remote_users_fact_owner }}"
group: "{{ remote_users_fact_group }}"
mode: "0755"
- name: Déployer le script remote_users.fact
ansible.builtin.copy:
src: "{{ remote_users_fact_name }}"
dest: "{{ remote_users_fact_dir }}/{{ remote_users_fact_name }}"
owner: "{{ remote_users_fact_owner }}"
group: "{{ remote_users_fact_group }}"
mode: "0755"
backup: true
register: _remote_users_fact_deployed
notify: Recharger les local facts
+24
View File
@@ -0,0 +1,24 @@
---
# =============================================================================
# tasks/main.yml — Déploiement et validation du local fact remote_users
# =============================================================================
- name: Inclure les tâches de déploiement
ansible.builtin.include_tasks: deploy.yml
tags:
- remote_users_fact
- deploy
- name: Inclure les tâches de validation
ansible.builtin.include_tasks: validate.yml
when: remote_users_fact_validate | bool
tags:
- remote_users_fact
- validate
- name: Inclure les tâches de résumé
ansible.builtin.include_tasks: summary.yml
when: remote_users_fact_display_summary | bool
tags:
- remote_users_fact
- summary
+34
View File
@@ -0,0 +1,34 @@
---
# =============================================================================
# tasks/summary.yml — Affichage du résumé et alertes éventuelles
# =============================================================================
- name: Afficher le résumé des sessions distantes
ansible.builtin.debug:
msg:
- "══════════════════════════════════════════"
- "Host : {{ inventory_hostname }}"
- "Timestamp : {{ ansible_local.remote_users.timestamp }}"
- "──────────────────────────────────────────"
- "SSH : {{ ansible_local.remote_users.sessions.ssh }}"
- "Citrix : {{ ansible_local.remote_users.sessions.citrix }}"
- "Horizon : {{ ansible_local.remote_users.sessions.horizon }}"
- "Total proto : {{ ansible_local.remote_users.sessions.total_by_protocol }}"
- "Who remote : {{ ansible_local.remote_users.sessions.who_remote }}"
- "──────────────────────────────────────────"
- "Verdict : {{ ansible_local.remote_users.reliability.verdict }}"
- "Ratio : {{ ansible_local.remote_users.reliability.ratio_who_over_total }}"
- "Détail : {{ ansible_local.remote_users.reliability.detail }}"
- "──────────────────────────────────────────"
- "Utilisateurs: {{ ansible_local.remote_users.users_remote | default('aucun') }}"
- "Citrix VDA : {{ ansible_local.remote_users.detection.citrix_vda_installed }}"
- "Horizon Agt : {{ ansible_local.remote_users.detection.horizon_agent_installed }}"
- "══════════════════════════════════════════"
- name: Alerter si le verdict est anormal
ansible.builtin.debug:
msg: >-
⚠ ATTENTION sur {{ inventory_hostname }} —
Verdict: {{ ansible_local.remote_users.reliability.verdict }} —
{{ ansible_local.remote_users.reliability.detail }}
when: ansible_local.remote_users.reliability.verdict in remote_users_fact_warn_verdicts
@@ -0,0 +1,37 @@
---
# =============================================================================
# tasks/validate.yml — Validation du fact (exécution + parsing JSON)
# =============================================================================
- name: Forcer le rechargement des facts si déploiement effectué
ansible.builtin.meta: flush_handlers
- name: Exécuter le script fact manuellement pour validation
ansible.builtin.command:
cmd: "{{ remote_users_fact_dir }}/{{ remote_users_fact_name }}"
register: _remote_users_fact_output
changed_when: false
failed_when: _remote_users_fact_output.rc != 0
- name: Valider que la sortie est du JSON parsable
ansible.builtin.set_fact:
_remote_users_fact_parsed: "{{ _remote_users_fact_output.stdout | from_json }}"
- name: Vérifier la présence des clés obligatoires
ansible.builtin.assert:
that:
- _remote_users_fact_parsed.sessions is defined
- _remote_users_fact_parsed.sessions.ssh is defined
- _remote_users_fact_parsed.sessions.citrix is defined
- _remote_users_fact_parsed.sessions.horizon is defined
- _remote_users_fact_parsed.sessions.total_by_protocol is defined
- _remote_users_fact_parsed.sessions.who_remote is defined
- _remote_users_fact_parsed.reliability is defined
- _remote_users_fact_parsed.reliability.verdict is defined
- _remote_users_fact_parsed.detection is defined
fail_msg: "Le fact remote_users ne retourne pas la structure JSON attendue"
success_msg: "Structure JSON validée avec succès"
- name: Recharger les ansible_local facts
ansible.builtin.setup:
filter: ansible_local