Thursday, July 15, 2010

Running Oracle Entitlements Server Java SM inside of JBOSS 5.1

First of all, in a shameless attempt to win an internal contest of which blog can register the most people for the Identity Management 11gR1 Launch, if you register from this link and send me your confirmation email, I will enter you in a drawing for a free copy of Professional Oracle Web Logic Server. Everyone who registers and sends me an email, will recieve a PDF version of this blog for the last year that I generated using Blog2Print.com - a $7.95 value. Sign up and learn about 11gR1, and help Chris, Brian, Alex and I out.

Now, back to business. This post is in response to customers' interest in the OES Spring integration post from a few weeks ago. In the spirit of full disclosure, at the time of the post, I hadn't wired the OES runtime into Spring and was only running Spring from a standalone JVM. Some customers had actually gotten ahead of me, and started trying to perform a similar integration using Spring, OES and JBOSS. I applaud your enthusiasm and thanks for being patient while I catch-up. I'm almost there, so I've decided to cover this topic - a full integration of OES/Spring running inside of JBOSS - in two separate posts. This post will cover the OES-JBOSS integration and a subsequent post will cover the details of pulling the entire solution together.

Overview


In setting off on the task of getting the Java SM to run inside of JBOSS, I decided to start with the most direct class loader approach - try to get everything in the system class path. Alex can attest to the pain that we encountered in getting the OES/OVD integration going - only to settle on adding everything to the system classpath. With that experience fresh in my mind, I started simply and added the jars from the Java SM into the JBOSS system classpath ( I'll explain the details of how to actually do this in a second ). After the normal "issues" with Log4J libraries, I got the server started. I installed a web-app with a JSP that invokes the JavaAPIExample that ships with the product, and got the Java SM running! I was very pleased with my self, until I tried to authenticate.

I tried both authentication and identity assertion with the Username identity asserter and in both cases, for whatever reason, instead of tyring to authenticate with the Authentication Providers configured inside of OES, it was trying the JAAS Login Modules associated with JBOSS. I could tell by looking at the stack trace. The exception was in coming from org.jboss.security.auth.spi.UsernamePasswordLoginModule. When I tried to authenticate originally, it complained that I missing a users.properties and roles.properties file - these are the files that this login module uses to identify users,password, and roles. How could this be happening?

JAAS Login Configuration


The java.security.auth.login.Configuration class controls the configuration of the JAAS Login modules inside a JVM. The default implementation simply reads the config the a file, but like a lot of things in Java security, you can change the default behavior, and this is exactly what JBOSS does. JBOSS uses its own XML format to define the JAAS Login Modules. By default, this information is stored in the JBOSS_HOME/server/servername/conf/login-config.xml and loaded at runtime into a custom implementation of the Configuration class. There is nothing sinister about this, in fact OES does a very similar thing. Instead of getting its configuration from a local file, it receives it from the SCM, and it two uses a custom Configuration class. Notice in the class definition that the setters and getters for the Configuration are static. This means there is 1 and only 1 defined for the entire JVM.

oes-jboss project


The good news is that JBOSS has a way to replace their implementation of the Configuration with a custom one, and this is what I did. I found a very good over-view of the JBOSS Security model and was able to get something going pretty quickly. Basically, all that my Configuration implementation does is first check what is defined in OES. If there is no configuration for the application, the I defer to JBOSS. This means that JBOSS is getting called for authentication and OES is getting called for the AuthenticationService. This is not a full JBOSS SM. This is just enough glue code to run the Java SM inside of JBOSS.

I created an oes-jboss project on samplecode.oracle.com. I've been starting to learn more about Maven and actually used it to build this project. The one "tricky" part is that there is no POM for OES, so I created one. I used an ant task to create a MANIFEST file that contained references to all of the OES jar files in the Class-Path. The POM then includes that MANIFEST in the jar file and then copies all of the libraries to the lib directory in the Maven repository (symbolic link would have worked too I suppose). All told, I think it works really nicely. These are the steps:

  • Check out the oes-jboss Subversion Repository
  • Download the Maven ANT task. Copy the jar file to MAVEN_HOME/lib.
  • Modify the oes-home,maven-home and maven-repo values build.xml for your environment
  • run ant - this should build the OES POM
  • mvn install - this should build the custom oes-jboss configuration. You should wind up with the file oes.jboss.auth.spi-0.0.1-SNAPSHOT.jar in the target directory.

If you don't want to build the jar, I've uploaded it here

Installing OES on JBOSS 5.1


These are basically the steps for getting the JavaAPIExample running from inside a JSP on JBOSS 5.1. Again, this is not a JBOSS SM. Authentication is being handled by JBOSS for all JBOSS resources. OES is only called for the Java API.

  • Create an instance of the Java SM on the same machine as JBOSS
  • Run the JavaAPIExample for that instance - this way you'll have sure that its actually working and that you won't be trying to debug two issues at once
  • Make a copy of the JAVA-SSM/instance/instance-name/bin/set-env.sh to set-env-jboss.sh
  • In the set-env-jboss.sh comment out the JAVA_HOME, the log4j properties, and the servlet and jasper jars

    # Comment this out
    #JAVA_HOME="/home/oracle/Oracle/Middleware/11gR1PS1/jrockit150_06/jre"
    #export JAVA_HOME

    BEA_HOME=/home/oracle/Oracle/Middleware/11gR1PS1
    export BEA_HOME

    INSTALL_HOME=/home/oracle/Oracle/Middleware/11gR1PS1/ales32-ssm/java-ssm
    export INSTALL_HOME

    ALES_SHARED_HOME=/home/oracle/Oracle/Middleware/11gR1PS1/ales32-shared
    export ALES_SHARED_HOME

    INSTANCE_HOME=/home/oracle/Oracle/Middleware/11gR1PS1/ales32-ssm/java-ssm/instance/jboss_inst
    export INSTANCE_HOME

    JAVA_OPTIONS="-Dwles.scm.port=7013 -Dwles.arme.port=18081"
    JAVA_OPTIONS="$JAVA_OPTIONS -Dwles.config.signer=oel55-64.localdomain"
    # Comment this out
    #JAVA_OPTIONS="$JAVA_OPTIONS -Dlog4j.configuration=file:$INSTANCE_HOME/config/log4j.properties -Dlog4j.ignoreTCL=true"
    JAVA_OPTIONS="$JAVA_OPTIONS -Dwles.ssl.passwordFile=$ALES_SHARED_HOME/keys/password.xml"
    JAVA_OPTIONS="$JAVA_OPTIONS -Dwles.ssl.passwordKeyFile=$ALES_SHARED_HOME/keys/password.key"
    JAVA_OPTIONS="$JAVA_OPTIONS -Dwles.ssl.identityKeyStore=$ALES_SHARED_HOME/keys/identity.jceks"
    JAVA_OPTIONS="$JAVA_OPTIONS -Dwles.ssl.identityKeyAlias=wles-ssm"
    JAVA_OPTIONS="$JAVA_OPTIONS -Dwles.ssl.identityKeyPasswordAlias=wles-ssm"
    JAVA_OPTIONS="$JAVA_OPTIONS -Dwles.ssl.trustedCAKeyStore=$ALES_SHARED_HOME/keys/trust.jks"
    JAVA_OPTIONS="$JAVA_OPTIONS -Dwles.ssl.trustedPeerKeyStore=$ALES_SHARED_HOME/keys/peer.jks"
    JAVA_OPTIONS="$JAVA_OPTIONS -Djava.io.tmpdir=$INSTANCE_HOME/work/jar_temp"
    JAVA_OPTIONS="$JAVA_OPTIONS -Darme.configuration=$INSTANCE_HOME/config/WLESarme.properties"
    JAVA_OPTIONS="$JAVA_OPTIONS -Dales.blm.home=$INSTANCE_HOME"
    JAVA_OPTIONS="$JAVA_OPTIONS -Dwles.scm.useSSL=true"
    export JAVA_OPTIONS

    # Set the OES classpath:
    CLASSPATH="$INSTALL_HOME/lib/api.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/css.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/asn1.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/saaj.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/framework.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/scmapi.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/log4j.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/jmx.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/connector.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/asi_classes.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/EccpressoCore.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/EccpressoJcae.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/jsafe.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/jsafeJCE.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/jsafeFIPS.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/jsafeJCEFIPS.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/sslplus.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/ssladapter.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/wlcipher.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/asitools.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/process.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/webservice.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/webserviceclient.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/org.mortbay.jetty.jar"
    # Comment these two out
    #CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/javax.servlet.jar"
    #CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/org.apache.jasper.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/sslserver.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/sslclient.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/pdsoap.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/antlr.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/ld-server-core.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/wlsdo.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/wlxbean.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/xbean.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/xqrl.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/ld-client.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/axis.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/commons-logging-1.0.4.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/commons-discovery-0.2.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/orawsdl14.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/jaxrpc.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/rmi-ssm.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/rmi-types.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/providers/ales/CR338979_414_jdk1.4.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/providers/ales/kodo-runtime.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/providers/ales/jdo.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/providers/ales/openjpa.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/providers/ales/commons-lang-2.1.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/providers/ales/jta-spec1_0_1.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/providers/ales/openjpa.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/providers/ales/commons-collections-3.2.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/providers/ales/commons-pool-1.3.jar"
    CLASSPATH="$CLASSPATH:$INSTALL_HOME/lib/providers/ales/serp.jar"
    CLASSPATH="$CLASSPATH:$INSTANCE_HOME/config"
    CLASSPATH="$CLASSPATH:$BEA_HOME"
    export CLASSPATH

  • Create a copy of the JBOSS_HOME/bin/run.conf called run_oes.conf. Modify it to call the set-env-jboss.sh and pass the JAVA_OPTS and CLASSPATH into JBOSS. Make sure to set the value of the -Dwles.realm to the name of the SM configuration. This is the name that appears in the OES Admin Console, not the name of the instance.

    . /home/oracle/Oracle/Middleware/11gR1PS1/ales32-ssm/java-ssm/instance/jboss_inst/bin/set-env-jboss.sh

    echo "$JAVA_OPTIONS"

    #
    # Specify options to pass to the Java VM.
    #
    if [ "x$JAVA_OPTS" = "x" ]; then
    JAVA_OPTS="-Xms128m -Xmx512m -XX:MaxPermSize=256m -Dorg.jboss.resolver.warning=true -Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000 $JAVA_OPTIONS -Dwles.realm=your_realm_name"
    fi

    JBOSS_CLASSPATH="$CLASSPATH"

  • Copy JBOSS_HOME/bin/run.sh to run_with_oes.sh

    #!/bin/sh
    ### ====================================================================== ###
    ## ##
    ## JBoss OES Bootstrap Script ##
    ## ##
    ### ====================================================================== ###

    export RUN_CONF=run_oes.conf

    ./run.sh

  • Modify the JBOSS_HOME/server/default/deploy/security/security-jboss-beans.xml - this is where we tell JBOSS to use our implementation of the Configuration by adding the OES Login Configuration MBean and configuring the SecurityConfig to use it

    <!-- Establish the basic XML Based Configuration-->
    <bean name="XMLLoginConfig" class="org.jboss.security.auth.login.XMLLoginConfig">
    <property name="configResource">login-config.xml</property>
    </bean>

    <bean name="OESLoginConfiguration" class="oes.jboss.auth.spi.LoginConfiguration">
    <property name="loginConfig"><inject bean="XMLLoginConfig"/></property>
    </bean>

    <bean name="SecurityConfig" class="org.jboss.security.plugins.SecurityConfig">
    <property name="mbeanServer"><inject bean="JMXKernel" property="mbeanServer"/></property>
    <!--
    <property name="defaultLoginConfig"><inject bean="XMLLoginConfig"/></property>
    -->
    <property name="loginConfig">jboss.security:service=OESLoginConfiguration</property>
    </bean>

  • Copy the oes.jboss.auth.spi-0.0.1-SNAPSHOT.jar to JBOSS_HOME/lib
  • Create a symbolic link from JBOSS_HOME/server/default/lib to JBOSS_HOME/lib - This causes the OES MBean to be loaded with all of the classes in the JBOSS_HOME/lib. I'm sure there are other ways to achieve the same thing by copying the oes.jboss.auth.spi-0.0.1-SNAPSHOT.jar to JBOSS_HOME/server/default/lib and then moving other jars from JBOSS_HOME/lib to there. If anyone works out the specifics, I'd love to hear them.
  • Copy exampleNames.xml from the JavaAPIExample/config to JBOSS_HOME/bin
  • Restart JBOSS - you should see the OES Runtime initializing.
  • Go a head and run the JavaAPIExample from inside a JSP - it should work!

Summary


In this instance, it wasn't classloading that was the issue, but rather the fact that both JBOSS and OES thought that they were controlling the list of JAAS Login Modules. With the oes.jboss.auth.spi-0.0.1-SNAPSHOT.jar and these instructions, it should be pretty straight forward for other people to get over this hump, and using the Java SM from inside JBOSS. My next post will expand on this example and show the OES Spring integration working.

Until then, don't forget to register for the Identity Management 11gR1 Launch.

4 comments:

  1. How can I send you the confirmation email? I'd like to get the PDF copy of this blog for last year... Thanks.

    ReplyDelete
  2. Vincent,

    Drop me a note at josh.bregman@oracle.com and I'd be happy to send you the PDF.

    JB

    ReplyDelete
  3. Apologies to Lily and Srikanth who had to battle through my 3 mistakes in this post. I've corrected them, but for the record here they are:

    1 - Removed the lib/oes.jboss.auth.spi-0.0.1-SNAPSHOT.jar from the set-env-jboss.sh
    2 - Updated the instructions to include creating a symbolic link from JBOSS_HOME/server/default/lib to JBOSS_HOME/lib
    3 - Updated the instructions to include the copying on exampleNames.xml to JBOSS_HOME/bin.

    Sorry for the confusion,

    JB

    ReplyDelete
  4. Hi Josh,

    We are trying to deploy an EAR which uses Hibernate. But we are seeing ClassNotFound Exception for HqlToken class. Though this class ispresent in Jboss_Home/common/lib..Any suggestions on this.?

    ReplyDelete

Note: Only a member of this blog may post a comment.