Colm O hEigeartaigh

XML Security improvements for JAX-RS in Apache CXF 3.0.0

Colm O hEigeartaigh - Tue, 04/29/2014 - 12:20
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.
Categories: Colm O hEigeartaigh

Apache Santuario - XML Security for Java 2.0.0 - part III

Colm O hEigeartaigh - Fri, 04/25/2014 - 12:31
In the previous couple of posts, I've introduced the new streaming functionality of Apache Santuario - XML Security for Java 2.0.0. The first post focused on XML Signature and the second post focused on XML Encryption. This post will discuss the performance of the new streaming approach. In particular, we will focus on the memory consumption of the DOM vs StAX implementations as the size of the XML tree increases. Both implementations are roughly equivalent in terms of timing, however as we will see there is a big different in terms of memory usage.

1) Encryption

Here is a graph that shows the memory consumption of the StAX versus DOM implementations for encryption, as the size of the XML tree grows.



2) Decryption

Here is a graph that shows the memory consumption of the StAX versus DOM implementations for decryption, as the size of the XML tree grows.


3) Signature Creation

Here is a graph that shows the memory consumption of the StAX versus DOM implementations for signature creation, as the size of the XML tree grows. This is the only case where the memory consumption of the streaming code does not remain relatively flat, as some caching is involved in the signature creation case. However, the memory consumption is still substantially less than for the DOM code.


4) Signature Verification

Here is a graph that shows the memory consumption of the StAX versus DOM implementations for signature verification, as the size of the XML tree grows.


5) Conclusion

The new streaming implementation in Apache Santuario - XML Security for Java uses far less memory for large XML trees than the current DOM implementation for XML Encryption and XML Signature verification. It also uses substantially less memory for large XML trees for XML Signature creation. If you are working with large XML trees then you should experiment with the new functionality to see if it improves performance.

Categories: Colm O hEigeartaigh

Apache Santuario - XML Security for Java 2.0.0 - part II

Colm O hEigeartaigh - Wed, 04/23/2014 - 13:26
In the previous blog post, I covered the new StAX-based (streaming) XML Signature functionality coming in Apache Santuario - XML Security for Java 2.0.0. In this post, I will focus on the new streaming XML Encryption functionality that will also be available in this release.

1) XML Encryption test-cases

I have uploaded some test-cases to github to show how to use the new StAX-based API. The tests and setup mirror the XML Signature testcases that I covered in the previous blog post. There are currently three junit tests in this project:

2) Outbound StAX configuration

To see how to configure the new outbound StAX-based XML Encryption functionality, take a look at the "encryptUsingStax" method used by the tests. The streaming XML Security functionality is configured by populating a XMLSecurityProperties Object. You must typically call the following methods for XML Encryption:
  • properties.setAction(XMLSecurityConstants.Action) - an "Action" to perform, which for XML Encryption purposes is XMLSecurityConstants.ENCRYPT. 
  • properties.setEncryptionKey(Key) - The encrypting key. Typically a SecretKey instance.
  • properties.setEncryptionSymAlgorithm(String) - Symmetric encryption Algorithm to use. The default is AES 256.
  • properties.addEncryptionPart(SecurePart) - Add a SecurePart to encrypt, e.g. encrypt a given QName. 
  • properties.setEncryptionTransportKey(Key) - The key to use to encrypt the secret key (if desired). Either a SecretKey or PublicKey instance.
  • properties.setEncryptionKeyTransportAlgorithm(String) - The encryption key transport algorithm to use, to encrypt the secret key (if desired). Default is RSA OAEP.
  • properties.setEncryptionKeyIdentifier(SecurityTokenConstants.KeyIdentifier) - How to reference the encrypting key/cert. The default is SecurityTokenConstants.KeyIdentifier_IssuerSerial.  
The valid Encryption KeyIdentifier types are:
  • SecurityTokenConstants.KeyIdentifier_KeyValue
  • SecurityTokenConstants.KeyIdentifier_KeyName
  • SecurityTokenConstants.KeyIdentifier_IssuerSerial
  • SecurityTokenConstants.KeyIdentifier_SkiKeyIdentifier
  • SecurityTokenConstants.KeyIdentifier_X509KeyIdentifier
  • SecurityTokenConstants.KeyIdentifier_X509SubjectName
  • SecurityTokenConstants.KeyIdentifier_NoKeyInfo
3) Inbound StAX configuration

To see how to configure the new inbound StAX-based XML Encryption functionality, take a look at the "decryptUsingStAX" method used by the tests. As with encryption creation, it is necessary to create a XMLSecurityProperties Object, and to tell it what "Action" to perform. In addition you must call the following method:
  • properties.setDecryptionKey(Key) - a key to use to decrypt the request.
In addition, it is possible to pass a SecurityEventListener to record what security events were performed (see TestSecurityEventListener used in the tests). This allows the user to check what algorithms were used, what was encrypted etc.
Categories: Colm O hEigeartaigh

Apache Santuario - XML Security for Java 2.0.0

Colm O hEigeartaigh - Tue, 03/18/2014 - 18:05
In recent posts I have described some of the new features of the forthcoming Apache WSS4J 2.0.0 release. In particular, I focused on the changes and improvements to the existing "in-memory" (DOM-based) WS-Security implementation. However, the biggest new feature of WSS4J 2.0.0 will be a new streaming (StAX-based) WS-Security stack. In the next couple of posts, we will examine the core streaming XML Security functionality that will be available in the Apache Santuario - XML Security for Java 2.0.0 release.

The existing Apache Santuario - XML Security for Java implementation is DOM-based. What this essentially means is that the complete XML Document must be read into memory before being signed or verified. For large XML Documents this carries a corresponding performance penalty. In addition, it means that XML Signature is not feasible for very large documents. In contrast, the StAX API uses a streaming approach, resulting in very low memory usage.

The streaming XML/WS-Security functionality is split between the Apache Santuario and WSS4J projects. The Apache Santuario project contains the core streaming capabilities for XML Signature and Encryption. The Apache WSS4J project builds on this functionality to deliver a streaming WS-Security stack. The entire streaming security functionality is the work of Marc Giger, who donated his SWSSF project to Apache. Marc has done an outstanding job to implement this technically difficult task, and also to integrate the functionality into existing Apache projects. If you wish to experiment with the new functionality, it is available via the 2.0.0-rc1 release.

1) XML Signature test-cases

In this post we will focus on XML Signature only. I have uploaded some test-cases to github to show how to use the new StAX-based API. There are currently three junit tests in this project:
2) Outbound StAX configuration

To see how to configure the new outbound StAX-based XML Signature functionality, take a look at the "signUsingStAX" method used by the tests. The streaming XML Security functionality is configured by populating a XMLSecurityProperties Object. You must typically call the following methods:
  • properties.setAction(XMLSecurityConstants.Action) - an "Action" to perform, which for XML Signature purposes is XMLSecurityConstants.SIGNATURE. 
  • properties.setSignatureKey(Key) - The signing key. Can be a PrivateKey or SecretKey.
  • properties.setSigningCerts(X509Certificate[]) - The signing certs. May be inserted into the Signature KeyInfo depending on the Signature KeyIdentifier.
  • properties.addSignaturePart(SecurePart) - Add a SecurePart to sign, e.g. sign a given QName. You can also specify a digest method or transform algorithm here. You can also sign the entire request via SecurePart.setSecureEntireRequest(boolean).
  • properties.setSignatureAlgorithm(String) - Signature Algorithm to use. The default depends on the signing key.
  • properties.setSignatureDigestAlgorithm(String) - Signature Digest Algorithm to use. The default is the URI for SHA-1.
  • properties.setSignatureCanonicalizationAlgorithm(String) - The canonicalization algorithm to use. The default is XMLSecurityConstants.NS_C14N_EXCL_OMIT_COMMENTS.
  • properties.setSignatureKeyIdentifier(SecurityTokenConstants.KeyIdentifier) - How to reference the signing key/cert. The default is SecurityTokenConstants.KeyIdentifier_IssuerSerial.  
The valid Signature KeyIdentifier types are:
  • SecurityTokenConstants.KeyIdentifier_KeyValue
  • SecurityTokenConstants.KeyIdentifier_KeyName
  • SecurityTokenConstants.KeyIdentifier_IssuerSerial
  • SecurityTokenConstants.KeyIdentifier_SkiKeyIdentifier
  • SecurityTokenConstants.KeyIdentifier_X509KeyIdentifier
  • SecurityTokenConstants.KeyIdentifier_X509SubjectName
  • SecurityTokenConstants.KeyIdentifier_NoKeyInfo
By default, the Signature Element is attached as the first child of the root document.

3) Inbound StAX configuration

To see how to configure the new inbound StAX-based XML Signature functionality, take a look at the "verifyUsingStAX" method used by the tests. As with signature creation, it is necessary to create a XMLSecurityProperties Object, and to tell it what "Action" to perform. In addition you must call the following method, unless the complete signing key is contained in the Signature KeyInfo:
  • properties.setSignatureVerificationKey(Key) - a key to use to verify the Signature.
In addition, it is possible to pass a SecurityEventListener to record what security events were performed (see TestSecurityEventListener used in the tests). This allows the user to check what keys were used for signature verification, what algorithms were used, what was signed etc. See the verifyUsingStAX method as above for some simple code to check the signing key and the elements that were signed.

Categories: Colm O hEigeartaigh

Apache CXF Authentication and Authorization test-cases

Colm O hEigeartaigh - Wed, 03/12/2014 - 17:18
I've recently uploaded some test-cases to github that show different ways to authenticate and authorize a web services invocation using Apache CXF. Each project has the same two simple use-cases:
  • A JAX-WS request where the service requires a WS-Security UsernameToken over TLS.
  • A JAX-WS request where the service requires HTTP Basic Auth over TLS.
Each project has an "AuthenticationTest" that just illustrates some tests (including negative tests) for authentication, and then an "AuthorizationTest" that relies on authorizing the client based on roles that are retrieved as part of the authentication process somehow. The projects are as follows:
  • cxf-ldap: This project uses JAAS to authenticate a user via LDAP to a Apache Directory backend. The roles are also retrieved for the AuthorizationTest.
  • cxf-shiro: This project uses Apache Shiro for authentication and authorization.
  • cxf-spring-security: This project uses Spring Security for authentication and authorization.
  • cxf-syncope: This project uses the REST API of Apache Syncope for authenticating and authorizating users.
Feel free to download and play around with the projects.
Categories: Colm O hEigeartaigh

Apache WSS4J 2.0.0 - part VI

Colm O hEigeartaigh - Mon, 02/17/2014 - 17:07
This is the sixth of a series of articles on the new features and changes that will be delivered in Apache WSS4J 2.0.0. The fifth article looked at support for signing and encrypting message attachments via the SOAP with Attachments (SWA) Profile 1.1 specification, as well as the associated WS-SecurityPolicy expressions to sign and encrypt attachments. This post looks at the WS-SecurityPolicy model in WSS4J 2.0.0 and how it is used by the streaming code to perform real-time policy validation of an incoming message.

1) WS-SecurityPolicy model in WSS4J 2.0.0

The user of a web services stack such as Apache CXF or Apache Axis can use
WS-SecurityPolicy to define security requirements for service requests/responses. All that is required in addition to this is some user-specific configuration such as usernames, keystores, etc. However, WSS4J (1.6.x) had no awareness of whether WS-SecurityPolicy was used to define the security requirements or not. It was up to the web service stack in question to parse the security policy, build a model, and use the model to configure WSS4J appropriately. Then it was also up to the web services stack to go through the security results produced by WSS4J on processing a message, to see if the results conform to the policy or not.

WSS4J 2.0.0 includes a WS-SecurityPolicy model as part of the new module "wss4j-policy" module. This means that all web services stacks that rely on WSS4J to perform WS-Security no longer need their own model. Instead, they can register the Apache Neethi AssertionBuilder implementations in the WSS4J module to be able to handle WS-SecurityPolicy policies.

2) Real time streaming policy validation

The DOM-based WS-Security implementation in WSS4J 2.0.0 is still not WS-SecurityPolicy aware, in other words the web services stack must still parse the model to set up the configuration for WSS4J, and parse the results list to validate the results against the model. However, a significant new feature of WSS4J 2.0.0 is that the new streaming WS-Security implementation has the ability to perform "real-time" validation of a request against the set of applicable WS-SecurityPolicy policies. This means that bogus requests can be rejected quicker that the older DOM-based code, which may help to avoid DoS based scenarios. In the next few blog posts in this series, I'll be looking at the new streaming WS-Security implementation in more detail.
Categories: Colm O hEigeartaigh

Apache WSS4J 2.0.0 - part V

Colm O hEigeartaigh - Mon, 02/10/2014 - 17:36
This is the fifth of a series of articles on the new features and changes that will be delivered in Apache WSS4J 2.0.0. The fourth article looked at the ability to encrypt passwords in Crypto properties files. This post looks at support for signing and encrypting message attachments via the SOAP with Attachments (SWA) Profile 1.1 specification, as well as the associated WS-SecurityPolicy expressions to sign and encrypt attachments. Note that there is no support in WSS4J 1.6.x for signing or encrypting message attachments.

1) Configuring WSS4J to secure message attachments

There are two ways of using WSS4J, via an "action"-driven approach where WSS4J must be explicitly configured to perform all of the desired functionality, and via a WS-SecurityPolicy-based approach, where the web services stack sets up the WSS4J configuration internally based on a security policy. Let's look at how to secure message attachments for both of these approaches:

a) Securing message attachments via the "action" approach

With the "action" approach to using WSS4J, the user specifies the parts to sign or encrypt via the following configuration tags:
  • ConfigurationConstants.SIGNATURE_PARTS ("signatureParts")
  • ConfigurationConstants.ENCRYPTION_PARTS ("encryptionParts")
The value of these tags is a String in a special format that looks something like "{Content}{http://example.org/paymentv2}CreditCard". In this example, the element to be secured has the name "CreditCard" and namespace "http://example.org/paymentv2". "Content" only applies to Encryption, and means that the Content should be encrypted (as opposed to the full "Element").

In WSS4J 2.0.0, it is possible to sign/encrypt all of the attachments by specifying the following as part of signatureParts/encryptionParts: "{}cid:Attachments;". It is not possible to only sign/encrypt individual attachments, it is all or nothing. Here is an Apache CXF client configuration file with an example of this.

b) Securing message attachments via WS-SecurityPolicy

An easier way to use WSS4J is in conjunction with a web services stack such as Apache CXF and a WS-SecurityPolicy-based policy. It is possible to sign/encrypt all attachments via the policies:
  • <sp:SignedParts><sp:Attachments /></sp:SignedParts>
  • <sp:EncryptedParts><sp:Attachments /></sp:EncryptedParts>
In addition, the "<sp:Attachments>" policy for SignedParts only has two optional child policies called "sp13:ContentSignatureTransform" and "sp13:AttachmentCompleteSignatureTransform", which dictate whether the attachment headers are included or not in the Signature.

2) Supplying the message attachments to WSS4J

Part 1 above only covers how to configure WSS4J to sign/encrypt message attachments. It is also necessary to actually supply the message attachment streams to WSS4J. This is done in WSS4J via a CallbackHandler approach. An AttachmentRequestCallback Object is used to retrieve either a particular Attachment (on the receiving side), or all attachments (on the sending side). The user must implement a CallbackHandler that sets a list of Attachments matching this request on the Callback. Correspondingly, there is also a AttachmentResponseCallback, which represents the secured/processed Attachment.

The good news is that if you are using Apache CXF then all of this is taken care of automatically by a CallbackHandler that retrieves and sets CXF message attachments. Therefore if you are using CXF then you can sign/encrypt message attachments just by passing the configuration detailed in part 1 of this post. Finally, there are some system tests available in CXF that show how both the "action" and "policy" based approaches work to secure attachments. The test code is here and the resource/configuration files are here.
Categories: Colm O hEigeartaigh

Apache WSS4J 2.0.0 - part IV

Colm O hEigeartaigh - Wed, 02/05/2014 - 18:16
This is the fourth of a series of articles on the new features and changes that will be delivered in Apache WSS4J 2.0.0. The third article looked at some changes in the area of caching tokens to detect replay attacks. This post looks at a new feature of WSS4J 2.0.0, which is the ability to encrypt passwords in Crypto properties files.

1) Crypto properties

Apache WSS4J uses the Crypto interface to get keys and certificates for encryption/decryption and for signature creation/verification. WSS4J currently ships with three implementations:
  • Merlin: The standard implementation, based around two JDK keystores for key/cert retrieval, and trust verification.
  • CertificateStore: Holds an array of X509 Certificates. Can only be used for encryption and signature verification.
  • MerlinDevice: Based on Merlin, allows loading of keystores using a null InputStream - for example on a smart-card device.
Typically, a Crypto implementation is loaded and configured via a Crypto properties file. This tells WSS4J what Crypto implementation to load, as well as implementation-specific properties such as a keystore location, password, default alias to use, etc. A typical example of the contents of a Crypto properties file for Signature creation is as follows:

org.apache.wss4j.crypto.provider=org.apache.wss4j.common.crypto.Merlin
org.apache.wss4j.crypto.merlin.keystore.type=jks
org.apache.wss4j.crypto.merlin.keystore.password=security
org.apache.wss4j.crypto.merlin.keystore.alias=wss40
org.apache.wss4j.crypto.merlin.keystore.file=keys/wss40.jks

Note that in WSS4J 2.0.0 the "org.apache.ws.security.crypto" prefix used previously is now "org.apache.wss4j.crypto", however both prefixes are accepted by the code.

2) Encrypting passwords in a Crypto properties file

Note in the example above that the password used to load the keystore is in cleartext. One of the new features of Apache WSS4J 2.0.0 is the ability to instead store a (BASE-64 encoded) encrypted version of the keystore password in the Crypto properties file. A new PasswordEncryptor interface is defined to allow for the encryption/decryption of passwords. A default implementation is now provided based on Jasypt called JasyptPasswordEncryptor, which uses "PBEWithMD5AndTripleDES".

The way this works is as follows. The WSPasswordCallback class has an additional "usage" called WSPasswordCallback.PASSWORD_ENCRYPTOR_PASSWORD, which is used to return the password used with a PasswordEncryptor implementation to decrypt encrypted passwords stored in Crypto properties files. When WSS4J is loading a Crypto implementation via a properties file, and it encounters a password encrypted in the format "ENC(encoded encrypted password)", it queries a CallbackHandler for the (master) password to decrypt the encrypted password
using the WSPasswordCallback usage tag given above.

It is possible to pass a custom PasswordEncryptor implementation to WSS4J via the new configuration tag ConfigurationConstants.PASSWORD_ENCRYPTOR_INSTANCE ("passwordEncryptorInstance").
Categories: Colm O hEigeartaigh

Apache WSS4J 2.0.0 - part III

Colm O hEigeartaigh - Mon, 01/27/2014 - 18:08
This is the third of a series of articles on the new features and changes that will be delivered in Apache WSS4J 2.0.0. The second article grouped together some new features that were too small to warrant a separate article on their own. This article will focus on some changes in the area of caching tokens to detect replay attacks.

1) Replay Attack detection in Apache WSS4J 1.6.x

Please see a previous article I wrote which covers what Replay Attacks are, and how to prevent them in Apache CXF (using WSS4J 1.6.x). Essentially, the goal is to ensure that an eavesdropper cannot copy a WS-Security enabled request, and make another successful invocation on a service. Three different types of Replay Attack detection exist in Apache WSS4J:
  • Signed Timestamps
  • UsernameToken nonces
  • SAML OneTimeUse Assertions (see here).
Apache WSS4J 1.6.5 introduced a ReplayCache interface, which can be used for replay attack detection for each individual use-case. In addition, WSS4J 1.6.5 shipped with a sample TreeMap-based implementation, which was not intended for production use. However, caching was not enabled by default in WSS4J itself, but rather was configured in Apache CXF using an Ehcache based solution. Please refer to the original article for more details.

2) Replay Attack detection in Apache WSS4J 2.0.0

A new major version release of Apache WSS4J allows us to shift the Replay Attack implementation from Apache CXF into WSS4J itself, so that other stacks can benefit. WSS4J 2.0.0 will ship with default support for detecting replay attacks for the following three scenarios, without any required configuration changes. The default ReplayCache implementation is based on Ehcache and uses the following configuration.

2.a) Signed Timestamp replay detection

By default, WSS4J 2.0.0 will cache a combination of a Timestamp Created value and the Signature Value that signs the Timestamp, that will be cached until the Timestamp "expiry" is reached (or until the default cache expiry is hit). The reason that the Timestamp must be signed is to preclude the rejection of two requests that have been created at the exact same time. The caching of signed Timestamps can be configured as follows:
  • ConfigurationConstants.TIMESTAMP_CACHE_INSTANCE ("timestampCacheInstance"): This holds a reference to a ReplayCache instance used to cache Timestamp Created Strings. The default instance that is used is the EHCacheReplayCache.
  • ConfigurationConstants.ENABLE_TIMESTAMP_CACHE ("enableTimestampCache"):  Whether to cache Timestamp Created Strings (these are only cached in conjunction with a message Signature). The default value is "true".
2.b) UsernameToken nonce replay detection

By default, WSS4J 2.0.0 will cache UsernameToken nonces, and reject any duplicate value. This can be configured as follows:
  • ConfigurationConstants.NONCE_CACHE_INSTANCE ("nonceCacheInstance"): This holds a reference to a ReplayCache instance used to cache UsernameToken nonces. The default instance that is used is the EHCacheReplayCache.
  • ConfigurationConstants.ENABLE_NONCE_CACHE ("enableNonceCache"):  Whether to cache UsernameToken nonces. The default value is "true".
2.c) SAML OneTimeUse replay detection

By default, WSS4J 2.0.0 will cache SAML 2.0 token identifiers, if the token has a OneTimeUse Condition, and reject any duplicate tokens. This can be configured as follows:
  • ConfigurationConstants. SAML_ONE_TIME_USE_CACHE_INSTANCE ("samlOneTimeUseCacheInstance"): This holds a reference to a ReplayCache instance used to cache SAML2 Token Identifier Strings (if the token contains a OneTimeUse Condition). The default instance that is used is the EHCacheReplayCache.
  • ConfigurationConstants.ENABLE_SAML_ONE_TIME_USE_CACHE ("enableSamlOneTimeUseCache"):  Whether to cache SAML2 Token Identifiers, if the token contains a "OneTimeUse" Condition. The default value is "true".
Categories: Colm O hEigeartaigh

Apache WSS4J 2.0.0 - part II

Colm O hEigeartaigh - Thu, 01/23/2014 - 17:59
This is the second of a series of articles on the new features and changes that will be delivered in Apache WSS4J 2.0.0. The first article gave an overview of the new features, detailed the new project structure, and covered a migration guide for existing users. This blog post groups together the new features that are too small to warrant an article on their own.

1) Kerberos Signature/Encryption support

Support was added in WSS4J 1.6.2 to obtain a Kerberos ticket from a KDC (Key Distribution Center) and convert it to a BinarySecurityToken to be inserted into the security header of a SOAP request. On the receiving side, support was added to validate the received Kerberos ticket accordingly. In WSS4J 1.6.3, support was added to use the secret key associated with a Kerberos Token to secure (sign and encrypt) the request. However, this functionality came with the limitation that there was no out-of-the-box way to extract the Symmetric Key on the receiving side, to decrypt the request or validate the Signature.

Instead, a KerberosTokenDecoder interface was provided, which defined methods for setting the AP-REQ token and current Subject, and a method to then get a session key. To support signature and encryption with Kerberos on an inbound request, the user had to implement this interface and set it on the KerberosTokenValidator. This process, along with a sample KerberosTokenDecoder implementation which relied on low-level Java APIs, was described in a previous blog post.

In WSS4J 2.0.0, a default implementation of the KerberosTokenDecoder interface is provided that can process Kerberos secret keys correctly, using functionality from Apache Directory. Therefore support for using Kerberos tokens to sign and encrypt SOAP messages is now provided out-of-the-box in WSS4J 2.0.0.

2) Action enhancements

When not using WSS4J with a WS-SecurityPolicy aware stack such as Apache CXF, outbound security is configured via "Actions". The list of supported actions is defined on the WSS4J configuration page, e.g. "UsernameToken", "Signature", "Encrypt", etc. There are some enhancements to "Actions" in WSS4J 2.0.0.

a) Custom Token Action

A new "CustomToken" Action is defined in WSS4J 2.0.0. If this action is defined, a token (DOM Element) will be retrieved from a CallbackHandler via WSPasswordCallback.Usage.CUSTOM_TOKEN and written out as is in the security header. This provides for an easy way to write out tokens that have been retrieved out of band.

b) Action tokens

A significant new feature in WSS4J 2.0.0 for actions is the ability to associate an Action with a corresponding token. In WSS4J 1.6.x, actions are always configured from configuration that is shared between actions. So for example, a Signature action takes its key and algorithm information from the corresponding configuration tags. However, this is problematic if you want to execute two Signature actions, as it's not possible using this approach to use (e.g.) two different Signature algorithms.

In WSS4J 2.0.0, the WSHandler class is configured with a list of HandlerAction Objects, which associate an Action with a SecurityActionToken. Default implementations of the SecurityActionToken interface are provided for signature, encryption etc., and are populated from the standard configuration tags. However, to add some custom configuration for a given Action, you can implement the SecurityActionToken interface to provide configuration specific to that Action.

3) Optional Signature and Encryption parts

In WSS4J 1.6.x, signature and encryption parts are determined respectively by the "signatureParts" and "encryptionParts" configuration tags. However, if a part is specified that does not exist in the request, then an exception is thrown. In WSS4J 2.0.0, two new configuration tags are defined called "optionalSignatureParts" and "optionalEncryptionParts". These specify the parts to sign and encrypt, but no exception is thrown if the parts cannot be located. The tags can be used in an analgous way to the WS-SecurityPolicy SignedParts and EncryptedParts policies, which only require that an Element be Signed/Encrypted if it appears in the request.

4) More sophisticated Basic Security Profile enforcement

Apache WSS4J 1.6.x provided support for enforcing the Basic Security Profile 1.1 (BSP) restrictions. However, one issue with the implementation was that it was not possible to ignore a particular set of rules defined in the specification, enforcement was "all or nothing". In WSS4J 2.0.0, it is possible to disable all Basic Security Profile rules as per WSS4J 1.6.x. However, it is now possible to specify individual rules to ignore. The RequestData class has a setIgnoredBSPRules method, that takes a list of BSPRule Objects as an argument. The BSPRule class contains a complete list of Basic Security Profile rules that are enforced in WSS4J.

Note that when BSP Compliance was switched off on the outbound side in WSS4J 1.6.x, it had the effect that an InclusiveNamespaces PrefixList was not generated as a CanonicalizationMethod child of a Signature Element (as required by the BSP specification). In WSS4J 2.0.0, this is now controlled by a separate configuration tag "addInclusivePrefixes", which defaults to true. 

5) Configurable SAML SubjectConfirmation validation

WSS4J enforces the SubjectConfirmation requirements of an inbound SAML Token. For sender-vouches, a Signature must be present that covers both the SOAP Body and the SAML Assertion. For holder-of-key, a Signature must be present that signs some part of the SOAP request using the key information contained in the SAML Subject. In WSS4J 2.0.0, a configuration tag is defined that allows the user to switch off this validation if required. The configuration tag is defined as ConfigurationConstants.VALIDATE_SAML_SUBJECT_CONFIRMATION ("validateSamlSubjectConfirmation"), which defaults to true.

Categories: Colm O hEigeartaigh

SAML "OneTimeUse" support in Apache CXF 2.7.8

Colm O hEigeartaigh - Thu, 01/09/2014 - 17:09
Apache WSS4J 1.6.13 contains a number of features to support working with SAML 2.0 tokens with a "OneTimeUse" Condition. Firstly, it is now possible to create a SAML 2.0 token with this attribute via the ConditionsBean. Secondly, support has been added to cache any token Identifier which has a "OneTimeUse" Condition. The idea is that any SAML 2.0 token with a "OneTimeUse" Condition cannot be used again (or replayed). Hence, this is another form of defence against replay attacks, similar to existing support to cache signed Timestamps and UsernameToken nonces.

This functionality in WSS4J has been integrated into Apache CXF. Two new configuration tags have been added to control caching SAML 2.0 tokens with "OneTimeUse" Conditions:
  • ws-security.enable.saml.cache -  Whether to cache SAML2 Token Identifiers, if the token contains a "OneTimeUse" Condition. The default value is "true" for message recipients, and "false" for message initiators.
  • ws-security.saml.cache.instance - This holds a reference to a ReplayCache instance used to cache SAML2 Token Identifiers, when the token has a "OneTimeUse" Condition. The default instance that is used is the EHCacheReplayCache.
Note that caching only applies when either a WS-SecurityPolicy "SamlToken" policy is in effect, or else that a SAML action (signed or unsigned) has been configured for the non-security-policy case. In either of these scenarios, a message recipient will automatically enforce OneTimeUse, unless it has been configured not to via the "enable" configuration tag defined above.

The client functionality in Apache CXF that gets a security token from an STS (SecurityTokenService) when the service has an "IssuedToken" policy has also been updated to take a "OneTimeUse" Condition into account. If the issued token from the STS has a "OneTimeUse" Condition, then the token is not cached on the message exchange. What this means is that if the client makes another service invocation, it will get a new token from the STS, as the "OneTimeUse" Condition of the previous token means that it can't be reused.



Categories: Colm O hEigeartaigh

Apache WSS4J 2.0.0 - part I

Colm O hEigeartaigh - Wed, 01/08/2014 - 18:28
Apache WSS4J is an open-source Java implementation of the security standards for web services. The project was founded in 2004 and is widely used, including by the web service stacks Apache CXF and Apache Axis. Apache WSS4J 1.6.0 was released in April 2011, and featured a wide range of improvements such as support for SAML 2.0 assertions. This blog post is the first in a series of articles on the new features and changes that will be arriving in the imminent WSS4J 2.0.0 release. In this article, we will provide an overview of the new features, the changed project structure, as well as a migration guide for existing users.

1) Overview of new features

Apache WSS4J 2.0.0 delivers the following major new features, along with a substantial set of minor features:
  • Support for a streaming (StAX) based WS-Security implementation that covers all of the main specifications. This is both faster and uses far less memory than the DOM-based alternative.
  • A WS-SecurityPolicy model that can be shared between both DOM + StAX implementations.
  • Support for "real-time" WS-SecurityPolicy validation for the StAX implementation.
  • Support for the SOAP with Attachments (SWA) Profile 1.1 specification.
  • Support for caching based on EhCache.
  • Support for encrypting passwords in Crypto properties files using Jasypt
These new features will be covered in more detail in future articles.

2) Project Structure

The source for Apache WSS4J 2.0.0 can be perused here. Support for building WSS4J using Apache Ant has been dropped, Apache Maven must be used to build the project. Support for JDK 1.5 has also been dropped. Unlike previous releases, WSS4J 2.0.0 now contains multiple Maven modules, the most important of which are as follows:
  • bindings: Contains code generated from security schemas
  • policy: Contains a (shared) WS-SecurityPolicy model
  • ws-security-common: Shared code between the DOM + StAX implementations
  • ws-security-dom: The DOM implementation.
  • ws-security-stax: The StAX implementation.
  • ws-security-policy-stax: The WS-SecurityPolicy validation layer for the StAX code.
Note that the old "org.apache.ws.security" package is no longer used as part of this refactoring, instead each module uses "org.apache.wss4j.X". The WS-SecurityPolicy model in the "policy" module replaces different models used in web service stacks such as Apache CXF + Axis, thus simplifying the code in the security components of these projects. The "ws-security-policy-stax" module gives us the ability to validate WS-SecurityPolicy against an inbound request in "real-time". This is opposed to the DOM implementation, which only validates WS-SecurityPolicy against the request after security processing has completed.

3) Migration Guide

Care has been taken to limit the impact of changes in WSS4J 2.0.0 on existing user configuration. However there are some inevitable incompatibilities, facilitated by the major version upgrade. I will details some of these changes in this section, and then expand on them on the website in more detail closer to release. These changes only affect the DOM in-memory implementation, as the StAX implementation is new in this release.

3.1) Signature Verification Crypto

In WSS4J 1.6.x, it was only possible to specify a Crypto implementation for both Signature Creation + Verification. In WSS4J 2.0.0, there is now a separate Signature Verification Crypto instance, that can be configured via the following configuration tags:
  • "signatureVerificationPropFile" - The path of the crypto property file to use for Signature verification.
  • "signatureVerificationPropRefId" - The key that holds a reference to the object holding complete information about the signature verification Crypto implementation.
3.2) WSPasswordCallback package change

In WSS4J, you need to define a CallbackHandler to supply a password to a WSPasswordCallback Object when dealing with UsernameTokens, or to unlock private keys for Signature creation, etc. In WSS4J 2.0.0, the functionality is exactly the same, except that the package of the WSPasswordCallback Object has changed from "org.apache.ws.security" to "org.apache.wss4j.common.ext". Any CallbackHandler implementation will need to be updated to use the new package.

3.3) SAML creation changes

A CallbackHandler implementation is required to create a SAML Assertion, by populating various beans. Similar to the WSPasswordCallback package change, there are also some package changes for SAML. The base package for the SAMLCallback class, and of the various "bean" classes, has changed from "org.apache.ws.security.saml.ext" to "org.apache.wss4j.common.saml".

In addition, the "samlPropFile" and "samlPropRefId" configuration tags have been removed. These tags pointed to a properties file/object, which could be used to define the issuer of the Assertion, as well as the Crypto configuration used to sign the Assertion. In WSS4J 2.0.0, it is the responsibility of the CallbackHandler to configure the SAMLCallback Object appropriately. The SAMLCallback Object has the following new properties, which can be configured to sign an Assertion:
  • boolean signAssertion
  • String issuerKeyName
  • String issuerKeyPassword
  • Crypto issuerCrypto
  • boolean sendKeyValue
  • String canonicalizationAlgorithm
  • String signatureAlgorithm
3.4) Caching changes

WSS4J 2.0.0 uses three EhCache-based caches by default for the following scenarios, to prevent replay attacks:
  • UsernameToken nonces
  • Signed Timestamps
  • SAML 2.0 OneTimeUse Assertions
If you are seeing a error about "replay attacks" after upgrade, then you may need to disable a particular cache. More on this in a future article.

Categories: Colm O hEigeartaigh

Security Advisory CVE-2013-4517 released

Colm O hEigeartaigh - Wed, 12/18/2013 - 13:44
A new security advisory for the Apache Santuario XML Security for Java library has been released:

"The Apache Santuario XML Security for Java project is vulnerable to a Denial of Service (DoS) type attack leading to an OutOfMemoryError, which is caused by allowing Document Type Definitions (DTDs) when applying Transforms. From the 1.5.6 release onwards, DTDs will not be processed at all when the "secure validation" mode is enabled."

This issue is fixed (when secure validation is enabled) in Apache Santuario XML Security for Java 1.5.6. This release is picked up by new releases of Apache WSS4J (1.6.13), and Apache CXF (2.7.8 and 2.6.11).
Categories: Colm O hEigeartaigh

Apache CXF STS client configuration options

Colm O hEigeartaigh - Fri, 11/08/2013 - 13:23
Apache CXF provides a Security Token Service (STS), which can issue (as well as validate, renew + cancel) security tokens using the WS-Trust protocol. A common SOAP security scenario is where a service provider requires that a client must authenticate itself to the service, by geting a token from an STS and including it in the service request. In this article, we will explore different ways of configuring the client with details of how to communicate with the STS, as well as how the service provider can provide these details to the client.

1) IssuedToken policies

The service provider can require that a client retrieve a security token from an STS by specifying a WS-SecurityPolicy IssuedToken policy (for example, in the WSDL of the service). The following IssuedToken policy fragment (see here for a concrete example) tells the client that it must include a SAML 1.1 token in the request. In addition, the token must include the client's PublicKey, the corresponding private key of which must be used to secure the request in some way (SOAP Message Signature, TLS client authentication):

<sp:IssuedToken
    sp:IncludeToken=".../IncludeToken/AlwaysToRecipient">
    <sp:RequestSecurityTokenTemplate>
        <t:TokenType>http://.../oasis-wss-saml-token-profile-1.1#SAMLV1.1</t:TokenType>
        <t:KeyType>http://.../ws-trust/200512/PublicKey</t:KeyType>
    </sp:RequestSecurityTokenTemplate>
</sp:IssuedToken>

2) STSClient configuration

So the CXF client will know that it must get a SAML 1.1 token from an STS when it sees the above policy, and that it must present the STS with a X.509 Certificate, so that the STS can embed it in the issued token. How does it know how to contact the STS? Typically, this is defined in an STSClient bean. The following configuration (see here for a concrete example), specifies the WSDL location of the STS, as well as the Service + Port QNames to use, as well as some additional security configuration:

<bean id="stsClient" class="org.apache.cxf.ws.security.trust.STSClient">
       <property name="wsdlLocation"
                 value="https://localhost:8443/SecurityTokenService/Transport?wsdl"/>
       <property name="serviceName"
                 value="{http://.../ws-trust/200512/}SecurityTokenService"/>
       <property name="endpointName"
                 value="{http://.../ws-trust/200512/}Transport_Port"/>
       <property name="properties">
           <map>
               <entry key="ws-security.username" value="alice"/>
               <entry key="ws-security.callback-handler"
                      value="org.apache.cxf.systest.sts.common.CommonCallbackHandler"/>
               <entry key="ws-security.sts.token.username" value="myclientkey"/>
               <entry key="ws-security.sts.token.properties" value="clientKeystore.properties"/>
               <entry key="ws-security.sts.token.usecert" value="true"/>
           </map>
        </property>
</bean>

While this type of configuration works well, it has a few drawbacks:
  • The client must have the WSDL (location) of the STS (as well as service + port QNames). 
  • The service can't communicate to the client which STS address to use (as well as service + port QNames).
Apache CXF provides two ways of addressing the limitations given above, that will be described in the next two points.

3) Communicating the STS address + service/port QNames to the client

From Apache CXF 2.7.8 it is possible for the service to communicate the STS address and service/port QNames to the client in a simple way (as opposed to using WS-MEX, as will be covered in the next section). This is illustrated by the IssuerTest.testSAML1Issuer in the CXF source. The IssuedToken policy of the service provider, has an additional child policy:

<sp:Issuer>
    <wsaw:Address>https://.../SecurityTokenService/Transport</wsaw:Address>
    <wsaw:Metadata xmlns:wst="http://.../ws-trust/200512/">
        <wsam:ServiceName EndpointName="Transport_Port">
            wst:SecurityTokenService
        </wsam:ServiceName>
    </wsaw:Metadata>
</sp:Issuer>

The "Address" Element communicates the STS address, and the "ServiceName" Element communicates the Service + Endpoint QNames to the client. With this configuration in the WSDL, the client configuration is greatly simplified. Instead of specifying the WSDL Location + Service/Port QNames, the client now only has to specify the security policy to be used in communicating with the STS. It also must set the security configuration tag "ws-security.sts.disable-wsmex-call-using-epr-address" to "true", to avoid using WS-MEX.

An obvious disadvantage to this method is that it still requires the client to have access to the security policy of the STS. However, it at least is a simple way of avoiding hardcoding service host + port numbers in client configuration. A more sophisticated method is to use WS-MEX, as will be described in the next section.

4) Using WS-MetadataExchange (WS-MEX)

The best way for the service to communicate details of the STS to the client is via WS-MetadataExchange (WS-MEX). This is illustrated by the IssuerTest.testSAML2MEX in the CXF source. The IssuedToken policy of the service provider has an Issuer policy that looks like:

<sp:Issuer>
    <wsaw:Address>https://.../SecurityTokenService/Transport</wsaw:Address>
    <wsaw:Metadata>
        <wsx:Metadata>
            <wsx:MetadataSection>
                <wsx:MetadataReference>
                    <wsaw:Address>https://.../SecurityTokenService/Transport/mex</wsaw:Address>
                </wsx:MetadataReference>
            </wsx:MetadataSection>
        </wsx:Metadata>
    </wsaw:Metadata>
</sp:Issuer>

The client uses the Metadata address to obtain the WSDL of the STS. A CXF Endpoint supports WS-MetadataExchange via a "/mex" suffix, when "cxf-rt-ws-mex" is on the classpath. Note that the client configuration does not need to define an STSClient Object at all any more, only to provide some security configuration for the request to the STS. The client first makes a call to the STS to get the WSDL that looks like:

<soap:Envelope>
    <soap:Header>
        <Action xmlns=".../addressing">http://schemas.xmlsoap.org/ws/2004/09/transfer/Get</Action>
       <MessageID xmlns=".../addressing">urn:uuid:1db606be-695b-46d4-8759-fe9d41746b42</MessageID>
       <To xmlns=".../addressing">https://.../SecurityTokenService/Transport/mex</To>
       <ReplyTo xmlns=".../addressing"><Address>.../addressing/anonymous</Address></ReplyTo>
   </soap:Header>
   <soap:Body/>
</soap:Envelope>

The STS responds with the WSDL embedded in the SOAP Body under a "Metadata" Element. The client then matches the Address defined in the Issuer policy with an endpoint address in the WSDL and uses the corresponding Service/Endpoint QName to invoke on the STS. Alternatively, the service could specify explicit QNames as per the previous example.


Categories: Colm O hEigeartaigh

XKMS functionality in Apache CXF

Colm O hEigeartaigh - Mon, 11/04/2013 - 17:51
Talend has recently donated an XKMS 2.0 implementation to Apache CXF, which is available from the CXF 2.7.7 release. It is documented on the CXF wiki here. The XKMS implementation consists of two parts. Firstly, an XKMS service is provided that exposes a SOAP interface that allows users to register X.509 certificates, as well as to both locate and validate X.509 certificates. Secondly, an implementation of the WSS4J Crypto interface is provided which allows a (WS-Security based) client to both find and validate certificates via the XKMS service.

This blog post will focus on a simple WS-Security system test in CXF, and how it uses XKMS for certificate location and validation. For more detailed information on XKMS, and how it is implemented in CXF, check out my Talend colleague Andrei Shakirin's excellent blog posts on XKMS.

1) XKMS system test with WS-Security

WS-Security is used to secure SOAP service requests/responses at the message level. How this is done is defined by a WS-SecurityPolicy fragment, which is usually defined in the WSDL of the service. Some additional configuration is required by CXF clients and services, such as what username to use, a CallbackHandler implementation to get passwords, and the location of property files which contain WSS4J Crypto configuration for signing and encrypting. See the following wiki and system tests for more information on using WS-Security and WS-SecurityPolicy in CXF.

The WS-SecurityPolicy specification defines two security "bindings" for use in securing SOAP messages at the message level - the "Symmetric" and "Asymmetric" bindings. With the Symmetric binding, the client creates a secret key to secure the message, and then uses the certificate of the service to encrypt the secret key, so that only the service can decrypt the secured message. The Asymmetric binding assumes that both the client and service have public/private key-pairs, and hence the client signs the request using its private key, and encrypts the request using the service's public key.

In each case, the client (typically) must have access to an X.509 certificate for the service. It must "locate" a certificate for the service on the outbound side for both the Symmetric and Asymmetric bindings, and it must "validate" the certificate used by the service to sign the response in the "Asymmetric" case. Up to now, the default WSS4J Crypto implementation (Merlin) uses a local Java keystore to obtain certificates. However, given that the tasks the client must perform ("locate" and "validate") map directly to XKMS operations, it's possible to use the new XKMS Crypto implementation instead.

The XkmsCryptoProvider is configured with a JAX-WS client proxy which can locate/validate X.509 Certificates from a remote XKMS SOAP service. Additionally, it can be composed with another Crypto implementation from which private keys can be retrieved (for example, when used for the Asymmetric Binding). It can also be configured with a cache to prevent repeated remote calls to the XKMS service to locate or validate a particular certificate. The default cache is based on EhCache.

Aside from the obvious advantages of being able to centralize certificate management by using XKMS, a cool additional advantage is that the client need have no local key information at all for the Symmetric binding, as it only requires the X.509 certificate of the message recipient, and no private key. This could greatly simplify key management in a large deployment.

Let's tie all of the above information on combining WS-Security with XKMS together by looking at some CXF system tests. The tests are available in the CXF WS-Security systests directory. The test source is here and test configuration files are available here. The tests show how to deploy an XKMS Service, and how to configure a JAX-WS client with the XKMS Crypto implementation to locate and validate certificates for a service invocation over both the Symmetric and Asymmetric bindings.

2) The XKMS Service

The XKMS service configuration for the test is available here. It describes a JAX-WS endpoint that can only be accessed over TLS. The endpoint implements the standard XKMS interface. A certificate repository is defined as follows:

<bean id="certificateRepo"
    class="org.apache.cxf.xkms.x509.repo.file.FileCertificateRepo">
    <constructor-arg value="src/test/resources/certs/xkms" />
</bean>

This is a simple file based certificate repository, where certificates are stored in a single directory on the filesystem (see here). A more appropriate implementation for the enterprise is the LDAP certificate repository, which is documented on the wiki. The service defines a single XKMS "locator":

<bean id="x509Locator"
    class="org.apache.cxf.xkms.x509.handlers.X509Locator">
    <constructor-arg ref="certificateRepo" />
</bean>

In other words, any "locate" query will try to find certificates in the file certificate store we have defined above. Similarly, two XKMS "validators" are configured:

<bean id="dateValidator"
    class="org.apache.cxf.xkms.x509.validator.DateValidator" />
<bean id="trustedAuthorityValidator"
    class="org.apache.cxf.xkms.x509.validator.TrustedAuthorityValidator">
    <constructor-arg ref="certificateRepo" />
</bean>

The first will validate that a given certificate is "in date". The second will look for a trusted certificate authority for the certificate in the certificate repo (under the "trusted_cas" subdirectory).

3) The JAX-WS client

Here we will just focus on the configuration for the client for the Symmetric binding use-case. It is configured as follows:

<jaxws:client
    name="{http://www.example.org/contract/DoubleIt}DoubleItSymmetricPort"
    createdFromAPI="true">
    <jaxws:properties>
        <entry key="ws-security.encryption.crypto" value-ref="xkmsCrypto"/>
        <entry key="ws-security.encryption.username" value="CN=bob, OU=eng, O=apache.org"/>
    </jaxws:properties>
</jaxws:client>

The client specifies an encryption username that corresponds to the Subject DN of the message recipient. It can also search for a certificate by the service "{serviceNamespace}serviceName" QName. The encrytion Crypto object is a reference to the XKMSCryptoProvider, which in turn is simply configured with the URL of the XKMS Service:

<bean id="xkmsClient"
    class="org.apache.cxf.xkms.client.XKMSClientFactory"
    factory-method="create">
    <constructor-arg>
        <value>https://localhost:${testutil.ports.XKMSServer}/XKMS</value>
    </constructor-arg>
    <constructor-arg ref="cxf"/>
</bean>

<bean id="xkmsCrypto"
    class="org.apache.cxf.xkms.crypto.impl.XkmsCryptoProvider">
    <constructor-arg>
        <ref bean="xkmsClient" />
    </constructor-arg>
</bean>

Before the service request, the client queries the XKMS service to locate an appropriate certificate using the configured encryption username:

Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:LocateRequest xmlns:ns2="http://www.w3.org/2002/03/xkms#" xmlns:ns3="http://www.w3.org/2001/04/xmlenc#" xmlns:ns4="http://www.w3.org/2000/09/xmldsig#" xmlns:ns5="http://www.w3.org/2002/03/xkms#wsdl" Id="6a17ae45-21a2-4484-b5ec-c71b04dda0b2" Service="http://cxf.apache.org/services/XKMS/"><ns2:QueryKeyBinding><ns2:UseKeyWith Application="urn:ietf:rfc:2459" Identifier="CN=bob, OU=eng, O=apache.org"/></ns2:QueryKeyBinding></ns2:LocateRequest></soap:Body></soap:Envelope>

The XKMS Service responds with:

Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:LocateResult xmlns:ns2="http://www.w3.org/2002/03/xkms#" xmlns:ns3="http://www.w3.org/2001/04/xmlenc#" xmlns:ns4="http://www.w3.org/2000/09/xmldsig#" xmlns:ns5="http://www.w3.org/2002/03/xkms#wsdl" ResultMajor="http://www.w3.org/2002/03/xkms#Success" RequestId="6a17ae45-21a2-4484-b5ec-c71b04dda0b2" Id="I-2984733849747242496" Service="http://cxf.apache.org/services/XKMS/"><ns2:UnverifiedKeyBinding><ns4:KeyInfo><ns4:X509Data><ns4:X509Certificate>MIIC...</ns4:X509Certificate></ns4:X509Data></ns4:KeyInfo></ns2:UnverifiedKeyBinding></ns2:LocateResult></soap:Body></soap:Envelope>

This certificate is then used to secure the service request using the Symmetric binding policy. For the Asymmetric testcase, the client also "validates" the certificate used by the service to secure the response.
Categories: Colm O hEigeartaigh

XML Encryption support in Apache Camel 2.12.0

Colm O hEigeartaigh - Mon, 09/09/2013 - 17:21
Apache Camel supports using XML Encryption (and decryption) in your Camel routes via the XML Security Data Format. I have contributed some additions to this component for the recent 2.12.0 release that may be of interest to existing or new users.

1) Upgrade to Apache Santuario 1.5.5

The Apache Santuario (XML Security for Java) dependency has been upgraded from 1.5.1 to 1.5.5. In addition, "secure validation" is now enabled by default. This property imposes some restrictions on acceptable XML Encryption Elements to limit potential attacks (although it applies more to XML Signature). See here for more information.

2) Switch to using RSA-OAEP as the Asymmetric Key Cipher algorithm

From Apache Camel 2.12.0, the default Asymmetric Key Cipher algorithm is now the RSA-OAEP algorithm. Previously it was RSA v1.5, which is vulnerable to attack. In addition, requests that use RSA v1.5 will be rejected by default, unless RSA v1.5 has been explicitly configured as the key cipher algorithm.

3) Support for some XML Encryption 1.1 algorithms

Support has been added for some XML Encryption 1.1 algorithms. Essentially this means the following:
  • You can now use "http://www.w3.org/2009/xmlenc11#rsa-oaep" as the Key Cipher Algorithm.
  • You can specify a stronger value for the digest algorithm when using RSA-OAEP. For example, you can use "http://www.w3.org/2001/04/xmlenc#sha256" instead of the default SHA-1 algorithm.
  • Support has been added for "gcm" symmetric cipher modes. For example, you can now set "http://www.w3.org/2009/xmlenc11#aes128-gcm" as the "xmlCipherAlgorithm" parameter.
  • Support has been added for MGF algorithms with stronger digest algorithms. For example, you can define "http://www.w3.org/2009/xmlenc11#mgf1sha256" for the "mgfAlgorithm" configuration parameter.
Categories: Colm O hEigeartaigh

Apache Syncope tutorial - part IV

Colm O hEigeartaigh - Tue, 08/20/2013 - 17:37
In the first tutorial on Apache Syncope, we showed how to deploy Syncope to Apache Tomcat, using MySQL as the internal storage mechanism. In the second and third tutorials, we showed how to import some users and roles into Syncope from database and directory backend resources. In this tutorial, we will show how an external client can query Syncope's REST API for the purposes of authentication and authorization. This tutorial assumes that Syncope is set up as described in tutorial I, and that Users + Roles have been imported as per tutorials II and III.

1) Syncope's REST API

Apache Syncope exposes its functionality via a rich REST API. Apache Syncope 1.1 features a new REST API, which is powered by Apache CXF. The new API has been created with the aim of applying RESTful best practices.

2) Querying Syncope's REST API

I've created some simple test-cases (hosted on github) based around a CXF SOAP client/service invocation, which show how to use Syncope's REST API for authentication and authorization.

a) Authentication

The Authentication test uses Syncope as an IDM for authentication. A CXF client sends a SOAP UsernameToken to a CXF Endpoint. The CXF Endpoint has been configured to validate the UsernameToken via the SyncopeUTValidator, which dispatches the username/passwords to Syncope for authentication via Syncope's REST API. Run the test via:
  • git clone git://github.com/coheigea/cxf-syncope.git
  • cd cxf-syncope
  • mvn test -Dtest=AuthenticationTest
Look at the console output to see how the CXF service dispatches the received Username/Password to Syncope for authentication. 

b) Authorization

The Authorization test uses Syncope as an IDM for authorization. It exploits the fact that we synchronized User's Roles into Syncope in tutorial IV. A CXF client sends a SOAP UsernameToken to a CXF Endpoint. The CXF Endpoint has configured the SyncopeRolesInterceptor, which authenticates the Username/Password to Syncope as per the authentication test. If authentication is successful, it then gets the roles of the user and populates a CXF SecurityContext with the user's name + roles.

The CXF Endpoint has also configured the SimpleAuthorizingInterceptor, which reads the current Subject's roles from the SecurityContext, and requires that a user must have role "boss" to access the "doubleIt" operation ("alice" has this role, "bob" does not). Run the test via:
  • git clone git://github.com/coheigea/cxf-syncope.git
  • cd cxf-syncope
  • mvn test -Dtest=AuthorizationTest


Categories: Colm O hEigeartaigh

Apache Syncope tutorial - part III

Colm O hEigeartaigh - Fri, 08/09/2013 - 17:07
In the first tutorial on Apache Syncope, we showed how to deploy Syncope to Apache Tomcat, and how to set up MySQL as the internal storage mechanism. In the second tutorial, we showed how to import some users into Syncope from a backend (Apache Derby) database resource. In this tutorial, we will look at synchronizing user and role data from an LDAP backend into Syncope, in this case Apache DS. This tutorial assumes that Syncope is set up as described in tutorial I, and that a Surname attribute has been added to the User attributes in Syncope, as described in tutorial II.

1) Apache DS

The basic scenario is that we have a directory that stores user and role information that we would like to import into Apache Syncope. In the previous tutorial, we only imported User data into Syncope. For the purposes of this tutorial, we will work with Apache DS. The first step is to download and launch Apache DS. I recommend installing Apache Directory Studio for an easy way to view the data stored in your directory.

Import the following ldif file into your Apache DS instance. Essentially this describes two users, "cn=alice,ou=users,ou=system" and "cn=bob,ou=users,ou=system", as well as two groups, "cn=employee,ou=groups,ou=system" and "cn=boss,ou=groups,ou=system". Both Alice and Bob are employees, but only Alice is the boss. We will import this user information into Syncope as per tutorial II. However, this time we will go further and import the group information as roles into Syncope. This will enable us to perform authorization checks against Syncope, as will be described in the next tutorial.

2) Synchronize user data into Apache Syncope

The next task is to import (synchronize) the user data from Apache DS into Apache Syncope. See the Syncope wiki for more information on this topic, as well as the following blog post. Launch Apache Syncope as per tutorial I/II.

a) Define a Connector

The first thing to do is to define a Connector. In tutorial I we configured two Connector bundles to use for Syncope, one for a DB backend, and one for an LDAP backend. In this section we select the LDAP Connector, and configure it to connect to the DS instance we have set up above. Go to "Resources/Connectors", and create a new Connector of name "org.connid.bundles.db.ldap". In the "Configuration" tab select:
  • Host: localhost
  • TCP Port: 10389
  • Principal: uid=admin,ou=system
  • Password: <password>
  • Base Contexts: ou=users,ou=system and ou=groups,ou=system
  • LDAP Filter for retrieving accounts: cn=*
  • groupObjectClasses: groupOfNames
  • Group member attribute: member
  • Uid attribute: cn
  • Base Context to Synchronize: ou=users,ou=system and ou=groups,ou=system
  • Object Classes to Synchronize: inetOrgPerson and groupOfNames
  • Status Management Class: org.connid.bundles.ldap.commons.AttributeStatusManagement
  • Tick "Retrieve passwords with search".
In the "Capabilities" tab select the following properties:
  • ONE_PHASE_CREATE
  • ONE_PHASE_UPDATE
  • ONE_PHASE_DELETE
  • SEARCH
  • SYNC
Click on the "helmet" icon in the "Configuration" tab to check to see whether Syncope is able to connect to the backend resource. If you don't see a green "Successful Connection" message, then consult the logs.

b) Define a Resource

Next we need to define a Resource that uses the LDAP Connector.  The Resource essentially defines how we use the Connector to map information from the backend into Syncope Users and Roles. Go into the "Resources" tab and select "Create New Resource". In the "Resource Details" tab select:
  • Name: (Select a name)
  • Connector: (Connector display name you have configured previously)
  • Enforce mandatory condition
  • Propagation Primary
  • Propagation Mode (see here): ONE_PHASE
  • Select "LDAPMembershipPropagationActions" for the "Actions class"
The next step is to create User mappings. Click on the "User mapping" tab, and create the following mappings:

    Enable "Account Link" and enter "'cn=' + username + ',ou=users,ou=system'", as shown in the screenshot. The next step is to create Role mappings. Click on the "Role mapping" tab, and create the following mapping:

    Enable "Account Link" and enter "'cn=' + name + ',ou=groups,ou=system'" as shown in the screenshot.

    c) Create a synchronization task

    Having defined a Connector and a Resource to use that Connector, with mappings to map User/Role information to and from the backend, it's time to import the backend information into Syncope.  Go to "Tasks" and select the "Synchronization Tasks" tab. Click on "Create New Task". On the "Profile" tab enter:
    • Name: (Select a name)
    • Resource Name: (The Resource name you have created above)
    • Actions Class: LDAPMembershipSyncActions
    • Create new identities
    • Updated matched identities
    • Delete matching identities
    • Status
    • Full reconciliation
    Save the task and then click on the "Execute" button. Now switch to the Users tab. You should see the users stored in the backend, and if you edit a user, you should be able to see what roles are associated with the user. In the "Roles" tab, you should see the imported Roles. For example, here are the roles that are associated with the user "Alice":



      Categories: Colm O hEigeartaigh

      Apache Syncope tutorial - part II

      Colm O hEigeartaigh - Fri, 07/26/2013 - 14:27
      In the previous tutorial on Apache Syncope, we described how to create a standalone application deployed in Apache Tomcat, and using MySQL as the persistent storage. In this tutorial we will show how to set up a basic schema for Syncope that describes the users that will be created in Syncope. Then we will show how to import users from a Database backend, which will be Apache Derby for the purposes of this tutorial.

      1) Creating a Schema attribute

      The first thing we will do is add a simple attribute for all users that will exist in Syncope. Launch Apache Syncope as per tutorial I. Click on the "Schema" tab, and then "Create New Attribute" in the Users/Normal subsection. Create a new attribute called "surname" which is of type "String" and "mandatory". So users in our Syncope application must have a "surname". Obviously, the schema allows you to do far more complex and interesting things, but this will suffice for the purposes of this tutorial.


      2) Apache Derby

      The basic scenario is that we have a SQL database that stores user information that we would like to import into Apache Syncope, to integrate into a BPEL workflow, expose via a RESTful interface, associate with roles, etc. For the purposes of this tutorial, we will work with Apache Derby. The first step is to download and launch Apache Derby, and then to populate it with a table with some user data. Hat tip to my Apache CXF colleague Glen Mazza for an excellent tutorial on setting up Apache Derby.

      a) Launch Apache Derby

      Download Apache Derby and extract it into a new directory ($DERBY_HOME). Create a directory to use to store Apache Derby databases ($DERBY_DATA). In $DERBY_DATA, create a file called 'derby.properties' with the content:

      derby.connection.requireAuthentication=true
      derby.user.admin=security

      In other words, authentication is required, and a valid user is "admin" with password "security". Now launch Apache Derby in network mode via:

      java -Dderby.system.home=$DERBY_DATA/ -jar $DERBY_HOME/lib/derbyrun.jar server start

      b) Create user data

      Create a new file called 'create-users.sql' with the following content:

      SET SCHEMA APP;
      DROP TABLE USERS;

      CREATE TABLE USERS (
        NAME   VARCHAR(20) NOT NULL PRIMARY KEY,
        PASSWORD  VARCHAR(20) NOT NULL,
        STATUS  VARCHAR(20) NOT NULL,
        SURNAME  VARCHAR(20) NOT NULL
      );

      INSERT INTO USERS VALUES('dave', 'password', 'true', 'yellow');
      INSERT INTO USERS VALUES('harry', 'password', 'true', 'blue');

      Launch Apache Derby via $DERBY_HOME/bin/ij. Then connect to the server via:

      connect 'jdbc:derby://localhost:1527/SYNCOPE;create=true;user=admin;password=security;';

      Populate user data via: run 'create-users.sql';

      You can now see the user data via: select * from users;

      3) Synchronize user data into Apache Syncope

      The next task is to import (synchronize) the user data from Apache Derby into Apache Syncope. See the Syncope wiki for more information on this topic.

      a) Define a Connector

      The first thing to do is to define a Connector. In tutorial I we configured two Connector bundles to use for Syncope, one for a DB backend, and one for an LDAP backend. In this section we select the DB Connector, and configure it to connect to the Derby instance we have set up above. Go to "Resources/Connectors", and create a new Connector of name "org.connid.bundles.db.table". In the "Configuration" tab select:
      • User: admin
      • User Password: security
      • Table: app.users
      • Key Column: name
      • Password Column: password
      • Status Column: status
      • JDBC Driver: org.apache.derby.jdbc.ClientDriver
      • JDBC Connection URL: jdbc:derby://localhost:1527/SYNCOPE
      • Enable 'Retrieve Password'
      Note that the Derby JDBC driver must be available on the classpath as per tutorial II. In the "Capabilities" tab select the following properties:
      • ONE_PHASE_CREATE
      • ONE_PHASE_UPDATE
      • ONE_PHASE_DELETE
      • SEARCH
      • SYNC
      Click on the "helmet" icon in the "Configuration" tab to check to see whether Syncope is able to connect to the backend resource. If you don't see a green "Successful Connection" message, then consult the logs.
        b) Define a Resource

        Next we need to define a Resource that uses the DB Connector.  The Resource essentially defines how we use the Connector to map information from the backend into Syncope Users and Roles. Go into the "Resources" tab and select "Create New Resource". In the "Resource Details" tab select:
        • Name: (Select a name)
        • Connector: (Connector display name you have configured previously)
        • Enforce mandatory condition
        • Propagation Primary
        • Propagation Mode (see here): ONE_PHASE
        • Select "DefaultPropagationActions" for the "Actions class"
        The next step is to create User mappings. Click on the "User mapping" tab, and create the following mappings:


          c) Create a synchronization task

          Having defined a Connector and a Resource to use that Connector, with mappings to map User information to and from the backend, it's time to import the backend information into Syncope.  Go to "Tasks" and select the "Synchronization Tasks" tab. Click on "Create New Task". On the "Profile" tab enter:
          • Name: (Select a name)
          • Resource Name: (The Resource name you have created above)
          • Actions class: DefaultSyncActions
          • Create new identities
          • Updated matched identities
          • Delete matching identities
          • Status
          • Full reconciliation
          Save the task and then click on the "Execute" button. Now switch to the Users tab. You should see the users stored in the backend. Click on one of the users, and see that the "surname" attribute is populated with the value mapped from the column stored in the backend:






            Categories: Colm O hEigeartaigh

            Apache Syncope tutorial - part I

            Colm O hEigeartaigh - Fri, 07/26/2013 - 14:26
            Apache Syncope is a new open source Identity Management project at Apache. This is the first of a planned four-part set of tutorials on how to get Apache Syncope up and running, how to integrate it with various backends, and how to interact with its REST API.

            In this tutorial we will explain how to create a new Apache Syncope project and how to deploy it to a container. We will also cover how to set up internal storage with a database, and how to install Connector bundles to communicate with backend resources. Please note that if you wish to download and play around with Apache Syncope, without going through the steps detailed in this tutorial to set it up for a standalone deployment, it is possible to download the 1.1.3 distribution and use an embedded Tomcat instance. In that case you can completely skip this tutorial and go straight to the next one.

            1) Set up a database for Internal Storage

            The first step in setting up a standalone deployment of Apache Syncope is to decide what database to use for Internal Storage. Apache Syncope persists internal storage to a database via Apache OpenJPA. In this article we will set up MySQL, but see here for more information on using PostgreSQL, Oracle, etc. Install MySQL in $SQL_HOME and create a new user for Apache Syncope. We will create a new user "syncope_user" with password "syncope_pass". Start MySQL and create a new Syncope database:
            • Start: sudo $SQL_HOME/bin/mysqld_safe --user=mysql
            • Log on: $SQL_HOME/bin/mysql -u syncope_user -p
            • Create a Syncope database: create database syncope; 
            2) Set up a container to host Apache Syncope

            The next step is to figure out in what container to deploy Syncope to. In this demo we will use Apache Tomcat, but see here for more information about installing Syncope in other containers. Install Apache Tomcat to $CATALINA_HOME. Now we will add a datasource for internal storage in Tomcat's 'conf/context.xml'. When Syncope does not find a datasource called 'jdbc/syncopeDataSource', it will connect to internal storage by instantiating a new connection per request, which carries a performance penalty. Add the following to 'conf/context.xml':

            <Resource name="jdbc/syncopeDataSource" auth="Container"
                type="javax.sql.DataSource"
                factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
                testWhileIdle="true" testOnBorrow="true" testOnReturn="true"
                validationQuery="SELECT 1" validationInterval="30000"
                maxActive="50" minIdle="2" maxWait="10000" initialSize="2"
                removeAbandonedTimeout="20000" removeAbandoned="true"
                logAbandoned="true" suspectTimeout="20000"
                timeBetweenEvictionRunsMillis="5000" minEvictableIdleTimeMillis="5000"
                jdbcInterceptors="org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;
                org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer"
                username="syncope_user" password="syncope_pass"
                driverClassName="com.mysql.jdbc.Driver"
                url="jdbc:mysql://localhost:3306/syncope?characterEncoding=UTF-8"/>

            Uncomment the "<Manager pathname="" />" configuration in context.xml as well. Next, download the JDBC driver jar for MySQL and put it in Tomcat's 'lib' directory. As we will be configuring a connector for a Derby resource in a future tutorial, also download the JDBC driver jar for Apache Derby and put it in Tomcat's 'lib' directory as well.

            3) Create a new Apache Syncope project

            To create a new Apache Syncope project, we must start with a Maven Archetype. For the purposes of this tutorial we will use Apache Syncope 1.1.3. Create a new directory to hold all of the project artifacts ($SYNCOPE_HOME). Create a new project in this directory as follows:

            mvn archetype:generate
                -DarchetypeGroupId=org.apache.syncope
                -DarchetypeArtifactId=syncope-archetype
                -DarchetypeRepository=http://repos1.maven.apache.org/maven2/
                -DarchetypeVersion=1.1.3

            Enter values as requested for the 'groupId', 'artifactId', 'version', 'package' and 'secretKey'. A new Syncope project will be created in a directory corresponding to the value entered for 'artifactId'. Build the project by going into the newly created directory and typing "mvn clean package". To launch Syncope in "embedded" mode, go into the "console" subdirectory and type "mvn -Pembedded". This provides a quick way to start up Syncope with some test data and connectors pre-installed, along with a H2 instance for internal storage. However, instead of doing this we will set up a proper standalone deployment.

            4) Install ConnId bundles

            Apache Syncope uses bundles supplied by the ConnId project to communicate with backend resources. In part III of this series of tutorials we will cover importing users from a database backend, and part IV will cover using a directory backend. Therefore, we need two ConnId bundles to handle these scenarios. Create two new directories in $SYNCOPE_HOME, one called "bundles" to store the ConnId bundles, and another called "logs" to store logging information. Go to the ConnId download page, and download the relevant jars to the bundles directory you have created. It should have the following files:
            • org.connid.bundles.ldap-1.3.6.jar
            • org.connid.bundles.db.table-2.1.5.jar.
            5) Configure the Apache Syncope project

            After creating the Apache Syncope project, we need to configure it to use the ConnId bundles we have downloaded, the logging directory we have created, and the MySQL instance for internal storage.

            Edit 'core/src/main/resources/persistence.properties' in your Syncope project, and replace the existing configuration with the following:

            jpa.driverClassName=com.mysql.jdbc.Driver
            jpa.url=jdbc:mysql://localhost:3306/syncope?characterEncoding=UTF-8
            jpa.username=syncope_user
            jpa.password=syncope_pass
            jpa.dialect=org.apache.openjpa.jdbc.sql.MySQLDictionary
            quartz.jobstore=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
            quartz.sql=tables_mysql.sql
            logback.sql=mysql.sql

            Edit 'core/src/main/webapp/WEB-INF/web.xml' and uncomment the "resource-ref" section (this is required as we are using a DataSource in Tomcat). If your Tomcat instance is starting on a port other than 8080, edit 'console/src/main/resources/configuration.properties' and change the port number.

            6) Deploy Apache Syncope to Tomcat

            Package everything up by executing the following command from the Syncope project:

            mvn clean package -Dbundles.directory=${bundles.dir} -Dlog.directory=${log.dir}

            Deploy 'core/target/syncope.war' and 'console/target/syncope-console.war' to the Tomcat 7 container. Start Tomcat and point a browser at "localhost:8080/syncope-console", logging in as "admin/password". You should see the following:


            At this point you should have successfully deployed Apache Syncope in the Apache Tomcat container, using MySQL as the internal storage. If this is not the case then consult the Tomcat logs, as well as the Syncope logs in the directory you have configured. In the next couple of tutorials we will look at importing data into our Syncope application from various backend resources.

            Categories: Colm O hEigeartaigh

            Pages

            Subscribe to Talend Community Coders aggregator - Colm O hEigeartaigh