Tuesday, April 29, 2014

XML Security improvements for JAX-RS in Apache CXF 3.0.0

Recently on this blog, I've covered the new streaming XML Security functionality that will be available in Apache Santuario - XML Security for Java 2.0.0. For more information about why to use the new streaming implementation, as well as how to use it, please review the following - XML Signature is covered here,  XML Encryption is covered here, and some memory benchmarks are presented here. This article will cover using the new streaming XML Security implementation with JAX-RS messages in Apache CXF 3.0.0.

Apache CXF has the ability to secure JAX-RS clients and service XML requests with both XML Signature and Encryption, please see the CXF documentation for more information. Given that a new StAX-based XML Security implementation was available via Apache Santuario - XML Security for Java 2.0.0, it was natural to port this to CXF to be used by JAX-RS clients and endpoints. To show how to use the new functionality (as well as the older DOM-based XML Security functionality), I've created a new cxf-jaxrs-xmlsecurity project in github.

1) XML Signature test-cases

The following tests show how to use XML Signature with JAX-RS clients and endpoints:
The clients are configured in code, and the service endpoints are configured in spring. The service configuration for the streaming case is here
 
2) XML Encryption test-cases

The following tests show how to use XML Encryption with JAX-RS clients and endpoints:
The clients are configured in code, and the service endpoints are configured in spring. The service configuration for the streaming case is here

3) Configuration

The streaming XML Security implementation is configured in a very similar way to the DOM implementation. In the tests above, the same configuration parameters (usernames, keys, callbackhandler, etc.) are passed as properties for both implementations. One difference is that the streaming implementation has a single unified interceptor for both XML Signature and XML Encryption, whereas the DOM code has separate interceptors for both cases.

For the outbound case, the interceptor is XmlSecOutInterceptor. This interceptor
has the following properties that can be configured:
  • EncryptionProperties encryptionProperties - An EncryptionProperties Object to use to configure algorithms for encryption.
  • SignatureProperties sigProps - A SignatureProperties Object to use to configure algorithms for signature.
  • boolean encryptSymmetricKey - Whether to encrypt the symmetric key or not in an EncryptedKey. The default is true.
  • SecretKey symmetricKey - A symmetric key to use. If not specified, it is generated randomly.
  • boolean signRequest - Whether to sign the request or not. Default is false.
  • boolean encryptRequest - Whether to encrypt the request or not. Default is false.
  • List<QName> elementsToSign - The QNames of Elements in request to sign. If not specified the entire request is signed.
  • List<QName> elementsToEncrypt - The QNames of Elements in request to encrypt. If not specified the entire request is encrypted.
  • boolean keyInfoMustBeAvailable - Whether to add a KeyInfo structure or not to the signature/encryption. The default is true.
The inbound interceptor is XmlSecInInterceptor. This has the following properties that can be configured:
  • EncryptionProperties encryptionProperties - An EncryptionProperties Object to use to configure algorithms for encryption.
  • SignatureProperties sigProps - A SignatureProperties Object to use to configure algorithms for signature. 
  • String decryptionAlias - The alias to use to retrieve a private key from the keystore to decrypt the request. If not specified it falls back to the default alias in the Crypto properties file (if specified).
  • String signatureVerificationAlias - The alias to use to retrieve a certificate/public key from the keystore to verify the Signature, if the Signature does not contain a KeyInfo with a complete certificate/key.
  • boolean requireSignature - Whether the request must be signed. The default is false.
  • boolean requireEncryption - Whether the request must be encrypted. The default is false.
4) Some observations

The new streaming JAX-RS XML Security implementation is quite similar in terms of functionality and behaviour to the older DOM implementation. However there are a few differences to note:
  • The DOM-based XML Signature implementation supports Enveloped, Enveloping and Detached "styles". The StAX implementation only supports Enveloped.
  • The decryption alias must be supplied for the StAX case (or a default alias in the Crypto properties file). The DOM code takes the EncryptedKey and checks for a matching private key in the Crypto properties file. The StAX code expects to be supplied with the matching private key.
  • The XmlSecInInterceptor has booleans "requireSignature" and "requireEncryption" which should be set if you want to enforce that a message should be signed and/or encrypted. However, there are some scenarios where the internal interceptor that enforces these requirements may run before security processing has finished. If you are seeing exceptions along these lines, then disable the boolean values, but it is up to you then to retrieve the stored security values and match them against the security requirements.

No comments:

Post a Comment