La saison 2015 de GMT est terminée ! C’est donc l’occasion de centraliser ici tous les podcast des 15 émissions de l’année pour patienter avant la rentrée !
Mois : août 2016
Une alternative au CAS Jasig: CASIno
Après quelques années d’exploitation d’un CAS Jasig/Aperero, et lors de l’étude d’une nouvelle architecture d’authentification, j’ai remarqué que cette solution n’est pas idéale pour une autre raison qu’historique, ce pour les raisons suivantes:
- nécessité d’utiliser la solution lourde et ultra-propriétaire Java + Tomcat: ~ entre 2 et 3 go de ram nécessaire / machine,
- impossible à intégrer dans une solution de déploiement automatisé,
- aucune visibilité sur le code,
- configuration par XML, très complexe,
- aucune possibilité de personnalisation du code.
Mes critères de recherche d’une nouvelle application (dans l’ordre de priorité)
- Stabilité,
- Implémentation standard + Single Sign-out,
- HA + répartition de charge,
- Possibilité d’utiliser plusieurs contextes d’authentification,
- Performance,
- HTML 5 / Standards web,
- Facilité de déploiement / intégration,
- Ouverture du code.
Après quelques temps et peu de résultats, je suis tombé sur la solution CASino qui utilise du Ruby On Rails.
Reprenons maintenant chacun des critères.
Stabilité: Après lecture rapide du code, il est propre (« clean base » comme ils e précisent. Pas de plantage en backend observé en 3 mois d’utilisation, j’ai juste trouvé un problème très spécifique à la propagation de la connexion lorsqu’on a plusieurs pages de connexion ouvertes en même temps. Autrement dit RAS. 9/10
Standard CAS: Support (confirmé) de CAS 1.0 and CAS 2.0 as well as CAS 3.1 Single Sign Out. ». Le Single Sign-ut est directement opérationnel, sur le CAS Jasig, ce n’est clairement pas le cas. 10/10
HA + RR: Déportée au backend SQL (dans mon cas un cluster Maria DB). our l’application rails, elle est load-balancée n amont par un HAProxy qui fait également du SSL offloading. Tout étant en base, il n’y a pas besoin de faire du RR avec sticky cookie. Sur le CAS Jasig, chaque cas stockait ses sessions propres (leur synchronisation étaient du « plus ») 10/10 aussi.
Multi-contexte: Non prévu dans l’application. Il s’avère que c’est un cas d’utilisation bien plus spécifique que je le pensais. Difficile donc de mettre une note.
Performance: l’applicatif tourne sur une machine avec 500 mo de RAM / 1 vCPU. Pas de fuites mémoire. 10/10, je pense pas qu’on puisse faire mieux dans des langages interprétés.
HTML 5 / Standard web: L’application est responsive, mobile friendly est très agréable. Utilisation de templates ERB/SASS pour personnalisation. 9/10
Déploiement / Intégration: Pour les non connaisseurs de rails, la premier déploiement peut être (très) rebutant. Pour les « débutants », un projets rails fonctionnel (sans avoir à gérer les gems de RoR) est fourni. La documentation paraît complète, mais omet certaines commandes de bases de rails. Concrètement, j’ai pu faire de l’intégration/déploiement continue, avec des sources hébergés sur un dépôt Git avec une branche dédiée au processus. 7/10
Open Source: code sur Github, Licence MIT (on peut ~ tout faire). Que dire de plus ? Ah.. c’est un petit projet avec peu de suivi donc il faut savoir faire avec. Ce qui vaut un 7/10.
Les autres « plus »
- Possibilité d’utiliser l’authentification à deux facteurs (GAuthenticator)
- Possibilité de voir et déconnecter ses autres session
Modification apportées et fork.
Je vous présente ici les modification que j’ai apportées sur le code pour intégré ce CAS dans notre environnement.
- Pour des raisons de compatibilité, l’implémentation d’un contexte de connexion (dans mon cas l’établissement de l’utilisateur), chacun correspondant à un filtre particulier sur le LDAP. L’identifiant retourné par le CAS est donc également contextualisé en fonction du service. Le CAS ainsi modifié devient alors une fédération d’identité centralisée, au contraire d’une architecture shibboleth où chaque Identity Provider est idépendant.
- Pour simplifier les usages, j’ai implémenté un filtre de groupe ou de contexte par service. Certains services sont dédiés à un établissement spécifique (pas de préfixe, ex d’identifiant fourni: john.doe), d’autres sont dans le contexte « global », et sont préfixés par l’établissement. john.doe devient alors etab1.john.doe. Enfin un service peut-être accessible uniquement à un groupe d’utilisateur défini dans l’annuaire LDAP. Le changement notable est que ces vérifications sont faites côté serveur, qui délivre alors des Service Ticket de manière conditionnelle ! On peut donc filtrer très simplement sans avoir à modifier le client CAS parfois très trivial (le module apache notamment).
Ces modifications m’ont pris environ une semaine de travail, pour produire une solution native et propre (et testée). L’essentiel du temps passé a été d me familiarisé avec Ruby que je découvrais, et CASino. Au final, la modification porte sur moins de 100 lignes, le fork est très proche de l’original et je pourrai envisager de merger facilement les nouvelles versions.
Je souhaite publier le fork produit, mais il me faut encore éliminer le code spécifique à l’entreprise avant de le rendre public. N’hésitez pas à me contacter si vous souhaitez le tester dans votre environnement.
Exemple d’architecture
Cette infrastructure est totalement redondante. Aucun élément ne constitue un SPOF (Sigle Point Of Failure).
- Corosync/Pacemaker sur les deux load-balancers (lb1 & lb2) fournissent une IP Virtuelle (vIP) avec bascule automatique
- HAProxy sur les deux load-balancers répartit la charge et redirige le trafic lorsqu’un serveur CASino tombe (erreur réseau mais aussi au niveau applicatif – erreur 500). Il faut de même pour la partie SQL, il reçoit les demandes de connexion au « pool », qu’il équilibre sur les deux serveurs actifs (+ failover);
- Le cluster MariaDB est en mode multi-master, chaque serveur peut écrire des données, ce qui accélère les traitements, et améliore la HA. Le cluster fonctionne normalement lorsqu’un élément tombe grâce au quorum.
- Les serveurs CASino ne stockent pas de données, ils sont donc totalement interchangeables
- Les LDAP sont en mode master/slave². Deux peux tomber sans interrompre le serveur (car il n’y pas de données temps-réel). L’applicatif CAsino bascule sur le suivant lorsqu’un ne réponds plus.
Mais…
Chose non prévue avant la mise en production. Le cluster MariaDB rencontre des soucis de synchronisation qui provoque des « deadlock » et donc des erreurs 500 (< 1/200 logins). C’est dû au nombre très important de modifications par rapport au nombre de lectures.
Un cluster actif/actif n’est peut-être pas forcément adapté pour des sites qui ont beaucoup d’iops en écritures, mais aujourd’hui je n’ai pas trouvé de meilleure solution….
Références
- http://casino.rbcas.com/ site officiel
- https://github.com/rbCAS dépôt GitHub