Thursday, July 29, 2010

More on the Identity and Access Management 11g Launch

Hopefully you all enjoyed Amit’s IAM 11g launch webinar. We will be adding a ton of content about the new software in the weeks and months to come but I wanted to get started and post a little bit of follow-up on the launch.

There is an ongoing identity manager launch center here.

The documentation for all the new products/versions in the release can be found in the current version of the Fusion Middleware Documentation Library here. There are links from there to the older product versions if you have a need for the older doc.

The actual software can be downloaded here: http://www.oracle.com/technetwork/middleware/downloads/oid-11g-161194.html

Now to be honest, the package names and all the pre-requisite requirements are a little confusing so while we’ll hold off on doing install related blogs for another day, I want to clarify some things about the various packages and downloads that you see if you follow the link above.

The Oracle Identity and Access Management (11.1.1.3.0) is the new package containing the new 11g versions of OAM and OIM; along with OAAM, OPSS (platform security layer that most Fusion Middleware security is built on), and APM (a tool for managing OPSS authorization policies).

The pre-requisites for this package include the full 11g version of the Oracle Database, the repository creation utility for Fusion Middleware, WebLogic 11g, and (perhaps surprisingly to many people), SOA Suite 11g which is needed for OIM 11g. Most people installing this package will also want or need an LDAP directory which is a good lead in to discussing the other big IDM package called Oracle Identity Management (11.1.1.3.0).

Oracle Identity Management is the original set of Identity Management products included in the Fusion Middleware 11g release that took place a year ago. It includes OID, OVD, OIF, and Enterprise Manager.

This package also requires the database and WebLogic. Additionally, you have to install 11.1.1.2 before upgrading to 11.1.1.3.

Finally, don’t get confused: the product Oracle Identity Manager (OIM) is in the package Oracle Identity and Access Management and not Oracle Identity Management!

Friday, July 23, 2010

Oracle Entitlements Server and Spring Integration Running on JBOSS 5.1

This post is a continuation of the discussion of how to get the "hypothetical" OES+SPRING integration working on an actual platform - in this case JBOSS. This post assumes that you've already got the Java SM running inside of JBOSS 5.1. This post will focus on the technical details of the OES Spring integration and how to extend the JBOSS environment to run a sample application.

Identifying the User


In the "hypothetical" OES-Spring integrtaion post, I said that it was a fairly solved problem to figure out who the user is making the request, and this largely turned out to be true for the OES-Spring integration. I decied to make this part of the model "pluggable" and extended the AuthorizationAspect to use Spring to find an instance of the ISecurityContext interface. This is the ISecurityContext interface:

package com.oracle.oes.springaop.aspect.spi;

import com.bea.security.*;

public interface ISecurityContext {

public AuthenticIdentity getAuthenticIdentity() throws Exception;
public AuthorizationService getAuthorizationService() throws Exception;
public AuthenticationService getAuthenticationService() throws Exception;

}


It seemed logical to bundle the AuthenticIdentity and the Authorization/Authentication Services of the Java SM together. In theory, I guess you could have separarte provides of the AuthorizationService and AuthenticIdentity, but simpler is better.

Now when it came down to providing an implemenation for JBOSS, I tried the standarda Java Security - Subject.getSubject(AccessController.getAccessControllContext()) - but that didn't seem to work. Instead, the JACC Policy Context seemed to do the trick. The JBOSS Security FAQ reveals that you can use the key javax.security.auth.Subject.container to get the current subject. Very nice. Unfortunately, this subject is not acceptable by the default WLS.Subject identity asserter, so I needed a way to get an identity from the subject. Here, I went with my good friend the UsernameIdentityAsserter that ships with the product. I pull the name from the Subject and assert it. I think that a "better" implementation would be one that takes the Subject as the token. Under the covers it could still just assert the username, but it could also make use of the JBOSS roles that are included. This is a pretty simple excercise, but again for simplicity and time sake, I just went with the UsernameIdentityAsserter.

This covered the case where there actually was a user, but what about when the Spring Context is getting loaded by the container? This method returns null. I decided that the simplest thing to do was to configure the implementation of the JBOSS ISecurityContext with a username/password of a user and use that user. There are probably better implementations like - to not have the OES Authorization aspect make any calls when the container is initializing OR use something more like a run-as identity, but this was simple to do. I encourage people to try other alternatives.

Here's the relevant code:

public AuthenticIdentity getAuthenticIdentity() throws Exception {

Subject subject = (Subject)javax.security.jacc.PolicyContext.getContext("javax.security.auth.Subject.container");
System.out.println("Subject="+subject);


if (subject==null) {


System.out.println("I'll try to login with "+this.defaultUser+" "+this.defaultPassword);
AuthenticationHandler handler = new AuthenticationHandler(this.defaultUser,this.defaultPassword);

return this.getAuthenticationService().authenticate(handler);

}

//Just get the 1st principal's name

String name = ((Principal)subject.getPrincipals().iterator().next()).getName();

return this.getAuthenticationService().assertIdentity("USERID_TOKEN", name );

}

I pulled all of this together into a separate POM (oes.jboss.spring.securitycontext) that also includes the Spring configuration. The only thing interesting is that this is is where the username and password for the administration user are specified

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">

<bean name="securityContext" class="com.oracle.security.entitlements.jbosssecuritycontext.JBOSSSecurityContext">
<property name="defaultUser">
<value>admin</value>
</property>
<property name="defaultPassword">
<value>password</value>
</property>
</bean>

</beans>

Since we're using the OES API, this user is going to be authenticated by OES (not JBOSS).

Adding Spring AOP to JBOSS Web Application


I don't want to dwell on this too much, but in pulling this sample together, I did stumble in getting the LTW to work. With eough googling, you find that you need project Snowdrop. So, instead of using the default loadtime weaver, you use the one from Snowdrop

<context:load-time-weaver weaver-class="org.jboss.instrument.classloading.JBoss5LoadTimeWeaver"/>

Building the oes-spring project


I continue to be very impressed with Maven - (I know - what took me so long), but it really made putting this thing together incredible simple. You can build the project from the version-1.0 tag from the subversion repository. The project is a collection of the following modules:

  • oes_spring_aop - The core annotations and aspects of the Spring/OES/AOP integration
  • oes_spring_aop_test - A test application and "dummy" ISecurityContext that demonstrates the OES annotations
  • oes.jboss.spring.securitycontext - The ISecurityContext implementation for JBOSS
  • jboss-sample-web - A sample web-application that shows the oes_spring_aop_test application run inside of a web-application running on JBOSS

Configuring JBOSS for running jboss-sample-web


There is a little bit of set-up that is required in order to run the jboss-sample-webapplication.

  • Modify run_with_oes.conf - The JBOSS start script needs to be modified to include the -javaagent setting to enable the Spring LTW.

    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 -javaagent:/path to spring/spring-framework-2.5.6.SEC02/dist/weaving/spring-agent.jar $JAVA_OPTIONS"
    fi

    You can either reference the spring-agent.jar from the repository or download it from springsource
  • Modify the server/default/conf/login-config.xml - The JBOSS web-app is protected with JEE security. The application requires the user to be in the role oes_users role. You can do this by configuring JBOSS to use simple files to define users and their passwords, and users and their roles.

    <application-policy name="other">
    <!--
    A simple server login module, which can be used when the number
    of users is relatively small. It uses two properties files:
    users.properties, which holds users (key) and their password (value).
    roles.properties, which holds users (key) and a comma-separated list of
    their roles (value).
    The unauthenticatedIdentity property defines the name of the principal
    that will be used when a null username and password are presented as is
    the case for an unuathenticated web client or MDB. If you want to
    allow such users to be authenticated add the property, e.g.,
    unauthenticatedIdentity="nobody"
    -->
    <authentication>
    <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule"
    flag="optional">
    <module-option name="usersProperties">oes-users.properties</module-option>
    <module-option name="rolesProperties">oes-roles.properties</module-option>
    <module-option name="unauthenticatedIdentity">anonymous</module-option>
    </login-module>
    </authentication>
    </application-policy>

    Put the oes-users.properties and oes-roles.properties in the same directory as login-config.xml. For example:
    oes-users.properties
    josh=password
    oes-roles.properties
    josh=oes_user
  • Deploy the application - Start JBOSS and goto servername:8080/admin-console. Log in with username admin password admin. You can deploy the web-application by simply uploading the .war. Alternatively, if JBOSS is running on the same machine, simply copy the .war to server/default/deploy

Testing the application with OES


Here is the policyIX export for the sample application

<?xml version="1.0" encoding="UTF-8"?>
<xb:policy_propagation xmlns:xb="http://policypropagation.ales.com/xmlbean">
<xb:policy_propagation_data_v2>
<xb:scopes>
<xb:application_entry value="RootOrg!MyOrg!jboss" boundSSM="jboss">
<xb:application_attributes>
<xb:application_attribute_entry name="sys_obj_allow_virtual" ASIType="boolean">
<xb:single_value_entry value="true"/>
</xb:application_attribute_entry>
</xb:application_attributes>
<xb:admin_roles>
<xb:admin_role_entry value="AppAdmin" isPrimary="true" description="Primary Application Admin Role of current Application">
<xb:admin_role_privileges>
<xb:admin_role_privilege_entry object="action" action="adminmanage"/>
<xb:admin_role_privilege_entry object="authorizationPolicy" action="adminmanage"/>
<xb:admin_role_privilege_entry object="authorizationPolicyReport" action="adminmanage"/>
<xb:admin_role_privilege_entry object="directory" action="adminview"/>
<xb:admin_role_privilege_entry object="extension" action="adminmanage"/>
<xb:admin_role_privilege_entry object="group" action="adminview"/>
<xb:admin_role_privilege_entry object="policyDistribution" action="adminmanage"/>
<xb:admin_role_privilege_entry object="policySimulator" action="adminmanage"/>
<xb:admin_role_privilege_entry object="resource" action="adminmanage"/>
<xb:admin_role_privilege_entry object="role" action="adminmanage"/>
<xb:admin_role_privilege_entry object="rolePolicy" action="adminmanage"/>
<xb:admin_role_privilege_entry object="rolePolicyReport" action="adminmanage"/>
<xb:admin_role_privilege_entry object="user" action="adminview"/>
</xb:admin_role_privileges>
</xb:admin_role_entry>
</xb:admin_roles>
<xb:resources>
<xb:resource_entry value="//resources/Person" isVirtualResoureAllowed="true"/>
</xb:resources>
<xb:actions>
<xb:action_entry value="any"/>
<xb:action_entry value="readConfidential"/>
<xb:action_entry value="txfer"/>
</xb:actions>
<xb:dynamic_attributes>
<xb:dynamic_attribute_entry name="amount" type="integer"/>
</xb:dynamic_attributes>
<xb:roles>
<xb:role_entry value="Anonymous" parent=""/>
<xb:role_entry value="Everyone" parent=""/>
</xb:roles>
<xb:policies>
<xb:authorization_policy_entry>
<xb:policy_effect value="grant"/>
<xb:policy_actions>
<xb:policy_action_entry value="any"/>
</xb:policy_actions>
<xb:policy_resources>
<xb:policy_resource_entry value="//resources"/>
</xb:policy_resources>
<xb:policy_subjects>
<xb:policy_user_entry name="weblogic" directory="jboss_dir" scope="RootOrg!MyOrg"/>
</xb:policy_subjects>
</xb:authorization_policy_entry>
<xb:authorization_policy_entry>
<xb:policy_effect value="grant"/>
<xb:policy_actions>
<xb:policy_action_entry value="readConfidential"/>
</xb:policy_actions>
<xb:policy_resources>
<xb:policy_resource_entry value="//resources/Person"/>
</xb:policy_resources>
<xb:policy_subjects>
<xb:policy_user_entry name="josh" directory="jboss_dir" scope="RootOrg!MyOrg"/>
</xb:policy_subjects>
</xb:authorization_policy_entry>
<xb:authorization_policy_entry>
<xb:policy_effect value="grant"/>
<xb:policy_actions>
<xb:policy_action_entry value="any"/>
</xb:policy_actions>
<xb:policy_resources>
<xb:policy_resource_entry value="//resources"/>
</xb:policy_resources>
<xb:policy_subjects>
<xb:policy_user_entry name="admin" directory="AdminDir" scope="RootOrg"/>
</xb:policy_subjects>
</xb:authorization_policy_entry>
<xb:authorization_policy_entry>
<xb:policy_effect value="grant"/>
<xb:policy_actions>
<xb:policy_action_entry value="txfer"/>
</xb:policy_actions>
<xb:policy_resources>
<xb:policy_resource_entry value="//resources/Person"/>
</xb:policy_resources>
<xb:policy_subjects>
<xb:policy_user_entry name="josh" directory="jboss_dir" scope="RootOrg!MyOrg"/>
</xb:policy_subjects>
<xb:policy_constraint value="sys_defined ( amount ) and amount &lt; 75"/>
</xb:authorization_policy_entry>
</xb:policies>
</xb:application_entry>
</xb:scopes>
<xb:security_configuration_data>
<xb:scms>
<xb:scm_entry name="adminconfig">
<xb:ssms>
<xb:ssm_entry name="asiadmin"/>
<xb:ssm_entry name="jboss"/>
<xb:ssm_entry name="oes10gR3cp4wlsssm"/>
</xb:ssms>
</xb:scm_entry>
</xb:scms>
</xb:security_configuration_data>
</xb:policy_propagation_data_v2>
</xb:policy_propagation>


  • Load this policy into OES.
  • Test the application, by going to http://servername:8080/jboss-sample-web-1.0/OESTest.jsp
  • Login with the username and password you added to the oes_user.properties (josh/password)
  • You get access to the sample application

Summary


This is a working example of the runtime aspects of the OES Spring integration working in an actual environment. The code is now available at https://oes-spring.samplecode.oracle.com. I'm really happy (with the help of Maven) how easy is was to pull all of this together. The admin story, still needs some work. Even though the annotations are generating data in a flat file format that OES can understand, its not integrated into the build process. As you saw from the example, I had to give you the export of the policies I worked with....not part of the maven process. I'd be interested in getting people's feedback on this issue - how do think that OES policy should be tied into the overall lifecycle in a scenario like this? I'll share with you my thoughts shortly

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.

Tuesday, July 13, 2010

WLS Session Cookie Overriding in an OAM/SSO Enabled Environment

First I’d like to remind everybody about the Identity Management 11g launch that is coming up. You can register for it here.

With that out of the way, today I’d like to conclude my series of posts on user session management in OAM/SSO enabled environments by talking in detail about the issue of WLS session cookie overriding.

The Problem

To review, if OAM is protecting multiple containers or applications that by default issue session cookies with the same name then it is important to realize that as a user moves from one container/application to another that the session cookie of the 2nd container/application will blow away the session cookie from the first container/application.

An example of this is OAM protecting multiple WebLogic applications that are not sharing a session. The JSESSIONID cookie issued when a user accesses a second application will blow away the JSESSIONID from the first application.

Now, what you usually see in such a setup is that the user can go back and access the first application without having to login again. However, underneath the covers they will be issued a new session. So, upon returning to the first application, any data associated with their original session will be lost and the application flow may be disrupted or different from the expected behavior.

Solutions

As far as I know there are 3 possible solutions to this issue:

  1. Enable session sharing between your WLS applications.
  2. Configure distinct WLS session cookie names (instead of JSESSIONID) for each application so that they won’t override each other.
  3. Configure distinct cookie paths for each application (by default the JSESSIONID created by WLS has a path of “/”) so that they won’t override each other.
None of these solutions is perfect, so we’ll now go through and discuss the advantages, disadvantages, and limitations of all 3.

Session Sharing

By default, applications do not share the same WLS session. However, for applications deployed in the same EAR, it is pretty easy to set it up so that they do share the user session. The main limitation here is that the applications have to be deployed in the same EAR.

To enable session sharing between applications in an EAR, set the sharing-enabled attribute in the session descriptor to true in the weblogic-application.xml.

Changing the Session Cookie Name

Going the route of giving unique names to the session cookie for each application is a solid solution and realistic solution to the session cookie overriding problem. However, there are a few draw backs that I’ll get to.

First, let’s talk about how to change the WLS session cookie names. On the application side, you set the cookie-name deployment descriptor variable in the weblogic.xml. If you are fronting WebLogic with a real web server, you’ll need to configure the mod_wl connector “routing rules” with the appropriate cookie name to be used for each application. Specifically with regard to OHS/Apache and mod_wl_ohs, the appropriate directive is WLCookieName. The following is an example mod_wl_ohs configuration using this directive:

Sample mod_wl (httpd.conf/mod_wl.conf) configuration

#### /AppA

SetHandler weblogic-handler
WebLogicHost test_server1
WebLogicPort 7001
WLCookieName cookie1
DynamicServerList OFF
Debug ALL
WLLogFile logs/httpd_proxy1.log


#### /AppB

SetHandler weblogic-handler
WebLogicHost test_server2
WebLogicPort 7001
WLCookieName cookie2
DynamicServerList OFF
Debug ALL
WLLogFile logs/httpd_proxy1.log


#### /AppC

SetHandler weblogic-handler
WebLogicCluster machine_1:7001,machine_2:7001
WLCookieName cookie3
Debug ALL
WLLogFile logs/httpd_proxy1.log



As you can see this does complicate your mod_wl configuration some in that you have to isolate the context-root of every application that is to have a unique cookie. You’ll also have to then distribute updates to every http server in your deployment. One other issue you might encounter with this solution is that you might have infrastructure software like monitoring software that is hard coded or pre-configured to look specifically for JSESSIONID. If you change the name of the session cookie your monitoring may break. Finally, some black box commercial applications that run on WebLogic cannot be changed to use alternative cookie names.

Changing Session Cookie Paths

Setting the “cookie path” of the session cookie for each application to the context root of the application allows you to maintain separate WLS session cookies for each application without having the cookies for different applications overwriting each other.
To implement this you simply need to set the cookie-path deployment descriptor variable in the weblogic.xml. One advantage to this approach is there are no required configuration changes on the web server / mod_wl side of things.

On the downside, the problem of black box applications running on WLS is arguably worse with the unique path solution than with the unique name solution. Just like with the cookie name, some black box commercial application that run on WebLogic cannot be changed to use different cookie paths and most of these have hard coded cookie paths set to “/”. In such situations these black box applications will not only interfere with each other, but you also will get conflicts between the black box applications and your custom applications for which you are properly setting the paths to the context root. From my little bit of testing of browser behavior it seems that the more specific path always wins so it seems it is mainly an issue of the session cookies for the black box apps being overwritten by your applications session cookies. In any case, it is definitely something to be aware of.

Conclusion

WLS Session Cookie Overriding is a common problem in an OAM/SSO enabled environment. There are 3 possible solutions to the problem: session sharing, application unique session cookie names, and application unique cookie paths.

However, all 3 solutions have their limitations.

Monday, July 12, 2010

Get the Scoop on Oracle Identity Management 11g

Last year, the Fusion Middleware 11g release included some key Identity Management components: Oracle Internet Directory, Oracle Virtual Directory and Oracle Identity Federation.

As great as that was, Oracle is now launching the 11g versions of the rest of the Identity Management stack. If you want to get a jump on this pivotal release, come join the Identity Management 11g launch webinar.

The event will be led by Amit Jasuja, Vice President Identity Management and Security Products and will occur on:

Date: Wednesday, July 21, 2010
Time: 10:00 a.m. PT / 1:00 p.m. ET

You can and should register for the Oracle Identity Management 11g launch webinar here.

Friday, July 2, 2010

T3S -T3 over SSL

T3 is the protocol used for RMI communication with WebLogic server. T3S is the version of the protocol over SSL when secure communication is required.

I was going to write up a post about doing T3 over SSL as it seems to be something that people get hung up on.

However, Markus Eisele seems to have beaten me to it with an excellent and fairly comprehensive post.

I’d just like to add:

When you import the trusted CA into the default JVM cacert store make sure it is on the CLIENT JVM (and as the blog points out the correct JVM).

Also, rather than importing the trusted CA into the default JVM cacert store, you can create your own keystore and specify to the client SSL stack to use that store instead.

If you are using a standard J2SE stack for the client then you do this by starting the client with the following flags:

-Djavax.net.ssl.trustStore=**trustStore file path**
-Djavax.net.ssl.trustStorePassword=**trustStorePassword**


However, if you are using the WLS stack for the client you would do this with these flags:

-Dweblogic.security.TrustKeyStore=CustomTrust
-Dweblogic.security.CustomTrustKeyStoreFileName=**trust store file path**
-Dweblogic.security.CustomTrustKeyStorePassPhrase=**keystore pass phrase**