Files
comi-audit-gpresult-user/README.md
T

147 lines
9.8 KiB
Markdown

# Audit GPResult — Utilisateur actif
Paquet WAPT d'audit des GPO et des groupes de sécurité de l'utilisateur actif. Le résultat structuré est enregistré dans **`audit-gpresult.user-gpo`**.
## Fonctionnement
1. `install()` ne réalise aucune action.
2. `audit()` appelle `quser.exe` avec un délai maximal de 30 secondes. Le script retient le premier utilisateur dont la ligne contient l'état `Active` ou `Actif`.
3. Si aucun utilisateur n'est détecté, il enregistre `NO_USER` et retourne `OK` à WAPT.
4. Sinon, il supprime un éventuel rapport précédent et lance GPResult avec un délai maximal de 120 secondes :
```text
gpresult.exe /USER "<utilisateur détecté>" /SCOPE USER /X "<rapport.xml>" /F
```
5. Il analyse `UserResults`, extrait l'identité du compte, classe les GPO et les groupes de sécurité.
6. Il transmet un dictionnaire à `WAPT.write_audit_data_if_changed`, avec `keep_days=365` et `max_count=1`.
7. La suppression du rapport temporaire est tentée dans `finally`, après succès comme après erreur.
Le chemin de GPResult est construit avec `makepath(system32(), "gpresult.exe")`. L'audit s'exécute dans le contexte de l'agent WAPT et cible explicitement le RSoP utilisateur. Il n'utilise pas `session_setup()`, ne lance pas de `gpupdate` et ne modifie pas les stratégies.
## Prérequis et sélection de la session
- Poste Windows disposant de `quser.exe`, de GPResult et de données RSoP accessibles pour l'utilisateur ciblé.
- Agent WAPT fournissant `setuphelpers` et `WAPT.write_audit_data_if_changed`.
- Droits suffisants pour consulter les sessions et les données RSoP, ainsi que pour écrire dans le répertoire temporaire.
La détection utilise la sortie texte de `quser`, et non les API WTS ou `win32ts`. Seuls les libellés `Active` et `Actif` sont reconnus. Les sessions déconnectées sont ignorées. Si plusieurs utilisateurs sont actifs, le premier reconnu dans la sortie est sélectionné ; aucun contrôle d'unicité n'est effectué.
Seul le nom d'utilisateur détecté est transmis à `/USER`. Le script lit ensuite le premier texte `Name` de `UserResults` comme identité RSoP, avec repli sur le nom détecté si ce champ est absent. Sur un poste comportant des comptes homonymes, vérifier l'identité effectivement remontée.
Une erreur de `quser`, une sortie vide ou un format non reconnu aboutit aussi à `NO_USER`. Consulter le journal pour distinguer une erreur de détection d'une absence réelle de session. Une session active, locale ou de domaine, ne garantit pas que ses données RSoP soient disponibles.
## Données produites
Catégorie : `audit-gpresult` ; clé : `user-gpo`.
Exemple illustratif d'un résultat de succès :
```json
{
"status": "OK",
"user": {
"account": "EXEMPLE\\utilisateur",
"username": "utilisateur",
"account_domain": "EXEMPLE",
"account_type": "domain"
},
"summary": {
"applied_gpo_count": 1,
"denied_gpo_count": 1,
"total_gpo_count": 2,
"domain_group_count": 1,
"local_group_count": 1,
"system_group_count": 1,
"other_group_count": 0
},
"applied_gpos": ["GPO Utilisateurs"],
"denied_gpos": ["GPO non appliquee"],
"domain_groups": ["EXEMPLE\\Domain Users"],
"security_groups": {
"domain": ["EXEMPLE\\Domain Users"],
"local": ["BUILTIN\\Users"],
"system": ["NT AUTHORITY\\INTERACTIVE"],
"other": []
}
}
```
| Champ | Signification |
| --- | --- |
| `status` | État de la collecte ; ce n'est pas un verdict de conformité. |
| `user.account` | Identité lue dans le RSoP, ou nom détecté si elle est absente. |
| `user.username` | Partie du compte après le premier `\`, ou compte entier sans préfixe. |
| `user.account_domain` | Préfixe du compte, généralement NetBIOS pour un domaine ou nom du poste pour un compte local ; vide sans préfixe. |
| `user.account_type` | `local` si le préfixe est vide ou égal au nom du poste ; `domain` sinon. |
| `summary.applied_gpo_count` / `summary.denied_gpo_count` | Nombre de GPO retenues dans chaque liste. |
| `summary.total_gpo_count` | Somme des deux compteurs de GPO. |
| `summary.domain_group_count` / `summary.local_group_count` / `summary.system_group_count` / `summary.other_group_count` | Nombre de groupes retenus dans chaque catégorie. |
| `applied_gpos` / `denied_gpos` | Noms des GPO, dans l'ordre de collecte. |
| `domain_groups` | Même liste que `security_groups.domain`, pour faciliter le reporting. |
| `security_groups` | Groupes répartis entre `domain`, `local`, `system` et `other`. |
La recherche de texte est récursive et ignore les namespaces XML. Le type de compte est déduit du préfixe ; il n'est pas validé par une requête AD.
### Évolution du schéma
Les consommateurs de l'ancien résultat doivent utiliser `user.username` à la place de `user.name` et `user.account_domain` à la place de `user.domain`. Le résultat actuel ne contient plus de bloc `computer`. `user.account_type`, les listes de groupes et leurs compteurs sont ajoutés.
## Classement des GPO
Une GPO est appliquée si `Enabled`, `IsValid` et `FilterAllowed` sont vrais et si `AccessDenied` est faux. Toutes les autres entrées retenues vont dans `denied_gpos` : cette liste couvre les GPO non appliquées, y compris les GPO filtrées, désactivées ou invalides.
Les valeurs `true`, `1`, `yes` et `oui`, sans distinction de casse, sont vraies. Toute autre valeur ou un champ absent est faux. Un indicateur positif absent empêche donc le classement comme GPO appliquée ; un `AccessDenied` absent est considéré comme faux. Aucun état indéterminable ne déclenche d'erreur spécifique dans cette version.
La recherche des balises `GPO` est récursive. Les entrées sans nom sont ignorées, sans repli sur un identifiant XML. Les doublons sont éliminés selon `(nom, VersionDirectory, VersionSysvol)` ; un nom peut apparaître plusieurs fois si les versions diffèrent. Les listes de GPO ne sont pas triées. Les compteurs décrivent les entrées retenues, sans constituer un inventaire de toutes les GPO du domaine.
## Classement des groupes de sécurité
Les groupes sont extraits des balises `SecurityGroup` du RSoP, sans requête LDAP supplémentaire. Le classement utilise les préfixes des noms, dans cet ordre :
| Catégorie | Règle |
| --- | --- |
| `system` | Préfixe `NT AUTHORITY\`. |
| `local` | Préfixe `BUILTIN\` ou nom du poste suivi de `\`. |
| `domain` | Préfixe du compte RSoP suivi de `\`, si ce préfixe est non vide et différent du nom du poste. |
| `other` | Toutes les autres identités. |
Un compte `POSTE01\utilisateur` ne fournit donc pas de préfixe AD pour classer les groupes de domaine. Les comparaisons et la déduplication ignorent la casse. Les entrées sans nom sont ignorées et chaque liste est triée alphabétiquement sans distinction de casse.
Ce classement repose sur les noms de l'export, sans validation par SID ou LDAP. Les noms localisés ou les groupes d'un autre domaine peuvent rester dans `other`. Les listes reflètent les données RSoP collectées ; elles ne constituent pas un inventaire exhaustif des groupes AD ou locaux.
## Statuts et cas particuliers
| Statut enregistré | Retour WAPT | Situation |
| --- | --- | --- |
| `OK` | `OK` | Export, analyse et enregistrement terminés, même avec des GPO non appliquées ou des listes vides. |
| `NO_USER` | `OK` | Aucun utilisateur actif reconnu, y compris en cas d'échec de détection capturé. |
| `ERROR` | `ERROR` | Exception capturée par l'audit : GPResult en échec, fichier absent, XML invalide, section `UserResults` absente, etc. |
Le résultat `NO_USER` contient `message`, `user: null`, des listes `applied_gpos`, `denied_gpos` et `domain_groups` vides, ainsi que les quatre catégories vides de `security_groups`. Il ne contient pas de bloc `summary`. Aucun statut `WARNING` n'est utilisé.
En cas d'erreur, la même clé reçoit uniquement `status: ERROR` et `message`. Les listes et compteurs du précédent succès ne sont pas recopiés. Les consommateurs doivent lire `status` avant d'accéder aux champs de succès.
La clé représente le dernier audit du poste, selon l'utilisateur sélectionné au moment de l'exécution ; aucune clé distincte par utilisateur n'est créée.
## Déploiement et dépannage
1. Mettre à jour `setup.py` dans les sources du paquet existant.
2. Adapter si nécessaire la description de `WAPT/control` pour mentionner les groupes de sécurité, en conservant l'identité et les autres métadonnées du paquet ; incrémenter sa version selon les conventions du dépôt.
3. Reconstruire, signer, téléverser et déployer le paquet.
4. Lancer l'audit avec une session active et consulter `audit-gpresult.user-gpo`.
La fréquence des audits dépend de la configuration WAPT ; le script ne crée pas de planification. Le journal indique l'utilisateur détecté, le compte RSoP, son type, les compteurs de GPO et de groupes de domaine ou l'erreur rencontrée.
- **`NO_USER` inattendu :** vérifier la sortie de `quser.exe`, les libellés reconnus et les éventuelles erreurs de détection dans le journal.
- **Compte inattendu :** vérifier l'ordre des sessions actives et comparer le nom détecté avec `user.account`.
- **Erreur GPResult ou XML :** vérifier les droits de l'agent, la disponibilité du RSoP pour ce compte, l'accès à GPResult et au répertoire temporaire.
Le rapport utilise le nom fixe `wapt-gpresult-user.xml` dans `tempfile.gettempdir()`. Éviter les audits simultanés partageant ce répertoire. Un échec de nettoyage est ignoré et peut laisser le fichier sur disque.
## Contenu du dépôt
- `setup.py` : détection de session, collecte et analyse des GPO et groupes de sécurité utilisateur.
- `README.md` : fonctionnement, schéma de données et exploitation.
- `WAPT/description.txt` : description fournie pour le contrôle existant ; elle décrit les GPO et ne mentionne pas encore les groupes de sécurité. Ce fichier ne remplace pas un `WAPT/control` complet.