The Server Labs Blog Rotating Header Image

Dynamic LDAP-based authentication and authorization in Servicemix 3

Recently, we have been working quite extensively with Apache Servicemix, a JBI-compliant ESB.
One of areas we have been looking into is securing services in general and how to perform ldap-based authentication and authorization for those services in particular.

A good starting point to understand Servicemix (SMX) security features can be found here. I will give a brief overview of the security features of JBI and SMX .

JBI does not very concisely define authentication and authorization mechanisms, but it does define the following:

  • JBI relies on JAAS definitions for security features (i.e. security Subject).
  • The Binding Components (e.g. servicemix-cxfbc) are expected to transform protocol-specific (e.g. WS-Security) credentials into a normalized format, a security Subject, and inject them into the normalized message.
  • The ESB will then apply the authentication and authorization mechanism based on Subject information.

In particular for SMX we have:

  • For authentication it relies on JAAS, being able to use custom Login modules to integrate different technologies (e.g. LDAP) and implement specific authentication logic. The SMX configuration for JAAS is located under $SERVICEMIX_HOME/conf/login.properties.
    • SMX comes by default with a file based authentication mechanism, which is not suitable for use in many environments since it requires an SMX restart after any change.
  • For authorization, SMX does not use JAAS, due to the different nature of the items to be authorized (i.e. service endpoints instead of Java code). It defines an specific ACL AuthorizationMap, used by the NormalizedRouter (SecureBroker) to allow or deny the invocation. The configuration file for this is located in $SERVICEMIX_HOME/conf/security.xml
    • Also in this case, SMX comes by default with a file based ACL definition, included in the security.xml file. Any change in the ACLs requires an SMX restart.

So the idea behind this post is to provide a dynamic authentication/authorization mechanism in SMX that does not require an ESB restart after changes whilst also making use of LDAP.

In this post I will go through a complete example that requires the following:

  1. Apache ServiceMix 3.3.2.
  2. OpenDS 2.2 as a test LDAP Server. However you can use any other LDAP server you prefer.
  3. Maven 2.0.9 or higher to build the projects.

The complete source code of this post can be found here. It contains:

  1. A LDAP ldif file with the sample directory structure used.
  2. As a test service, a secured version of the SMX’s cxf-wsdl-first, now called cxf-wsdl-first-secure.
  3. A smx-ldap maven project with the classes we need to deploy in SMX in order to enable LDAP.
  4. A smxConfig directory with the required SMX configuration.

With that in mind, let’s go through the details:

Install Servicemix and OpenDS

You can skip the OpenDS section if you have your own LDAP server, just make sure the relevant LDAP configuration parameters are used in the coming sections.

  1. Download and install Servicemix. No additional modifications are required at this stage.
  2. Download and install OpenDS. If you want to use the sample LDAP ldif file, setup the directory server with the following configuration:
    • Select as “Directory Base DN”: dc=theserverlabs,dc=com.
    • Select import data from LDIF and choose the file included in the source package.
    • Complete installation.

The users and passwords defined in the sample ldif are:

  • reader:reader
  • smx:smx
  • testuser:testuser

Create a test service that requires authentication

To show the authentication and authorization of a service deployed in SMX I took the “cxf-wsdl-first” example that is included in the SMX distribution and enabled WS-Security authentication headers. The result project is included in the source files as “cxf-wsdl-first-secure”.

For that I just added the following interceptors configuration into the xbean.xml file of the CXFBC service unit “wsdl-first-cxfbc-secure-su”:



     
             
             
      




     
         
		
		
		
		
	
    

In this case as you see the required passwordCallbackClass just defines a DummyCallbackHandler (also included in the cxfbc su) that does nothing at all, delegating the whole authentication/authorization to SMX.
This is the simplest case and obviously you could have a class that performs additional checks or needs to deal with keystore passwords in case encryption is used. I will not get into the details here about WSS4J as this can be a subject worth a whole entry by itself.

Also, for a very good background reading of WS-Security and SMX check this blog post by Torsten Mielke.

To install the example project into SMX, just build the maven project and copy the service assembly to the hotdeploy directory of SMX:

cd Source/cxf-wsdl-first-secure/
mvn clean install
cp  wsdl-first-cxf-secure-sa/target/wsdl-first-cxf-secure-sa-3.3.2.zip $SERVICEMIX_HOME/hotdeploy
 

An example soap request with the WS-Security headers would be:



   
       
            
                   testuser
                   testuser
            
       
   
   
      
         world
      
   

 

Setup the required LDAP classes for JAAS and SMX AuthorizationMap

The required JAAS LDAP Login Module and the SMX AuthorizationMap contains many LDAP connectivity logic that are common and can be found in several open-source implementations.
I took as a reference the ActiveMQ classes and modify them to fit the SMX needs.

You can find the two classes in the smx-ldap maven project:

  • LdapLoginModule: This class implements the JAAS LoginModule interface and it is responsible to perform the authentication (login method) based on the passed credentials. It is also responsible to extract the user’s roles once it is authenticated and inject them into the Subject as additional principals. The provided class is basically the same implementation used for ActiveMQ, no changes are required.
  • LdapAuthorizationMap: This class implements the AuthorizationMap interface offered by SMX. The interface has just one method:
    Set getAcls(endpoint, operation)
    

    The class simply provides a set of Principals allowed to invoke the passed endpoint and operation. Also in this case, I took as a baseline the LdapAuthorizationMap include in ActiveMQ. We need to adapt it as ActiveMQ maps work on queues and topics, not endpoints.

Having reached this point I needed to define the level of granularity and also the format of the entries in LDAP defining the ACLs. I provide one implementation possibility here and it is definitely not perfect. Depending on your needs you can take this as a baseline an implement a more complex logic, add caching of endpoints ACLs, etc…

So this is the format I defined:

  • Endpoint ACLs are located under “ou=endpoints,ou=smx” in the LDAP tree.
  • The entries defining the ACLs will be “GroupOfUniqueNames”, having an entry per allowed group.
  • The “cn” of the ACLs has the form:
    cn=::
    

    In the defined schema you can also use wildcards on Service and Operation. Examples of ACLs definition for the cxf-wsdl-first-secure project would be:

    cn=http://servicemix.apache.org/samples/wsdl-first:*:*   
           Grant permissions to all services on that ns.    
    
    cn=http://servicemix.apache.org/samples/wsdl-first:PersonService:*   
           Grant permissions to all operations of PersonService.    
    
    cn=http://servicemix.apache.org/samples/wsdl-first:*:GetPerson   
           Grant permissions to GetPerson operations of all services in that ns.    
    

    Another example in case you use dynamic SMX ftp endpoints would be:

    cn=urn:servicemix:ftp:* 
           Grant permissions to all dynamic endpoints of the servicemix-ftp BC. 
    

This logic is implemented in the LdapAuthorizationMap class.

Both ActiveMQ classes are highly configurable using properties as we will see how to setup their usage in SMX.

To install the classes, build the maven project and copy the jar file to the lib directory of SMX:

cd Source/smx-ldap/
mvn clean install
cp  cp target/smx-ldap-1.0-SNAPSHOT.jar $SERVICEMIX_HOME/lib


 

Configure SMX

To make use of the LDAP authentication and authorization two SMX files need to be modified:

  • $SERVICEMIX_HOME/conf/login.properties: This is the JAAS authentication configuration and must define the LdapLoginModule. The parameters are for locally configured OpenDS LDAP, modify them with your configuration if required:
    servicemix-domain {
        com.tsl.jbi.smx.security.login.LDAPLoginModule REQUIRED
            debug=true
            initialContextFactory=com.sun.jndi.ldap.LdapCtxFactory
            connectionURL="ldap://localhost:389"
            connectionUsername="cn=reader,ou=people,dc=theserverlabs,dc=com"
            connectionPassword=reader
            connectionProtocol=s
            authentication=simple
            userBase="ou=people,dc=theserverlabs,dc=com"
            userRoleName=dummyUserRoleName
            userSearchMatching="(uid={0})"
            userSearchSubtree=false
            roleBase="ou=groups,dc=theserverlabs,dc=com"
            roleName=cn
            roleSearchMatching="(member={0})"
            roleSearchSubtree=true
            ;
    };
    
     

    You can see that there are two parameters, userSearchMatching and roleSearchMatching that allow us to define the user/roles search filter that fit our environment.

  • $SERVICEMIX_HOME/conf/security.xml. This file contains general SMX security configuration and here we will define the bean for the LdapAuthorizationMap:
      
      
      
      
      
     
      
      
        
        
        
        
        
        
        
        
      
     

    Also in this case, we have an endpointRoleFilterFormat that defines the ACL’s search filter. This can be modified to match whatever other LDAP directory setup you want to define for ACLs.

  • $SERVICEMIX_HOME/conf/servicemix.xml. We need to modify the authorizationMap used by the secured broker and point to the new ldap-based map.
        
          
    
           .....
        
    


Restart ServiceMix to apply the changes and you are ready to go!

Test the service and play around

You can test the configuration with SoapUI (example project included in sources) or make use of the client.html (thanks SMX guys for this!!!) included in the cxf-wsdl-first-secure project.

The simplest one is the client.html, just load it in your web browser and fire away.

Test Web Service Client

Test Web Service Client

The test should run successfully and return the Person information.

Now, it’s time to start playing around with the LDAP and see dynamic authentication/authorization:

  • For instance, you can change the ACL group in the endpoint LDAP to SMX-GROUP2 and see how you get a “Endpoint is not authorized for this user” exception.
  • Create a more fine grained endpoint ACL that only assigns SMX-GROUP1 to:
    cn="http://servicemix.apache.org/samples/wsdl-first:PersonService:GetPerson"
    
  • Change the password used for authentication of testuser in the SOAP request to get an LDAP login error.

Conclusions

Dynamic authentication/authorization configuration in an ESB with mechanisms like LDAP is mandatory in any real deployment scenario.

You have seen that adding LDAP-based authentication/authorization to SMX is not difficult but to have a robust model some implementation work is required. The implementation shown in this post can be taken as a good starting point but there are areas of improvement both in terms of performance (e.g. cache, etc…) and in the authorization model itself (e.g. precedence of ACLs, etc…).

Also, the SMX authentication/authorization mechanisms described are for version 3.x. They should be applicable also for SMX 4 with its new architecture based on OSGi, as the same type of NMR is sitting on top of the OSGi runtime.

Leave a Reply