...
On peut espérer que le DefaultTicketRegistryCleaner appelle le ticketRegistry Redis pour supprimer les TGTs stockés dans ces clefs CAS_PRINCIPAL:uid ... mais force est de constater que ça ne semble pas être le cas sur notre installation.
Comme on avait pu le constater avec le JPA Ticket Registry (cf notre retour de 2019 à ce propos) le fonctionnement du Ticket Registry semble avoir été pensé pour déléguer les tâches d'expiration des données au système de stockage (registry) choisi.
Jusque-là le Redis Ticket Registry fonctionnait bien ainsi, mais l'apparition de ces entrées CAS_PRINCIPAL:uid (sorte de rustine ayant pour but de retrouver rapidement les tickets d'un utilisateur donné) vient casser ce système et il semble aventureux de fonctionner ainsi.
Notre CAS avec esup-otp utilisant dès à présent pour certaines données une base MongoDB, on s'est naturellement tourné vers le Ticket Registry sous MongoDB.
Passage au Ticket Registry MongoDB
Dans le build.gradle de l'overlay on remplace
Ce que l'on peut supposer ici, c'est que Redis supprime naturellement les entrées du type CAS_TICKET:TGT-numero en fonction du TTL positionné ; aussi lorsque le DefaultTicketRegistryCleaner passe, les tickets déjà supprimés par Redis lui-même ne sont pas listés/pris en compte et la procédure de CAS ne les supprime de fait pas des sets listés dans CAS_PRINCIPAL:uid ; on peut considérer naturellement que c'est un bug.
Notre CAS avec esup-otp utilisant dès à présent pour certaines données une base MongoDB, on s'est naturellement tourné vers le Ticket Registry sous MongoDB.
Passage au Ticket Registry MongoDB
Dans le build.gradle de l'overlay on remplace
| Bloc de code | ||
|---|---|---|
| ||
org.apereo.cas:cas-server-support-redis-ticket- | ||
| Bloc de code | ||
| ||
org.apereo.cas:cas-server-support-redis-ticket-registry |
par
| Bloc de code | ||
|---|---|---|
| ||
org.apereo.cas:cas-server-support-mongo-ticket-registry |
...
CAS positionne donc bien un expireAt (index TTL, lié à un expireAfterSeconds) propre à MongoDB dans les enregistrements, notamment les TGT (collection ticketGrantingTicketsCollection).
Notre installation/configuration faisait que ces TGT étaient, même sans le remember-me d'actif, de 14 jours.
On avait en effet positionné le cas.ticket.tgt.primary.max-time-to-live-in-seconds à 14 jours, pour correspondre à cas.ticket.tgt.remember-me.time-to-kill-in-seconds
Cette configuration est adéquate avec Redis ; après tests, on estime que ça ne l'est pas (au moins en 6.6.9) avec le ticket registry MongoDB
On a modifié cas.ticket.tgt.primary.max-time-to-live-in-seconds pour correspondre à 8H20
On a ainsi les configurations suivantes à ce sujet:
configuration autour des durées de vies des tickets est la suivante :
| Bloc de code | ||
|---|---|---|
| ||
# 15 jours au max -> mongodb supprimera lui-même les tickets au bout de 15 jours si nécessaire
| ||
| Bloc de code | ||
| ||
cas.ticket.tgt.primary.max-time-to-live-in-seconds=30000 cas.ticket.tgt.primary.time-to-kill-in-seconds=28800 1296000 # DefaultTicketRegistryCleaner supprimera les tickets non remember-me au bout de 8 heures cas.ticket.tgt.primary.time-to-kill-in-seconds=28800 cas.ticket.tgt.remember-me.enabled=true cas.ticket.tgt.remember-me.time-to-kill-in-seconds=1209600 |
Les expireAt (TTL) des TGT sont maintenant positionnés à 8H20 quand le RememberMe n'est pas actionné, et 14 jours sinon.
On graphe dès à présent quelques métriques mongo via munin et https://github.com/comerford/mongo-munin (dont on a converti les scripts en python3 via 2to3).
D'ici quelques jours, on espère pouvoir ajouter à cette page wiki des graphes montrant que tout va bien sur notre CAS avec le ticket registry sous mongo.
A l'usage, nous ne ressentons (pour l'instant) pas d'impact de performances par rapport au fonctionnement avec Redis.
cas.ticket.tgt.remember-me.enabled=true ### Valeur expiration tickets service/proxy : 10sec par défaut, on augmente car latence sur les sogo ...
cas.ticket.pt.timeToKillInSeconds=60
cas.ticket.st.timeToKillInSeconds=60
# rememberme
cas.ticket.tgt.rememberMe.enabled=true
# DefaultTicketRegistryCleaner supprimera les tickets non remember-me au bout de 14 jours
cas.ticket.tgt.remember-me.time-to-kill-in-seconds=1209600
# rememberme 2 semaines ok pour le cookie
tgc.remember.me.maxAge=1209600
cas.tgc.rememberMeMaxAge=1209600 |
Les expireAt des TGT sont positionnés à la date du jour + 8H quand le RememberMe n'est pas actionné, et 14 jours sinon.
Les expireAfterSeconds (TTL) sont positionnés à 14 jours.
Aussi, les tickets sont supprimés par CAS lui-même via DefaultTicketRegistryCleaner en fonction de ce expireAt.
Et "au pire", ils sont supprimés par le mécanisme interne de MongoDB via le expireAfterSeconds au bout de 14 jours.
Cf la documentation MongoDB à ce sujet.
On graphe dès à présent quelques métriques mongo via munin et https://github.com/comerford/mongo-munin (dont on a converti les scripts en python3 via 2to3).
D'ici quelques jours, on espère pouvoir ajouter à cette page wiki des graphes montrant que tout va bien sur notre CAS avec le ticket registry sous mongo.
A l'usage, nous ne ressentons (pour l'instant) pas d'impact de performances par rapport au fonctionnement avec Redis.
On note par contre que la demande de suppression des sessions CAS d'un utilisateur (cf le script en place et partagé sur ce même espace wiki) est maintenant très rapide (était très lent précédemment).
Cf le retour de Pascal concernant la consommation CPU de MongoDB via CAS, nous avons supprimé les index plein texts et avons ajouté un index simple sur le numéro de ticket de cette façon :
| Bloc de code | ||
|---|---|---|
| ||
db.proxyGrantingTicketsCollection.dropIndex('json_text_type_text_ticketId_text')
db.proxyTicketsCollection.dropIndex('json_text_type_text_ticketId_text')
db.serviceTicketsCollection.dropIndex('json_text_type_text_ticketId_text')
db.ticketGrantingTicketsCollection.dropIndex('json_text_type_text_ticketId_text')
db.proxyGrantingTicketsCollection.createIndex({ ticketId: 1 }, {name:'json_text_type_text_ticketId_text'})
db.proxyTicketsCollection.createIndex({ ticketId: 1 }, {name:'json_text_type_text_ticketId_text'})
db.serviceTicketsCollection.createIndex({ ticketId: 1 }, {name:'json_text_type_text_ticketId_text'})
db.ticketGrantingTicketsCollection.createIndex({ ticketId: 1 }, {name:'json_text_type_text_ticketId_text'}) |
Notez l'astuce de forcer le nom des nouveaux index simples par le nom des index plein texte créé normalement par CAS : ainsi au redémarrage de CAS, les index plein texte ne sont pas recréés.
La bonne solution serait évidemment que la correction soit apportée dans CAS directementOn note par contre que la demande de suppression des sessions CAS d'un utilisateur (cf le script en place et partagé sur ce même espace wiki) est maintenant très rapide (était très lent précédemment).