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:
1.2) Modifying configuration
Once apt-get has finished, we need to modify the Kerberos configuration file ("sudo vi /etc/krb5.conf"):
The next step is to create some principals. Create a master key via:
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:
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:
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:
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.:
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:
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.ORGYou 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:
1.3) Create principals[logging]
kdc = FILE:/var/log/krb5kdc.log
admin_server = FILE:/var/log/kadmin.log
default = FILE:/var/log/krb5lib.log
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"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.
addprinc bob/service.ws.apache.org
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 aliceTo 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.
ktadd -k /etc/bob.keytab bob/service.ws.apache.org
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.
<sp:KerberosToken sp:IncludeToken=".../Once">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.
<wsp:Policy>
<sp:WssGssKerberosV5ApReqToken11/>
</wsp:Policy>
</sp:KerberosToken>
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 {and the service endpoint (bob) uses:
com.sun.security.auth.module.Krb5LoginModule required
refreshKrb5Config=true useKeyTab=true keyTab="/etc/alice.keytab"
principal="alice";
};
bob {2.3) Service endpoint configuration
com.sun.security.auth.module.Krb5LoginModule required
refreshKrb5Config=true useKeyTab=true storeKey=true
keyTab="/etc/bob.keytab" principal="bob/service.ws.apache.org";
};
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 ...>"kerberosValidator" is defined as:
<jaxws:properties>
<entry key="ws-security.bst.validator" value-ref="kerberosValidator"/>
</jaxws:properties>
</jaxws:endpoint>
<bean id="kerberosValidator"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.
class="org.apache.ws.security.validate.KerberosTokenValidator">
<property name="contextName" value="bob"/>
<property name="serviceName" value="bob@service.ws.apache.org"/>
</bean>
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"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.
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>