...
The configuration files that are enabled are specified in pentaho-solutions/system/pentaho-spring-beans.xml
.
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<beans> <!-- omitted --> <import resource="applicationContext-spring-security.xml" /> <import resource="applicationContext-common-authorization.xml" /> <import resource="applicationContext-spring-security-*.xml" /> <import resource="applicationContext-pentaho-security-*.xml" /> <!-- omitted --> </beans> |
...
But InMemoryDaoImpl
doesn't take a UserMapFactoryBean
! It takes a UserMap
! The secret to this working lies in the Spring type called FactoryBean
. When Spring detects a bean of this type, instead of returning the instance, it returns instance.getObject()
.
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<bean id="userDetailsService" class="org.springframework.security.userdetails.memory.InMemoryDaoImpl"> <property name="userMap"> <ref local="userMapFactoryBean" /> </property> </bean> <bean id="userMap" class="java.lang.String"> <constructor-arg type="java.lang.String"> <!-- case matters --> <value> <![CDATA[joe=password,ceo,Admin,User,Authenticated suzy=password,cto,is,User,Authenticated pat=password,dev,User,Authenticated tiffany=password,dev,devmgr,User,Authenticated]]> </value> </constructor-arg> </bean> <bean id="userMapFactoryBean" class="org.pentaho.platform.plugin.services.security.userrole.memory.UserMapFactoryBean"> <property name="userMap"> <ref local="userMap" /> </property> </bean> |
...
There's one more property to mention: allAuthorities
. This defines all authorities that are allowed to be granted to users. Why can't the platform get this information from the UserRoleListEnhancedUserMap
? That's because the UserRoleListEnhancedUserMap
might only contain a subset of all the available authorities.
Code Block | |||||||
---|---|---|---|---|---|---|---|
| |||||||
<bean id="userRoleListEnhancedUserMapFactoryBean" class="org.pentaho.platform.plugin.services.security.userrole.memory.UserRoleListEnhancedUserMapFactoryBean"> <property name="userMap" ref="userMap" /> </bean> <bean id="inMemoryUserRoleListService" class="org.pentaho.platform.plugin.services.security.userrole.memory.InMemoryUserRoleListService"> <property name="userRoleListEnhancedUserMap"> <ref local="userRoleListEnhancedUserMapFactoryBean" /> </property> <property name="userDetailsService" ref="userDetailsService" /> <property name="allAuthorities"> <list> <bean class="org.springframework.security.GrantedAuthorityImpl"> <constructor-arg value="Authenticated" /> </bean> <bean class="org.springframework.security.GrantedAuthorityImpl"> <constructor-arg value="Admin" /> </bean> <!-- some authorities omitted --> </list> </property> <property name="usernameComparator"> <bean class="org.pentaho.platform.engine.security.DefaultUsernameComparator" /> </property> <property name="grantedAuthorityComparator"> <bean class="org.pentaho.platform.engine.security.DefaultGrantedAuthorityComparator" /> </property> </bean> <bean id="pentahoUserRoleListService" class="org.pentaho.platform.engine.security.userrole.UserDetailsRoleListService"> <property name="userRoleListService"> <ref local="inMemoryUserRoleListService" /> </property> </bean> |
...
Note: Be sure to add
as username
andas authorities
where appropriate in your queries.
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<bean id="jdbcUserRoleListService" class="org.pentaho.platform.plugin.services.security.userrole.jdbc.JdbcUserRoleListService"> <constructor-arg index="0" ref="userDetailsService" /> <property name="allAuthoritiesQuery"> <value> <![CDATA[SELECT distinct(authority) as authority FROM AUTHORITIES ORDER BY authority]]> </value> </property> <property name="allUsernamesInRoleQuery"> <value> <![CDATA[SELECT distinct(username) as username FROM GRANTED_AUTHORITIES where authority = ? ORDER BY username]]> </value> </property> <property name="allUsernamesQuery"> <value> <![CDATA[SELECT distinct(username) as username FROM USERS ORDER BY username]]> </value> </property> <property name="dataSource" ref="dataSource" /> </bean> <bean id="pentahoUserRoleListService" class="org.pentaho.platform.engine.security.userrole.UserDetailsRoleListService"> <property name="userRoleListService"> <ref local="jdbcUserRoleListService" /> </property> </bean> |
...
And since DefaultLdapUserRoleListService
is configured via Spring, the task is reduced to defining three GenericLdapSearch
instances (plus an LdapUserDetailsService
) in Spring! But before the Spring config is presented, the equivalent configuration via Java code is presented. This route is chosen since Spring configuration can be very verbose and most are more familiar with the more ubiquitous Java syntax.
Code Block | |||||||
---|---|---|---|---|---|---|---|
| |||||||
// create params factory with the following settings: // search base="ou=users", // filterExpr="(objectClass=person)", LdapSearchParamsFactory paramsFactory = new LdapSearchParamsFactoryImpl( "ou=users", "(objectClass=Person)"); // create a resultsTransformer that extracts the uid attribute Transformer transformer = new SearchResultToAttrValueList("uid"); // create a GenericLdapSearch with objects created above; // (don't worry about getContextSource()--just know that // it returns an ContextSource) LdapSearch allUsernamesSearch = new GenericLdapSearch( getContextSource(), paramsFactory, transformer); |
Now the equivalent Spring config is presented.
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<bean id="allUsernamesSearch" class="org.pentaho.platform.plugin.services.security.userrole.ldap.search.GenericLdapSearch"> <constructor-arg index="0" ref="contextSource" /> <constructor-arg index="1"> <bean class="org.pentaho.platform.plugin.services.security.userrole.ldap.search.LdapSearchParamsFactoryImpl"> <constructor-arg index="0" value="ou=users" /> <constructor-arg index="1" value="objectClass=Person" /> </bean> </constructor-arg> <constructor-arg index="2"> <bean class="org.pentaho.platform.plugin.services.security.userrole.ldap.transform.SearchResultToAttrValueList"> <constructor-arg index="0" value="uid" /> </bean> </constructor-arg> </bean> |
...
The contents of application-pentaho-security-ldap.xml
is below. Notice that some of the bean references refer to beans defined in applicationContext-spring-security-ldap.xml
.
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<!-- be sure to escape ampersands --> <bean id="allUsernamesSearch" class="org.pentaho.platform.plugin.services.security.userrole.ldap.search.GenericLdapSearch"> <constructor-arg index="0" ref="contextSource" /> <constructor-arg index="1"> <bean class="org.pentaho.platform.plugin.services.security.userrole.ldap.search.LdapSearchParamsFactoryImpl"> <constructor-arg index="0" value="ou=users" /> <constructor-arg index="1" value="objectClass=Person" /> </bean> </constructor-arg> <constructor-arg index="2"> <bean class="org.pentaho.platform.plugin.services.security.userrole.ldap.transform.SearchResultToAttrValueList"> <constructor-arg index="0" value="uid" /> </bean> </constructor-arg> </bean> <!-- be sure to escape ampersands --> <bean id="allAuthoritiesSearch" class="org.pentaho.platform.plugin.services.security.userrole.ldap.search.GenericLdapSearch"> <constructor-arg index="0" ref="contextSource" /> <constructor-arg index="1"> <bean class="org.pentaho.platform.plugin.services.security.userrole.ldap.search.LdapSearchParamsFactoryImpl"> <constructor-arg index="0" value="ou=roles" /> <constructor-arg index="1" value="objectClass=organizationalRole" /> </bean> </constructor-arg> <constructor-arg index="2"> <bean class="org.apache.commons.collections.functors.ChainedTransformer"> <constructor-arg index="0"> <list> <bean class="org.pentaho.platform.plugin.services.security.userrole.ldap.transform.SearchResultToAttrValueList"> <constructor-arg index="0" value="cn" /> </bean> <bean class="org.pentaho.platform.plugin.services.security.userrole.ldap.transform.StringToGrantedAuthority"> <property name="rolePrefix" value="" /> <property name="convertToUpperCase" value="false" /> </bean> </list> </constructor-arg> </bean> </constructor-arg> </bean> <!-- not currently used --> <bean id="usernamesInRoleSearch" class="org.pentaho.platform.plugin.services.security.userrole.ldap.search.NoOpLdapSearch"> </bean> <bean id="ldapUserRoleListService" class="org.pentaho.platform.plugin.services.security.userrole.ldap.DefaultLdapUserRoleListService"> <constructor-arg index="0" ref="contextSource" /> <property name="allAuthoritiesSearch"> <ref local="allAuthoritiesSearch" /> </property> <property name="allUsernamesSearch"> <ref local="allUsernamesSearch" /> </property> <property name="userDetailsService"> <ref bean="userDetailsService" /> </property> <property name="usernamesInRoleSearch"> <ref local="usernamesInRoleSearch" /> </property> <property name="usernameComparator"> <bean class="org.pentaho.platform.engine.security.DefaultUsernameComparator" /> </property> <property name="grantedAuthorityComparator"> <bean class="org.pentaho.platform.engine.security.DefaultGrantedAuthorityComparator" /> </property> </bean> <bean id="pentahoUserRoleListService" class="org.pentaho.platform.engine.security.userrole.UserDetailsRoleListService"> <property name="userRoleListService"> <ref local="ldapUserRoleListService" /> </property> </bean> |
...