Colm O hEigeartaigh

Apache CXF STS documentation - part I

Colm O hEigeartaigh - Wed, 10/19/2011 - 18:00
The forthcoming Apache CXF 2.5 release will have an STS (Security Token Service) implementation which has been donated by Talend. This is the first in a series of blog posts where I will be going into the STS implementation in detail. In this post I will be explaining what an STS is and talking about the STS provider framework in CXF.

1) What is a Security Token Service?

An informal description of a Security Token Service is that it is a web service that offers some or all of the following services (amongst others):
  • It can issue a Security Token of some sort based on presented or configured credentials.
  • It can say whether a given Security Token is valid or not
  • It can renew (extend the validity of) a given Security Token
  • It can cancel (remove the validity of) a given Security Token
  • It can transform a given Security Token into a Security Token of a different sort.
Offloading this functionality to another service greatly simplifies client and service provider functionality, as they can simply call the STS appropriately rather than have to figure out the security requirements themselves. For example, the WSDL of a service provider might state that a particular type of security token is required to access the service. A client of the service can ask an STS for a Security Token of that particular type, which is then sent to the service provider. The service provider could choose to validate the received token locally, or dispatch the token to an STS for validation. These are the two most common use-cases of an STS.

A client can communicate with the STS via a protocol defined in the WS-Trust specification. The SOAP Body of the request contains a "RequestSecurityToken" element that looks like:

<wst:RequestSecurityToken Context="..." xmlns:wst="...">
    <wst:TokenType>...</wst:TokenType>
    <wst:RequestType>...</wst:RequestType>
    <wst:SecondaryParameters>...</wst:SecondaryParameters>
    ...
</wst:RequestSecurityToken>

The Apache CXF STS implementation supports a wide range of parameters that are passed in the RequestSecurityToken element. The SOAP Body of the response from the STS will contain a "RequestSecurityTokenResponse(Collection)" element, e.g.:

<wst:RequestSecurityTokenResponseCollection xmlns:wst="...">
    <wst:RequestSecurityTokenResponse>
    ...
    </wst:RequestSecurityTokenResponse>
</wst:RequestSecurityTokenResponseCollection>

1.1 A sample request/response for issuing a Security Token

A sample client request is given here, where the client wants the STS to issue a SAML 2.0 token for the "http://cxf.apache.org:8080/service" service:

<wst:RequestSecurityToken Context="..." xmlns:wst="...">
    <wst:TokenType>
       http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0
    </wst:TokenType>
    <wst:RequestType>
        http://docs.oasis-open.org/ws-sx/ws-trust/200512/Issue
    </wst:RequestType>
    <wsp:AppliesTo>http://cxf.apache.org:8080/service</wsp:AppliesTo>
</wst:RequestSecurityToken>

The STS responds with:

<wst:RequestSecurityTokenResponseCollection xmlns:wst="...">
    <wst:RequestSecurityTokenResponse>
         <wst:TokenType>
         http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0
         </wst:TokenType>
         <wst:RequestedSecurityToken>
             <saml2:Assertion xmlns:saml2="..." ... />
         </wst:RequestedSecurityToken>
    </wst:RequestSecurityTokenResponse>
</wst:RequestSecurityTokenResponseCollection>

2) The STS provider framework in Apache CXF

The first support for an STS in Apache CXF appeared in the 2.4.0 release with the addition of an STS provider framework in the WS-Security module. This is essentially an API that can be used to create your own STS implementation. As the STS implementation shipped in CXF 2.5 is based on this provider framework, it makes sense to examine it in more detail.

The SEI (Service Endpoint Interface) is available here. It contains the following methods that are relevant to the STS features discussed above:
  • RequestSecurityTokenResponseCollectionType issue(RequestSecurityTokenType request) - to issue a security token
  • RequestSecurityTokenResponseType issueSingle( RequestSecurityTokenType request) - to issue a security token that is not contained in a "Collection" wrapper (for legacy applications).
  • RequestSecurityTokenResponseType cancel(RequestSecurityTokenType request) - to cancel a security token
  • RequestSecurityTokenResponseType validate(RequestSecurityTokenType request) - to validate a security token
  • RequestSecurityTokenResponseType renew(RequestSecurityTokenType request) - to renew a security token
The SEI implementation handles each request by delegating it to a particular operation, which is just an interface that must be implemented by the provider framework implementation. Finally, a JAX-WS provider is available, which dispatches a request to the appropriate operation.

Significant updates to the STS Provider framework after the CXF 2.4.0 release include support for SOAP 1.2, a major bug fix to support operations other than issue,  better exception propagation, and adding support for the WS-Trust 1.4 schema. These features are all available in the Apache CXF 2.4.3 release onwards.
Categories: Colm O hEigeartaigh

Using Kerberos with Web Services - part II

Colm O hEigeartaigh - Tue, 10/11/2011 - 18:03
This is the second of a two-part series on using Kerberos with Web Services, with Apache WSS4J and CXF. Part I showed how to set up a KDC distribution, and how to generate client and service principals to use in some CXF system tests. The system tests showed how to obtain a Kerberos token from a KDC, package it in a BinarySecurityToken, and send it to a service endpoint for validation. In other words, part I illustrated how to use Kerberos for client authentication in a web service setting.

This article builds on part I by showing how to use the secret key associated with a Kerberos Token to secure (sign and encrypt) the request. This functionality was added as part of WSS4J 1.6.3, and the related WS-SecurityPolicy functionality was released as part of CXF 2.4.3.

1) Setting up the Kerberos system tests in Apache CXF 

If you have not done so already, follow the instructions in part I to install a Kerberos distribution and to generate client and service principals to run the CXF Kerberos system tests. The KerberosTokenTest in Apache CXF contains a number of different Kerberos tests. In this article we will examine the tests that involve obtaining a Kerberos Token, and using the associated secret key to secure some part of the request.

Firstly, make sure that the JDK has unlimited security policies installed, and then checkout the CXF WS-Security system tests via:
svn co https://svn.apache.org/repos/asf/cxf/trunk/systests/ws-security/1.1) Installing a custom KerberosTokenDecoder

Once the client obtains an AP-REQ token from the KDC, the client also has easy access to the session key, which can be used to secure the request in some way. Unfortunately, there appears to be no easy way to obtain the session key on the receiving side. WSS4J does not support extracting a Kerberos session key on the receiving side to decrypt/verify a secured request out-of-the-box. Instead, a KerberosTokenDecoder interface is provided, which defines methods for setting the AP-REQ token and current Subject, and a method to then get a session key. An implementation must be set on the KerberosTokenValidator to obtain a session key to decrypt or verify a signed request.

To run the Kerberos system tests that require a secret key on the receiving side, download an implementation of the KerberosTokenValidator interface here, and copy it to "systests/ws-security/src/test/java/org/apache/cxf/systest/ws/kerberos/server". The implementation is based on code written by the Java Monkey, and uses internal sun APIs, and so can't be shipped in Apache CXF/WSS4J. Once this implementation has been copied into the ws-security module, then you must compile or run any tests with the "-Pnochecks" profile enabled, as otherwise the code fails checkstyle.

Open the server configuration file ("src/test/resources/org/apache/cxf/systest/ws/kerberos/server/server.xml"), and uncomment the "kerberosTicketDecoderImpl" bean, and the property of the "kerberosValidator" bean that refers to it:
<bean id="kerberosTicketDecoderImpl"   class="org.apache.cxf.systest.ws.kerberos.server.KerberosTokenDecoderImpl"/>
 
<bean id="kerberosValidator"
       class="org.apache.ws.security.validate.KerberosTokenValidator">
        <property name="contextName" value="bob"/>
        <property name="serviceName" value="bob@service.ws.apache.org"/>
        <property name="kerberosTokenDecoder" ref="kerberosTicketDecoderImpl"/>
</bean> 1.2) Running the tests

Open KerberosTokenTest.java and comment out the "@org.junit.Ignore" entries for the last four tests, "testKerberosOverTransportEndorsing", "testKerberosOverAsymmetricEndorsing", "testKerberosOverSymmetricProtection" and "testKerberosOverSymmetricDerivedProtection". Finally, run the tests via:
mvn -Pnochecks test -Dtest=KerberosTokenTest -Djava.security.auth.login.config=src/test/resources/kerberos.jaas 2) The tests in more detail

In this section, we'll look at the tests in more detail. 

2.1) WS-SecurityPolicy configuration

The wsdl that defines the service endpoints contains WS-SecurityPolicy expressions that define the security requirements of the endpoints. The following security policies are used for the four tests defined above:
  • testKerberosOverTransportEndorsing: A (one-way) transport binding is defined, with a KerberosToken required as an EndorsingSupportingToken. 
  • testKerberosOverAsymmetricEndorsing: An asymmetric binding is used, where a KerberosToken is required as an EndorsingSupportingToken.
  • testKerberosOverSymmetricProtection: A symmetric binding is used, where a KerberosToken is specified as a ProtectionToken of the binding.
  • testKerberosOverSymmetricDerivedProtection: The same as the previous test-case, except that any secret keys that are used must be derived.
The first two test-cases use an EndorsingSupportingToken, which means that the secret key associated with the KerberosToken is used to sign (endorse) some message part (the timestamp for the Transport binding). This illustrates proof-of-possession. For the latter two test-cases, the KerberosToken is defined as a ProtectionToken, meaning that the secret key is used to sign/encrypt the request (e.g. instead of using an X.509 Token to encrypt a session key).

2.2) Kerberos LoginModule configuration

Both the CXF client and service endpoint use JAAS to authenticate to the KDC. The JAAS file used as part of the system test is passed to the tests via the System property "java.security.auth.login.config". The client (alice) uses the following login module:
alice {
    com.sun.security.auth.module.Krb5LoginModule required
    refreshKrb5Config=true useKeyTab=true keyTab="/etc/alice.keytab"
    principal="alice";
};and the service endpoint (bob) uses:
bob {
    com.sun.security.auth.module.Krb5LoginModule required
    refreshKrb5Config=true useKeyTab=true storeKey=true
    keyTab="/etc/bob.keytab" principal="bob/service.ws.apache.org";
}; 2.3) Service endpoint configuration

The service endpoints are spring-loaded. Each endpoint definition contains the JAX-WS property "ws-security.bst.validator" which is defined in SecurityConstants. WSS4J uses Validator implementations to perform validation on received security tokens. This particular property means that BinarySecurityTokens are to be validated by the given reference, e.g.:

<jaxws:endpoint ...>
    <jaxws:properties>      
        <entry key="ws-security.bst.validator" value-ref="kerberosValidator"/>
    </jaxws:properties>
</jaxws:endpoint> "kerberosValidator" is a KerberosTokenValidator instance given above. It requires a "contextName" property, which corresponds to the JAAS context name, as well as an optional "serviceName" property, and an optional "kerberosTokenDecoder" property to use to obtain a secret key. Combined with the JAAS properties file, this is all that is required for the service endpoint to validate a received Kerberos Token. 

2.4 Client configuration

Finally, the client must contact a KDC and obtain a Kerberos Token, once it sees that the service endpoint has a security policy that requires a KerberosToken. The client configuration is available here. A sample configuration for the Kerberos Test case is as follows:
<jaxws:client name="{...}DoubleItKerberosTransportPort"
       createdFromAPI="true">
       <jaxws:properties>
           <entry key="ws-security.kerberos.client">
               <bean class="org.apache.cxf.ws.security.kerberos.KerberosClient">
                   <constructor-arg ref="cxf"/>
                   <property name="contextName" value="alice"/>
                   <property name="serviceName" value="bob@service.ws.apache.org"/>
               </bean>           
           </entry>
       </jaxws:properties>
</jaxws:client>The JAX-WS property "ws-security.kerberos.client" (again, defined in SecurityConstants) corresponds to a KerberosClient object. Similar to the KerberosTokenValidator on the receiving side, this is configured with a JAAS context Name and service Name.
Categories: Colm O hEigeartaigh

Apache CXF STS articles

Colm O hEigeartaigh - Tue, 10/11/2011 - 15:21
Two of my colleagues have written excellent articles on the forthcoming STS (Security Token Service) implementation in Apache CXF, complete with sample projects. See here for the article from Oliver Wulff, and here for the article from Glen Mazza.
Categories: Colm O hEigeartaigh

Using Kerberos with Web Services - part I

Colm O hEigeartaigh - Mon, 10/10/2011 - 18:00
This is the first of a two-part series on using Kerberos with Web Services, with Apache WSS4J and CXF. WSS4J 1.6.2 adds support for obtaining a Kerberos ticket from a KDC (Key Distribution Center) and converting it to a BinarySecurityToken to be inserted into the security header of a SOAP request. On the receiving side, support has been added to validate the received Kerberos ticket accordingly. CXF 2.4.2 extends the Kerberos functionality available in WSS4J 1.6.2 to add support for WS-SecurityPolicy. No support is available yet (as of CXF 2.4.2) to use a secret key to sign and encrypt message parts, this will be the subject of part II.

In this post we will talk about installing the MIT Kerberos distribution in Ubuntu, and creating the necessary credentials to run some tests. Then we will go into some system tests in CXF that show how a client can get a Kerberos AP-REQ ticket from a KDC and send it to a service provider, who then authenticates the ticket, all driven by some spring configuration and WS-SecurityPolicy.

1) Installing MIT Kerberos

1.1) Installing the product

In this section we cover how to install the MIT Kerberos distribution in Ubuntu. This is needed to run the CXF Kerberos system tests. See here for more information on using Kerberos on Ubuntu. Open a command prompt and type:
sudo apt-get install krb5-kdc krb5-admin-serverWhen the product is installing you'll be asked for the default Kerberos Version 5 realm. Enter:
WS.APACHE.ORG You will then be prompted for the hostnames of Kerberos servers in the WS.APACHE.ORG Kerberos realm. As we are installing the KDC and running the tests on the same machine, we only need to enter "localhost". Similarly, enter "localhost" when prompted for the Administrative server for the Kerberos realm.

1.2) Modifying configuration

Once apt-get has finished, we need to modify the Kerberos configuration file ("sudo vi /etc/krb5.conf"):
  • Under the "[realms]" section, add a "default_domain" entry for ws.apache.org. The entire entry should look like:
    WS.APACHE.ORG = {
                 kdc = localhost
                 admin_server = localhost
                 default_domain = ws.apache.org
    }
  • Under the "[domain_realm]" section, add the following:     
ws.apache.org = WS.APACHE.ORG   
.ws.apache.org = WS.APACHE.ORG
  • Finally, add a logging section:
[logging]

        kdc = FILE:/var/log/krb5kdc.log
        admin_server = FILE:/var/log/kadmin.log
        default = FILE:/var/log/krb5lib.log 1.3) Create principals

The next step is to create some principals. Create a master key via:
sudo kdb5_util create -sThe next step is to start kadmin locally via:
sudo kadmin.localIf you run "listprincs" at the prompt you should see the ticket-granting-ticket principal "krbtgt/WS.APACHE.ORG@WS.APACHE.ORG". We will add a client principal and service principal:
addprinc alice
addprinc bob/service.ws.apache.org"quit" the kadmin prompt, and start the KDC with "sudo krb5kdc". If you see no error messages then everything should be working correctly. To test this try to get a ticket for "alice" via "kinit alice", entering the password given when creating the "alice" principal.

1.4) Create keytabs

To avoid having to enter passwords when running the tests, we will create Keytabs. Start kadmin.local again ("sudo kadmin.local"), and enter:
ktadd -k /etc/alice.keytab alice
ktadd -k /etc/bob.keytab bob/service.ws.apache.orgTo check that the keytabs were create correctly, you can inspect them with klist, e.g. "sudo klist -k /etc/alice.keytab". Finally make sure the keytabs are readable via "sudo chmod og+r /etc/*.keytab" - obviously this is not secure, but it is sufficient for this test application.

2) Running the Kerberos system tests in Apache CXF

Now that we have installed Kerberos and created the relevant principals, we can run the Kerberos system tests in Apache CXF. These tests are @Ignore'd by default. The KerberosTokenTest contains a number of different Kerberos tests. In this article we will just examine the tests that involve obtaining a Kerberos Token, and not any of the tests that involve using the secret key associated with a Kerberos Token to secure some part of the request.

Firstly, make sure that the JDK has unlimited security policies installed, and then checkout the CXF WS-Security system tests via:
svn co https://svn.apache.org/repos/asf/cxf/trunk/systests/ws-security/Open KerberosTokenTest.java and comment out the "@org.junit.Ignore" entries for the first four tests, "testKerberosOverTransport", "testKerberosOverSymmetric", "testKerberosOverSymmetricSupporting" and "testKerberosOverAsymmetric". Finally, run the tests via:

        mvn test -Dtest=KerberosTokenTest -Djava.security.auth.login.config=src/test/resources/kerberos.jaas

2.1) WS-SecurityPolicy configuration

The wsdl that defines the service endpoints contains WS-SecurityPolicy expressions that define the security requirements of the endpoints. The following security policies are used for the four tests defined above:
  • testKerberosOverTransport: A (one-way) transport binding is defined, with a KerberosToken required as a SupportingToken. Essentially, this means that the communication is secured with TLS, and authentication is handled by a Kerberos token.
  • testKerberosOverSymmetric: A symmetric binding is used, where a KerberosToken is required as a SignedSupportingToken. 
  • testKerberosOverSymmetricSupporting: A symmetric binding is used, where a KerberosToken is required as a SupportingToken.
  • testKerberosOverAsymmetric: An asymmetric binding is used, where a Kerberos token is required as a SignedSupportingToken.
The WS-SecurityPolicy expression used for a KerberosToken is:
<sp:KerberosToken sp:IncludeToken=".../Once">
    <wsp:Policy>
        <sp:WssGssKerberosV5ApReqToken11/>
    </wsp:Policy>
</sp:KerberosToken>This means that a GSS V5 AP-REQ Token is required "once", in other words the initial invocation between the client and service endpoint must contain a token of this type encoded as a BinarySecurityToken in the security header of the request.

2.2) Kerberos LoginModule configuration

Both the CXF client and service endpoint use JAAS to authenticate to the KDC. The JAAS file used as part of the system test is passed to the tests via the System property "java.security.auth.login.config". The client (alice) uses the following login module:
alice {
    com.sun.security.auth.module.Krb5LoginModule required 
    refreshKrb5Config=true useKeyTab=true keyTab="/etc/alice.keytab"  
    principal="alice";
};and the service endpoint (bob) uses:
bob {
    com.sun.security.auth.module.Krb5LoginModule required
    refreshKrb5Config=true useKeyTab=true storeKey=true
    keyTab="/etc/bob.keytab" principal="bob/service.ws.apache.org";
}; 2.3) Service endpoint configuration

The service endpoints are spring-loaded. Each endpoint definition contains the JAX-WS property "ws-security.bst.validator" which is defined in SecurityConstants. WSS4J uses Validator implementations to perform validation on received security tokens. This particular property means that BinarySecurityTokens are to be validated by the given reference, e.g.:
<jaxws:endpoint ...>   
    <jaxws:properties>      
        <entry key="ws-security.bst.validator" value-ref="kerberosValidator"/>
    </jaxws:properties>
</jaxws:endpoint> "kerberosValidator" is defined as:
<bean id="kerberosValidator"
    class="org.apache.ws.security.validate.KerberosTokenValidator">
    <property name="contextName" value="bob"/>
    <property name="serviceName" value="bob@service.ws.apache.org"/>
</bean>The KerberosTokenValidator class ships with Apache WSS4J. It requires a "contextName" property, which corresponds to the JAAS context name, as well as an optional "serviceName" property. Combined with the JAAS properties file, this is all that is required for the service endpoint to validate a received Kerberos Token. 

2.4 Client configuration

Finally, the client must contact a KDC and obtain a Kerberos Token, once it sees that the service endpoint has a security policy that requires a KerberosToken. The client configuration is available here. A sample configuration for the Kerberos Test case is as follows:
<jaxws:client name="{...}DoubleItKerberosTransportPort"
       createdFromAPI="true">
       <jaxws:properties>
           <entry key="ws-security.kerberos.client">
               <bean class="org.apache.cxf.ws.security.kerberos.KerberosClient">
                   <constructor-arg ref="cxf"/>
                   <property name="contextName" value="alice"/>
                   <property name="serviceName" value="bob@service.ws.apache.org"/>
               </bean>           
           </entry>
       </jaxws:properties>
</jaxws:client>The JAX-WS property "ws-security.kerberos.client" (again, defined in SecurityConstants) corresponds to a KerberosClient object. Similar to the KerberosTokenValidator on the receiving side, this is configured with a JAAS context Name and service Name.
Categories: Colm O hEigeartaigh

Improving decryption performance in Apache Santuario 1.5

Colm O hEigeartaigh - Fri, 10/07/2011 - 13:10
Andreas Veithen alerted me some months back to a performance problem in Apache Santuario when decrypting messages. The issue emerged when some profiling was done on Dennis Sosnoski's test-code for measuring WS-Security performance across different web services stacks (see the original article here).

The test scenario involves deploying an Apache CXF 2.4.2 endpoint in Tomcat and repeatedly testing the "signencr" invocation defined in the article (WS-Security signing of body and headers, with timestamp and encryption of body) using a CXF client. Two types of test-runs were executed, 1000 "large" messages at 0.2 density in one run, and 10000 "small" messages at 0.05 density in another. When doing some profiling using a sampling profiler on the client, it emerged that the time it took to deserialize a decrypted XML String into a DOM element was taking around 20% of the total execution time for all WS-Security processing!

The way the default deserializing algorithm works in Apache Santuario 1.4.x is to parse the decrypted XML String into a new Document object, which is then imported into the existing Document. As Apache Xerces defers the creation of Node objects, the import operation triggers the full expansion of the DOM tree.

There are a number of alternatives to using the DocumentBuilder/importNode approach used in Santuario 1.4.x. The first approach is to use a Transformer object to transform the Source (XML String) into a placeholder Node belonging to the existing Document. This approach avoids having to explicitly import the nodes back to the existing Document. The second approach, is to use the streaming API available in the JDK 1.6 (not an option for Santuario 1.5 which must compile against the JDK 1.5).

Here are some (ad-hoc) test results. The first results show the total time for each test-run using both algorithms:
  • Large Messages:
    • Document Serializer: 119.46s
    • Transform Serializer: 115.68s
  • Small Messages:
    • Document Serializer: 222.32s
    • Transform Serializer: 216.76s
The next results show the time spent in the Serializer.deserialize() operation as a percentage of the total WS-Security processing time:
  • Large Messages:
    • Document Serializer: 19.92%
    • Transform Serializer: 18.04%
  • Small Messages:
    • Document Serializer: 24.54%
    • Transform Serializer: 18.36%
As there is a clear performance improvement in using the Transformer approach, it makes sense to use this as the default serializing mechanism in Apache Santuario 1.5. The Serializer interface is now public, and a different implementation can be set on XMLCipher. Two implementations are provided in the code, DocumentSerializer and TransformSerializer (the new default algorithm). If anyone is interested in running experiments of their own, the StreamSerializer algorithm is available here.

Do you have any suggestions on how this could be improved further? Clearly, the time it takes to deserialize a decrypted XML String into a DOM node still takes far longer than it should. A fully StAX approach for XML Security would surely offer much improved performance - this is under development and planned for next year.
Categories: Colm O hEigeartaigh

Apache WSS4J 1.6.3 released

Colm O hEigeartaigh - Tue, 10/04/2011 - 14:39
Apache WSS4J 1.6.3 has been released. It can be downloaded here and the issues fixed are listed in the WSS4J JIRA.

Probably the most significant part of this release is that WSS4J now fully supports the Kerberos Token Profile 1.1. In the previous release, support was added to retrieve a Kerberos token from a KDC, and insert it into the security header of a request, and then validate it accordingly on the receiving side. In WSS4J 1.6.3, support has been added to use the secret key associated with the Kerberos token to sign and encrypt the request, and to verify and decrypt on the receiving side. I am planning on writing a series of blog posts soon about how to use Kerberos with WSS4J and CXF. The forthcoming Apache CXF 2.4.3 release will have full WS-SecurityPolicy support for working with Kerberos, based on the work done in WSS4J 1.6.3.

In addition to the Kerberos work, WSS4J 1.6.3 features an upgraded Opensaml dependency, as well as several bug fixes.
Categories: Colm O hEigeartaigh

Talend donates Security Token Service (STS) to Apache CXF

Colm O hEigeartaigh - Fri, 09/23/2011 - 16:31
I am pleased to announce that Talend has donated a Security Token Service (STS) implementation to Apache CXF, which will be part of the forthcoming 2.5 release. Since the 2.4.0 release, CXF ships with an STS framework (in the ws-security module), as well as a simple implementation of the framework in the examples. The STS that Talend has donated to the community is a sophisticated implementation of the STS framework that builds on top of CXF's existing mature security functionality.

In future blog posts I will document the features of the STS and how to configure it, as well as walk through some system tests. Here are some of the features and standards that the new STS supports:
  • WS-Trust 1.3/1.4
  • WS-SecurityPolicy1.3
  • Authentication Mechanisms for a RST:UsernameToken, SAML token (1.1/2.0), KerberosToken, X.509 Token.
  • Security Binding supported: Symmetric,Asymmetric, Transport 
  • Supports WS-Trust Issue/Validate and Cancel binding 
  • Can issue the following tokens:SAML 1.1/2.0Holder-Of-Key/Bearer, SecurityContextTokens, Custom Tokens.
  • Issued token can be encrypted 
  • Validate binding supports issuing a new token (token transformation).
  • Custom Validators can be implemented 
  • Creation of SAML tokens can be customized.
  • Advanced RST elements:KeyType (Public, Symmetric, Bearer), Entropy (Symmetric, Public) , OnBehalfOf, ActAs, Claims, SecondaryParameters
  • Pluggable claims handling and management
Categories: Colm O hEigeartaigh

Specifying custom AlgorithmSuite policies in Apache CXF 2.4.3

Colm O hEigeartaigh - Mon, 09/19/2011 - 12:01
When specifying a security binding via WS-SecurityPolicy, it is possible to define the algorithm suite via the "sp:AlgorithmSuite" policy. WS-SecurityPolicy defines a number of standard AlgorithmSuite policies, which control various security properties like the maximum and minimum Symmetric and Asymmetric key lengths, the encryption/signature/digest algorithms to use, etc. An example policy is given below. For this policy, the minimum symmetric key length is 256 bits, and the encryption algorithm is AES256:

<sp:AlgorithmSuite>
    <wsp:Policy>
        <sp:Basic256 />
    </wsp:Policy>
</sp:AlgorithmSuite>

There are certain scenarios where a user might want to use a non-standard AlgorithmSuite. For example, the minimum Asymmetric Key Length for all standard AlgorithmSuites is 1024 bits. This requires that the JDK has unrestricted security policies installed. If it is not possible to install unresticted security policies, a user might decide that using 512 bits RSA keys is sufficient (this is not recommended).

Apache CXF 2.4.3 provides support for specifying custom algorithm suites. A new interface is defined to create an AlgorithmSuite object given a policy, with a default implementation that supports the standard AlgorithmSuite policies. It is possible to create a new implementation of the AlgorithmSuiteLoader interface, and install it as a bus extension. For an example, there is a CXF system test that allows 512 bit asymmetric keys, with custom AlgorithmSuiteLoader and AlgorithmSuite implementations. The custom AlgorithmSuiteLoader implementation is spring-loaded, and registers itself as a bus extension.
Categories: Colm O hEigeartaigh

SAML SecurityPolicy enforcement in CXF 2.4.2

Colm O hEigeartaigh - Mon, 09/12/2011 - 14:44
Apache CXF 2.4.2 was released recently. In this blog post I want to delve into how CXF 2.4.2 enforces WS-SecurityPolicy expressions relating to SAML Assertions on the inbound side.

There are two policy expressions relating to SAML Assertions, the SamlToken and IssuedToken policy assertions. On the outbound side, the SamlToken expression will trigger a CallbackHandler to obtain a SAML Assertion to insert into the outbound security header, and the IssuedToken expression will use the STSClient to obtain a SAML Assertion from a Security Token Service (STS).

On the inbound side, any SAML Assertion received as part of the security header will be parsed initially by WSS4J. If the assertion is signed, then the signature is verified. If the confirmation method of the Subject of the Assertion is "holder-of-key", then WSS4J will parse the Subject KeyInfo and extract whatever credentials it can find, i.e. secret key or an X509Certificate. If no credential is found (or understood), then the default behaviour is to throw an exception. If the confirmation method is "holder-of-key", then the default behaviour (which is configurable) is to enforce that the Assertion is signed. Finally, WSS4J verifies trust in a certificate that was used to sign the assertion.

After WSS4J is done with validating a received SAML Assertion, CXF does some additional validation according to the configured security policy. For more information on any of the following terms (holder-of-key, sender-vouches, etc.), please consult the SAML Token Profile 1.1 specification.

1) SamlToken policy

If a SamlToken policy is used, the version of the received Assertion (1.1 or 2.0) is checked against the policy, e.g. if <sp:WssSamlV20Token11 /> is configured in the SAMLToken policy then the received Assertion must be a SAML 2.0 Assertion. Two checks are then done on the received Assertion, depending on what the subject confirmation method is.
  • Holder-of-key: If the subject confirmation method is "holder-of-key", there must be some proof-of-possession of the key associated with the subject of the assertion. CXF will enforce that either the key was used to sign some portion of the SOAP request, or alternatively the subject credential of the SAML Assertion must match a client certificate credential when 2-way TLS is used.
  • Sender-Vouches: If the subject confirmation method is "sender-vouches", then CXF will enforce that the SAML Assertion and SOAP Body are signed by the same signature. Alternatively, it will check that 2-way TLS is used.
2) IssuedToken Policy

If an IssuedToken policy is used, then the receiver is expecting to get a SAML Assertion that is issued by a third-party security service. If the subject confirmation method of the Assertion is "holder-of-key", then it does the same check as described above for a SamlToken policy. Additionally, if a "<sp:RequestSecurityTokenTemplate..../>" policy is configured, it will attempt to match the received Assertion against the RSTTemplate parameters:
  • TokenType: If a TokenType parameter is specified in the template, it will match this against the version of the received Assertion. For example, if the TokenType is "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1", then the Assertion must be a SAML 1.1 Assertion.
  • KeyType: If a KeyType parameter is specified in the template which ends with "SymmetricKey", then the subject of the Assertion must contain a secret key. If the KeyType parameter ends with "PublicKey", then the Subject must contain a Certificate or PublicKey.
Here is an example of a RequestSecurityTokenTemplate:

<sp:RequestSecurityTokenTemplate>
    <t:TokenType>
      http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile1.1#SAMLV1.1
   </t:TokenType>
   <t:KeyType>
     http://docs.oasis-open.org/ws-sx/ws-trust/200512/PublicKey
   </t:KeyType>
</sp:RequestSecurityTokenTemplate>

Issuer or IssuerName policies are not yet enforced, this will probably be done in a future version of CXF.
Categories: Colm O hEigeartaigh

Apache WSS4J 1.5.12 and 1.6.2 released

Colm O hEigeartaigh - Thu, 08/18/2011 - 15:21
Apache WSS4J 1.5.12 and 1.6.2 have been released.

WSS4J 1.5.12 is a bug-fix release, which fixes some problems relating to future-dated Timestamps, fixes a bug with deriving keys from UsernameTokens, and fixes a concurrency issue with EnvelopeIdResolver, amongst other things.

WSS4J 1.6.2 contains some enhancements for SAML Token creation, fixes a bug with deriving keys from UsernameTokens, adds initial support for the Kerberos Token Profile 1.1, and fixes some problems relating to signature verification in certain containers.
Categories: Colm O hEigeartaigh

SAML token creation in Apache WSS4J 1.6

Colm O hEigeartaigh - Tue, 08/16/2011 - 20:10
WSS4J 1.6 uses Opensaml2 to create and parse SAML Assertions. WSS4J ships with a library that wraps the Opensaml API to greatly simplify the process of creating a SAML Assertion. The user implements a CallbackHandler instance which must be able to handle a WSS4J SAMLCallback object. and set certain properties on this object. WSS4J then parses the properties that were set on the object and creates a SAML Assertion accordingly. In this blog post we will examine the process of creating a SAML Assertion by populating a SAMLCallback object in more detail.

1) Obtain a SAMLCallback object

First off, a SAMLCallback object must be obtained in the CallbackHandler implementation, e.g.:

if (callbacks[i] instanceof SAMLCallback) {
    SAMLCallback callback = (SAMLCallback) callbacks[i];
    ....
}

2) Set the SAML Version

The first thing to do is to set the desired SAML Version of the Assertion you want to create on the SAMLCallback object, e.g.:

callback.setSamlVersion(SAMLVersion.VERSION_11);

This method takes an org.opensaml.common.SAMLVersion object. For normal purposes, it will be one of the following:
  • SAMLVersion.VERSION_11
  • SAMLVersion.VERSION_20
The default value in SAMLCallback is VERSION_11.

3) Set the Issuer

The next thing to do is to set the issuer (String) name of the token, e.g.:

callback.setIssuer("sts");

4) Set the Subject

The next thing to do is to set the Subject of the Assertion. WSS4J defines a SubjectBean which encapsulates a SAML Subject. The Subject Name, NameQualifier, NameIDFormat and ConfirmationMethod Strings can be set on the SubjectBean instance. The NameIDFormat and ConfirmationMethod values that can be set are largely defined in the SAML1Constants and SAML2Constants classes. The default value for the SubjectBean NameIDFormat is SAML1Constants.NAMEID_FORMAT_UNSPECIFIED. Both constants classes contain the following values that can be used for the ConfirmationMethod value:
  •  SAML[1|2]Constants.CONF_BEARER
  •  SAML[1|2]Constants.CONF_HOLDER_KEY
  •  SAML[1|2]Constants.CONF_SENDER_VOUCHES
In addition to this, WSS4J defines a KeyInfoBean that can be set on the SubjectBean, which represents a KeyInfo structure that will be embedded in a SAML Subject. There are a number of different ways to set the KeyInfo value:
  • A DOM element can be defined for a pre-existing KeyInfo element
  • A PublicKey object can be used
  • An X.509 Certificate can be used
For the latter two cases, the KeyInfoBean contains a CERT_IDENTIFIER enum which defines how the PublicKey or X.509 Certificate will be output. The following values can be configured:
  • X509_CERT: An X509Certificate element will be output
  • X509_ISSUER_SERIAL: An X509 IssuerSerial element will be output
  • KEY_VALUE: A KeyValue element will be output
The default value in the KeyInfoBean is X509_CERT. Here is a sample that shows how to create a SubjectBean:

SubjectBean subjectBean = new SubjectBean();
subjectBean.setSubjectName("uid=joe");
subjectBean.setSubjectNameQualifier("apache.org");
subjectBean.setSubjectConfirmationMethod(
     SAML1Constants.CONF_SENDER_VOUCHES
);
KeyInfoBean keyInfo = new KeyInfoBean();
keyInfo.setCertificate(cert);
subjectBean.setKeyInfo(keyInfo);

Finally, it remains to store the SubjectBean instance in the SAMLCallback object. A SAML 2.0 Assertion contains a single Subject, and so for this case the SubjectBean instance can be set directly on the SAMLCallback, e.g.:

callback.setSubject(subjectBean);

For a SAML 1.1 Assertion, the Subject can be in a SubjectStatement (in which case it can be set directly on the SAMLCallback), or it can be embedded in one of the other statements which we will cover next.

5) Create and set a Statement

WSS4J contains a number of beans to create Statements for SAML Assertions, that can be set on a SAMLCallback object. They can be used in either SAML 1.1 or SAML 2.0 Assertions, with the caveat that SubjectBean instances are not used with statements in SAML 2.0.

a) Attribute Statements

WSS4J contains an AttributeStatementBean for creating Attribute statements. This contains a SubjectBean (for the SAML 1.1 case), and a list of AttributeBean objects. An attribute simple name, qualified name, and name format Strings can be set on the AttributeBean, as well as a list of attribute value Strings. Here is an example of creating and adding an AttributeStatement to a SAMLCallback object:

AttributeStatementBean attrBean = new AttributeStatementBean();
attrBean.setSubject(subjectBean);
AttributeBean attributeBean = new AttributeBean();
attributeBean.setSimpleName("role");
attributeBean.setAttributeValues(Collections.singletonList("user"));
attrBean.setSamlAttributes(Collections.singletonList(attributeBean));
callback.setAttributeStatementData(Collections.singletonList(attrBean));

b) Authentication Statements

WSS4J contains an AuthenticationStatementBean for creating Authentication statements. For SAML 1.1 a SubjectBean instance can be set on this object. In addition to this, an authentication instant and authentication method can be set, as well as a SubjectLocalityBean object and a session index String. Various authentication method Strings are defined in the SAML1Constants and SAML2Constants given above. Here is an example:

AuthenticationStatementBean authBean = new AuthenticationStatementBean();
authBean.setSubject(subjectBean);
SubjectLocalityBean subjectLocality = new SubjectLocalityBean();
subjectLocality.setIpAddress(subjectLocalityIpAddress);
subjectLocality.setDnsAddress(subjectLocalityDnsAddress);
authBean.setSubjectLocality(subjectLocality);
authBean.setAuthenticationMethod("Password");     callback.setAuthenticationStatementData(Collections.singletonList(authBean));

c) Authorization Decision Statements

WSS4J contains an AuthDecisionStatementBean for creating Authorization Decision Statements. For SAML 1.1 a SubjectBean instance can be set on this object. A Decision enum can be set (PERMIT, INDETERMINATE, DENY), as well as a resource String, evidence Object, and a list of ActionBeans, which in turn contain an action namespace and action contents. Here is an example:

AuthDecisionStatementBean authzBean = new AuthDecisionStatementBean();
authzBean.setSubject(subjectBean);
ActionBean actionBean = new ActionBean();
actionBean.setContents("Read");
authzBean.setActions(Collections.singletonList(actionBean));
authzBean.setResource("endpoint");
authzBean.setDecision(AuthDecisionStatementBean.Decision.PERMIT);
authzBean.setResource(resource);  callback.setAuthDecisionStatementData(Collections.singletonList(authzBean));
 
6) Create a Conditions object

Finally, a ConditionsBean object can be used to specify a set of Conditions on the SAML Assertion. This is optional, as by default a Conditions element will be generated with a NotBefore value of the present instant and a NotOnOrAfter value corresponding to 5 minutes into the future. This can be changed by creating a ConditionsBean and specifying either "notBefore" and "notAfter" dates, or else a token period in minutes in which the token is valid. It is also possible to specify an audience restriction URI on the ConditionsBean object. Here is an example:

ConditionsBean conditions = new ConditionsBean();
conditions.setTokenPeriodMinutes(10);
conditions.setAudienceURI("http://ws.apache.org/wss4j");
callback.setConditions(conditionsBean);

For some examples of CallbackHandlers used to create SAML Assertions, check out the following CallbackHandlers used in the WSS4J unit tests - SAML1AuthnHOKHandler, SAML1CallbackHandler and SAML2CallbackHandler.
Categories: Colm O hEigeartaigh

WS-Trust 1.4 support in CXF

Colm O hEigeartaigh - Mon, 08/15/2011 - 17:43
Apache CXF has had support for sending a WS-Trust 1.4 ActAs element as part of a RequestSecurityToken call to a Security Token Service (STS) since the 2.2.10 release. To quote from the WS-Trust 1.4 specification:
/wst:RequestSecurityToken/wst:ActAs
 
This OTPIONAL (sic) element indicates that the requested token is expected to contain information about the identity represented by the content of this element and the token requestor intends to use the returned token to act as this identity. The identity that the requestor wants to act-as is specified by placing a security token or <wsse:SecurityTokenReference> element within the <wst:ActAs> element.The object to be placed in an ActAs element can be set by the SecurityConstants tag "STS_TOKEN_ACT_AS" on the Message properties. Prior to Apache CXF 2.4.1 the ActAs object could either be an XML String or else a DOM Element. See the following CXF wiki page for more information.

Several enhancements were made in CXF 2.4.1 as part of this JIRA. First of all, support was added for OnBehalfOf. To quote from the spec again:
/wst:RequestSecurityToken/wst:OnBehalfOf
This OPTIONAL element indicates that the requestor is making the request on behalf of another.  The identity on whose behalf the request is being made is specified by placing a security token, <wsse:SecurityTokenReference> element, or <wsa:EndpointReference> element within the <wst:OnBehalfOf> element. The requestor MAY provide proof of possession of the key associated with the OnBehalfOf identity by including a signature in the RST security header generated using the OnBehalfOf token that signs the primary signature of the RST (i.e. endorsing supporting token concept from WS-SecurityPolicy). Additional signed supporting tokens describing the OnBehalfOf context MAY also be included within the RST security header.The object to be placed in an OnBehalfOf element can be set by the SecurityConstants tag "STS_TOKEN_ON_BEHALF_OF" on the Message properties. Similar to ActAs, this object can be an XML String or a DOM Element. In addition to this, the object for both ActAs and OnBehalfOf can now be a CallbackHandler instance. The CallbackHandler implementation must be able to process a DelegationCallback object, which has access to the current CXF Message, and returns a DOM Element to the STSClient for insertion into either ActAs or OnBehalfOf.

Two sample CallbackHandler implementations are shipped with CXF 2.4.1 that can be used for either OnBehalfOf or ActAs. The ReceivedTokenCallbackHandler obtains the previously received message from the current message property of the DelegationCallback object, and extracts a token that has been received in that message (SAML Token/UsernameToken/BinarySecurityToken). This token is then used as the delegation token. This CallbackHandler implementation is useful as part of an WS-Trust intermediary scenario. Secondly, the WSSUsernameCallbackHandler obtains a username via the jax-ws property "ws-security.username" (SecurityConstants.USERNAME), and creates a wsse:UsernameToken (with no password) to be used as the delegation token.
Categories: Colm O hEigeartaigh

Custom token validation in Apache CXF 2.4

Colm O hEigeartaigh - Tue, 06/28/2011 - 15:37
A previous blog post has covered validators in Apache WSS4J 1.6, why they were introduced, what default implementations ship with WSS4J, etc. It ends with a paragraph on how to use a custom Validator implementation with Apache CXF 2.4. This post expands further on this topic.

1) Use-cases for custom Token Validation

Let's consider first of all the use-cases for specifying a custom Validator implementation in CXF. When a security header is being processed by WSS4J, it delegates each security token to a Processor implementation, depending on the QName of the token. In WSS4J 1.6, Processors do not do any validation of extracted credentials from a token, they merely process it, make sure it meets basic requirements, etc. Validation is delegated to a Validator interface which is associated with that Processor implementation.

However, there are many possible use-cases where a user may wish to replace or remove or extend the default validation behaviour associated with a particular security token. Some examples include:
  1. Validating a UsernameToken, where the CallbackHandler implementation does not have access to the password.
  2. Validating a BinarySecurityToken of some custom type.
  3. Validating the attributes of a received SAML Assertion
  4. Validating a Timestamp in a more tolerant manner than the default.
  5. Dispatching a received security token to a third-party security service for validation/authentication.
2) Configuring custom Validators in CXF
    The CXF SecurityConstants class (javadoc) defines some configuration items to override the default validators used to validate a received security token. The values associated with each configuration option must correspond to an implementation of the Validator interface. The configuration tags are:
    1. "ws-security.ut.validator" - Override UsernameToken validation.
    2. "ws-security.saml1.validator" - Override SAML1 token validation.
    3. "ws-security.saml2.validator" - Override SAML2 token validation.
    4. "ws-security.timestamp.validator" - Override Timestamp validation.
    5. "ws-security.signature.validator" - Override trust verification on a signature
    6. "ws-security.bst.validator" - Override BinarySecurityToken validation.
    To disable the validation of a particular token, specify the NoOpValidator as the value of the configuration tag corresponding to that token.

    3) Using Validators with WS-Trust

    To see the power and flexibility of the approach of separating processing from validation, consider the STSTokenValidator that ships with CXF 2.4. This validator implementation has the ability to dispatch a received BinarySecurityToken, UsernameToken, or SAML Assertion to an STS (Security Token Service) for validation via WS-Trust. On invocation, it delegates the credential to another validator (STSSamlAssertionValidator). This validator essentially catches an exception caused by a signature validation failure of the SAML Assertion and sets a flag. Only if signature validation is unsuccessful does the STSTokenValidator dispatch the token to the STS for validation.

    An example of how to configure the STSTokenValidator to validate a SAML1 Assertion against an STS in spring is as follows:

    <jaxws:endpoint ...>
      <jaxws:properties>
        <entry key="ws-security.saml1.validator">
          <bean class="org.apache.cxf.ws.security.trust.STSTokenValidator"/>
        </entry>
        <entry key="ws-security.sts.client">
          <bean class="org.apache.cxf.ws.security.trust.STSClient">
            <constructor-arg ref="cxf"/>
            <property name="wsdlLocation" value="..."/>
            <property name="serviceName" value=".../>
            <property name="endpointName" value="..."/>
             ...       
           </bean>           
         </entry>
       </jaxws:properties>
     </jaxws:endpoint>

    The STSTokenValidator also has the ability to obtain a transformed token from the STS and store it in the credential, where it is available as part of the WSSecurityEngineResult under the TAG_TRANSFORMED_TOKEN tag.
    Categories: Colm O hEigeartaigh

    WS-SecurityPolicy/SAML sample in Talend Service Factory 2.4.0

    Colm O hEigeartaigh - Fri, 06/10/2011 - 23:05
    In this post I will walk through the WS-SecurityPolicy sample that ships with Talend Service Factory 2.4.0. This sample shows how to secure a web service provider using both a UsernameToken and a SAML Assertion. For this post I will concentrate exclusively on the SAML case.

    1) Download the artifacts

    Go here and download Talend Service Factory 2.4.0. When this is done, go here and download the Talend Service Factory 2.4.0 examples (registration required). Extract the examples into the Talend Service Factory (TSF) install directory ($TSF_HOME). Finally, this sample requires that unlimited strength security policies be installed in the JDK.

    2) Build and run the sample

    Go to $TSF_HOME/examples/jaxws-ws-secpol and start with the README.txt. Run "mvn eclipse:eclipse" to generate eclipse projects, and "mvn install" to build and install the various modules. There are two options to run the sample.

    2.1) Run the sample using maven

    To start the service go to the service folder, and run "mvn exec:java". To run the test then go to the client folder and also run "mvn exec:java".

    2.2) Run the sample in Karaf

    To deploy the service and run the client in an OSGi environment, we can take advantage of the Karaf distribution that ships with TSF. Go to $TSF_HOME/container/bin and run the "karaf" binary. Install the three bundles in Karaf with:
    • install mvn:com.talend.sf.examples.jaxws-ws-secpol/ws-secpol-common/1.0
    • install mvn:com.talend.sf.examples.jaxws-ws-secpol/ws-secpol-server/1.0
    • install mvn:com.talend.sf.examples.jaxws-ws-secpol/ws-secpol-client/1.0
    Each of these commands will print out a bundle id. Run the sample by invoking "start <id>" for each of the three bundle ids in turn.

    3) The Service Provider

    3.1) The Security Policy

    The Service endpoint is secured via the following security policy fragment, which is defined in the WSDL ("ws-secpol-wsdl/greeter.wsdl" in the common folder):

    <wsp:All>
      <sp:AsymmetricBinding xmlns:sp=".../ws-securitypolicy/200702">
        <wsp:Policy>
          <sp:InitiatorToken>
            <wsp:Policy>
              <sp:X509Token sp:IncludeToken=".../AlwaysToRecipient">
                <wsp:Policy>
                  <sp:RequireThumbprintReference />
                  <sp:WssX509V3Token10 />
                </wsp:Policy>
              </sp:X509Token>
            </wsp:Policy>
          </sp:InitiatorToken>
          <sp:RecipientToken>
            <wsp:Policy>
              <sp:X509Token sp:IncludeToken=".../Never">
                <wsp:Policy>
                  <sp:RequireThumbprintReference />
                  <sp:WssX509V3Token10 />
                </wsp:Policy>
              </sp:X509Token>
            </wsp:Policy>
          </sp:RecipientToken>
          ...
        </wsp:Policy>
      </sp:AsymmetricBinding>
      ...
      <sp:SignedSupportingTokens xmlns:sp=".../ws-securitypolicy/200702">
        <wsp:Policy>
          <sp:SamlToken sp:IncludeToken=".../AlwaysToRecipient">
            <wsp:Policy>
              <sp:WssSamlV20Token11/>
            </wsp:Policy>
          </sp:SamlToken>
        </wsp:Policy>
      </sp:SignedSupportingTokens>
    </wsp:All>

    This Security Policy defines that the Asymmetric Binding is to be used in communication with the service provider, i.e. that the client must sign the request using its private key, and include the corresponding X509 Certificate in the security header of the request, and encrypt the request using the public key of the service provider. Authentication is performed on the basis of trust verification of the client's certificate, as the client illustrates proof-of-possession by signing some part of the request.

    In addition to the Asymmetric Binding, the policy requires that a SAML 2.0 Assertion must be included in the service request, and it must be signed by the signature defined by the Asymmetric Binding policy. The (policy-driven) ability to add a SAML Assertion to a SOAP Request is new to Apache CXF 2.4.

    Finally, the WSDL defines input and output policies (not included here), which specify that the SOAP Body must be signed and encrypted, and that all of the addressing headers must be signed if present.

    3.2) The configuration

    The standalone (maven-driven) case is configured entirely in code. The various security configuration items are added as properties to the JAX-WS Endpoint object. The same security configuration items are also used for the case of deploying the service provider in Karaf, except that it is all driven through spring, e.g.:

    <jaxws:server id="SAMLGreeter" xmlns:ns1="..."
      endpointName="ns1:SAMLGreeterPort"
      serviceClass="demo.secure_greeter.server.GreeterImpl">
      <jaxws:properties>
        <entry key="ws-security.callback-handler" value="..."/>
        <entry key="ws-security.encryption.properties" value="..."/>
        <entry key="ws-security.signature.properties" value="..."/>
        <entry key="ws-security.saml2.validator" value="..."/>
      </jaxws:properties>
    </jaxws:server>

    Four security-related configuration options are used for the service provider. "ws-security.callback-handler" points to a CallbackHandler implementation that is used to supply a password for extracting a private key from a keystore to decrypt the request and sign the response. "ws-security.encryption.properties" refers to a properties file which contains configuration options for loading the keystore used for encryption. Similarly, "ws-security.signature.properties" refers to a properties file for signature creation (and decryption).

    "ws-security.saml2.validator" is a configuration tag new to CXF 2.4, and refers to an instance of the WSS4J Validator interface. The Validator interface is used in WSS4J to validate received security tokens. In this case, we are extending the default SAML2 Token Validation with a custom Validator. This Validator does some additional verification on the received token, namely checking who the issuer is, checking that the confirmation method is "sender-vouches", and checking that the Assertion contains an AttributeStatement, with an Attribute "attribute-role" containing a value "authenticated-client".

    All of these configuration tags are defined in the SecurityConstants class in CXF.

    4) The client

    When the client wants to invoke on the service provider, it parses the security policy described above in the WSDL. As with the service provider, the client standalone case is configured entirely in code. For the case of deploying the client in Karaf, it is configured in spring as follows: 

    <jaxws:client id="samlgreeter" wsdlLocation="..." serviceClass="..."
      xmlns:ns1="" serviceName="ns1:SecureGreeterService"
      endpointName="ns1:SAMLGreeterPort">
      <jaxws:properties>
        <entry key="ws-security.signature.username" value="..."/>
        <entry key="ws-security.encryption.username" value="..."/>
        <entry key="ws-security.callback-handler"><bean class="..."/></entry>
        <entry key="ws-security.signature.properties" value="..."/>
        <entry key="ws-security.encryption.properties" value="..."/>
        <entry key="ws-security.saml-callback-handler" value="..."/>
      </jaxws:properties>
    </jaxws:client>

    "ws-security.callback-handler", "ws-security.signature.properties" and "ws-security.encryption.properties" have been covered in the section on configuring the service provider. "ws-security.signature.username" refers to the keystore alias of the private key to use to sign the request, and "ws-security.encryption.username" refers to the keystore alias to use to encrypt the request.

    "ws-security.saml-callback-handler" is a configuration tag new to CXF 2.4, and refers to a CallbackHandler which will supply WSS4J with the information to create a SAML Assertion. This sample ships with a CallbackHandler that creates a simple SAML 2.0 Assertion with a subject confirmation method of "sender-vouches". It adds an Attribute to the Assertion that conveys to the Web Service Provider that the client has authenticated an external user in some way (not shown as part of this sample), and has assigned the attribute role of "authenticated-client" to the external user. The assertion that will be generated from this CallbackHandler instance will be signed by the client, as per the policy definition ("SignedSupportingTokens").

    5) The Client Request

    The security header of the client request contains a BinarySecurityToken which contains the certificate to use to verify the signature. It also contains a Timestamp, an EncryptedKey which is used to encrypt the SOAP Body, a SAML2 Assertion, and a Signature which signs the Timestamp, Assertion and encrypted SOAP Body. The Assertion looks like this:

    <saml2:Assertion xmlns:saml2="..." xmlns:xsi="..." ID="..." IssueInstant="..."
      Version="2.0" xsi:type="saml2:AssertionType">
     <saml2:Issuer>...</saml2:Issuer>
     <saml2:Subject>
       <saml2:NameID Format=...:unspecified">uid=auth_client</saml2:NameID>
       <saml2:SubjectConfirmation Method="...:sender-vouches">
         <saml2:SubjectConfirmationData/>
       </saml2:SubjectConfirmation>
     </saml2:Subject>
     <saml2:Conditions NotBefore="..." NotOnOrAfter="..."/>
     <saml2:AttributeStatement>
       <saml2:Attribute FriendlyName="attribute-role" NameFormat="...">
         <saml2:AttributeValue xsi:type="xs:string">
           authenticated-client
         </saml2:AttributeValue>
       </saml2:Attribute>
     </saml2:AttributeStatement>
    </saml2:Assertion>

    The service provider processes the received security header as follows:
    1. It checks that the Timestamp is valid
    2. It uses its private key to decrypt the EncryptedKey, and then uses the decrypted key to decrypt the SOAP Body.
    3. It verifies that the Assertion is valid, and passes the Assertion to the custom Validator defined above to validate the contents of the Assertion.
    4. It verifies that the certificate defined in the BinarySecurityToken can validate the signature, verifies trust in the certificate, and checks that each of the References of the signature produce the correct digest.
    At this point security processing is complete, and the service provider constructs a secured response to the client.
    Categories: Colm O hEigeartaigh

    WSS4J 1.6.1 released

    Colm O hEigeartaigh - Wed, 06/08/2011 - 15:11
    Apache WSS4J 1.6.1 has been released. The distribution can be downloaded here, and the list of issues that have been fixed is here. There are a number of bug fixes to the new functionality introduced in the 1.6.0 release, including some fixes to the SAML Assertion creation code, and a fix to get WSS4J 1.6 working with the IBM JDK. A noteworthy new feature is support for CRLs, as documented by a previous blog post.

    In other news, my employer has published a short questionnaire to find out what topics users of open-source integration software are interested in learning about. So for example if you are interested in hearing more from me on enabling security in Apache CXF, navigate to the CXF part of the survey and select the appropriate checkbox for "WS-Security in Apache CXF".
    Categories: Colm O hEigeartaigh

    CRL support in WSS4J 1.6.1

    Colm O hEigeartaigh - Mon, 05/30/2011 - 16:12
    Support for Certificate Revocation Lists (CRLs) has been a long sought feature in WSS4J, and will arrive in the imminent release of WSS4J 1.6.1. This will ensure that the certificate used to validate a signature is not revoked by the issuing Certificate Authority.

    Support for CRLs is covered by the task WSS-278. The default behaviour is that certificate revocation is not enabled for backwards compatibility reasons. Two parameters must be configured to enable certificate revocation. The first is that the WSHandlerConstants property "enableRevocation" must be set to "true", if WSS4J is being used in the context of WSHandler. If the handler architecture is not being used, then a new method has been added to the Crypto interface for signature trust validation which explicitly enables certificate revocation:
    • public boolean verifyTrust(X509Certificate[] certs, boolean enableRevocation) throws WSSecurityException;
    The previous verifyTrust(certs) method has been deprecated. Please bear in mind that any custom Crypto implementation must be updated with the new method, or else you will face a compilation error on upgrading to WSS4J 1.6.1.

    The second is that the Crypto instance that is used must be supplied with CRL information. This can be done in a number of different ways. The default Crypto instance that ships with WSS4J (Merlin), has a new configuration property:
    • org.apache.ws.security.crypto.merlin.x509crl.file: The location of an (X509) CRL file to be loaded via CertificateFactory.generateCRL(...).
    Merlin also has two new accessor methods to set/get a CertStore object to be used for CRL checking (i.e. setCRLCertStore(CertStore crlCertStore)), if you wish to supply CRL information programatically to the Crypto instance.

    Update: You can see a test for this feature here.
    Categories: Colm O hEigeartaigh

    Apache XML Security for Java 1.4.5 released

    Colm O hEigeartaigh - Fri, 05/27/2011 - 15:53
    Apache XML Security for Java 1.4.5 has been released:
    The Apache Santuario team are pleased to announce the release of
    version 1.4.5 of the Apache XML Security for Java library. This
    release fixes a thread safety issue in the ResourceResolver, and a
    regression in signature generation for the Canonical XML 1.1
    algorithm, as well as a number of other bug fixes.

    Please see the release notes for more information:

    https://issues.apache.org/jira/browse/SANTUARIO/fixforversion/12315957

    You can download the library here:

    http://santuario.apache.org/download.html
    Categories: Colm O hEigeartaigh

    Talend ESB Standard Edition released

    Colm O hEigeartaigh - Wed, 05/18/2011 - 19:36
    Last week the Talend ESB Standard Edition was released:
    A core component of the unified platform for data services, Talend ESB includes messaging, Web services, mediation and adapters in an open and standards-based offering used to integrate distributed systems across functional, enterprise and/or geographic boundaries. Powered by leading Apache open source integration projects Apache CXF, Apache Camel and Apache ActiveMQ, Talend ESB is a versatile and flexible ESB that allows organizations to address any integration challenge, from simple departmental projects to complex, heterogeneous IT environments.Of particular interest to readers of this blog might be the Security Token Service (STS) framework which ships as part of Talend ESB. More on this in a future blog post.

    To download Talend ESB Standard Edition go here. For more information, see the datasheet here.

    In other Talend-related news, Talend is now a sponsor of the Apache Software Foundation.
    Categories: Colm O hEigeartaigh

    WS-Trust sample in Talend Service Factory 2.4.0

    Colm O hEigeartaigh - Wed, 05/11/2011 - 18:18
    In this post I will walk through the WS-Trust sample that ships with Talend Service Factory 2.4.0.

    1) Download the artifacts

    Go here and download Talend Service Factory 2.4.0. When this is done, go here and download the Talend Service Factory 2.4.0 examples (registration required). Extract the examples into the Talend Service Factory (TSF) install directory ($TSF_HOME).

    2) Build and run the sample

    Go to $TSF_HOME/examples/jaxws-ws-trust and start with the README.txt. Run "mvn eclipse:eclipse" to generate eclipse projects, and "mvn install" to build and install the various modules.

    Both the CXF service provider and Metro STS used in this sample are deployed in Tomcat. To see how to configure Maven to install/uninstall these artifacts in Tomcat follow the instructions here. Finally, you need to make sure that the path to the keystores is correct for the Metro STS - follow the instructions in the README.txt for this.

    Start Tomcat, and from the sts-war folder run "mvn install tomcat:deploy". Run the same command from the service-war folder to deploy the CXF service provider in Tomcat.

    Finally to run the test, go to the client folder and run "mvn install exec:exec". You also have the option of running the client in Karaf (follow the instructions in the README.txt).

    3) The sample

    Three service invocations take place as part of this sample. For simplicity, I'll just concentrate on the third one, which shows how a SAML2 Assertion is used in a WS-Trust scenario.

    3.1) The Service Provider

    We'll start with the Service Provider, as the client will use the security policies defined in the WSDL of the Service Provider to access the STS. The Service is spring-loaded via the following configuration:

    <jaxws:endpoint id="doubleitsaml2"
          implementor="service.DoubleItPortTypeImpl"
          address="/doubleitsaml2"
          endpointName="DoubleItPortSAML2"
          wsdlLocation="WEB-INF/wsdl/DoubleIt.wsdl">
           
          <jaxws:properties>
             <entry key="ws-security.callback-handler" value="..."/>
             <entry key="ws-security.signature.properties" value="..."/>
             <entry key="ws-security.is-bsp-compliant" value="false"/>
          </jaxws:properties>
    </jaxws:endpoint>

    Three properties are required for the endpoint. The CallbackHandler implementation is required to provider the password used to access the private key in the Keystore, which is in turn configured in the "ws-security.signature.properties" file. The "ws-security.is-bsp-compliant" configuration turns off Basic Security Profile 1.1 compliance enforcement. This is required as the Metro STS generates a non BSP-compliant SAML Assertion (try removing this line, redeploying the service provider in tomcat and see what happens when the test is re-run).

    The WSDL (DoubleIt.wsdl) contains the security policies for the service provider. It requires that the input and output SOAP Body elements must be signed and encrypted, and that all of the addressing headers must be signed in both directions. It also contains the following policy snippet:

    <sp:SymmetricBinding>
      <wsp:Policy>
        <sp:ProtectionToken>
          <wsp:Policy>
            <sp:IssuedToken sp:IncludeToken="...AlwaysToRecipient">
              <sp:RequestSecurityTokenTemplate>
                <t:TokenType>...#SAMLV2.0</t:TokenType>
                <t:KeyType>.../SymmetricKey</t:KeyType>
                <t:KeySize>256</t:KeySize>
              </sp:RequestSecurityTokenTemplate>
              ...
              <sp:Issuer>
                <wsaw:Address>http://.../DoubleItSTSServiceUT</wsaw:Address>
                <wsaw:Metadata>
                  ...
                </wsaw:Metadata>
              </sp:Issuer>
            </sp:IssuedToken>
          </wsp:Policy>
        </sp:ProtectionToken>
        ...
      </wsp:Policy>
    </sp:SymmetricBinding>

    This SecurityPolicy snippet defines that the communication with the service provider is secured via the SymmetricBinding, i.e. that it is secured via a secret key. The ProtectionToken policy describes how the secret key in turn is conveyed to the service provider in a secure way. In this example, it defines an IssuedToken policy, which is always sent to the recipient (service provider). Once the client sees this policy, it will know that it must contact a Security Token Service (STS) via the WS-Trust protocol to obtain a (issued) token that will convey the symmetric key to the service provider.

    The IssuedToken policy has a RequestSecurityTokenTemplate policy, which the client will copy verbatim when contacting the STS for a security token. It describes the token type that is required (a SAML2 Assertion), the KeyType conveyed in the Assertion (Symmetric Key), and the size of the symmetric key (256 bits). It also contains an Issuer policy which describes how the STS may be contacted via a wsa EndpointReferenceType.

    3.2) The Security Token Service (STS)

    The STS used in this sample is the Metro STS. The port is secured with the following security policy binding:

    <sp:AsymmetricBinding>
      <wsp:Policy>
         <sp:InitiatorToken>
           <wsp:Policy>
             <sp:X509Token sp:IncludeToken=".../AlwaysToRecipient">
               <wsp:Policy>
                 <sp:WssX509V3Token10 />
               </wsp:Policy>
             </sp:X509Token>
           </wsp:Policy>
           </sp:InitiatorToken>
         <sp:RecipientToken>
           <wsp:Policy>
             <sp:X509Token sp:IncludeToken=".../Never">
               <wsp:Policy>
                 <sp:WssX509V3Token10 />
                 <sp:RequireIssuerSerialReference />
               </wsp:Policy>
             </sp:X509Token>
           </wsp:Policy>
         </sp:RecipientToken>
          ...
      </wsp:Policy>
    </sp:AsymmetricBinding>

    This Security Policy defines that the Asymmetric Binding is to be used in communication with the STS, i.e. that the client must sign the request using its private key, and include the corresponding X509 Certificate in the security header of the request, and encrypt the request using the public key of the STS. Authentication is performed on the basis of trust verification of the client's certificate, as the client illustrates proof-of-possession by signing some part of the request.

    The WSDL of the STS also contains a "STSConfiguration" policy fragment, which defines that the issued key is encrypted, and lists the service provider endpoints, including the corresponding public keys.

    3.3) The client

    When the client wants to invoke on the service provider, it parses the security policy described above in the WSDL, and sees that it must first obtain an IssuedToken from a STS before it can construct the service request. The client is configured in spring as follows:

    <jaxws:client name="{...}DoubleItPortSAML2" createdFromAPI="true">
      <jaxws:properties>
        <entry key="ws-security.sts.client">
          <bean class="org.apache.cxf.ws.security.trust.STSClient">
            <constructor-arg ref="cxf"/>
            <property name="wsdlLocation" value="DoubleItSTSService.wsdl"/>
            <property name="serviceName" value="{...}DoubleItSTSService"/>
            <property name="endpointName" value="{...}IDoubleItSTS..Port"/>
            <property name="properties">
              <map>
                <entry key="ws-security.signature.username" value="..."/>
                <entry key="ws-security.callback-handler" value="..."/>
                <entry key="ws-security.signature.properties" value="..."/>
                <entry key="ws-security.encryption.properties" value="..."/>
                <entry key="ws-security.encryption.username" value="..."/>
              </map>
            </property>
          </bean>           
        </entry>
      </jaxws:properties>
    </jaxws:client>

    The STSClient bean contains the configuration required to contact the STS. The client parses the WSDL of the STS, and uses the supplied configuration parameters to construct a request that is secured by the Asymmetric Binding, as discussed above. This request is done via the WS-Trust protocol.

    3.4) The STS request

    In the SOAP Body of the request is the following information (decrypted):

    <wst:RequestSecurityToken>
      <wst:SecondaryParameters>
        <t:TokenType>...#SAMLV2.0</t:TokenType>
        <t:KeyType>.../SymmetricKey</t:KeyType>
        <t:KeySize>256</t:KeySize>
      </wst:SecondaryParameters>
      <wst:RequestType>.../Issue</wst:RequestType>
      <wsp:AppliesTo>
        <wsa:EndpointReference>
        ...
        </wsa:EndpointReference>
      </wsp:AppliesTo>
      ...
      <wst:Entropy>
        <wst:BinarySecret Type=".../Nonce">...</wst:BinarySecret>
      </wst:Entropy>
      <wst:ComputedKeyAlgorithm>.../CK/PSHA1</wst:ComputedKeyAlgorithm></wst:RequestSecurityToken>

    The SecondaryParameters element is copied verbatim from the RequestSecurityTokenTemplate defined in the policy of the service provider. The RequestType element defines an "Issue" URI. AppliesTo refers to the address of the service provider. Entropy contains some client-generated entropy (which the STS will combine with its own Entropy to form a symmetric key), using the ComputedKeyAlgorithm URI.

    3.5) The STS response

    The response from the STS contains the following (decrypted) SOAP Body. It contains the token type of the requested token, the token itself, different ways of referring to the requested token, some entropy that the client can use to recreate the symmetric key, the lifetime of the requested token, etc:

    <trust:RequestSecurityTokenResponseCollection>
      <trust:RequestSecurityTokenResponse>
        <trust:TokenType>...#SAMLV2.0</trust:TokenType>
        <trust:RequestedSecurityToken>
          <saml2:Assertion>
          ...
          </saml2:Assertion>
        </trust:RequestedSecurityToken>
        <trust:RequestedAttachedReference>...</trust:RequestedAttachedReference>
        <trust:RequestedUnattachedReference>
        ...
        </trust:RequestedUnattachedReference>
        <wsp:AppliesTo...>...</wsp:AppliesTo>
        <trust:RequestedProofToken>
            <trust:ComputedKey>.../CK/PSHA1</trust:ComputedKey>
        </trust:RequestedProofToken>
        <trust:Entropy>
          <trust:BinarySecret Type=".../Nonce">...</trust:BinarySecret>
        </trust:Entropy>
        <trust:Lifetime>
          <wsu:Created...>...</wsu:Created>
          <wsu:Expires...>...</wsu:Expires>
        </trust:Lifetime>
        <trust:KeySize>256</trust:KeySize>
      </trust:RequestSecurityTokenResponse>
    </trust:RequestSecurityTokenResponseCollection>

    The requested security token that is returned above is reproduced here. Note that the SubjectConfirmation Method is "holder-of-key", meaning that the client must illustrate proof of possession of the key contained in the EncryptedKey element of the Assertion. The EncryptedKey element is encrypted using the service provider's public key.

    <saml2:Assertion ID="..." IssueInstant="..." Version="2.0">
      <saml2:Issuer>DoubleItSTSIssuer</saml2:Issuer>
      <ds:Signature>...</ds:Signature>
      <saml2:Subject>
        <saml2:NameID NameQualifier="...">...</saml2:NameID>
        <saml2:SubjectConfirmation Method="...:cm:holder-of-key">
          <saml2:SubjectConfirmationData>
          ...
          <xenc:EncryptedKey
          ...
          </xenc:EncryptedKey>
          ...
          </saml2:SubjectConfirmationData>
       </saml2:SubjectConfirmation>
     </saml2:Subject>
     <saml2:Conditions NotBefore="..." NotOnOrAfter="..."></saml2:Conditions>
     <saml2:AttributeStatement>
       <saml2:Attribute...>
         <saml2:AttributeValue>authenticated</saml2:AttributeValue>
       </saml2:Attribute>
     </saml2:AttributeStatement>
    </saml2:Assertion>

    3.5) The Service Provider request

    Once the client receives the Issued Token from the STS, it recreates the symmetric key needed to communicate with the service provider, by combining the entropy received from the STS with its own entropy to form the session key. The (decrypted) SAML2 Assertion is inserted into the security header "as is". The symmetric key is referenced in the request via the following structure:

    <ds:KeyInfo Id="...">
      <wsse:SecurityTokenReference  wsse11:TokenType="...#SAMLV2.0" >
        <wsse:KeyIdentifier ValueType="...#SAMLID">...</wsse:KeyIdentifier>
      </wsse:SecurityTokenReference>
    </ds:KeyInfo>


    The Service Provider verifies the signature of the STS on the SAML Assertion, and then decrypts the EncryptedKey fragment using its private key, to obtain the symmetric key used to decrypt/verify the client request. As the confirmation method is "holder-of-key", the Service Provider ensures that the same key was used to sign some portion of the request, thus proving that the client is in possession of the key.
    Categories: Colm O hEigeartaigh

    Talend Service Factory 2.4.0 released

    Colm O hEigeartaigh - Fri, 04/29/2011 - 16:36
    Talend Service Factory 2.4.0 has been released. It's based on Apache CXF 2.4.0, and so contains all of the security features in WSS4J 1.6.0, as well as the extensive support for SAML Assertions in CXF 2.4.0, that I have been blogging about for the last while.

    In addition to this, some examples are available for download, which illustrate how to get these (security) features working in an OSGi container. A lot of work has gone into making sure that security libraries such as Apache Santuario, Apache WSS4J and Opensaml can be used in an OSGi environment, so I recommend checking the examples out to see how it can be done.

    See Glen's blog for more information on the security examples. Also, see Sergey's blog for a discussion on some other examples based around transforming XML.
    Categories: Colm O hEigeartaigh

    Pages

    Subscribe to Talend Community Coders aggregator - Colm O hEigeartaigh