4

I'm trying to configure CAS (4.1) to work on a cluster envinronment inside amazon aws. I've configured Tomcat 7 for clustering, but on aws you can't use multicast autodiscovery, so i've set up database session replication on tomcat context. Session replication seems to be working good (other applications inside the same cluster uses it correctly):

<Context path="cas" crossContext="true">
        <Manager className="org.apache.catalina.session.PersistentManager" distributable="true"  processExpiresFrequency="3" maxIdleBackup="1" >
               <Store className="org.apache.catalina.session.JDBCStore"
               driverName="org.postgresql.Driver"
               connectionURL="jdbc:postgresql://*****:5432/****"
               connectionName="*****" connectionPassword="*****"
               sessionAppCol="app_name" sessionDataCol="session_data" sessionIdCol="session_id"
               sessionLastAccessedCol="last_access" sessionMaxInactiveCol="max_inactive"
               sessionTable="persistent_sessions" sessionValidCol="valid_session" />
       </Manager>
</Context>

Next i've configured jpaTicketRegistry and uniqueGenerators on cas configuration, like explained in cas configuration guide:

<bean id="cleanerLock"
    class="org.jasig.cas.ticket.registry.support.JpaLockingStrategy"
    p:uniqueId="${host.name}" p:applicationId="cas-ticket-registry-cleaner" />

<bean id="jobDetailTicketRegistryCleaner"
    class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"
    p:targetObject-ref="ticketRegistryCleaner" p:targetMethod="clean" />

<bean id="triggerJobDetailTicketRegistryCleaner"
    class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean"
    p:jobDetail-ref="jobDetailTicketRegistryCleaner" p:startDelay="20000"
    p:repeatInterval="5000000" />

and

<bean id="ticketGrantingTicketUniqueIdGenerator" class="org.jasig.cas.util.DefaultUniqueTicketIdGenerator"
        c:maxLength="50" c:suffix="${host.name}" />

    <bean id="serviceTicketUniqueIdGenerator" class="org.jasig.cas.util.DefaultUniqueTicketIdGenerator"
        c:maxLength="20" c:suffix="${host.name}" />

    <bean id="loginTicketUniqueIdGenerator" class="org.jasig.cas.util.DefaultUniqueTicketIdGenerator"
        c:maxLength="30" c:suffix="${host.name}" />

    <bean id="proxy20TicketUniqueIdGenerator" class="org.jasig.cas.util.DefaultUniqueTicketIdGenerator"
        c:maxLength="20" c:suffix="${host.name}" />

    <util:map id="uniqueIdGeneratorsMap">
        <entry
            key="org.jasig.cas.authentication.principal.SimpleWebApplicationServiceImpl"
            value-ref="serviceTicketUniqueIdGenerator" />
    </util:map>

and

<bean id="ticketGrantingTicketCookieGenerator" 
        class="org.jasig.cas.web.support.CookieRetrievingCookieGenerator"
        c:casCookieValueManager-ref="cookieValueManager"
        p:cookieSecure="true"
        p:cookieMaxAge="-1"
        p:cookieName="TGC"
        p:cookiePath="/cas" />

    <bean id="cookieCipherExecutor" class="org.jasig.cas.util.DefaultCipherExecutor"
        c:secretKeyEncryption="${tgc.encryption.key}"
        c:secretKeySigning="${tgc.signing.key}" />

    <bean id="cookieValueManager" class="org.jasig.cas.web.support.DefaultCasCookieValueManager"
          c:cipherExecutor-ref="cookieCipherExecutor" />

Now, application is starting up and is working correctly on single node, but when i start the second node, most of time login ticket is not being recognized, and this leads client applications to fail to login:

17:52:48,986 ERROR [http-bio-8443-exec-11][CASFilter:83] org.jasig.cas.client.validation.TicketValidationException: _            Ticket 'ST-1-uFUEA1PDhSv4GPQ61E1T-customers01.dwssystems.com' not recognized_     [Sanitized]
org.jasig.cas.client.validation.TicketValidationException: _            Ticket 'ST-1-uFUEA1PDhSv4GPQ61E1T-customers01.mycompany.com' not recognized_     [Sanitized]
    at org.jasig.cas.client.validation.Cas20ServiceTicketValidator.parseResponseFromServer(Cas20ServiceTicketValidator.java:73)
    at org.jasig.cas.client.validation.AbstractUrlBasedTicketValidator.validate(AbstractUrlBasedTicketValidator.java:188)
    at com.liferay.portal.servlet.filters.sso.cas.CASFilter.processFilter(CASFilter.java:194)
    at com.liferay.portal.kernel.servlet.BaseFilter.doFilter(BaseFilter.java:59)
    at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.processDoFilter(InvokerFilterChain.java:204)
    at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:109)
    at com.liferay.portal.kernel.servlet.BaseFilter.processFilter(BaseFilter.java:169)
    at com.liferay.portal.sharepoint.SharepointFilter.processFilter(SharepointFilter.java:88)
    at com.liferay.portal.kernel.servlet.BaseFilter.doFilter(BaseFilter.java:59)
    at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.processDoFilter(InvokerFilterChain.java:204)
    at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:109)
    at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.processDirectCallFilter(InvokerFilterChain.java:185)
    at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:96)
    at org.tuckey.web.filters.urlrewrite.UrlRewriteFilter.doFilter(UrlRewriteFilter.java:738)
    at com.liferay.portal.servlet.filters.urlrewrite.UrlRewriteFilter.processFilter(UrlRewriteFilter.java:57)
    at com.liferay.portal.kernel.servlet.BaseFilter.doFilter(BaseFilter.java:59)
    at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.processDoFilter(InvokerFilterChain.java:204)
    at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:109)
    at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.processDirectCallFilter(InvokerFilterChain.java:165)
    at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:96)
    at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.processDirectCallFilter(InvokerFilterChain.java:165)
    at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:96)
    at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.processDirectCallFilter(InvokerFilterChain.java:185)
    at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:96)
    at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilter.doFilter(InvokerFilter.java:119)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
    at org.apache.catalina.ha.session.JvmRouteBinderValve.invoke(JvmRouteBinderValve.java:219)
    at org.apache.catalina.ha.tcp.ReplicationValve.invoke(ReplicationValve.java:335)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1023)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

i'm using different hostnames for the two nodes, as described on cas reference. The ticket is registered inside the database table, but it seems the second node is unable to verify it.

I'm not sure if the problem is about session replication, lack of autodiscovery between nodes or some configuration.

Has QUIT--Anony-Mousse
  • 76,138
  • 12
  • 138
  • 194
  • It does not look like you actually configured the JPATicketRegistry. At least you did not show its config in your message. My guess your CAS Server is still using the default ticket registry. – John Gasper May 30 '16 at 20:23
  • the table with the tickets are being populated. Config files are all in place, how can i check if jpaTicketRegistry is being used? – Emanuele Righetto May 30 '16 at 21:07
  • Are they being added from both nodes or just one node? – John Gasper May 31 '16 at 03:49
  • the table ticketgrantingticket contains rows like: "TGT-20-XXX-customers01.company.com" "TGT-21-XXX-customers01.company.com" "TGT-39-XXX-customers02.company.com" so i think both nodes are adding tickets. NB: customers01 and customers02 are hostnames of the two nodes – Emanuele Righetto May 31 '16 at 15:37
  • :@EmanueleRighetto did you managed to fix ? – Jay May 10 '17 at 16:05
  • Yes, l'll post as a reply for better visibility – Emanuele Righetto May 12 '17 at 07:14

1 Answers1

0

I've managed to fix it, with the following modifications: - configured tomcat cluster with static membership (because i can't use multicast due to AWS limitations) - updated two beans configuration:

<bean id="warnCookieGenerator" class="org.jasig.cas.web.support.CookieRetrievingCookieGenerator"
          p:cookieDomain="mycompany.com" // ---->> added this
          p:cookieSecure="true"
          p:cookieMaxAge="-1"
          p:cookieName="CASPRIVACY"
          p:cookiePath="/cas"/>

<bean id="ticketGrantingTicketCookieGenerator" 
            class="org.jasig.cas.web.support.CookieRetrievingCookieGenerator"
            c:casCookieValueManager-ref="cookieValueManager"
            p:cookieDomain="mycompany.com" // --->> added this
            p:cookieSecure="true"
            p:cookieMaxAge="-1"
            p:cookieName="TGC"
            p:cookiePath="/cas" />