Configuring Mutual SSL in WSO ESB Proxy Services and REST APIs
What Mutual SSL?
Mutual authentication is the process where client authenticate with server and vice versa. With this approach client clients can be make sure that they are dealing business exclusively with trusted entities and from the server's perspective it can be certain that all would-be users are attempting to gain access for legitimate purposes.Two-way SSL authentication is one way of achieving the mutual SSL. During mutual SSL negotiation process, application acting as an SSL client presents its certificate to the SSL server after the SSL server authenticates itself to the SSL client
Mutual SSL for proxy service
Edit https transportListener in axis2.xml in {ESB_HOME}/repository/conf/axis2/ folder and Add SSLVerifyClient to optional as follow.
<transportReceiver name="https" class="org.apache.synapse.transport.passthru.PassThroughHttpSSLListener">
<parameter name="port" locked="false">8243</parameter>
<parameter name="non-blocking" locked="false">true</parameter>
<parameter name="httpGetProcessor" locked="false">org.wso2.carbon.transport.nhttp.api.PassThroughNHttpGetProcessor</parameter>
<parameter name="keystore" locked="false">
<KeyStore>
<Location>repository/resources/security/wso2carbon.jks</Location>
<Type>JKS</Type>
<Password>wso2carbon</Password>
<KeyPassword>wso2carbon</KeyPassword>
</KeyStore>
</parameter>
<parameter name="truststore" locked="false">
<TrustStore>
<Location>repository/resources/security/client-truststore.jks</Location>
<Type>JKS</Type>
<Password>wso2carbon</Password>
</TrustStore>
</parameter>
<parameter name="SSLVerifyClient">optional</parameter>
<!--supports optional|require or defaults to none -->
</transportReceiver>
Next step is to enable the mutual SSL per proxy as it’s not required to all the proxies. In order to do that, create a local entry in ESB with following policy
<?xml version="1.0" encoding="UTF-8"?>
<wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="MutualSSL">
<wsp:ExactlyOne>
<wsp:All>
<sp:TransportBinding xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:TransportToken>
<wsp:Policy>
<sp:HttpsToken RequireClientCertificate="true" />
</wsp:Policy>
</sp:TransportToken>
<sp:AlgorithmSuite>
<wsp:Policy>
<sp:Basic256 />
</wsp:Policy>
</sp:AlgorithmSuite>
<sp:Layout>
<wsp:Policy>
<sp:Lax />
</wsp:Policy>
</sp:Layout>
</wsp:Policy>
</sp:TransportBinding>
<rampart:RampartConfig xmlns:rampart="http://ws.apache.org/rampart/policy">
<rampart:encryptionUser>useReqSigCert</rampart:encryptionUser>
<rampart:timestampPrecisionInMilliseconds>true</rampart:timestampPrecisionInMilliseconds>
<rampart:timestampTTL>300</rampart:timestampTTL>
<rampart:timestampMaxSkew>300</rampart:timestampMaxSkew>
<rampart:tokenStoreClass>org.wso2.carbon.security.util.SecurityTokenStore</rampart:tokenStoreClass>
<rampart:nonceLifeTime>300</rampart:nonceLifeTime>
</rampart:RampartConfig>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
Create a sample proxy service and configure the policy as follow.
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse" name="Test" transports="https" statistics="disable" trace="disable" startOnLoad="true">
<target>
<inSequence>
<log level="full" />
<respond />
</inSequence>
</target>
<enableSec />
<policy key="MutualSSLPolicy" />
<description />
</proxy>
4. After that it required to create a new client keystore and truststore which need to configured in the client that communicate with the ESB. Follow below steps to setup the configurations. (This uses keytool commands to configure the keystore, trustore and certificates
Create client keystore name client-keystore.jks
keytool -genkey -keyalg RSA -keystore client-keystore.jks -alias wso2clientkeystore -dname "CN=wso2clientkeystore" -validity 3650 -keysize
2048
Export the keystore certificate which will need to be imported for the trustores
keytool -export -keyalg RSA -keystore client-keystore.jks -alias wso2clientkeystore -file wso2clientkeystore.cert
Next step is to create the client side truststore where it stores the client certificates (public keys)
keytool -import -file wso2clientkeystore.cert -alias wso2client -keystore wso2clienttrustore.jks
Now it’s required to import the ESB Server public certificate to client side truststore. First export the public key of the keystore of ESB in {ESB_HOME}//repository/resources/security/wso2carbon.jks as follow
keytool -export -keyalg RSA -keystore /repository/resources/security/wso2carbon.jks -alias wso2carbon -file wso2carbon.cert
Above certificate need to be imported to client side truststore which is wso2clienttrustore.jks
keytool -import -file wso2carbon.cert -alias wso2carbon -keystore wso2clienttrustore.jks
Import the client side certificate to ESB client truststore located in the {ESB_HOME}//repository/resources/security/client-truststore.jks
keytool -import -file wso2clientkeystore.cert -alias wso2clientkeystore -keystore /repository/resources/security/client-truststore.jks
With the above certificate configuration, it should be possible to access the proxy service with mutual SSL
To test this, we can use SOAP UI
First configure the keystore and truststore for the project pointing to client-keystore.jks and wso2clienttrustore.jks. Refer the below screenshot
Then select the keystore as client-keystore.jks in properties. Refer below screenshot
Then service should be able to execute successfully. But before it, following SOAP Fault should seen in the SOAP UI
Sample Mutul SSL SOAP client and REST Client can be found in [1] which written by Asela.
Mutual SSL for REST service
Since certificates are already configured, following steps can be continue without configuring the certificates again.
To configure Mutual SSL in a REST API in WSO2 ESB, it’s required to have a handler configured.
In location [2], it can be found source for the handler which is a modified version of it’s original author Asela.
-
Then create a API with following API definition
<?xml version="1.0" encoding="UTF-8"?>
<api context="/test" name="Test">
<resource methods="GET" protocol="https" uri-template="/value/{tag}">
<inSequence>
<payloadFactory media-type="json">
<format>{"Status":"OK"}</format>
<args />
</payloadFactory>
<log>
<property name="JSON-Payload" value="test" />
</log>
<property action="remove" name="NO_ENTITY_BODY" scope="axis2" />
<property name="messageType" scope="axis2" type="STRING" value="application/json" />
<respond />
</inSequence>
</resource>
<handlers>
<handler class="org.soasecurity.apim.authentication.handler.MutualSSLAuthenticationHandler" />
</handlers>
</api>
Above we have configured API with Mutual Authentication Handler which enforce the Mutual SSL authentication
To test the API, it can be used the client in [1] or the modified client which adjust to prepare this sample in [4]
With the client, API should be able to invoke successfully
Information sources taken mainly from [5] and [6] which are written by Asela and Hasitha.:)
[3] - https://svn.wso2.org/repos/wso2/people/harsha/mutual-ssl-hander/target/
[5] - http://tryitnw.blogspot.com.es/2015/06/setting-up-mutual-ssl-in-wso2-esb-and.html
[6] - http://xacmlinfo.org/2015/06/02/securing-apis-using-mutual-ssl-with-wso2-api-manager/