Jasig

CASify PSI-Probe

PSI-Probe is an extended Tomcat manager.  This post outlines how to place it behind CAS and specify permissions based on an LDAP attribute.  The method outlined in this post has been adapted from documentation from Jasig on Tomcat Container Authentication, written by Marvin S. Addison.

Although the current stable build of PSI-Probe cannot be placed behind CAS (the role names are hard coded into the program), the current source code allows for flexible role names.

Check out the source code (SVN). The command can be found on psi-probe’s website.  A readme is included in the source, follow the instructions found there (an Oracle driver must be imported into Maven to properly build psi-probe).  The readme explains how to package the source into a .war which can then be deployed on the server.

The process of modifying the configuration files to support CAS authentication can either be done in the source code before building the .war or afterward on the server (by modifying the unpacked files).  My preference, for the sake of flexibility, is to put in a place holder for the attribute names (role names) before building the .war, then use a script to string replace the placeholder with the attribute name within the modified configuration files on the server.

Before modifying any configurations, you must obtain several .jar files and place them in your $TOMCAT_HOME/lib directory.

Found in CAS-Client under modules (can be downloaded from Jasig) :

  • cas-client-core-$VERSION.jar
  • cas-client-integration-tomcat-common-$VERSION.jar
  • cas-client-integration-tomcat-v6-$VERSION.jar
  • commons-logging-$VERSION.jar
  • xmlsec-$VERSION.jar
  • commons-codec-$VERSION.jar

Can be obtained from Apache and OpenSAML

  • log4j-$VERSION.jar
  • opensaml-1.1b.jar

The first file that must me modified is the context.xml.  It can be found at the following locations:

Source: $SOURCE_DIR/web/src/main/conf/META-INF/context.xml
Server: $TOMCAT_HOME/conf/Catalina/localhost/probe.xml

The file should read:

<?xml version="1.0" encoding="UTF-8"?>
<Context path="/probe" privileged="true" >
<!--
 The following configuration uses the SAML 1.1 protocol and role data
 provided by the assertion to enable dynamic server-driven role data.
 The attribute used for role data is "memberOf".
 -->
<Realm
 className="org.jasig.cas.client.tomcat.v6.AssertionCasRealm"
 roleAttributeName="memberOf"
 />
 <Valve
 className="org.jasig.cas.client.tomcat.v6.Saml11Authenticator"
 encoding="UTF-8"
 casServerLoginUrl="https://login.example.com/cas/login"
 casServerUrlPrefix="https://login.example.com/cas/"
 serverName="your.server.example.com"
 />
<!-- Single sign-out support -->
<Valve
 className="org.jasig.cas.client.tomcat.v6.SingleSignOutValve"
 artifactParameterName="SAMLart"
 />
 </Context>

The attribute does not have to be memberOf, any attribute name can be specified here.

Next the roles have to be specified in the application.  This is done in spring-probe-security.xml

Source: $SOURCE_DIR/web/src/main/webapp/WEB-INF/spring-probe-security.xml
Server: $TOMCAT_HOME/webapps/probe/WEB-INF/spring-probe-security.xml

The following section should be modified to read as outlined below.  ROLE_ must be followed by the name of the attribute or entitlement you set up to grants permission.

<sec:filter-invocation-definition-source>
     <sec:intercept-url pattern="/adm/**" access="ROLE_ATTRIBUTE"/>
     <sec:intercept-url pattern="/sql/**,/adm/restartvm.ajax" access="ROLE_ATTRIBUTE"/>
     <sec:intercept-url pattern="/app/**" access="ROLE_ATTRIBUTE"/>
     <sec:intercept-url pattern="/**" access="ROLE_ATTRIBUTE"/>
</sec:filter-invocation-definition-source>

Finally, the web.xml must be modified to properly filter access.

Source: $SOURCE_DIR/web/src/main/webapp/WEB-INF/web.xml
Server: $TOMCAT_HOME/webapps/probe/WEB-INF/web.xml
<context-param>
     <description>Role that can view session attribute values</description>
     <param-name>attribute.value.roles</param-name>
     <param-value>ROLE_ATTRIBUTE</param-value>
</context-param>
<auth-constraint>
     <role-name>$attribute_name</role-name>
</auth-constraint>
<security-role>
     <role-name>$attribute_name</role-name>
</security-role>

You will notice that there are several entries for ROLE and security-role within web.xml.  These provide levels of access, which can be specified (you will have to modify spring-probe-security.xml to reflect permission levels set in web.xml).  If you don’t deem them necessary, you can remove them completely from web.xml and simply leave a single entry (as shown above).

External Mapping of LDAP attributes in CAS

One of the features that is attractive about CAS is it’s ability to pass LDAP attributes to a specified application via SAML. This functionality is starting to become more heavily used by our web developers, creating demand for more and more attributes to mapped. An issue arose from this; CAS must be rebuilt every time a new attribute is to be mapped. The solution was to externalize the resultAttributeMapping property to a configuration file. This can be achieved through the use of the util schema.

Add the schema to deployerConfigContext.xml:

xmlns:util="http://www.springframework.org/schema/util"

Append the following to schemaLocation:

http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.0.xsd

The resultAttributeMapping property (in deployerConfigContext) will look like this:

<property name="resultAttributeMapping">
<util:properties id="attr" location="file:/etc/cas/ldap.attributes" />
</property>

Your attributes file cannot contain other property configurations, due to how the file is referenced.  It is a collection that follows the form: key=value, with each entry placed on its own line.  Here is an example ldap.attributes property file:

cn=cn
uid=ssoid
givenname=givenName
mail=email