Adding Extra Roles or Usernames to LDAP Searches

Suppose that you want to use the role Anonymous in ACLs. If you don't have that role defined in the LDAP directory, how do you get that role into the list of available roles? Use a StaticListLdapSearch! This class simply returns a list of objects--could be String instances, or GrantedAuthorityImpl instances, or anything. When used along with UnionizingLdapSearch, you can add arbitrary objects to the list of objects returned by a "real" LDAP search. Both StaticListLdapSearch and UnionizingLdapSearch are located in the org.pentaho.platform.plugin.services.security.userrole.ldap.search package.

Let's add the role Anonymous to the list of all authorities (aka roles). By default, the "all authorities search" is the bean with id allAuthoritiesSearch in applicationContext-pentaho-security-ldap.xml. We want to edit allAuthoritiesSearch by first wrapping the existing search into a UnionizingLdapSearch. This is shown below. Note how the id attribute has been moved from the GenericLdapSearch below to the UnionizingLdapSearch.

Wrapping the allAuthoritiesSearch bean with a UnionizingLdapSearch
<bean id="allAuthoritiesSearch" class="org.pentaho.platform.plugin.services.security.userrole.ldap.search.UnionizingLdapSearch">
  <property name="searches">
    <set>
      <bean class="org.pentaho.platform.plugin.services.security.userrole.ldap.search.GenericLdapSearch">
        <!-- omitted for brevity; notice that the id has been removed for this bean -->
      </bean>
    </set>
  </property>
</bean>

Now we have the ability to add other searches and UnionizingLdapSearch will automatically merge all the search results. Here's where StaticListLdapSearch comes in. We'll add that as the "other" search. As stated before, it simply returns the list that is set as its staticList property. Shown below is how a StaticListLdapSearch would be used alone.

Using the StaticListLdapSearch
<bean class="org.pentaho.platform.plugin.services.security.userrole.ldap.search.StaticListLdapSearch">
  <property name="staticList">
    <list>
      <!-- could be any bean or string value -->
      <bean class="org.springframework.security.GrantedAuthorityImpl">
        <constructor-arg value="Anonymous" />
      </bean>
    </list>
  </property>
</bean>

Finally, let's put it all together. Shown below is the complete solution.

applicationContext-pentaho-security-ldap.xml
<bean id="allAuthoritiesSearch" class="org.pentaho.platform.plugin.services.security.userrole.ldap.search.UnionizingLdapSearch">
  <property name="searches">
    <set>
      <bean 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>
      <bean class="org.pentaho.platform.plugin.services.security.userrole.ldap.search.StaticListLdapSearch">
        <property name="staticList">
          <list>
            <bean class="org.springframework.security.GrantedAuthorityImpl">
              <constructor-arg value="Anonymous" />
            </bean>
          </list>
        </property>
      </bean>
    </set>
  </property>
</bean>