MongoDBTicketRegistry : RegistryCleaner / InvalidTicketException

39 views
Skip to first unread message

Jérôme Rautureau

unread,
Feb 28, 2021, 12:33:07 PM2/28/21
to cas-...@apereo.org
Hi guys,

We have a very strange issue on your 6.2.8 CAS (tomcat cluster of 2 nodes) up-to-date with replicaSet (3 nodes) mongoDB installation.

We have some (a few) tickets without the 6 "normal" fields (only 3 fields : above an example on these "partial" tickets, i have anonymized the ticket). It's not causes any particular issue on clients except that the RegistryCleaner stops on first of these tickets with a "InvalidTicketException" (of course type field is null).

I have scheduled a task to delete periodically these tickets : 

db.getCollection('TicketGrantingTicketCollection').deleteMany({type:{$exists:false}})  => it gives me between 1 and up to 100 tickets deleted (We have 1000 TGT into our mongodb collection).

After some research, it seems that the "update" mongodb operation is the only case where we can have a partial insert of ticket. 

we use a lot a PGT/TGT/TGC/ST maybe a rare race condition causes this behavior. We don't know. 

{
    "_id" : ObjectId("60381e3bf03bee7c9f759a09"),
    "ticketId" : "TGT-130-rBbfvpvFeTWzleLKqDge-erk-yr0tzBltCuCp-eCxiHp-Yzz2hxSBeUtbuQSt0MuAJI-java-01-prd",
    "json" : "{\"@class\":\"org.apereo.cas.ticket.TicketGrantingTicketImpl\",\"@id\":1,\"id\":\"TGT-130-rBbfvpvFeTWzleLKqDge-erk-yr0tzBltCuCp-eCxiHp-Yzz2hxSBeUtbuQSt0MuAJI-java-01-prd\",\"authentication\":{\"@class\":\"org.apereo.cas.authentication.DefaultAuthentication\",\"authenticationDate\":1614283226.325062,\"principal\":{\"@class\":\"org.apereo.cas.authentication.principal.SimplePrincipal\",\"id\":\"XX.XXXXXXX\",\"attributes\":{\"@class\":\"java.util.TreeMap\",\"birthdate\":[\"java.util.ArrayList\",[[\"java.sql.Date\",-361328400000]]],\"birthname\":[\"java.util.ArrayList\",[\" XX.XXXXXX \"]],\"civility\":[\"java.util.ArrayList\",[\"Mme\"]],\"company\":[\"java.util.ArrayList\",[\"Ville de La Rochelle\"]],\"country\":[\"java.util.ArrayList\",[\"Charente-Maritime\"]],\"created_at\":[\"java.util.ArrayList\",[\"20210107134252Z\"]],\"department\":[\"java.util.ArrayList\",[\"Restauration\"]],\"description\":[\"java.util.ArrayList\",[\"RESSOURCES\"]],\"display_name\":[\"java.util.ArrayList\",[\" XX.XXXXXX \"]],\"dn\":[\"java.util.ArrayList\",[\" XX.XXXXXX  \"]],\"email\":[\"java.util.ArrayList\",[\" XX.XXXXXX  \"]],\"family_name\":[\"java.util.ArrayList\",[\" XX.XXXXXX \"]],\"full_name\":[\"java.util.ArrayList\",[\" XX.XXXXXX \"]],\"gender\":[\"java.util.ArrayList\",[\"F\"]],\"given_name\":[\"java.util.ArrayList\",[\"Catherine\"]],\"grh_chemin_service\":[\"java.util.ArrayList\",[\" / VILLE DE LA ROCHELLE / Direction générale des services / DGA Education, Culture, Sports, Affaires maritimes / Direction de l'Education / Education - Ressources\"]],\"grh_code_collectivite\":[\"java.util.ArrayList\",[\"VLR\"]],\"grh_echelon\":[\"java.util.ArrayList\",[\"9ème échelon\"]],\"grh_emploi\":[\"java.util.ArrayList\",[\"Chef.fe du service Ressources\"]],\"grh_filiere\":[\"java.util.ArrayList\",[\"Administrative\"]],\"grh_grade\":[\"java.util.ArrayList\",[\"Attaché principal\"]],\"grh_id_poste\":[\"java.util.ArrayList\",[8325]],\"grh_id_service\":[\"java.util.ArrayList\",[1049]],\"grh_id_service_parent\":[\"java.util.ArrayList\",[853]],\"grh_libelle_service\":[\"java.util.ArrayList\",[\"Education - Ressources\"]],\"grh_niveau_service\":[\"java.util.ArrayList\",[5]],\"grh_numero_poste\":[\"java.util.ArrayList\",[\" XX.XXXXXX \"]],\"grh_poste\":[\"java.util.ArrayList\",[\"Chef.fe du service Ressources\"]],\"grh_statut\":[\"java.util.ArrayList\",[\"Titulaire CNRACL\"]],\"grh_titulaire\":[\"java.util.ArrayList\",[false]],\"groups\":[\"java.util.ArrayList\",[\" XX.XXXXXX  \"]],\"street\":[\"java.util.ArrayList\",[\"Hôtel de ville\"]],\"title\":[\"java.util.ArrayList\",[\"Chef du service Ressources\"]],\"type\":[\"java.util.ArrayList\",[\"Agent\"]],\"uid\":[\"java.util.ArrayList\",[\" XX.XXXXXX  \"]],\"uniqueId\":[\"java.util.ArrayList\",[\" XX.XXXXXX  \"]],\"url\":[\"java.util.ArrayList\",[\" XX.XXXXXX  \"]]}},\"credentials\":[\"java.util.ArrayList\",[{\"@class\":\"org.apereo.cas.authentication.metadata.BasicCredentialMetaData\",\"id\":\"ca.chapon-phelut@VLR\",\"credentialClass\":\"org.apereo.cas.authentication.credential.RememberMeUsernamePasswordCredential\"}]],\"attributes\":{\"@class\":\"java.util.LinkedHashMap\",\"credentialType\":[\"java.util.ArrayList\",[\"RememberMeUsernamePasswordCredential\"]],\"samlAuthenticationtatementAuthMethod\":[\"java.util.ArrayList\",[\"urn:oasis:names:tc:SAML:1.0:am:unspecified\"]],\"authenticationDate\":[\"java.util.ArrayList\",[[\"java.lang.Long\",1614283226]]],\"credential\":[\"java.util.ArrayList\",[\"eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.ZXlKNmFYQWlPaUpFUlVZaUxDSmhiR2NpT2lKa2FYSWlMQ0psYm1NaU9pSkJNVEk0UTBKRExVaFRNalUySWl3aVkzUjVJam9pU2xkVUlpd2lkSGx3SWpvaVNsZFVJbjAuLjBPdFNjUzNfLXJ3TjR4dzZ5ZU9oMlEuVXkyZmtNTURQRnFZdVdPcXlGNWxsZy5GUGgXXXXXXXXXXXXXX\"]],\"authenticationMethod\":[\"java.util.ArrayList\",[\"LdapAuthenticationHandler\"]],\"successfulAuthenticationHandlers\":[\"java.util.ArrayList\",[\"LdapAuthenticationHandler\"]]},\"successes\":{\"@class\":\"java.util.LinkedHashMap\",\"LdapAuthenticationHandler\":{\"@class\":\"org.apereo.cas.authentication.DefaultAuthenticationHandlerExecutionResult\",\"handlerName\":\"LdapAuthenticationHandler\",\"credentialMetaData\":{\"@class\":\"org.apereo.cas.authentication.metadata.BasicCredentialMetaData\",\"id\":\"ca.chapon-phelut@vlr\",\"credentialClass\":\"org.apereo.cas.authentication.credential.RememberMeUsernamePasswordCredential\"},\"principal\":{\"@class\":\"org.apereo.cas.authentication.principal.SimplePrincipal\",\"id\":\"ca.chapon-phelut\",\"attributes\":{\"@class\":\"java.util.TreeMap\",\"dn\":[\"java.util.ArrayList\",[\" XX.XXXXXX  \"]],\"uid\":[\"java.util.ArrayList\",[\" XX.XXXXXX  \"]]}}}}},\"expirationPolicy\":{\"@class\":\"org.apereo.cas.ticket.expiration.SurrogateSessionExpirationPolicy\",\"name\":\"SurrogateSessionExpirationPolicy-b6ceeee6-9898-4d1d-b6d2-4b82142da6c0\",\"policies\":{\"@class\":\"java.util.LinkedHashMap\",\"SURROGATE\":{\"@class\":\"org.apereo.cas.ticket.expiration.HardTimeoutExpirationPolicy\",\"timeToLive\":1800,\"name\":\"HardTimeoutExpirationPolicy-ed16c749-d1d9-415d-9701-eaf74c0ff0fc\"},\"DEFAULT\":{\"@class\":\"org.apereo.cas.ticket.expiration.RememberMeDelegatingExpirationPolicy\",\"name\":\"RememberMeDelegatingExpirationPolicy-a21302f4-4bd1-4730-87b0-1075c5a4b12f\",\"policies\":{\"@class\":\"java.util.LinkedHashMap\",\"REMEMBER_ME\":{\"@class\":\"org.apereo.cas.ticket.expiration.HardTimeoutExpirationPolicy\",\"timeToLive\":1209600,\"name\":\"HardTimeoutExpirationPolicy-1f4e924e-28c4-40ab-8a2f-7030dda4015e\"},\"DEFAULT\":{\"@class\":\"org.apereo.cas.ticket.expiration.TicketGrantingTicketExpirationPolicy\",\"timeToLive\":28800,\"timeToIdle\":7200,\"name\":\"TicketGrantingTicketExpirationPolicy-c057b823-dc59-4487-9446-6367abc519df\"}}}}},\"lastTimeUsed\":1614283226.362107,\"previousTimeUsed\":1614283226.325708,\"creationTime\":1614283226.325708,\"countOfUses\":1,\"expired\":true,\"services\":{\"@class\":\"java.util.HashMap\",\"ST-602-vsTAvp1rNbgTzWtvbovA2EmwRvk-java-01-prd\":{\"@class\":\"org.apereo.cas.authentication.principal.SimpleWebApplicationServiceImpl\",\"id\":\"https://totem.larochelle.fr/c/portal/login?redirect=%2Faccueil\",\"originalUrl\":\"https://totem.larochelle.fr/c/portal/login?redirect=%2Faccueil\",\"principal\":\" XX.XXXXXX  \",\"source\":\"service\",\"loggedOutAlready\":false,\"format\":\"XML\"}},\"prefix\":\"TGT\"}"


--
Jérôme Rautureau

Jérôme Rautureau

unread,
Mar 6, 2021, 3:44:00 AM3/6/21
to cas-...@apereo.org
So i see this :


it seems the mongodb update operation has been changed...i can't see why...it was an upsert operation it became a updateFirst operation.
--
Jérôme Rautureau

Jérôme Rautureau

unread,
Mar 8, 2021, 9:43:08 AM3/8/21
to cas-...@apereo.org
ok. It was that.

I merged the MongoDbTicketRegistry.updateTicket() code based on 6.2 branch on my 6.2.x branch and no more partial tickets anymore.

I think this change on MongoDbTicketRegistry (updateFirst instead of upsert) should be back-ported on 6.2.x and 6.3.x branches.


it was :
          
            val update = Update.update(TicketHolder.FIELD_NAME_JSON, holder.getJson());
            this.mongoTemplate.upsert(query, update, collectionName);

this is indeed better :


            val update = Update.update(TicketHolder.FIELD_NAME_JSON, holder.getJson());
            val result = this.mongoTemplate.updateFirst(query, update, collectionName);
            log.debug("Updated ticket [{}] with result [{}]", ticket, result);
            return result.getMatchedCount() > 0 ? ticket : null;

 
--
Jérôme Rautureau
Reply all
Reply to author
Forward
0 new messages