Configuring Luna HSM Software on AIX

Addendum: The Luna SA 4 series API separated the JCA and JCE into two separate jars. The Luna SA 5 API has combined all of the objects and methods into a single file, LunaProvider.jar.

We’re using a Luna HSM with Tomcat running on IBM AIX to sign PDFs in a web application. There were a few extra steps required to get the Luna software working with Java that the setup instructions did not mention, so I’m documenting them here.

The LunaSA software installed to /usr/lunasa. The Java Security Provider API for the Luna includes three files, which are found in /usr/lunasa/jsp/lib. They are libLunaAPI.so, the native (C++ I presume) library for accessing the Luna; and LunaJCASP.jar and LunaJCESP.jar, which are the security providers for Java.

First, we verified that we had a randomness generator configured in the right directory, as described by the Luna setup instructions. Then we installed the software. Next we configured a trust relationship between the Luna and our server by exchanging certificates, as per instructions.

The additional steps were setting some environment variables for the user account that Tomcat runs with:

JAVA_OPTS should include -Djava.library.path=/usr/lunasa/jsp/lib/. Putting the Luna library directory on java.library.path makes the native libLunaAPI.so library available to the Java Native Interface. If it is not there, any application trying to use the Luna API will throw an ”UnsatisfiedLinkException”.

LIBPATH should be set and should include /usr/lunasa/jsp/lib/. This is another way of getting the native Luna API library on java.library.path. It may not be necessary if the path is set in JAVA_OPTS.

CLASSPATH should be set and should include /usr/lunasa/jsp/lib/LunaJCASP.jar and /usr/lunasa/jsp/lib/LunaJCESP.jar. Contrary to our expectations, just having the jar files in the /lib folder of our war file didn’t seem to make the jar files available to our web app. Adding them to the Tomcat user’s classpath made everything work.

We are using the 64-bit Luna software with IBM Java 6, 64-bit.

Advertisements

#aix, #hsm, #java, #luna, #tomcat

Grails File-Serving Controller and Tomcat SSL Problem

I’ve been working on a Grails application to serve up PDFs and other files, and I’ve run into a documented issue involving Internet Explorer and Apache Tomcat with SSL. I’ll explain the solution I implemented.

First of all, here’s the code I was using to serve files from a Grails controller. The list action of the controller is pretty standard – it fetches a list of documents from the database, using some selection criteria, and then it displays the documents on list.gsp, with links to the show action that pass the document’s id as a parameter.


class BulletinsController {

def list = {
List bulletins = Bulletin.getBulletins()
[params:params, bulletins:bulletins]
}

def show = {

def bulletin = bulletinService.getBulletinById(Integer.parseInt(params.id))

String fullPath =
bulletin.rootPath + "/" +
bulletin.filename
File file = new File(fullPath)
byte[] content = file.readBytes()

OutputStream out = response.getOutputStream();

// Set headers
response.setContentType(bulletin.contentType)
response.setContentLength(content.size())
response.setHeader("Content-disposition", "attachment; filename=${bulletin.filename}")

// Write the file content
out.write(content)
out.close()
}

}

This code works as expected in Firefox 3. But on Internet Explorer 7, it resulted in an error message, and no file being received:

Internet Explorer cannot download %filename% from %hostname%.

Internet Explorer cannot download filename from hostname.

Internet Explorer was not able to open this Internet site. The requested site is either unavailable or cannot be found. Please try again later.

Researching this message turned up Microsoft KB article 323308, which explains that when Internet Explorer tries to open a file using a third-party application like Adobe Reader, it has to temporarily cache the file somewhere so that the other application can access it. If the remote web server serving the file has specified Cache-control=no-cache in the HTTP response header, IE will honor this directive and will not cache the file — which causes a problem, since the third-party application won’t have a file to read.

I also found numerous mentions of a somewhat unexpected behavior of Apache Tomcat: When you define a security constraint for a resource, making it CONFIDENTIAL, Tomcat not only encrypts the resource with SSL, it also automatically appends cache control headers for it.

I confirmed that this was happening with my application by uncommenting the RequestDumperValve line in my Tomcat conf/server.xml and restarting Tomcat.

<Valve className="org.apache.catalina.valves.RequestDumperValve"/>

The next time I tried to download a PDF, Tomcat recorded the response headers in catalina.log:

Apr 21, 2009 3:36:10 PM org.apache.catalina.valves.RequestDumperValve invoke
INFO: contentLength=196923
Apr 21, 2009 3:36:10 PM org.apache.catalina.valves.RequestDumperValve invoke
INFO: contentType=application/pdf
Apr 21, 2009 3:36:10 PM org.apache.catalina.valves.RequestDumperValve invoke
INFO: header=Pragma=No-cache
Apr 21, 2009 3:36:10 PM org.apache.catalina.valves.RequestDumperValve invoke
INFO: header=Cache-Control=no-cache
Apr 21, 2009 3:36:10 PM org.apache.catalina.valves.RequestDumperValve invoke
INFO: header=Expires=Wed, 31 Dec 1969 19:00:00 EST
Apr 21, 2009 3:36:10 PM org.apache.catalina.valves.RequestDumperValve invoke
INFO: header=Content-disposition=attachment; filename=CFG-09-2012.pdf

There are ways to disable this behavior in Tomcat’s config. However, I think that this is a desirable behavior most of the time, and I’m only modifying it at all because of Internet Explorer’s problem. So my solution is to simply override the headers that Tomcat appends by appending my own in this particular Grails controller action. Here’s the working version of the show action:


def show = {
def bulletin = bulletinService.getBulletinById(Integer.parseInt(params.id))

String fullPath =
bulletin.rootPath + "/" +
bulletin.filename
File file = new File(fullPath)
byte[] content = file.readBytes()

OutputStream out = response.getOutputStream();

// Set headers
response.setContentType(bulletin.contentType)
response.setContentLength(content.size())
response.setHeader("Content-disposition", "attachment; filename=${bulletin.filename}")

/* By default, Tomcat will set headers on any SSL content to deny
* caching. This will cause downloads to Internet Explorer to fail. So
* we override Tomcat's default behavior here. */
response.setHeader("Pragma", "")
response.setHeader("Cache-Control", "private")
Calendar cal = Calendar.getInstance()
cal.add(Calendar.MINUTE,5)
response.setDateHeader("Expires", cal.getTimeInMillis())

// Write the file content
out.write(content)
out.close()
}

Setting the Pragma header to an empty string takes care of user-agents implementing HTTP 1.0. Setting the Cache-control header to private does the same for HTTP 1.1. And setting the Expires header to a value five minutes in the future instead of in the past should take care of any user-agents that use the expiration as a cache-control convention.

#cache-control, #grails, #groovy, #internet-explorer, #ssl, #tomcat

Which environment is this?

Some context:  I’m working on a Grails web application that integrates with our internal business administration systems.  It runs on a Tomcat web server and it connects to a DB2 UDB database. 

Now, like any proper enterprise development effort, we’ve set up multiple environments to facilitate development and testing separately from our stable production systems.  In each environment, we’ve got a copy of the DB2 database, an instance of the business admin system’s executables, an instance of Tomcat running some build of our web app, and a copy of any other systems or objects that are part of the whole ecosystem. 

In addition, in some environments, we’ve actually got more than one instance of Tomcat.  In production, we run the web-facing applications on a separate instance from the the web applications used internally, for security.  And we’ve got an extra Tomcat instance exposed to the internet that runs against the user acceptance testing database, on which we can demo a beta of our web app for a select group of customers.

Problem:  So, given that we’ve got all of these different copies of our website, even if you know which URL and port you’ve navigated to, it can still be pretty easy to get confused about which system you’re interacting with at any given moment.  Except for the address, the screens look identical.  Imagine having one session open into the production system where you’re helping an end user and another one where you’re currently testing code.  And then you enter some test data into the production system by accident.  D’oh!

Before we even had the web app in production, users started requesting a visible indication on each page of the website showing which environment they were looking at.

Solution:  We really had two platforms that we needed to identify for users: which instance of the database they were connected to and which instance of Tomcat and build of the web application they were logged into.

On DB2 UDB, you can retrieve the database name using this statement: values current server.

So it was easy enough to code up a method in Groovy to fetch the db name:


static String getEnvironmentName() {
def sql = your connection string here
String env = new String()
try {
env = (String) sql.firstRow("values current server")[0]
} catch (SQLException e) {
// This is a db2 statement. May fail if run on other platforms.
env = null
}
return env
}

To identify the Tomcat instance, we had to be a bit more creative.  Most of our Tomcat instances run on the same host, and coding up some kind of matrix that would correlate a port number to an instance was something I had no inclination to have to maintain.  And there’s nothing that I know of built into Tomcat that applies a name to a server, other than a hostname.  Tomcat does, however, allow you to add your own environment variables in its conf/context.xml file.  So I decided upon a convention of adding an environment variable to each Tomcat instance specifying its name, and got our sysadmins to agree to it.


<Context>
...
<Environment name="appServerInstance" value="DEVELOPMENT" type="java.lang.String" over
ride="false"/>
...
</Context>

With an appServerInstance value assigned in each instance, we could use the following code to retrieve the instance name. At our sysadmin’s suggestion, we also decided not to assign a name to the production instance, and I wrote my code so that if no appServerInstance value is found, to show nothing on the web page. So, on every instance except the one our end users see, we’ve got an environment name at the top of the page. Our end users see nothing, since the system name wouldn’t be relevant to them anyway.


import javax.naming.InitialContext
import javax.naming.Context
import javax.naming.NameNotFoundException

...

static String getAppServerInstanceName() {
Context env = (Context) new InitialContext().lookup("java:comp/env")
String name = new String()
try {
name = (String) env.lookup("appServerInstance")
} catch (NameNotFoundException e) {
/* If the appServerInstance property has not been set in
Tomcat, then fail gracefully. */
name = null
}
return name
}

Now, to make the solution complete, I added some lazy initialization methods to our login controller that cache both names as session variables.


import javax.servlet.http.HttpSession
import org.springframework.web.context.request.RequestContextHolder

class SysUtil {

/**
* Retrieves the database environment name and caches the
* value on the session context.
*/
static String getEnvironmentName() {
String env = new String()
HttpSession session =
RequestContextHolder.currentRequestAttributes().getSession()
if (!session.environment) {
env = Sys.getEnvironmentName()
session.environment = env
} else {
env = session.environment
}
return env
}

/**
* Retrieves the app server instance name and caches the
* value on the session context.
*/
static String getAppServerInstanceName() {
String env = new String()
HttpSession session =
RequestContextHolder.currentRequestAttributes().getSession()
if (!session.appServer) {
env = Sys.appServerInstanceName()
session.appServer = env
} else {
env = session.appServer
}
return env
}

}

All that was left was to show the names somewhere in the main web page template. In a Grails application, that’s easily accomplished by editing grails-app/views/layouts/main.gsp. At a co-worker’s suggestion (thanks, Andy), I added the names to the page’s <title> tag, so that the environment name would show up in the taskbar button name of a minimized window. I also added it to a <div> at the top of the page:


<%@ page import="myPackage.SysUtil" />
...
<head>
<g:set var="environment" value="${SysUtil.getEnvironmentName()}" />
<g:set var="appServer" value="${SysUtil.getAppServerInstanceName()}" />
...
<title>
<g:if test="${appServer}">${appServer}: </g:if>
<g:layoutTitle default="Grails" />
</title>
...
</head>
<body>
<g:if test="${appServer}">
<div class="env">App Server: ${appServer} / Environment: ${environment}</div>
</g:if>
...
</body>

#best-practices, #db2, #grails, #groovy, #tomcat