Use Mule3 as WS-Security proxy

As I wrote before it is quite easy to set up a web service proxy with Mule3. in this example I take it a step further and I describe how you can add WS-Security implementation to it. Although in the end this also is quite easy you have to make the correct configuration choices to get everything to work.

The first thing I had to do in my Mule config was to drop the pattern prefix. This took me a while to discover because I think this isn’t very clear in the documentation. Anyway, after that change it is fairly straight forward.

Here is the Mule config I ended up with:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns="http://www.mulesoft.org/schema/mule/core"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:cxf="http://www.mulesoft.org/schema/mule/cxf"
      xmlns:spring="http://www.springframework.org/schema/beans"
      xmlns:http="http://www.mulesoft.org/schema/mule/http"
      xsi:schemaLocation="
        http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/3.2/mule.xsd
        http://www.mulesoft.org/schema/mule/cxf http://www.mulesoft.org/schema/mule/cxf/3.2/mule-cxf.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/3.2/mule-http.xsd">
 
    <flow name="create-client">
        <http:inbound-endpoint address="http://localhost:8080/create-client">
            <cxf:proxy-service/> 
        </http:inbound-endpoint>
        <http:outbound-endpoint address="http://localhost:8081/create-client">
            <cxf:proxy-client>
                <cxf:outInterceptors>
                    <spring:bean class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor">
                        <spring:constructor-arg>
                            <spring:map>
                                <spring:entry key="action" value="Timestamp Signature" />
                                <spring:entry key="user" value="${signature.user}" />
                                <spring:entry key="signaturePropFile" value="ws-security.properties" />
                                <spring:entry key="passwordCallbackClass" value="nl.redstream.adapter.MyKeystorePasswordCallback"/>
                            </spring:map>
                        </spring:constructor-arg>
                    </spring:bean>
                    <spring:bean class="org.apache.cxf.interceptor.LoggingOutInterceptor" />
                </cxf:outInterceptors>
            </cxf:proxy-client>
        </http:outbound-endpoint>    
    </flow>
    <flow name="get-client-status">
        <http:inbound-endpoint address="http://localhost:8081/get-status">
            <cxf:proxy-service>
                <cxf:inInterceptors>
                    <spring:bean class="org.apache.cxf.interceptor.LoggingInInterceptor" />
                    <spring:bean class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
                        <spring:constructor-arg>
                            <spring:map>
                                <spring:entry key="action" value="Signature" /> 
                                <spring:entry key="signaturePropFile" value="ws-security.properties" />
                            </spring:map>
                        </spring:constructor-arg>
                    </spring:bean>
                </cxf:inInterceptors>
            </cxf:proxy-service>
        </http:inbound-endpoint>
        <http:outbound-endpoint address="http://localhost:8080/get-status">
            <cxf:proxy-client />
        </http:outbound-endpoint>    
    </flow>
</mule>

As you can see I have added two flows. The first flow is ‘create-client’. I receive the incoming call from my own ‘inside’-application and add a signature and timestamp to it before I forward it to the ‘outside’ service.
The second flow works the other way around: I receive a signed message from the ‘outside’ client app and I need to validate this before I pas the message to my ‘inside’ application. To create the signature I need the password for to make use of my private key in the keystore. To supply this password I simply implemented the PasswordCallbackHandler that returns the corresponding password by looking it up in a property file. For more info about configuring the WS-security with CFX see here and also I found this entry about Apache WSS4J quite handy.
The security property file that is referred to in my Mule config file contains the following:

1
2
3
4
org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=JKS
org.apache.ws.security.crypto.merlin.file=/KeyStores/redstreamKeystore.jks
org.apache.ws.security.crypto.merlin.keystore.password=myPassword

For both flows I added the logging interceptor which is quite handy during testing and developing to see what is received and sent out. In the next post I will show how to generate the keystores and configure SoapUI to test the proxy manually.

tags: , ,

About Pascal Alma

Pascal started as an Oracle Developer in 1997 and developed numerous applications with Oracle Designer/Developer and PL/SQL. Since 2001 Pascal becomes more and more active with the development of software at the Java/J2EE platform. Nowadays Pascal is a senior JEE Developer/ Architect and has a lot of experience with several open source initiatives/ frameworks especially within the Enterprise Integration area. Besides these technical skills Pascal is a big Scrum enthusiastic.

Leave a Reply