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.
Thursday, January 23, 2014
Thursday, January 9, 2014
SAML "OneTimeUse" support in Apache CXF 2.7.8
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:
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.
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.
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.
Wednesday, January 8, 2014
Apache WSS4J 2.0.0 - part I
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:
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:
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:
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:
WSS4J 2.0.0 uses three EhCache-based caches by default for the following scenarios, to prevent replay attacks:
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
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.
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.
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
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
Wednesday, December 18, 2013
Security Advisory CVE-2013-4517 released
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).
"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).
Friday, November 8, 2013
Apache CXF STS client configuration options
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:
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.
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).
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.
Monday, November 4, 2013
XKMS functionality in Apache CXF
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.
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.
Monday, September 9, 2013
XML Encryption support in Apache Camel 2.12.0
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:
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.
Subscribe to:
Posts (Atom)