Friday, January 7, 2011

[WSS4J 1.6] Action/Processor loading change

Following on from yesterday's post about changes to crypto property files in WSS4J 1.6, this post details some changes that have been made to how Actions and Processors are loaded in WSS4J. These changes do not affect the end user per se, apart from the case of adding custom Actions or Processors, but are probably important enough to take note of.

In WSS4J 1.5.x, WSSConfig stores a <QName, String> map of default Processors. On processing a security header, it tries to match the QName of the child elements with the Map keys, and then uses the corresponding Map value to load the Processor class and then create a new instance of it.

The problem with this approach is that every time a message is received, each processor that is required gets class loaded again, which is highly inefficient. See this JIRA for more details. The same problem also exists for Action classes that are also loaded by WSSConfig.

The simple solution is to change the default Action/Processor maps in WSSConfig to store Class instances rather than Strings. Each time an Action/Processor object is required, it is simply created with <Class>.newInstance(). It is still possible to add custom Action/Processor objects to the custom Action/Processor maps. It is claimed in the JIRA above that:
The patch brings a massive performance enhancement, at least in the jetty-environment (I didn't test other application server) due to not looking up the classes on every invocation. The CPU-time of the wss4j library went from ~50% down to 2%.

Thursday, January 6, 2011

[WSS4J 1.6] Crypto property change

One of my goals for this blog is to document ongoing changes to the forthcoming WSS4J 1.6 release. This way I will be able to collate all of the entries into a single resource to put on the WSS4J website. I'm mainly going to focus on changes that affect the end-user, as the internal changes are too numerous to mention. Note that these blog posts are not intended to be definitive, as certain things may change before the release goes out.

This entry focuses on some changes to the Crypto property files.  These files are used to load keys and certificates for various WS-Security operations, and are loaded by the CryptoFactory class. CryptoFactory parses a single property in the file:
  • org.apache.ws.security.crypto.provider - WSS4J specific provider used to create Crypto instances (default value is "org.apache.ws.security.components.crypto.Merlin").
WSS4J 1.6 will only ship with this provider, WSS4J 1.5.x ships with a (largely redundant) BouncyCastle provider as well. The rest of the crypto property file is parsed by AbstractCrypto. The old configuration tags that were available in WSS4J 1.5.x are:
  • org.apache.ws.security.crypto.merlin.file - location of keystore
  • org.apache.ws.security.crypto.merlin.keystore.provider - provider of keystore
  • org.apache.ws.security.crypto.merlin.keystore.password - password used to load keystore
  • org.apache.ws.security.crypto.merlin.keystore.type - type of keystore (defaults to java.security.KeyStore.getDefaultType())
  • org.apache.ws.security.crypto.merlin.load.cacerts - whether to load the CA certs in ${java.home}/lib/security/cacerts or not (default is true)
  • org.apache.ws.security.crypto.merlin.cacerts.password - the password to use to load the CA certs (default is "changeit")
  • org.apache.ws.security.crypto.merlin.cert.provider - the provider to use to load certificates
  • org.apache.ws.security.crypto.merlin.keystore.alias - the default keystore alias to use, if none is specified
There are a number of issues with the old configuration values. The Java CA certs were loaded by default (for backwards compatiblity reasons), which slows things down if they're not needed. Secondly, there is no clean separation of the keystore used to obtain private/secret keys, and that used to verify trust on received credentials. Thirdly, some of the config tag names are inconsistent. The new crypto property tags for WSS4J 1.6 are as follows:

Provider tags:
  • org.apache.ws.security.crypto.merlin.keystore.provider - the provider used to load keystores (including the truststore)
  • org.apache.ws.security.crypto.merlin.cert.provider - the provider used to load certificates
These are identical to the 1.5.x provider tags.

KeyStore tags:
  • org.apache.ws.security.crypto.merlin.keystore.file - location of keystore
  • org.apache.ws.security.crypto.merlin.keystore.password - password used to load keystore
  • org.apache.ws.security.crypto.merlin.keystore.type - type of keystore (defaults to java.security.KeyStore.getDefaultType())
  • org.apache.ws.security.crypto.merlin.keystore.alias - the default keystore alias to use, if none is specified
Note that this is identical to the 1.5.x tags, apart from the location of the keystore file. This value falls back to the old value of "org.apache.ws.security.crypto.merlin.file" if it is not specified.

Truststore Tags:
  • org.apache.ws.security.crypto.merlin.load.cacerts - whether to load the CA certs in ${java.home}/lib/security/cacerts or not (default is false)
  • org.apache.ws.security.crypto.merlin.truststore.file - location of truststore
  • org.apache.ws.security.crypto.merlin.truststore.password - truststore password (default value is "changeit")
  • org.apache.ws.security.crypto.merlin.truststore.type - truststore type (defaults to java.security.KeyStore.getDefaultType())
Note that the Java CA certs are not now loaded by default. It is now possible to specify the keystore to be used as the truststore, as well as the password used to load the truststore, and the truststore type. It is not possible to both load a truststore and use the JDK CA Certs.

One final note - when building a validation chain to validate a received credential, WSS4J uses both the truststore and the keystore. This is for backwards compatibility reasons, where the user does not specify a truststore using the new config. The previous sentence applies to WSS4J 1.6.0, but does not apply from WSS4J 1.6.1 onwards. From WSS4J 1.6.1, WSS4J only uses the truststore when building a validation chain if it is specified. If it is not specified, then it falls back to using the keystore. See this issue for more details.