This is mostly a reference for myself but I though it might be useful for someone...
The idea is to use JBoss Portal's authentication and authorization to control access to Pentaho. We have a legacy project and I won't be migrating to GateIn soon, although I have Pentaho working in GateIn (if you're interested get in touch with me).
I'm using Pentaho 3.7 which uses Spring Security so it is really flexible and makes it easier to integrate with custom authentication/authorization solutions.
First, thanks to this post, we'll move the portal's application policy to the server's root so it applies to all our webapps:
server/default/conf/login-config.xml :
<application-policy name="portal">
<authentication>
<login-module code="org.jboss.portal.identity.auth.IdentityLoginModule" flag="required">
<module-option name="unauthenticatedIdentity">guest</module-option>
<module-option name="userModuleJNDIName">java:/portal/UserModule</module-option>
<module-option name="roleModuleJNDIName">java:/portal/RoleModule</module-option>
<module-option name="userProfileModuleJNDIName">java:/portal/UserProfileModule</module-option>
<module-option name="membershipModuleJNDIName">java:/portal/MembershipModule</module-option>
<module-option name="additionalRole">Authenticated</module-option>
<module-option name="password-stacking">useFirstPass</module-option>
</login-module>
<login-module code = "org.jboss.portal.identity.auth.DBIdentityLoginModule" flag="sufficient">
<module-option name="dsJndiName">java:/PortalDS</module-option>
<module-option name="principalsQuery">SELECT jbp_password FROM jbp_users WHERE jbp_uname=?</module-option>
<module-option name="rolesQuery">SELECT jbp_roles.jbp_name, 'Roles' FROM jbp_role_membership INNER JOIN jbp_roles ON jbp_role_membership.jbp_rid = jbp_roles.jbp_rid INNER JOIN jbp_users ON jbp_role_membership.jbp_uid = jbp_users.jbp_uid WHERE jbp_users.jbp_uname=?</module-option>
<module-option name="hashAlgorithm">MD5</module-option>
<module-option name="hashEncoding">HEX</module-option>
<module-option name="additionalRole">Authenticated</module-option>
</login-module>
</authentication>
</application-policy>
Now, enable SSO using Tomcat's Valve:
server/default/deploy/jboss-web.deployer/server.xml:
<valve className="org.apache.catalina.authenticator.SingleSignOn" />
Set the security domain in Pentaho to portal:
server/default/deploy/pentaho.war/WEB-INF/jboss-web.xml:
<security-domain>java:jaas/portal</security-domain>
Now, add the relevant security rolet to pentaho's webapp. This will be used by our preauth filter to get the roles of the Principal. We could probably create our own roles retriever but I'm just using a WebXmlMappableAttributesRetriever
server/default/deploy/pentaho.war/WEB-INF/web.xml:
<security-role>
<role-name>User</role-name>
</security-role>
<security-role>
<role-name>Admin</role-name>
</security-role>
<security-role>
<role-name>Authenticated</role-name>
</security-role>
Remove securityContextHolderAwareRequestFilter and add a j2eePreAuthFilter before authenticationProcessingFilter:
pentaho-solutions/system/applicationContext-spring-security.xml:
<bean id="j2eePreAuthFilter" class="org.springframework.security.ui.preauth.j2ee.J2eePreAuthenticatedProcessingFilter">
<property name="authenticationManager" ref="authenticationManager" />
<property name="authenticationDetailsSource" ref="authenticationDetailsSource" />
</bean>
<bean id="preAuthenticatedAuthenticationProvider" class="org.springframework.security.providers.preauth.PreAuthenticatedAuthenticationProvider">
<property name="preAuthenticatedUserDetailsService" ref="preAuthenticatedUserDetailsService" />
</bean>
<bean id="preAuthenticatedUserDetailsService" class="org.springframework.security.providers.preauth.PreAuthenticatedGrantedAuthoritiesUserDetailsService" />
<bean id="authenticationDetailsSource" class="org.springframework.security.ui.preauth.j2ee.J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource">
<property name="mappableRolesRetriever" ref="j2eeMappableRolesRetriever" />
<property name="userRoles2GrantedAuthoritiesMapper" ref="j2eeUserRoles2GrantedAuthoritiesMapper" />
</bean>
<bean id="j2eeUserRoles2GrantedAuthoritiesMapper" class="org.springframework.security.authoritymapping.SimpleAttributes2GrantedAuthoritiesMapper">
<property name="convertAttributeToUpperCase" value="false" />
<property name="attributePrefix" value="" />
</bean>
<bean id="j2eeMappableRolesRetriever" class="org.springframework.security.ui.preauth.j2ee.WebXmlMappableAttributesRetriever">
<property name="webXmlInputStream"><bean factory-bean="webXmlResource" factory-method="getInputStream" />
</property>
</bean>
<bean id="webXmlResource" class="org.springframework.web.context.support.ServletContextResource">
<constructor-arg ref="servletContext" />
<constructor-arg value="/WEB-INF/web.xml" />
</bean>
<bean id="servletContext" class="org.springframework.web.context.support.ServletContextFactoryBean" />
<bean id="authenticationManager" class="org.springframework.security.providers.ProviderManager">
<property name="providers">
<list>
<ref bean="preAuthenticatedAuthenticationProvider" />
<ref bean="daoAuthenticationProvider" />
<ref local="anonymousAuthenticationProvider" />
</list>
</property>
</bean>
And that should work, allowing any JBoss Portal User to get access to Pentaho. I'm using Form based authentication and have
<security-constraint>
<web-resource-collection>
<web-resource-name>Authenticated</web-resource-name>
<description></description>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>Authenticated</role-name>
</auth-constraint>
</security-constraint>
in my jboss/server/default/deploy/jboss-portal.sar/portal-server.war/WEB-INF/web.xml. So any user which is logged in gets the Authenticated role which, fortunatelly, maps nicely to the roles in Pentaho.
We can create new roles easy, just add the, to the security roles in pentaho's WEB-INF since the role mappes just goes through these and figures out if the user has that role.
JAAS
I will probably also try to get direct login to Pentaho working with JAAS so these are a couple of notes I've got on that:
Add a jaasAuthenticationProvider,,,
pentaho-solutions/system/applicationContext-spring-security.xml:
<bean id="authenticationManager" class="org.springframework.security.providers.ProviderManager">
<property name="providers">
<list>
<ref bean="preAuthenticatedAuthenticationProvider" />
<ref bean="jaasAuthenticationProvider" />
<ref bean="daoAuthenticationProvider" />
<ref local="anonymousAuthenticationProvider" />
</list>
</property>
</bean>
<bean id="jaasAuthenticationProvider" class="org.springframework.security.providers.jaas.JaasAuthenticationProvider">
<property name="loginConfig">
<value>auth.conf</value>
</property>
<property name="loginContextName">
<value>pentaho</value>
</property>
<property name="callbackHandlers">
<list>
<bean class="org.springframework.security.providers.jaas.JaasNameCallbackHandler" />
<bean class="org.springframework.security.providers.jaas.JaasPasswordCallbackHandler" />
</list>
</property>
<property name="authorityGranters">
<list>
<ref bean="jaasAuthorityGranter" />
</list>
</property>
</bean>
<bean id="jaasAuthorityGranter" class="pt.inevo.pentaho.jaas.JaasAuthorityGranter" />
When using JAAS we'll be performing the queries to java:/PortalDS and since we have different Hibernate versions we get into trouble. I haven't done much work regarding this issue but changing the libs in the JBoss server should work.
Also a couple of issues with the query AST might come up so use:
server/default/deploy/ejb3.deployer/META-INF/persistence.properties:
hibernate.bytecode.provider=cglib</code></p>