Web service proxy server in Karaf with Camel and cxf adds 1000 to MTOM messages - web-services

I am creating new proxy for web services in Karaf 4.4.1 with Camel 3.18.1 and cxf 3.5.3.(I've tried it on older versions too 4.4.0, 3.18.0, 3.5.2). And it works fine, but I have a problem with MTOM attachments. For some reason it adds several times number 1000 into the message. And it is not every 1000 bytes. The spaces between them are different (from 377 to 4157 bytes). Here is picture of comparison of my incoming messages. The bad one goes through proxy and the good one don't:
comparsion 1
comparsion 2
Does anyone knows where is the mistake?
Here is my blueprint:
...
<camelcxf:cxfEndpoint id="SrvEndpoint">
<camelcxf:properties>
<entry key="dataFormat" value="CXF_MESSAGE" />
<entry key="ws-security.ut.no-callbacks" value="true"/>
<entry key="ws-security.validate.token" value="false"/>
<entry key="schema-validation-enabled" value="true" />
<entry key="lazyStartProducer" value="true" />
<entry key="mtom-enabled" value="true" />
</camelcxf:properties>
<camelcxf:inInterceptors>
<ref component-id="SrvWsSecInterceptor" />
<ref component-id="SrvAuthenticationInterceptor"/>
<ref component-id="SrvLoggingInInterceptor"/>
</camelcxf:inInterceptors>
<camelcxf:outInterceptors>
<ref component-id="SrvLoggingOutInterceptor"/>
</camelcxf:outInterceptors>
</camelcxf:cxfEndpoint>
<!-- this is the Camel route which proxies the real web service and forwards SOAP requests to it -->
<camelContext id="SrvRoute" trace="false" xmlns="http://camel.apache.org/schema/blueprint">
<route>
<!-- CXF consumer using CXF_MESSAGE format -->
<from uri="cxf:bean:SrvEndpoint"/>
<!-- Need to remove the http headers which could confuse the http endpoint -->
<removeHeaders pattern="CamelHttp*"/>
<!-- Don't know why but if not set returns empty response header and body -->
<setProperty name="CamelCXFDataFormat"><constant>PAYLOAD</constant></setProperty>
<!-- send proxied request to real web service -->
<to uri="{{SrvProxy.target.url}}?throwExceptionOnFailure=false"/>
</route>
</camelContext>
I've tried to change dataFormat to PAYLOAD and clean it from authentication and validation but nothing helped.

Related

CXF interceptors only for client using configuration

I have added interceptor only in cxf_client.xml but same interceptor are invoking for incoming apis as well(i.e cxf_server). below are my changes.
Can some one please tell me why this interceptor are invoking for incoming APIs?
is it because same bus use for both server and client?
cxf_client.xml
<bean id="XCustomInterceptor" class="com.test.XCustomInterceptor"/>
<cxf:bus>
<cxf:inInterceptors>
<ref bean="XCustomInterceptor"/>
</cxf:inInterceptors>
<cxf:outInterceptors>
<ref bean="XCustomInterceptor"/>
</cxf:outInterceptors>
</cxf:bus>*
Because you are using
<cxf:inInterceptors>
<ref bean="XCustomInterceptor"/>
</cxf:inInterceptors>
Check documentation http://cxf.apache.org/docs/bus-configuration.html
inInterceptors
The interceptors contributed to inbound message interceptor chains. A list of s or s
You can use specific interceptors for inbound connection and outbound connections in server and cliente
For example, here it is the configuration of a jax-ws endpoint and client with in and out interceptors
<!-- The SOAP endpoint -->
<jaxws:endpoint
id="helloWorld"
implementor="demo.spring.HelloWorldImpl"
address="http://localhost/HelloWorld">
<jaxws:inInterceptors>
<ref bean="customInInterceptor"/>
</jaxws:inInterceptors>
<jaxws:outInterceptors>
<ref bean="customOutInterceptor"/>
</jaxws:outInterceptors>
</jaxws:endpoint>
<!-- The SOAP client bean -->
<jaxws:client id="helloClient"
serviceClass="demo.spring.HelloWorld"
address="http://localhost/HelloWorld">
<jaxws:inInterceptors>
<ref bean="customClientInInterceptor"/>
</jaxws:inInterceptors>
<jaxws:outInterceptors>
<ref bean="customClientOutInterceptor"/>
</jaxws:outInterceptors>
</jaxws:client>

AWS SQS and ElasticBeanStalk environment set up

Following is my spring configuration for aws sqs.
<bean id="CredentialsProviderBean"
class="com.myapp.util.ClasspathPropertiesFileCredentialsProvider" />
<bean id="ConnectionFactoryBuilder"
class="com.amazon.sqs.javamessaging.SQSConnectionFactory$Builder">
<property name="regionName" value="us-east-1" />
<property name="numberOfMessagesToPrefetch" value="1" />
<property name="awsCredentialsProvider" ref="CredentialsProviderBean" />
</bean>
<bean id="ConnectionFactory" class="com.amazon.sqs.javamessaging.SQSConnectionFactory"
factory-bean="ConnectionFactoryBuilder" factory-method="build" />
<bean id="Connection" class="javax.jms.Connection" factory-bean="ConnectionFactory"
factory-method="createConnection" init-method="start" destroy-method="close" />
<bean id="QueueName" class="java.lang.String">
<constructor-arg value="myqueue" />
</bean>
<bean id="amazonMessageListener" class="com.myapp.daemon.AsyncMessageListener" />
<bean id="messageListener"
class="org.springframework.jms.listener.adapter.MessageListenerAdapter">
<property name="delegate" ref="amazonMessageListener" />
<property name="defaultListenerMethod" value="onMessage" />
<property name="messageConverter">
<null />
</property>
</bean>
<bean id="jmsContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="ConnectionFactory" />
<property name="destinationName" ref="QueueName" />
<property name="messageListener" ref="messageListener" />
</bean>
I am having trouble understanding how to set this up in the AWS.
ElasticBeanStalk provides 2 types of environments,
1. worker and 2. webserver.
Thought the worker type environment fits the bill, according to the documentation. AWS deploys a daemon in ec2 instances, and pulls off the message from SQS and envelopes that into a message body of the http post request. This post request can be used to post to a web server.
http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/using-features-managing-env-tiers.html#worker-environ
However the component I wrote does that. Pulls off the message from the queue, and does some background processing.
In this case which environment type should i opt?
If you have to use worker tier you do not need to use your component and you make sure the background processing part of your application has an HTTP Post interface. You can leave polling to the daemon provided by beanstalk. I would recommend this if you want to use elasticbeanstalk.
If you want to use your component then you might as well just use web tier although if you are just doing background processing and not serving Web traffic then you will have ports listening for Web traffic, ELB for no reason.

Getting error while creating a secured proxy

I am trying to configure WSS4JInInterceptor in my cxf endpoint through camel-config.xml
Below is my camel-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- START SNIPPET: e1 -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:camel="http://camel.apache.org/schema/spring"
xmlns:cxf="http://camel.apache.org/schema/cxf"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
http://camel.apache.org/schema/cxf http://camel.apache.org/schema/cxf/camel-cxf.xsd">
<!-- spring property placeholder, ignore resource not found as the file resource is for unit testing -->
<context:property-placeholder location="classpath:incident.properties,file:target/custom.properties"
ignore-resource-not-found="true"/>
<!-- bean that enriches the SOAP request -->
<bean id="enrichBean" class="org.apache.camel.example.cxf.proxy.EnrichBean"/>
<bean id="loggingOutInterceptor" class="org.apache.cxf.interceptor.LoggingOutInterceptor"/>
<bean id="loggingInInterceptor" class="org.apache.cxf.interceptor.LoggingInInterceptor"/>
<bean id="wss4jInInterceptor" class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
<property name="properties">
<map>
<entry key="action" value="UsernameToken Timestamp"/>
<entry key="passwordType" value="PasswordDigest"/>
<entry key="ws-security.is-bsp-compliant" value="false"/>
<entry key="passwordCallbackClass" value="org.apache.camel.example.cxf.proxy.UTPasswordCallback"/>
</map>
</property>
</bean>
<!-- this is the CXF web service we use as the front end -->
<cxf:cxfEndpoint id="versionService"
address="http://localhost:${proxy.port}/camel-example-cxf-proxy/webservices/versionAdapter"
endpointName="s:VersionHttpSoap11Endpoint"
serviceName="s:Version"
wsdlURL="etc/versionAdapter.wsdl"
xmlns:s="http://axisversion.sample">
<cxf:inInterceptors>
<ref bean="loggingInInterceptor"/>
<ref bean="wss4jInInterceptor"/>
</cxf:inInterceptors>
<cxf:outInterceptors>
<ref bean="loggingOutInterceptor"/>
</cxf:outInterceptors>
</cxf:cxfEndpoint>
<!-- this is the Camel route which proxies the real web service and forwards SOAP requests to it -->
<camelContext xmlns="http://camel.apache.org/schema/spring">
<!-- property which contains port number -->
<propertyPlaceholder id="properties" location="classpath:incident.properties,file:target/custom.properties"/>
<endpoint id="callRealWebService" uri="http://localhost:${real.port}/axis2/services/Version?bridgeEndpoint=true&throwExceptionOnFailure=false"/>
<route>
<!-- CXF consumer using MESSAGE format -->
<from uri="cxf:bean:versionService?dataFormat=MESSAGE"/>
<!-- log input received -->
<to uri="log:input"/>
<!-- enrich the input by ensure the incidentId parameter is set -->
<to uri="bean:enrichBean"/>
<!-- opp removing headers... testing -->
<removeHeaders pattern="*" />
<!-- send proxied request to real web service -->
<to uri="callRealWebService"/>
<!-- log answer from real web service -->
<to uri="log:output"/>
</route>
</camelContext>
</beans>
<!-- END SNIPPET: e1 -->
When i invoke my proxy webservice i am getting error. Here is the complete error trace..
INFO: Inbound Message
----------------------------
ID: 1
Address: http://localhost:9080/camel-example-cxf-proxy/webservices/versionAdapter
Encoding: UTF-8
Http-Method: POST
Content-Type: text/xml;charset=UTF-8
Headers: {accept-encoding=[gzip,deflate], connection=[keep-alive], Content-Length=[1097], content-type=[text/xml;charset
=UTF-8], Host=[localhost:9080], SOAPAction=["urn:getVersion"], User-Agent=[Apache-HttpClient/4.1.1 (java 1.5)]}
Payload: <soapenv:Envelope xmlns:axis="http://axisversion.sample" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelop
e/">
<soapenv:Header><wsse:Security soapenv:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-20
0401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utilit
y-1.0.xsd"><wsu:Timestamp wsu:Id="TS-42"><wsu:Created>2014-11-19T12:41:10Z</wsu:Created><wsu:Expires>2014-11-19T13:14:30
Z</wsu:Expires></wsu:Timestamp><wsse:UsernameToken wsu:Id="UsernameToken-41"><wsse:Username>opp</wsse:Username><wsse:Pas
sword Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">m0c8nW1n+
/jfHzwM5lHc9F3+B1g=</wsse:Password><wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soa
p-message-security-1.0#Base64Binary">VUr9FAuf1J/UYWEBMdTAlA==</wsse:Nonce><wsu:Created>2014-11-19T12:41:10.455Z</wsu:Cre
ated></wsse:UsernameToken></wsse:Security></soapenv:Header>
<soapenv:Body>
<axis:getVersion/>
</soapenv:Body>
</soapenv:Envelope>
--------------------------------------
Inside UTPasswordCallback Method # UTPasswordCallback class
Wed Nov 19 18:10:33 IST 2014 Inside UTPasswordCallback()--> UTPasswordCallback Class
Nov 19, 2014 6:10:33 PM org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor checkActions
WARNING: Security processing failed (actions mismatch)
Nov 19, 2014 6:10:33 PM org.apache.cxf.phase.PhaseInterceptorChain doDefaultLogging
WARNING: Interceptor for {http://axisversion.sample}Version has thrown exception, unwinding now
org.apache.cxf.binding.soap.SoapFault: An error was discovered processing the <wsse:Security> header.
at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.createSoapFault(WSS4JInInterceptor.java:809)
at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.handleMessage(WSS4JInInterceptor.java:313)
at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.handleMessage(WSS4JInInterceptor.java:93)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:307)
at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:243)
at org.apache.cxf.transport.http_jetty.JettyHTTPDestination.doService(JettyHTTPDestination.java:261)
at org.apache.cxf.transport.http_jetty.JettyHTTPHandler.handle(JettyHTTPHandler.java:70)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1088)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1024)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:135)
at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:255)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116)
at org.eclipse.jetty.server.Server.handle(Server.java:370)
at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:494)
at org.eclipse.jetty.server.AbstractHttpConnection.content(AbstractHttpConnection.java:982)
at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.content(AbstractHttpConnection.java:1043)
at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:865)
at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:240)
at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:82)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:696)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:53)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:543)
at java.lang.Thread.run(Thread.java:722)
Caused by: org.apache.wss4j.common.ext.WSSecurityException: An error was discovered processing the <wsse:Security> heade
r
at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.checkActions(WSS4JInInterceptor.java:339)
at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.handleMessage(WSS4JInInterceptor.java:297)
... 23 more
I am unable to figure out what this error is all about and how can i rectify this error?
Please help on this..
Please use CXF_MESSAGE data format instead of MESSAGE data format.

common webservice interceptor and UsernameTokenValidation compatible with Spring-WS and CXF

I have a scenario, where I want to configure a webservice security interceptor, and a UsernameTokenValidator and put this into say myws-security.jar. Which can be then be used by any webservice (be it CXF based or Spring-WS) that uses this jar. What would be the practice to deal with this scenario.
Would configuring an interceptor with org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor class , or org.springframework.ws.soap.security.wss4j.Wss4jSecurityInterceptor work for me in this case ?
In both Spring-WS and CXF, you typically do not provide your own WSS interceptor, you simply configure the provided interceptor with an appropriate callback handler. So in your case if you create an appropriate callback handler(based on the type of securement action), which needs to inherit from javax.security.auth.callback.CallbackHandler, this callback handler can be reused in Spring-WS and Apache CXF:
In Spring-WS you would do something along these lines:
<bean id="wss4jSecurityInterceptor" class="org.springframework.ws.soap.security.wss4j.Wss4jSecurityInterceptor">
<property name="validationCallbackHandler" ref="callBackHandler" />
<property name="validationActions" value="UsernameToken" />
</bean>
And in Apache CXF:
<jaxws:endpoint address=".." id=".." implementor="#memberendpoint">
<jaxws:inInterceptors>
<bean class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
<constructor-arg>
<map>
<entry key="action" value="UsernameToken" />
<entry key="passwordType" value="PasswordDigest" />
<entry key="passwordCallbackRef">
<ref bean="callBackHandler" />
</entry>
</map>
</constructor-arg>
</bean>
</jaxws:inInterceptors>
And the common callbackhandler should work for you in both cases

Configure a common webservice interceptor and usernameTokenValidator compatible with Spring-WS and CXF

Right now I have below configuration for one of my WS endpoints.
<jaxws:endpoint id="myService" implementor="#myServiceImpl" address="/myService">
<jaxws:inInterceptors>
<bean class="org.apache.cxf.binding.soap.saaj.SAAJInInterceptor" />
<ref bean="myServiceInterceptor"/>
</jaxws:inInterceptors>
<jaxws:properties>
<entry key="ws-security.ut.validator" value-ref="myServiceUsernameTokenValidator"/>
<jaxws:properties>
</jaxws:endpoint>
<bean id=" myServiceInterceptor " class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
<constructor-arg>
<map>
<entry key="action" value="UsernameToken" />
<entry key="passwordType" value="PasswordText" />
</map>
</constructor-arg>
</ bean>
Now I want to move this bean="myServiceInterceptor" and custom userNameToken Validator config (jaxws:properties) to a separate jar (say A). So that any spring WS using that jar A , can leverage same interceptor and customUseranameToken functionality.
My questions:
1) How do I setup/configure a generic webservice security interceptor rather than a cxf specific interceptor.
2) How can I setup a common <jaxws:properties> that can be used by all the endpoints.
Thanks!
MOST of the stuff could be configured at the Bus level and thus inherited by anything that uses that bus:
<cxf:bus>
<cxf:inInterceptors>....
<cxf:properties>....
</cxf:bus>