Wednesday, July 2, 2008

Web services security: Encryption with Rampart

This post discusses how to secure your web service with Rampart - through message encryption.

1. Setting up the environment

- Make sure you have installed Java and set your PATH env variable to C:\Program Files\Java\jdk1.5.0_06\bin [i.e : JAVA_HOME\bin]

- Download Axis2 1.4 - unzip and set the AXIS2_HOME env variable

- Download Rampart 1.4

- Copy [RAMPART_HOME]\lib\*.jar files to [AXIS2_HOME]\lib

- Copy [RAMPART_HOME]\modules\*.mar files to [AXIS2_HOME]\repository\modules

- Download Bouncy Castle jar and copy it to [AXIS2_HOME]\lib

- Download Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files 5.0 from here and copy the two jar files from the extracted jce directory (local_policy.jar and US_export_policy.jar) to $JAVA_HOME/jre/lib/security.

- Add all the jars inside [AXIS2_HOME]\lib to your CLASSPATH [I have created a batch file for this - so you can skip this step if you want]

2. Create keystores for the service and the client

- Assume you have a folder c:\keystores and two subfolders c:\keystores\service and c:\keystores\client

- For the case of encrption client will use the public key of the service and the service will use the public key of the client.

- For the case of decryption client will use it's private key and the service will use it's private key.

- So we need to have two key pairs for both the service and the client.

- Lets first create a key pair for the service and store them in a keystore.

\> cd c:\keystores\service
\> keytool -genkey -alias service -keyalg RSA -keysize 1024 -keypass servicekey -keystore service.jks -storepass servicestorekey

- This will create a keystore "service.jks" inside c:\keystores\service

- Password of the service.jks is "servicestorekey" [-storepass servicestorekey]

- Password of the private key of the service is "servicekey" [-keypass servicekey]

- Now lets create a key pair for the client and store them in a different keystore.

\> cd c:\keystores\client
\> keytool -genkey -alias client -keyalg RSA -keysize 1024 -keypass clientkey -keystore client.jks -storepass clientstorekey

- This will create a keystore "client.jks" inside c:\keystores\client

- Password of the client.jks is "clientstorekey" [-storepass clientstorekey]

- Password of the private key of the client is "clientkey" [-keypass clientkey]

- Now we are done creating two keystores with public/private key pairs for our service and the client

- But.. as I mentioned earlier client needs to know the public key of the service and the service needs to know the public key of the client.

- So we need to export the public key of the service from the service.jks and import it to the client.jks

\> cd c:\keystores\service
\> keytool -alias service -export -keystore service.jks -storepass servicestorekey -file servicepublickey.cer
\> cd c:\keystores\client
\> keytool -import -alias service -file ../service/servicepublickey.cer -keystore client.jks -storepass clientstorekey

- Now we need to export the public key of the client from the client.jks and import it to the service.jks

\> cd c:\keystores\client
\> keytool -alias client -export -keystore client.jks -storepass clientstorekey -file clientpublickey.cer
\> cd c:\keystores\service
\> keytool -import -alias client -file ../client/clientpublickey.cer -keystore service.jks -storepass servicestorekey

- Now we are done and we have two keystores.

1. c:\keystores\client\client.jks
2. c:\keystores\service\service.jks

3. Write and deploy the service

- Download and extract rampart-sample.zip from here.

- Copy c:\keystores\service\service.jks and [rampart-sample]\service\service.properties to [AXIS2_HOME]

- Build the service

[rampart-sample]\> classpath.bat
[rampart-sample]\> cd service
\> javac org/apache/rampart/samples/sample05/*.java
\> jar cvf SimpleService.aar *

- Copy the [rampart-sample]\service\SimpleService.aar to [AXIS2_HOME]\repository\services

- Run Axis2 simple server [[AXIS2_HOME]\bin\axis2server.bat]

- Type http://localhost:8080/axis2/services/ in the browser - you will simple SimpleService being deployed.

Now, lets highlight some of the Rampart related stuff we used while creating the service.

Service should ideally use the public key of the Client to encrypt the messages it sends and use it's own private key to decrypt messages it recieves.

By now we know both these keys are in service.jks keystore and we have copied it to the service classpath - where the service can pick the required keys.

All the configuration properties related to the service.jks are written to the property file [AXIS2_HOME]\service.properties

If you open the file service.properties, you'll see the following two properties there.


org.apache.ws.security.crypto.merlin.keystore.password=servicestorekey
org.apache.ws.security.crypto.merlin.file=service.jks


Here we specify the name of the keystore to use and the password to access the keystore. [this is the password we gave while we were creating the keystore].

Now the question is, how does the service pick this service.properties file.

That - we mention in the services.xml file [[rampart-sample]\service\META-INF\services.xml]
.

<parameter name="OutflowSecurity">
<action>
<items>Encrypt</items>
<encryptionuser>client</encryptionuser>
<encryptionpropfile>service.properties</encryptionpropfile>
</action>
</parameter>
If you can recall - we use the alias 'client' at the time we import the client public key to the service.jks. So the same name is used here for the encryptionuser.

The above discussion is related to encryption. How come Rampart knows the password of it's private key - to decrypt the receiving messages.
.

<parameter name="InflowSecurity">
<action>
<items>Encrypt</items>
<passwordCallbackClass>org.apache.rampart.samples.sample05.PWCBHandler</passwordCallbackClass>
<decryptionPropFile>service.properties</decryptionPropFile>
</action>
</parameter>
Here the Rampart uses a callback mechanism to retrieve the password - where the service author needs to implement the password callback class [[[rampart-sample]\service\org\apache\rampart\samples\sample05\PWCBHandler.java].

4. Write and run the client

- Build the Client

[rampart-sample]\> classpath.bat
[rampart-sample]\> cd client
\> javac org/apache/rampart/samples/sample05/*.java
\> java org/apache/rampart/samples/sample05/Client http://localhost:8080/axis2/services/SimpleService.SimpleServiceHttpEndpoint C:\axis2-1.4\repository

- C:\axis2-1.4\repository is for [AXIS2_HOME]\repository

- If everything is fine client should run with no issues.

- Configurations related to Rampart is similar to the way it was discussed previously for the service.

- You'll find client.jks and client.properties at [rampart-sample]\client - which is in the path of execution.

- You'll also find password callback class at the client end at [rampart-sample]\client\org\apache\rampart\samples\sample05\PWCBHandler.java

0 comments: