fapolicyd est un démon de RHEL, basé sur fanotify, qui autorise ou bloque l'exécution des binaires et le chargement des bibliothèques selon une politique de confiance. Il complète SELinux : là où SELinux confine ce qu'un processus a le droit de faire, fapolicyd décide ce qui a le droit de s'exécuter. C'est le whitelisting applicatif natif de RHEL, un différenciant fort en durcissement enterprise. Ce guide s'adresse aux sysadmins RHEL et à la préparation RHCSA/RHCE qui veulent aller au-delà du programme officiel.
fanotify est le mécanisme du noyau Linux qui permet à un démon d'être notifié,
et de statuer, sur les accès aux fichiers. fapolicyd s'en sert pour intercepter
chaque tentative d'exécution et la comparer à sa base de confiance.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Situer fapolicyd face à SELinux et firewalld, trois couches aux rôles distincts.
- Construire et interroger la trust database (base de confiance).
- Écrire des règles
allow/denydansrules.d/et les compiler. - Tester en mode permissive avant d'enforcer, et diagnostiquer un refus.
- Éviter le piège classique qui brique des démons légitimes au démarrage.
Prérequis
Section intitulée « Prérequis »- Un système RHEL 8.4 ou 9 (ou un clone : Rocky Linux, AlmaLinux).
Le répertoire de règles modulaire
rules.d/est disponible depuis RHEL 8.4. - Un accès root (les commandes ci-dessous s'exécutent en root ou via
sudo).
fapolicyd, SELinux et firewalld : trois couches distinctes
Section intitulée « fapolicyd, SELinux et firewalld : trois couches distinctes »Ces trois mécanismes sont souvent confondus alors qu'ils répondent à des questions différentes et se complètent. Les empiler, c'est faire de la défense en profondeur.
| Couche | Ce qu'elle contrôle | La question |
|---|---|---|
| firewalld | le trafic réseau (ports, zones) | qui a le droit de se connecter |
| SELinux | ce qu'un processus peut faire (MAC par étiquettes) | ce qu'un processus a le droit de faire |
| fapolicyd | ce qui peut s'exécuter (whitelisting) | ce qui a le droit de s'exécuter |
Le MAC (Mandatory Access Control, contrôle d'accès obligatoire) de SELinux et le whitelisting de fapolicyd ne se remplacent pas. Un binaire malveillant déposé par un attaquant peut être correctement étiqueté par SELinux et pourtant illégitime : fapolicyd le bloque parce qu'il n'est pas dans la base de confiance. C'est la parade directe aux binaires détournés, cousine côté Linux du principe vu pour Windows avec LOLBAS.
Installer et démarrer fapolicyd
Section intitulée « Installer et démarrer fapolicyd »Le paquet est disponible dans les dépôts de base.
# Installer le démonsudo dnf install fapolicydLa trust database : le concept clé
Section intitulée « La trust database : le concept clé »Tout repose sur la trust database (base de confiance) : la liste des fichiers autorisés à s'exécuter, avec leur taille et leur empreinte SHA256. fapolicyd fait confiance par défaut à tout ce qui est installé par RPM (la base RPM sert de source de confiance), ce qui couvre l'essentiel d'un système sain.
La commande centrale reconstruit et rafraîchit cette base :
# Reconstruire la base de confiance depuis la base RPMsudo fapolicyd-cli --updateCette commande notifie le démon de recharger sa base de confiance. À lancer après chaque installation ou mise à jour de paquets, sinon les nouveaux binaires seront inconnus de fapolicyd, donc refusés. Sur un système sain, la base compte des dizaines de milliers d'entrées : par exemple 50624 sur l'AlmaLinux 8.10 (fapolicyd 1.3.2) qui a servi à valider ce guide.
Pour vérifier ce que fapolicyd considère comme fiable, videz la base :
# Lister les entrées de confiance (fichiers RPM + fichiers ajoutés à la main)sudo fapolicyd-cli --dump-db | headChaque ligne suit le format <source> <chemin> <taille> <empreinte SHA256>, par
exemple rpmdb /usr/bin/bash <taille> <sha256>. Le préfixe rpmdb indique
que la confiance vient de la base RPM. Une longue liste de chemins connus
(/usr/bin/..., /opt/...) confirme que la base est bien peuplée. Les fichiers
de confiance ajoutés manuellement vivent dans /etc/fapolicyd/fapolicyd.trust
et dans le répertoire /etc/fapolicyd/trust.d/.
Écrire et compiler des règles
Section intitulée « Écrire et compiler des règles »Les règles décident, pour chaque accès, s'il faut autoriser (allow) ou
refuser (deny). Elles sont modulaires, réparties dans des fichiers du
répertoire /etc/fapolicyd/rules.d/, traités dans l'ordre des noms de
fichiers (d'où le préfixe numérique, 10-, 20-, etc.).
L'ordre compte : fapolicyd applique la première règle qui correspond. Une
règle deny placée avant un allow gagne.
# Lister les règles compilées, numérotées (utile pour lire les logs)sudo fapolicyd-cli --listLa politique par défaut d'AlmaLinux/RHEL se termine par un catch-all qui refuse tout ce qui n'a pas été explicitement autorisé (extrait réel) :
2. allow perm=any uid=0 trust=1 : all9. allow perm=execute all : trust=112. allow perm=any all : ftype=text/x-shellscript13. deny_audit perm=execute all : allDeux règles portent toute la logique. La règle 9 n'autorise l'exécution que
si le fichier est de confiance (trust=1) ; la règle 13, le catch-all
final, refuse et journalise (deny_audit) toute exécution non couverte. Ce
couple est ce qui bloque un binaire inconnu.
Après toute modification d'un fichier de rules.d/, il faut recompiler.
L'outil fagenrules assemble tous les fichiers de rules.d/ en un fichier
unique compiled.rules :
# Recompiler les règles puis recharger le démonsudo fagenrules --loadPermissive puis enforcing : ne jamais brûler l'étape
Section intitulée « Permissive puis enforcing : ne jamais brûler l'étape »Le mode de fonctionnement se règle dans le fichier de configuration principal
/etc/fapolicyd/fapolicyd.conf, avec l'option permissive.
permissive = 1: fapolicyd journalise ce qu'il aurait bloqué, sans rien empêcher. C'est le mode d'apprentissage.permissive = 0: fapolicyd enforce, il bloque réellement.
La méthode sûre consiste à démarrer en permissive, observer les refus qui seraient survenus, corriger la base de confiance et les règles, puis seulement basculer en enforcing.
Les refus se lisent dans le journal d'accès :
# Suivre les décisions de fapolicyd (refus inclus)sudo tail -f /var/log/fapolicyd-access.logUn refus vous donne le chemin du fichier et le numéro de règle appliquée
(corrélé avec fapolicyd-cli --list), de quoi diagnostiquer précisément ce qui
manque à la base de confiance.
Le piège qui vaut de l'or
Section intitulée « Le piège qui vaut de l'or »C'est l'erreur qui coûte une soirée, et que presque aucune doc ne mentionne clairement. Une base de confiance corrompue, vide ou périmée fait bloquer par fapolicyd tout ce qu'elle ne connaît pas. En lab, une base lmdb corrompue était tombée à 14 entrées ; la reconstruire de zéro l'a ramenée à 50624.
# Reconstruire une base de confiance corrompue, de zérosudo systemctl stop fapolicydsudo rm -f /var/lib/fapolicyd/*.mdbsudo fapolicyd-cli --updatesudo systemctl start fapolicydLa règle à graver : reconstruire la base de confiance avant d'enforcer, et tester en permissive d'abord. Un service bloqué par une base corrompue ressemble à une panne de permissions, jamais à fapolicyd, d'où la perte de temps.
Ajouter une application au trust
Section intitulée « Ajouter une application au trust »Un binaire ELF installé hors RPM (une application maison dans /opt, un
binaire Go compilé sur place) n'est pas dans la base RPM : il est inconnu,
donc refusé par le catch-all. Un script, lui, passe déjà (voir le piège des
scripts plus haut). Ajoutez le binaire à la base de confiance :
# Ajouter un binaire (ou tout un répertoire) à la base de confiancesudo fapolicyd-cli --file add /opt/pavois-helloLa commande écrit l'entrée de confiance et notifie le démon ; sa sortie le confirme :
Fapolicyd was notifiedLe binaire est aussitôt exécutable, sans --update (validé en lab). Si le
chemin est un répertoire, fapolicyd parcourt l'arborescence et ajoute chaque
fichier régulier avec son empreinte SHA256. À refaire (ou via
fapolicyd-cli --file update) après chaque recompilation de votre
application, sinon l'empreinte ne correspond plus et l'exécution est refusée.
Le combo sûr, de bout en bout
Section intitulée « Le combo sûr, de bout en bout »Le déroulé fiable, du paquet à l'enforcement, tient en peu d'étapes.
-
Installer sans activer.
Fenêtre de terminal sudo dnf install fapolicyd -
Reconstruire la base de confiance depuis la base RPM.
Fenêtre de terminal sudo fapolicyd-cli --update -
Ajouter vos binaires ELF hors RPM, s'il y en a (l'ajout notifie le démon, pas besoin de
--update).Fenêtre de terminal sudo fapolicyd-cli --file add /opt/pavois-hello -
Tester en permissive : mettre
permissive = 1dans/etc/fapolicyd/fapolicyd.conf, activer le service, puis observer.Fenêtre de terminal sudo systemctl enable --now fapolicydsudo tail -f /var/log/fapolicyd-access.log -
Basculer en enforcing une fois les faux refus corrigés :
permissive = 0, puis redémarrer le service.Fenêtre de terminal sudo systemctl restart fapolicyd
Dépannage
Section intitulée « Dépannage »Face à un blocage, ce tableau relie le symptôme à sa cause et à la correction.
| Symptôme | Cause probable | Correction |
|---|---|---|
| Un service échoue avec « Permission denied » | Souvent des permissions de fichiers ou un refus SELinux (AVC), parfois une base de confiance corrompue | Vérifier les modes et les AVC SELinux, puis seulement la base (rebuild, voir le piège) |
| Un binaire ELF maison est refusé | Absent de la base (installé hors RPM) | fapolicyd-cli --file add <chemin> (notifie le démon) |
| Refus après recompilation d'une appli | Empreinte SHA256 changée | fapolicyd-cli --file update puis --update |
| Les règles éditées n'ont aucun effet | rules.d/ non recompilé | fagenrules --load |
| Le démon ne démarre pas | Erreur de configuration | fapolicyd-cli --check-config |
| Incohérence base de confiance / disque | Fichiers modifiés hors trust | fapolicyd-cli --check-trustdb |
À retenir
Section intitulée « À retenir »-
fapolicyd contrôle ce qui a le droit de s'exécuter, en complément de SELinux (ce qu'un processus peut faire) et de firewalld (le réseau).
-
Tout repose sur la base de confiance : les fichiers RPM sont fiables par défaut,
fapolicyd-cli --updatela reconstruit. -
Toujours reconstruire la base avant d'enforcer, et tester en permissive : c'est la règle qui évite de briquer des services légitimes.
-
Les règles vivent dans
rules.d/, se compilent avecfagenrules --load, et l'ordre des fichiers décide de la prioritéallow/deny. -
Un binaire hors RPM doit être ajouté à la main (
fapolicyd-cli --file add) et réajouté après chaque recompilation. -
Les refus se diagnostiquent dans
/var/log/fapolicyd-access.log, corrélés au numéro de règle viafapolicyd-cli --list.