S’assurer que SELinux ne bloque pas un programme 7


Les distros Linux récentes viennent souvent avec des surcouches de protections type policykit, apparmor, SELinux, etc.

Tout ça est bien loin de la simplicité de la notion user/group et leurs permissions, et peut mener à un arrachage de cheveux en règle.

Cette après midi par exemple, on avait notre backend qui ne répondait pas sur le serveur tout neuf. On a changé toutes les permissions, passé de sock:// à http://, tweaké les fichiers de settings de iptables, varnish, nginx, gunicorn, supervisor, django… Puis en dernier recours, on a viré toutes les couches une par une, desinstaller les programmes, réinstaller à neuf, reset les fichiers de config en valeur par défaut, créé des fichiers de config minimaux pour toute la stack, nada. La journée frustrante et foutue en l’air.

On a quand même isolé le point de blocage sur varnish, et après avoir fait tous les tests possibles et des sacrifices humains, Max a eu l’intuition SELinux.

Voici maintenant ce qui se passe généralement dans cette situation.

Dans un élan de colère, l’utilisateur impatient fera un rapide test pour savoir si SELinux le protège comme les USA ont protégé les irakiens :

echo 0 >/selinux/enforce

Ça désactive tout le bouzin jusqu’au prochain reboot, mettre 1 inversant la tendance.

Lançant son programme et voyant que ça marche, notre dev échaudé se fend de l’équivalent du chmod 777 -R pour SELinux, à savoir éditer le fichier de config (/etc/sysconfig/selinux sur Centos) et changer rageusement SELINUX=enforcing pour SELINUX=disabled. Reboot and forget.

Une solution radicale et efficace, certes, mais qui laisse quand même un petit poids sur le conscience : diantre, il y a sûrement un moyen propre d’essuyer toute cette merde. Où sont les 3 coquillages ?

La solution est dans un petit programme appelé audit2allow, qui fait parti d’un package plus gros qu’il vous faudra trouver pour votre OS. Sous CentOs, puisque c’était notre config ce jour là, on a du faire un petit :

yum install policycoreutils-python

Ensuite, on lance notre audit :

audit2allow -a -w

Et après un peu de moulinage, il va vous sortir tout un listing de blocage, et quoi faire pour s’en sortir. Un petit grep votre_prog sur la sortie et vous obtenez ceci :

type=AVC msg=audit(1331500393.450:25): avc:  denied  { name_connect } for  pid=1276 comm="varnishd" dest=81 scontext=unconfined_u:system_r:varnishd_t:s0 tcontext=system_u:object_r:reserved_port_t:s0 tclass=tcp_socket
        Was caused by:
        One of the following booleans was set incorrectly.
        Description:
        Allow varnishd to connect to all ports, not just HTTP.

        Allow access by executing:
        # setsebool -P varnishd_connect_any 1
        Description:
        Allow system to run with NIS

        Allow access by executing:
        # setsebool -P allow_ypbind 1

Nous, c’était varnish qui était bloqué, comme le confirme le discret denied dans ce gros blog d’informations illisibles. A croire que les gars de SELinux ont tout fait pour créer la techno la moins user friendly possible. Je pense que la ligne ne commence pas par “AVC” pour rien, chaque fois que SELinux bloque un truc, un devops stagiaire meurt quelque part.

Il suffit ensuite de suivre docilement les instructions. Pour ce cas, on rentre avec les droits admin la commande :

setsebool -P varnishd_connect_any 1

Et on est bon.

Enfin, jusqu’à la prochaine après midi de debug incompréhensible qui vous fera revenir à SELinux. Max est beaucoup tenté par la solution 1 pour éviter une nouvelle galère.

7 thoughts on “S’assurer que SELinux ne bloque pas un programme

  • Salas

    Perso moi j’ai fait la solution 1, j’en ai même fait un template open vz et j’installe mes vm avec.

    Pas frapper.

  • Sam Post author

    Faudrait se faire un site de todo list genre camarchepas.com par theme :

    Mon process x ne marche pas :

    • redem le process;
    • tail le fichier de log;
    • check l’existance du fichier sock, pid, et conf;
    • checker le user et groupe du process;
    • checker le groupe et user des dits fichiers;
    • checker les permissions rw des dits fichiers pour les dits groupes;
    • checker les permissions x des dossiers parents des dits fichiers;
    • tenter de remplacer l’url sock par http;
    • tenter de désactiver iptables;
    • tenter de désactiver SELinux;
    • redem le serveur;

    Fichier statiques django django ne marchent pas :

    • tenter de faire un collectstatics;
    • checker les permissions du serveur et des fichiers;
    • checker la config nginx pour savoir si on passe par lui pour les fichier;

    Etc.

    Et à chaque fois, avec les paquets à installer, les commandes à lancer, les commandes à relancer pour inverser ce qu’on a fait (on veut pas laisser le serveur sans iptables :)), etc…

  • foxmask

    c’est LE truc le plus pénible sur Redhat/Centos – ca te bloque TOUT – HTTP, Oracle, les comm’ réseaux (genre ssh) , on croit que c’est le pare feu mais nan, c’est LA merde – c’est la premiere chose que je shoote quand j’ai une nouvelle VM sous les mains.

  • Sam Post author

    “Oubli du . final dans un enregistrement DNS, de fait le nom de la zone ou le $ORIGIN est concaténé à l’enregistrement.” Oh le piège à con.

  • Marc

    J’ai été emmerdé aussi par ça sur la VM du boulot qui héberge tous nos services Python, je l’ai également désactivé avec un gros poids sur la conscience, ça me rassure de voir que je ne suis pas le seul.

  • François

    L’idée de todo list est bonne, ca s’appellerait plutôt check list. Je peux te conseiller le livre the checklist manifesto. Ca se lit vite et c’est intéressant de voir l’usage dans d’autres corps de métier.

    Mon point de départ était ce billet : http://www.davidmanise.com/deux-checklists/

Leave a comment

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <pre> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Des questions Python sans rapport avec l'article ? Posez-les sur IndexError.