Inserito da: pasquale rizzi | Luglio 31, 2008

Pentaho’s secrets:Enabling Single Sign On with CAS and JBoss Portal (last step)

Configuration of CAS Client in Acegi-based apps

The web application side of CAS is made easy due to Acegi
Security. It is assumed you already know the basics of using Acegi
Security, so these are not covered again below. Only the CAS-specific
beans are mentioned.

First of all modify Pentaho’s web.xml to link only one applicationContext file (I’ve called it spring-acegi.xml):

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring-acegi.xml
</param-value>
</context-param>

You will need to add a ServiceProperties bean
to your application context (spring-acegi.xml).

This represents your service:

<bean id=”serviceProperties” class=”org.acegisecurity.ui.cas.ServiceProperties”>

<property name=”service”>

<value>

https://localhost:8443/pentaho/j_acegi_cas_security_check

</value>

</property>

<property name=”sendRenew”><value>false</value></property>

</bean>

The service must equal a URL that will be monitored by the CasProcessingFilter. The
sendRenew defaults to false, but should be set to true if your application is particularly sensitive. What this parameter does is tell the CAS login service that a single sign on login is unacceptable. Instead, the user will need to re-enter their username and password in order to gain access to the service.

The following beans should be configured to commence the CAS authentication process:

<bean id=”casProcessingFilter” class=”org.acegisecurity.ui.cas.CasProcessingFilter”>

<property name=”authenticationManager”>

<ref bean=”authenticationManager”/>

</property>

<property name=”authenticationFailureUrl”>

<value>/casfailed.jsp</value>

</property>

<property name=”defaultTargetUrl”>

<value>/</value>

</property>

<property name=”filterProcessesUrl”>

<value>/j_acegi_cas_security_check</value>

</property>

</bean>

<bean id=”casProcessingFilterEntryPoint” class=”org.acegisecurity.ui.cas.CasProcessingFilterEntryPoint”>

<property name=”loginUrl”>

<value>https://localhost:8443/cas-server-webapp-3.2.1/login</value>

</property>

<property name=”serviceProperties”>

<ref bean=”serviceProperties”/>

</property>

</bean>

<bean id=”exceptionTranslationFilter” class=”org.acegisecurity.ui.ExceptionTranslationFilter”>

<property name=”authenticationEntryPoint”>

<ref local=”casProcessingFilterEntryPoint”/>

</property>

</bean>

You will also need to add the CasProcessingFilter to web.xml:

<filter>

<filter-name>Acegi CAS Processing Filter</filter-name>

<filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class>

<init-param>

<param-name>targetClass</param-name>

<param-value>org.acegisecurity.ui.cas.CasProcessingFilter</param-value>

</init-param>

</filter>

<filter-mapping>

<filter-name>Acegi CAS Processing Filter</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

The CasProcessingFilter has very similar properties to the AuthenticationProcessingFilter
(used for form-based logins). Each property is self-explanatory.

For CAS to operate, the ExceptionTranslationFilter must have its authenticationEntryPoint property set to the CasProcessingFilterEntryPoint bean.

The CasProcessingFilterEntryPoint must refer to the ServiceProperties bean (discussed above),
which provides the URL to the enterprise’s CAS login server. This is where the user’s browser will be redirected.

Next you need to add an AuthenticationManager that uses CasAuthenticationProvider and its
collaborators:

<bean id=”authenticationManager” class=”org.acegisecurity.providers.ProviderManager”>

<property name=”providers”>

<list>

<ref bean=”casAuthenticationProvider”/>

</list>

</property>

</bean>

<bean id=”casAuthenticationProvider” class=”org.acegisecurity.providers.cas.CasAuthenticationProvider”>

<property name=”casAuthoritiesPopulator”>

<ref bean=”casAuthoritiesPopulator”/>

</property>

<property name=”casProxyDecider”>

<ref bean=”casProxyDecider”/>

</property>

<property name=”ticketValidator”>

<ref bean=”casProxyTicketValidator”/>

</property>

<property name=”statelessTicketCache”>

<ref bean=”statelessTicketCache”/>

</property>

<property name=”key”>

<value>my_password_for_this_auth_provider_only</value>

</property>

</bean>

<bean id=”casProxyTicketValidator” class=”org.acegisecurity.providers.cas.ticketvalidator.CasProxyTicketValidator”>

<property name=”casValidate”>

<value>

https://localhost:8443/cas-server-webapp-3.2.1/proxyValidate

</value>

</property>

<property name=”proxyCallbackUrl”>

<value>

https://localhost:8443/pentaho/casProxy/receptor

</value>

</property>

<property name=”serviceProperties”>

<ref bean=”serviceProperties”/>

</property>

<property name=”trustStore”>

<value>$JAVA_HOME/jre/lib/security/cacerts</value>

</property>

</bean>

<bean id=”cacheManager” class=”org.springframework.cache.ehcache.EhCacheManagerFactoryBean”>

<property name=”configLocation”>

<value>classpath:/ehcache-failsafe.xml</value>

</property>

</bean>

<bean id=”ticketCacheBackend” class=”org.springframework.cache.ehcache.EhCacheFactoryBean”>

<property name=”cacheManager”>

<ref local=”cacheManager”/>

</property>

<property name=”cacheName”>

<value>ticketCache</value>

</property>

</bean>

<bean id=”statelessTicketCache” class=”org.acegisecurity.providers.cas.cache.EhCacheBasedTicketCache”>

<property name=”cache”>

<ref local=”ticketCacheBackend”/>

</property>

</bean>

<bean id=”casAuthoritiesPopulator” class=”org.acegisecurity.providers.cas.populator.DaoCasAuthoritiesPopulator”>

<property name=”userDetailsService”>

<ref bean=”userDetailsService”/>

</property>

</bean>

<bean id=”casProxyDecider” class=”org.acegisecurity.providers.cas.proxy.RejectProxyTickets”/>

Ageci is set up around the inMemoryDaoImpl, four users are defined Admin and User. This DAO is used
to get the credentials for the users who are authenticated by CAS, CAS can only check if a user is authenticated.
See the example below:

<bean id=”userDetailsService” class=”org.acegisecurity.userdetails.memory.InMemoryDaoImpl”>

<property name=”userMap”>

<value>

Admin=***,ROLE_ADMIN,ROLE_AUTHENTICATED

User=***,ROLE_AUTHENTICATED

</value>

</property>

</bean>

Or if you prefer:

<bean id=”userDetailsService”

class=”org.acegisecurity.userdetails.jdbc.JdbcDaoImpl”>

<property name=”dataSource”>

<ref local=”dataSource” />

</property>

<property name=”authoritiesByUsernameQuery”>

<value>

<![CDATA[SELECT username, authority FROM granted_authorities

WHERE username = ?]]>

</value>

</property>

<property name=”usersByUsernameQuery”>

<value>

<![CDATA[SELECT jbp_uname, jbp_password, enabled

FROM jbp_users WHERE jbp_uname = ?]]>

</value>

</property>

</bean>

Note the granted authorities, usually configured in acegi security, are ignored by CAS because
it has no way of communicating the granted authorities to calling applications.
CAS is only concerned with username and passwords (and the enabled/disabled status).
In this implementation of userDetailsService we use default ROLE_* name definition.
If you want to mantain (for easy understanding) roles coming from CAS credentials remember to
write “ROLE_” prefix before your desired Role, otherwise you’ll obtain an error response
(about UNKNOWN ROLE) while deploying pentaho.war.

Otherwise try to modify role_prefix property to anoter prefix…
see Spring acegi security documentation for this.

If you have to use proxyTickets:

Note the CasProxyTicketValidator has a remarked out trustStore property. This property might be helpful if you experience HTTPS certificate issues. Also note the proxyCallbackUrl is set so the service can receive a proxy-granting ticket. As mentioned above, this is optional and unnecessary if you do not require proxy-granting tickets. If you do use this feature, you will need to configure a suitable servlet to receive the proxy-granting tickets. We suggest you use CAS’ ProxyTicketReceptor by adding the following to yourweb application’s web.xml:

<servlet>

<servlet-name>casproxy</servlet-name>

<servlet-class>edu.yale.its.tp.cas.proxy.ProxyTicketReceptor</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>casproxy</servlet-name>

<url-pattern>/casProxy/*</url-pattern>

</servlet-mapping>

Finally for logout from Pentaho you need to add the following:

<bean id=”logoutFilter” class=”org.acegisecurity.ui.logout.LogoutFilter”>
<constructor-arg value=”https://administrator-desktop:8443/cas-server-webapp-3.2.1/logout”>
<constructor-arg>
<list>
<bean class=”com.pentaho.security.ProPentahoLogoutHandler”>
<bean class=”org.acegisecurity.ui.logout.SecurityContextLogoutHandler”>
</bean>
</bean>
<property name=”filterProcessesUrl” value=”/Logout”>
</property></list></constructor-arg></constructor-arg></bean>

and remember to add “logoutFilter” to filterChainProxy at the beginning of the configuration file.

This completes the configuration of CAS. If you haven’t made any mistakes, your web application should happily work within the framework of CAS single sign on. No other parts of Acegi Security need to be concerned about the fact CAS handled authentication.

A full example of applicationContext file is here.

Just adapt it to Pentaho’s and CAS configuration parameters.

This guide was written looking at:

If I made some mistakes please post here your suggestions…

Thanks a lot.


Risposte

  1. Alla fine l’hai spostato eh? brav brav

    come ti trovi con wordpress?

  2. benissimo…però mi sa che ho imparato una cosa…prima scrivo con word e poi lo importo con la funzione che ha il wysiwyg di wordpress, che è na figata…

  3. Now I am at the last step and stuck again.

    With pentaho.war deployed, I get the same problem as before. If I remove it, the portal + CAS works.
    The exception is:

    09:26:49,500 INFO [STDOUT] 2008-08-19 09:26:49,500 INFO [org.jasig.cas.CentralA
    uthenticationServiceImpl] –
    09:26:49,546 ERROR [STDERR] 2008/08/19 09:26:49:546 CEST [ERROR] CASReceipt – ed
    u.yale.its.tp.cas.client.CASAuthenticationException: Unable to validate ProxyTic
    ketValidator [[edu.yale.its.tp.cas.client.ProxyTicketValidator proxyList=[null]
    [edu.yale.its.tp.cas.client.ServiceTicketValidator casValidateUrl=[https://local
    host/cas/serviceValidate] ticket=[ST-3-tygpLb0vUtBIOdxC1eQuKiHQQD62N6R4QYK-20] s
    ervice=[https%3A%2F%2Flocalhost%3A443%2Fportal%2Fauthsec%2Fportal%2Fdefault%2Fde
    fault] renew=false]]]

    So it must be a problem with the pentaho.war.
    I have downloaded the spring-acegi.xml and adapted the port (I use 443).
    In the web.xml there is already a filter similar to what you add:

    Acegi Filter Chain Proxy
    org.acegisecurity.util.FilterToBeanProxy

    targetBean
    filterChainProxy

    Do you have to combine them? O remove this one? The filter class is the same.

    Before, I get also the error:

    09:25:39,750 ERROR [STDERR] 2008/08/19 09:25:39:750 CEST [ERROR] Logger – misc-org.pentaho.core.system.PentahoSystem: PentahoSystem.ERROR_0007 – userDetailsRoleListService property of PentahoSystem has not been set. Make sure that an instance of UserDetailsRoleListService is defined in a Spring XML file. Note that UserDetailsRoleListService will attach itself automatically to PentahoSystem. It simply needs to be defined in Spring.
    09:25:39,750 ERROR [STDERR] [es_68] Pentaho BI Platform server failed to properly initialize. The system will not be available for requests.

    That is a bean in WEB-INF/applicationContext-pentaho-security-memory.xml which is not defined in the spring-acegi.xml. Do you have to add it?
    I use Pentaho 1.7.0.

    Grazie mile

  4. Hi,
    for Acegi Filter Chain Proxy you have to add another filter entry to your web.xml:

    <filter>
    <filter-name>Acegi Filter Chain Proxy</filter-name>
    <filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class>
    <init-param>
    <param-name>targetBean</param-name>
    <param-value>filterChainProxy</param-value>
    </init-param>
    </filter>

    <filter-mapping>
    <filter-name>Acegi Filter Chain Proxy</filter-name>
    <url-pattern>/*</url-pattern>
    </filter-mapping>

    FOR SPRING.ACEGI.XML
    i don’t use userDetailsRoleListService.
    So if you can, remove its definition.
    If you have toubles post your spring.acegi.xml or better make it available on the web and post the link…

  5. If I don’t define userDetailsRoleListService in the spring xml file, I get the error above and Pentaho does not start. So I don’t understand how does it work for you without it. Which version of Pentaho do you use?
    I tried to add all bean dependencies for userDetailsRoleListService. Then the application starts, but I get still the original problem (Unable to validate ProxyTicketValidator).
    If you send me an email, I can send you the spring-acegi.xml file. (I put you also a message in Pentaho).

    Thanks

  6. Please post your spring.acegi.xml here.

    In your reply you can attach your spring.cegi.xml..

    and I’ll help you…

  7. you have to remove beans “pentahoUserRoleListService”, “inMemoryUserRoleListService” and all beans related to them…

    better from bean “pentahoUserRoleListService” to “</beans>” shift-ctrl-end then canc…this is the solution.
    I think that you have to read more about spring acegi security with cas integration and you’ll have serenity in mind…

  8. Well, that was my first trial.
    When I remove the pentaho beans stuff from spring-acegi.xml, I get again

    12:39:49,796 ERROR [Logger] misc-org.pentaho.core.system.PentahoSystem:
    PentahoSystem.ERROR_0007 - userDetailsRoleListService property of PentahoSystem has not
    been set. Make sure that an instance of UserDetailsRoleListService is defined in
    a Spring XML file. Note that UserDetailsRoleListService will attach itself automatically
    to PentahoSystem. It simply needs to be defined in Spring.
    12:39:49,796 ERROR [STDERR] [es_68] Pentaho BI Platform server failed to properly
    initialize. The system will not be available for requests.
    

    Have you tried with version 1.7.0? Maybe there is a change wrt older versions.

    And the CAS login does not work:

    12:53:36,375 ERROR [STDERR] 2008/08/20 12:53:36:375 CEST [ERROR] CASReceipt - ed
    u.yale.its.tp.cas.client.CASAuthenticationException: Unable to validate ProxyTic
    ketValidator [[edu.yale.its.tp.cas.client.ProxyTicketValidator proxyList=[null]
    [edu.yale.its.tp.cas.client.ServiceTicketValidator casValidateUrl=[https://local
    host/cas/serviceValidate] ticket=[ST-2-GrE4AtKz2lzsyp0iw6BLaKGa0K0EHzpOnJM-20] s
    ervice=[https%3A%2F%2Flocalhost%3A443%2Fportal%2Fauthsec%2Fportal%2Fdefault%2Fde
    fault] renew=false]]]
    

    Thanks

  9. Dove si possono trovare programmatori esperti della piattaforma Pentaho??

    • per programmatori cosa intendi?
      sviluppatori della piattaforma?o esperti nell’utilizzo della piattaforma e delle sue integrazioni?

  10. Grazie per gli articoli perchè mi sono stati di molto aiuto. Ti volevo chiedere se quanto descritto rimane valido anche nel caso in cui Pentaho sia su Tomcat 5.5 ?

    • ovviamente sì, devi solo documentarti su come integrare cas in tomcat ma è relativamente semplice. A riguardo c’è molta documentazione…

  11. Ok grazie, solo per riassumere:
    Il mio problema è integrare un portale definito in Jboss-portal-2-7.1 con pentaho installatato su Tomcat 5.5.

    (1) Integro CAS in jboss cosi come hai descritto nei tuoi articoli.
    (2) Integro CAS in tomcat.
    (3) Configuro Pentaho.

    Grazie ed un saluto

    • Attento però…se jboss-portal e pentaho girano su due application server differenti devi seguire altre strade.
      Il single sign-on generalmente lo si usa per poter condividere un unico accesso ad applicazioni diferenti residenti sullo stesso application server.
      Da quel che mi sembra di capire tu utilizzi due application servers diversi: uno per jboss-portal e uno per tomcat…quindi la strada da seguire è un’altra

  12. I’m getting into redirect loop problem… with following url: https://localhost:8443/cas-server-webapp-3.3.1/login?service=http%3A%2F%2Flocalhost%3A8080%2Fpentaho%2Fj_acegi_cas_security_check
    can someone help me?

    • Redirect Loop could have more causes:

      1) The user tries to access a service protected by a CAS client.
      2) The CAS client sees that the user does not have a local session
      and did not bring a ticket, so it redirects the user to the CAS
      server.
      3) The user logs in at the CAS server and establishes a session
      (i.e. TGT) with the CAS server.
      4) The CAS server redirects the user back to the original service.
      5) The service sees the ticket and tries to validate it, but cannot
      do so for any number of reasons. Such reason might be:
      a) The CAS client is misconfigured
      b) A firewall blocks connection between the client and server
      c) The server is malfunctioning
      d) The CAS server replies with a validation failure response
      6) Now, in this situation, the client should issue an error message
      to the user, but some client’s don’t. Instead, we get this:
      The CAS client redirects the user back to the CAS server.
      7) The CAS server sees that the users has already authenticated, so
      it creates a new service ticket and redirects the user back to
      the original service.

      Please Review your settings about cas and redirecting after login…

  13. Thanx for response…
    problem was, that I forget to put casProcessingFilter into filterChainProxy…

  14. I need to implement single sign out… can you help?

  15. Follow last lines of this guide…where it says:”Finally for logout from Pentaho you need to add the following:”


Lascia un commento

La tua risposta:

Categorie