springmulews-securityproperties-filewss4j

Setting up WS-Security in MULE without properties file (WSS4JInInterceptor with signaturePropRefId)


I'm tryring to set up WS-Security in a CXF Proxy MULE Project. I currently have it working with a properties file, but I would like to take some info out of the properties file and insert it in the DataBase so it can be secured there but I can't find a way to make it work.

The relevant data in my project now looks like this:

CXF Proxy in flow:

<cxf:proxy-service  doc:name="CXF Server" wsdlLocation="${wss.http.protocol}://${wss.http.host}:${wss.http.port}${wss.http.base_path}?${wss.http.wsdl_file}"  payload="envelope" bindingId="${wss.http.binding_id}" namespace="${wss.http.namespace}" service="${wss.http.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.properties" />
                </spring:map>
            </spring:constructor-arg>
        </spring:bean>
    </cxf:inInterceptors>
</cxf:proxy-service>

ws.properties file:

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=myTrustStore.jks
org.apache.ws.security.crypto.merlin.keystore.password=myTrustStorePass

I'd need to take those file and keystore.password parameters out of the files of the project and set them in the DataBase in order to be injected.

I have vainly (as labels like util:properties are throwing a 'The prefix "util" for element "util:properties" is not bound' error) tried an approach similar to the one shown here: http://cxf.547215.n5.nabble.com/WS-Security-Properties-Reference-td5505704.html

I've also tried to set the properties file this way in order to get the relevant data from the BD, but this data is not getting injected:

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=${wss.trustKeystore.file}
org.apache.ws.security.crypto.merlin.keystore.password=${wss.trustKeystore.password}

Am I doing anything wrong? Can this be solved in any of the ways exposed (or any other)? If so, how?

Thanks.

EDIT due to a new scenario for this problem:

When I load the configuration for the interceptor from a properties file everything works fine, but I need to inject those configuration properties from DB, so I decided to configure it by using a java.util.properties object in the XML file in order to inject the values later. As a previous step to stablishing the injections, this is the code I have:

<mule xmlns:mulexml="http://www.mulesoft.org/schema/mule/xml"
 xmlns:tls="http://www.mulesoft.org/schema/mule/tls"
 xmlns:http="http://www.mulesoft.org/schema/mule/http"
 xmlns:cxf="http://www.mulesoft.org/schema/mule/cxf"
 xmlns="http://www.mulesoft.org/schema/mule/core"
 xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
 xmlns:spring="http://www.springframework.org/schema/beans" 
 xmlns:util="http://www.springframework.org/schema/util"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.mulesoft.org/schema/mule/xml http://www.mulesoft.org/schema/mule/xml/current/mule-xml.xsd
 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
 http://www.mulesoft.org/schema/mule/core 
 http://www.mulesoft.org/schema/mule/core/current/mule.xsd
 http://www.mulesoft.org/schema/mule/http 
 http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
 http://www.mulesoft.org/schema/mule/cxf 
 http://www.mulesoft.org/schema/mule/cxf/current/mule-cxf.xsd
 http://www.mulesoft.org/schema/mule/tls 
 http://www.mulesoft.org/schema/mule/tls/current/mule-tls.xsd">

 <http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="5081" doc:name="HTTP Listener Configuration"/>
 <http:request-config name="HTTP_Request_Configuration" host="${conf.prop.host}" port="${conf.prop.port}" doc:name="HTTP Request Configuration" connectionIdleTimeout="60000" responseTimeout="60000"/>

 <spring:beans>
     <spring:bean id="WrongResultException" name="WrongResultException" class="transform.WrongResultException"/>
     <spring:bean name="wsCryptoProperties" class="java.util.Properties">
         <spring:constructor-arg>
             <spring:map>
                    <spring:entry key="org.apache.ws.security.crypto.provider" value="org.apache.ws.security.components.crypto.Merlin"/>
                    <spring:entry key="org.apache.ws.security.crypto.merlin.keystore.type" value="JKS"/>
                    <spring:entry key="org.apache.ws.security.crypto.merlin.keystore.password" value="my_truststore_password"/>
                    <spring:entry key="org.apache.ws.security.crypto.merlin.file" value="my_truststore.jks"/>
                </spring:map>
            </spring:constructor-arg>
     </spring:bean>
 </spring:beans>

 <flow name="HttpsCall">
     <http:listener config-ref="https-listener-configured-in-domain-app" path="/my_path/my_service" doc:name="HTTPS"/>
     <logger message="HTTPS call" level="INFO" doc:name="Logger HTTPS"/>
     <flow-ref name="HttpCall" doc:name="HttpCall"/>
 </flow>

 <flow name="HttpCall">
     <http:listener config-ref="http-listener-configured-in-domain-app" path="/my_path/my_service" doc:name="HTTP"/>
     <cxf:proxy-service  doc:name="CXF Server" wsdlLocation="${service.protocol}://${service.host}:${service.port}${service.base_path}?${service.wsdl_file}"  payload="envelope" bindingId="${service.binding_id}" namespace="${service.namespace}" service="${service.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" />
                         <!-- This is how the Crypto object is configured when using a properties file
                         <spring:entry key="signaturePropFile" value="security_conf_file.properties" />-->
                         <spring:entry key="signaturePropRefId" value="wsCryptoProperties"/>
                     </spring:map>
                 </spring:constructor-arg>
             </spring:bean>
         </cxf:inInterceptors>
     </cxf:proxy-service>
     <message-properties-transformer doc:name="Message Properties">
         <add-message-property key="SOAPAction" value="#[message.inboundProperties.SOAPAction]"/>
     </message-properties-transformer>
     <cxf:proxy-client payload="envelope" doc:name="CXF Client" />
     <http:request config-ref="HTTP_Request_Configuration" path="${service.base_path}" method="POST" doc:name="HTTP" />
     <exception-strategy ref="mule-serviceCatch_Exception_Strategy" doc:name="Reference Exception Strategy"/>
 </flow>

 <catch-exception-strategy name="mule-serviceCatch_Exception_Strategy">
     <logger message="Exception: #[message]" level="INFO" doc:name="Logger"/>
     <transformer ref="WrongResultException" doc:name="Transformer Reference"/>
     <mulexml:object-to-xml-transformer doc:name="Object to XML"/>
 </catch-exception-strategy>

The fact is that everything compiles properly even when configuring the properties via java.util.Properties but, when calling to the service, an error is thrown saying that the properties were not loaded correctly:

WARN  2017-05-03 12:08:27,448 [[mule_domain_app].http-listener-configured-in-domain-app.worker.01] org.apache.ws.security.handler.WSHandler: The Crypto reference wsCryptoProperties specified by signaturePropRefId could not be loaded
WARN  2017-05-03 12:08:27,467 [[mule_domain_app].http-listener-configured-in-domain-app.worker.01] org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor: 
org.apache.ws.security.WSSecurityException: General security error (WSSecurityEngine: No crypto property file supplied to verify signature)
 at
org.apache.ws.security.message.token.X509Security.getX509Certificate(X509Security.java:100) ~[wss4j-1.6.18.jar:1.6.18]
 at 
org.apache.ws.security.message.token.SecurityTokenReference.getKeyIdentifier(SecurityTokenReference.java:491) ~[wss4j-1.6.18.jar:1.6.18] ...

And so on...

Can anybody throw some light over this issue? I'm completely stuck.


Solution

  • Solved!

    This line was missing beetween the entries of the map passed in the WSS4JInInterceptor constructor:

    <spring:entry key="wsCryptoProperties" value-ref="wsCryptoProperties"/>
    

    Doing this, an injection in the values of the props of the java.util.Properties object works as a charm.

    Hope this helps anybody in the future!