Monday, October 10, 2011

Using Kerberos with Web Services - part I

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-server

When 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:

If 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:

To 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 trunk via:

svn co https://svn.apache.org/repos/asf/cxf/trunk/

Go into the "trunk" directory, and compile and install CXF via "mvn -Pfastinstall" (this will avoid running tests). Finally go into the WS-Security system tests in "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:

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.

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:

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.:

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:

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.

Yes, look at section "2" - "Running the Kerberos system tests in Apache CXF ". It goes through some Kerberos tests in Apache CXF, where a client contacts a KDC (set up in section "1") to get a ticket and send it to a service provider using WS-Security.

About Me

Software architect at Talend, security expert at ASF. Active committer on lots of Apache projects such as Apache Santuario, CXF, Camel, Syncope, WSS4J, etc. In what seems like another lifetime, I also acquired a PhD in the area of cryptography.
The views expressed on this site are mine alone and do not necessarily reflect the views of my employer.