Using LdapExtLoginModule with JaasSecurityDomain (securing passwords)

In my last post I wrote about how to connect a JBoss to LDAP defining an LdapExtLoginModule. Clearly, as suggested by the comment of Terry, the password in the xml is in plain text. In this post I’ll explain how to secure this password.

This is really easy to do as suggested in the JBoss docs, just add the following xml to the file $JBOSS_HOME/server/$PROFILE/conf/jboss-service.xml, which will add a JaasSecurityDomain bean to the jmx-console, which will be available for encrypting passwords in Base64:

  <mbean code="org.jboss.security.plugins.JaasSecurityDomain"
      name="jboss.security:service=JaasSecurityDomain,domain=jmx-console">
      <constructor>
         <arg type="java.lang.String" value="jmx-console"></arg>
      </constructor>
      <attribute name="KeyStorePass">some_password</attribute>
      <attribute name="Salt">abcdefgh</attribute>
      <attribute name="IterationCount">66</attribute>
   </mbean>

After this, start the JBoss server and navigate to the JMX Console (http://localhost:8080/jmx-console/ by default) and select the org.jboss.security.plugins.JaasSecurityDomain MBean.

On the org.jboss.security.plugins.JaasSecurityDomain page, look for the encode64(String password) method. Pass the plain text version of the password being used by the LdapExtLoginModule to this method, and invoke it. The return value will be the encrypted version of the password encoded as Base64.

After this, open login-config.xml, edit the LdapExtLoginModule created previously, replacing the password with the encrypted one and tell the module that the password is in encrypted form. The policy should look have the following lines (adding the jaasSecurityDomain option and editing the bindCredential):

   <module-option name="jaasSecurityDomain">jboss.security:service=JaasSecurityDomain,domain=jmx-console</module-option>
   <module-option name="bindCredential">6gf.s7eQiJi</module-option> <!-- LDAP password:  -->

Restart the server and that’s it!

As we see, in this case, the keystore password is still as plain text in the jboss-service.xml file, but this password can be stored in a secure location, for example, using a keystore, as suggested in: https://community.jboss.org/wiki/JBossAS7SecuringPasswords

Authenticate JBoss application using JAAS and LDAP

It is very easy to connect a JBoss to an LDAP server and creating Java EE applications that use the LDAP information for authorization and authentication. Following these simple steps you will be able to configure your JBoss and a web application (configuring an ejb deployment is similar, just read the Java EE API to map the attributes from web.xml to ejb annotations).

For this example I already have an Apache Directory Server running locally, with the sample LDIF with the sevenSeas company imported. You can find the file and tutorial in the Apache DS documentation.

There are two main steps to be able to use LDAP as an authentication mechanism:

  1. Configure JBoss to connect to LDAP server
  2. Configure the application to use the application policy

Configure JBoss to connect to LDAP server

The JBoss connects to the LDAP server using an application-policy, which is configured in %server_path%/conf/login-config.xml
Just add the following entry in the login-config.xml. You can see the description of the important attributes:

  <application-policy name="ApacheDS">
   <authentication>
   <login-module code="org.jboss.security.auth.spi.LdapExtLoginModule" flag="required" >
   <module-option name="java.naming.factory.initial">com.sun.jndi.ldap.LdapCtxFactory</module-option>
   <module-option name="java.naming.provider.url">ldap://localhost:10389</module-option> <!-- LDAP url-->
   <module-option name="java.naming.security.authentication">simple</module-option>
   <module-option name="bindDN">uid=admin,ou=system</module-option> <!-- LDAP user to connect -->
   <module-option name="bindCredential">secret</module-option> <!-- LDAP password -->
   <module-option name="baseCtxDN">ou=people,o=sevenSeas</module-option>
   <module-option name="baseFilter">(uid={0})</module-option>

   <module-option name="rolesCtxDN">ou=groups,o=sevenSeas</module-option> <!-- context where to search for groups -->
   <module-option name="roleFilter">(uniquemember={1})</module-option> <!-- filter, this searches for groups which have the user set in the attribute 'uniquemember' -->
   <module-option name="roleAttributeID">cn</module-option>
   <module-option name="searchScope">SUBTREE_SCOPE</module-option> <!-- Search for groups in all subtrees -->
   <module-option name="roleRecursion">0</module-option> <!-- how many levels to search recursively inside a group for a user  -->
   <module-option name="allowEmptyPasswords">true</module-option>
   </login-module>
   </authentication>
  </application-policy>

As you can see, the bindCredential is not encrypted. In order to do so, you can check out my post about securing the LdapExtLoginModule

Configure the web application to use the application policy

First, we need to connect the java web application to the application policy defined in JBoss. In order to do this, you need to create the file jboss-web.xml in the WEB-INF folder, the same folder where the web.xml resides.
Here is the content of the file (this works for JBoss 5 in a windows machine, you may need to change the header of the file):

<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE jboss-web
    PUBLIC "-//JBoss//DTD Web Application 2.3V2//EN"
    "http://www.jboss.org/j2ee/dtd/jboss-web_3_2.dtd">

<jboss-web>
  <security-domain>java:/jaas/ApacheDS</security-domain>
</jboss-web>

This will tell the container to use the ApacheDS application-policy we defined previously in JBoss.

After this, we only need to restrict the specific urls or servlets to certain roles. In this example, we will only allow access for users in the group “HMS Bounty”, otherwise a 403 (forbidden) will be issued.
In order to do this, we need to edit the web.xml file, adding the following configuration:

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.5"
 xmlns="http://java.sun.com/xml/ns/javaee"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
 <servlet>
  <servlet-name>AServlet</servlet-name>
  <servlet-class>com.app.AServlet</servlet-class>
 </servlet>
 <servlet-mapping>
  <servlet-name>AServlet</servlet-name>
  <url-pattern>/AServlet</url-pattern> 
 </servlet-mapping>
 
 <!-- ... more servlets and config ...-->
 
 <security-constraint>
  <display-name>All resources</display-name>
  <web-resource-collection>
   <web-resource-name>All resources</web-resource-name>
   <url-pattern>/*</url-pattern>
  </web-resource-collection>
  <auth-constraint>
   <role-name>HMS Bounty</role-name>
  </auth-constraint>
 </security-constraint>
 <login-config>
  <auth-method>BASIC</auth-method>
 </login-config>

</web-app>

Following this example, you can restrict access to different resources to other roles.

Configure an EJB based WS to use the application policy

If, in turn, you want to secure an EJB based WS, just adding these annotations at the start of the implementing class will do:

@org.jboss.wsf.spi.annotation.WebContext(contextRoot="MyCtxRoot" , authMethod = "BASIC", secureWSDLAccess = false)
@org.jboss.ejb3.annotation.SecurityDomain( "java:/jaas/ApacheDS" )
@RolesAllowed("HMS Bounty")
public class MyWSImplementation implements MyWSInterface{
...

Search LDAP from Java

This post explains how to connect to an LDAP server (in my case Apache DS) and retrieve elements which match a certain filter.

I have deployed an Apache Directory Server version 2.0 and imported the demo LDIF containing users and groups for the “sevenSeas” organization. You can download the file from the apache DS documentation.

This java code connects to the Apache DS deployed locally using the default port and user, and searches the context “ou=groups,o=sevenSeas” for groups the user “Fletcher Christian” belongs to.

import java.util.Properties;

import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.InitialLdapContext;

public class LdapSearch {
   public static void main(String[] args) throws NamingException {
      InitialLdapContext ctx = constructInitialLdapContext();
      // the name of the context to search
      String contextName = "ou=groups,o=sevenSeas";
      // Filter expression
      String filterExpr = "(uniquemember={0})"; // selects the groups a user belongs to.

      // Filter parameters (name of the user)
      String userDN = "cn=Fletcher Christian,ou=people,o=sevenSeas";
      Object[] filterArgs = { userDN };

      SearchControls constraints = new javax.naming.directory.SearchControls();
      constraints.setSearchScope(SearchControls.SUBTREE_SCOPE); // SUBTREE_SCOPE means recursive search

      NamingEnumeration<SearchResult> search = ctx.search(contextName,
            filterExpr, filterArgs, constraints);
      while (search.hasMoreElements()) {
         System.out.println(search.next().getName());
      }
   }

   private static InitialLdapContext constructInitialLdapContext()
         throws NamingException {
      Properties env = new Properties();
      env.put("java.naming.factory.initial",
            "com.sun.jndi.ldap.LdapCtxFactory");
      // LDAP url
      env.put("java.naming.provider.url", "ldap://localhost:10389");
      // ldap login
      env.put("java.naming.security.principal", "uid=admin,ou=system");
      env.put("java.naming.security.credentials", "secret");

      return new InitialLdapContext(env, null);
   }

}

With the demo LDIF imported in Apache DS the output will be:

cn=HMS Bounty,ou=crews

Lua real multithreading using Lanes and Linda

Introduction

In this post I’ll share my first impression and thoughts about developing mulithreaded applications in lua.
When developing in lua you may have realized that there is no such thing as multithreading, but there is a concept that is propposed as an alternative, called coroutines, which is useful for developing single-threaded applications and sharing the processor between several routines.
Coroutines may be the desired approach for several programs, but sometimes real multithreading is required, as in the case of 2 routines that must execute simultaneously and at a different frequency or when you need a thread to block waiting for user input while doing some background processing. There are lots of examples about this, but I think I made my point.
In my case I wanted to implement a keyboard controlled wheeled robot, so I needed 2 threads, one that would block waiting for user input (arrow keys), and another which would use the input values to control my robot.

Lanes

In order to develop the keyboard controlled robot I found a multithreading library for lua called Lua Lanes (you can find more information in the LuaLanes github project), which allows running multiple lua states in parallel.
Installing Lua Lanes is very easy, just run from the terminal:

luarocks install lanes

After installing I tried the lua scripts proposed as examples in the page, but for my surprise, they didn’t work!
I am using lua version 5.1 and Lua Lanes dated december 2010, and in my case, looking at examples and by trial and error I got to a very simple and working example, which runs 2 functions in parallel, here is the script:

–import extension and initialize
lanes = require "lanes".configure()

–thread 1 function
local function loop1( )
while true do
print("loop1")
os.execute("sleep 0.1")
end
end

–thread 2 function
function loop2()
while true do
print("loop2")
os.execute("sleep 0.1")
end
end

–create and start the threads, notice the ‘()’ to start the thread. you can parameters to the function.
thread1= lanes.gen("*",loop1)()
thread2= lanes.gen("*",loop2)()

This script works fine for me, it should work also for you. You could even define each loop in different lua files, decoupling the function from the threads script.

Linda

After successfully running lua lanes, the only thing left is to pass data from one lane (thread) to another. The api to do this is called Linda, which offers two ways of sending data between lanes:

  • Data queue, as a producer/consumer way (send/receive functions)
  • Single Data slot, which is overriden every time it’s written to (set/get functions)

There is some example using send and receive functions in the lanes documentation, and here is a working example using set and get.

lanes = require "lanes".configure()

local linda= lanes.linda()

local function loop( )
for i=1,10 do
print( "sending: "..i )
linda:set( "x", i )
end
print("end sender")
end

function receiver()
while true do
print("receiving")
local val= linda:get( "x" )
if val==nil then
print( "nil received" )
–break
else
print( "received: "..val )
break
end

end
print("end receiver")
end

a= lanes.gen("*",loop)()
b= lanes.gen("*",receiver)()

Conclusions and considerations

Lanes and Lindas are a nice alternative to multithreading in lua, since there are no built in functionality to do this.
It may be seem not trivial to configure it at the beginning, but once you have a working example it works fine.
Last but not least, it’s not trivial to find errors on a specific lane; in case one lane stops running due to a failed assertion or some other error, that lane won’t print an error to the console and will stop running. This can be avoided by not using assert, printing errors and exit the program in case an error is detected to signal other lanes to stop.