How to configure a websocket service in Apache Knox with basic authentication - websocket

I managed to configure a websocket service in Knox which for test purposes is ws://echo.websocket.org
Here are my configuration files:
service.xml
<service role="ECHOWS" name="echows" version="0.0.1">
<policies>
<policy role="webappsec"/>
<policy role="authentication" name="Anonymous"/>
<policy role="rewrite"/>
<policy role="authorization"/>
</policies>
<routes>
<route path="/echows">
<rewrite apply="ECHOWS/echows/inbound" to="request.url"/>
</route>
</routes>
</service>
rewrite.xml
<rules>
<rule dir="IN" name="ECHOWS/echows/inbound" pattern="*://*:*/**/echows">
<rewrite template="{$serviceUrl[ECHOWS]}"/>
</rule>
</rules>
{topology}.xml section:
<service>
<role>ECHOWS</role>
<url>ws://echo.websocket.org</url>
</service>
I can connect to it:
wscat -c wss://my-knox-server/gateway/default/echows
connected (press CTRL+C to quit)
> Hello Knox!
< Hello Knox!
But I'd like Knox accept connection only when proper credentials are given:
wscat --auth <username:password> -c wss://my-knox-server/gateway/default/echows
My Knox configuration for http services works in this way that I have to put credentials, otherwise I get 401:
curl -i https://my-knox-server/gateway/default/my_service/ping
HTTP/1.1 401 Unauthorized
curl -i -u '<user>:<password>' https://my-knox-server/gateway/default/my_service/ping
HTTP/1.1 200 OK
I'd like to achieve the same result with websockets.
[EDIT]
Moreover I don't fully understand the above service.xml configuration for my websocket service, since it is different than the simplest possible configuration for a http service I was able to use:
<service role="MY_APP" name="my_app" version="0.0.1">
<routes>
<route path="/my_app/**"/>
</routes>
</service>
Why in case of a websocket service I need policies, and what do they mean?
Why <routes>/<route> has an element <rewrite> and what is its semantics? Does it correspond to <rule>/<rewrite> from rewrite.xml? What does request.url mean there?

Good question, unfortunately the Authentication and Authorization mechanism in Knox is based on Http servlet filters which won't be applicable for Websocket.
One thing you can do is have a HTTP side that does the authentication and then opens up the websocket connection.
If you want you can open up a JIRA for this enhancement.
[EDIT]
Answers to followup questions
In case of Websockets have no meaning, they are artifacts from http
Again the in rewrites can be explained better with http context than with websocket. What they do is, tell Knox when to apply the rewrite rule i.e. request.url, request.body, response.url, response.body etc. Since, rules are based on HTTP servlet filters they are not used to rewrite websocket data. I believe there should be some JIRA lying around for that.

Related

Configuring embedded Jetty 9 for X-FORWARDED-PROTO with Spring Boot

I am running a Spring Boot application in AWS. The application is running behind an Elastic Load Balancer (ELB). The ELB is configured to use https (port 443) to the outside world, but passes through http (port 8080) to the application. The ELB is configured to pass through the x-forwarded-proto header. I am using Jetty 9.0.0.M0, with Spring Boot 1.1.5 RELEASE.
I appear to be getting incorrect redirects sent back from the application via the ELB where the redirect responses are coming back as http, rather than https. Now, I read here that I should set the "forwarded" header to true using:
<Set name="forwarded">true</Set>
I can't see how to do this with the embedded version of Jetty in Spring Boot because there is no XML configuration file as part of my source.
I have looked at the EmbeddedServletContainerCustomizer infrastructure but I still can't get the right incantation to get this setup to work.
The application is built and tested outside of the AWS https environment, so the application needs to transparently work with http too. Directly hitting the application endpoints without going through the ELB works. It's just that the ELB to application route that's not working.
Any ideas?
Had a similar issue myself and while researching stumbled across your question. I found this was quite easy to to programatically however isn't really explained in the Jetty docs.
The structure of the Jetty xml configuration files are matched by the structure of the java API so you can just replicate it in code.
So following the Jetty guide on how to configure using the XML configuration file here
I was able to configure the embedded server programatically like this:
Server server = new Server( port );
// Create HTTP Config
HttpConfiguration httpConfig = new HttpConfiguration();
// Add support for X-Forwarded headers
httpConfig.addCustomizer( new org.eclipse.jetty.server.ForwardedRequestCustomizer() );
// Create the http connector
HttpConnectionFactory connectionFactory = new HttpConnectionFactory( httpConfig );
ServerConnector connector = new ServerConnector(server, connectionFactory);
// Make sure you set the port on the connector, the port in the Server constructor is overridden by the new connector
connector.setPort( port );
// Add the connector to the server
server.setConnectors( new ServerConnector[] { connector } );
Try setting the following property in your spring boot application:
server.use-forward-headers=true
The will ensure the correct protocol is read from the header. Refer to documentation here:
https://docs.spring.io/spring-boot/docs/1.5.9.RELEASE/reference/html/howto-embedded-servlet-containers.html
I found a couple problems with the default Spring Boot Jetty configuration, not the least of which are enabled SSL algorithms which SSLLabs Check doesn't like.
Anyway: The fix I found for this was something like:
#Bean
public JettyEmbeddedServletContainerFactory jettyEmbeddedServletContainerFactory()
{
// Deploy the nuclear option, kill the default Spring Boot factory
// and replace with mine that disables extra crud.
JettyEmbeddedServletContainerFactory fac = new JettyEmbeddedServletContainerFactory();
// This allows ELB to work.
fac.setUseForwardHeaders( true );
return fac;
}
There are also a number of other ELB options that you need to setup if you want SSL end-to-end. I had to use the command line client with some tweaks and change the health checks to TCP:8443 b/c the EC2 instance certificates look invalid to the load balancer.
Here's what just worked for us with a Spring app behind jetty-runner-9.3.6.jar. In our case, our jetty.xml didn't have any addConnector already, and trying to add just the addConnector would error out.
Found it here - https://github.com/george-hawkins/authsite/blob/2c5d61b984a328ef878216a3acfd0ad2593f81b1/src/main/config/etc/jetty.xml
<New id="httpConfig" class="org.eclipse.jetty.server.HttpConfiguration">
<Call name="addCustomizer">
<Arg><New class="org.eclipse.jetty.server.ForwardedRequestCustomizer"/></Arg>
</Call>
</New>
<Call name="addConnector">
<Arg>
<New class="org.eclipse.jetty.server.ServerConnector">
<Arg name="server"><Ref refid="Server" /></Arg>
<Arg name="factories">
<Array type="org.eclipse.jetty.server.ConnectionFactory">
<Item>
<New class="org.eclipse.jetty.server.HttpConnectionFactory">
<Arg name="config"><Ref refid="httpConfig" /></Arg>
</New>
</Item>
</Array>
</Arg>
<Set name="port"><SystemProperty name="jetty.port" default="8080"/></Set>
</New>
</Arg>
</Call>
What this DOES is to modify the Request object that is passed through to make it -look- like it didn't come through a proxy (replacing the details with whatever X-Forwarded headers are available and supported).
See http://archive.eclipse.org/jetty/9.0.0.M4/apidocs/index.html?org/eclipse/jetty/server/ForwardedRequestCustomizer.html
This customizer looks at at HTTP request for headers that indicate it has been forwarded by one or more proxies. Specifically handled are:
X-Forwarded-Host
X-Forwarded-Server
X-Forwarded-For
X-Forwarded-Proto
If these headers are present, then the Request object is updated so that the proxy is not seen as the other end point of the connection on which the request came
I have been unable to find a simple Jetty 9 solution to this question. Other than recommending that I upgrade to a later version of Jetty (which is good advice) I have received no other suggestions (at this time, as you can see)
My solution for the sake of expedience is to abandon Jetty, and instead to use embedded tomcat, where this functionality is a simple matter of configuration in the application.properties file. Simply add the following line to application.properties:
server.tomcat.remote_ip_header=x-forwarded-for
This appears to do the trick using the default embedded tomcat that comes as part of Spring Boot.

Cannot connect to secured JAXRS endpoint (via CXF via Spring)

I try to implement one JAXRS endpoint with https protocol. I followed the instructions of http://cxf.apache.org/docs/secure-jax-rs-services.html#SecureJAX-RSServices-Configuringendpoints here.
I have declared a jaxrs:server endpoint in my XML file which depends on the httpj:engine-factory.
A log file tells me that my service is started and that it is running, but if I try to connect to it, the Firefox web browser tells me "Error: Data Transfer Interrupted" (German: "Fehler: Datenübertragung unterbrochen"). The web service (or JAXRS or CXF) doesn't throw an error message. Opera just says that it cannot connect to the server. Wireshark tells me that the client tries to reconnect to the server a few times and then the client (web browser) seems to give up.
My configuration looks like this:
<httpj:engine-factory id="httpsSettings" bus="cxf">
<httpj:engine port="8545">
<httpj:tlsServerParameters>
<sec:keyManagers keyPassword="...">
<sec:keyStore type="PKCS12" password="..." file="..."/>
</sec:keyManagers>
<sec:trustManagers>
<sec:keyStore type="JKS" password="..." file="..."/>
</sec:trustManagers>
<sec:cipherSuitesFilter>
<sec:include>.*_EXPORT_.*</sec:include>
<sec:include>.*_EXPORT1024_.*</sec:include>
<sec:include>.*_WITH_DES_.*</sec:include>
<sec:include>.*_WITH_NULL_.*</sec:include>
<sec:exclude>.*_DH_anon_.*</sec:exclude>
</sec:cipherSuitesFilter>
<sec:clientAuthentication want="true" required="false"/>
</httpj:tlsServerParameters>
</httpj:engine>
</httpj:engine-factory>
<jaxrs:server id="cdmiSSLService" address="https://localhost:8545/"
depends-on="httpsSettings" beanNames="...">
<jaxrs:inInterceptors>
<ref bean="..."/>
</jaxrs:inInterceptors>
<jaxrs:providers>
<ref bean="..."/>
...
</jaxrs:providers>
<jaxrs:serviceBeans>
<ref bean="..."/>
...
</jaxrs:serviceBeans>
</jaxrs:server>
I should add that I had only one JAXRS endpoint configured at this time, and if I change the JAXRS endpoint configuration to http protocol, everything works fine and I can connect to the web service without any problems.
Can someone please help me what I can do here? I know that isn't much information, but it doesn't give me more information at the moment. Please bear with me, it's the first time that I implement it in that way. I'm a beginner here. It's a Maven multi-module project which uses the Spring Framework. The configuration needs to be via jaxrs:server.
Many thanks in advance!
Problem is solved. Please don't answer anymore. It helped me to test the with the jks files http://svn.apache.org/repos/asf/cxf/trunk/distribution/src/main/release/samples/jax_rs/basic_https/src/main/config/ and the configuration of http://svn.apache.org/repos/asf/cxf/trunk/distribution/src/main/release/samples/jax_rs/basic_https/src/main/resources/ServerConfig.xml.

Http post forwarding on tomcat level to different domain

I have two set of server on different domains using tomcat .
Now I want to forward http post call from one server to another preserving the payload in http entity throughout.
Problem is I donot want to change code and want this to be done on tomcat level anymeans.
I currently is trying to use URLrewriteFilter but not getting through.
any suggestions ?
URLrewriteFilter may help. You can define a proxy type for element.
The request will be proxied to the full url specified. commons-http
and commons-codec must both be in the classpath to use this feature.
Sample:
<rule>
<name>A Rule</name>
<from>^/something$</from>
<to type="proxy">http://anotherserver.com/something</to>
</rule>

Spring Integration call Web service

I'm still new to Spring Integration and I've few question.
I have a service with WSDL deploy in tomcat server.
and I would like to send parameter from my spring integration flow to that service and receive
response back to do next things in the flow.
I should use outbound WS gateway to do this right?
and how to config the xml to do this?
i've try temperature example but still don't understand it.
thank you.
///////////////////////////////////////////////////////////////
Here is my config:
<int:gateway service-interface="com.app.service.IRequester" id="IRequester"
default-request-channel="requestChannel"
default-reply-channel="responseChannel"
error-channel="errorChannel" >
</int:gateway>
<int:service-activator input-channel="requestChannel" id="bu1"
ref="BU1" method="bu1Method"
output-channel="buChannel">
</int:service-activator>
<int:service-activator input-channel="errorChannel"
ref="handlerError" method="errorReturnToGateway"
output-channel="responseChannel" >
</int:service-activator>
<int:router id="routingChannel" input-channel="buChannel" ref="RoutingChannel" method="routingChannel">
<int:mapping value="firstChannel" channel="channelFirst" />
<int:mapping value="otherChannel" channel="channelOther" />
</int:router>
<int:service-activator id="firstBU" input-channel="channelFirst"
ref="FirstBU" method="doSomething" output-channel="responseChannel">
</int:service-activator>
<int:service-activator id="otherBU" input-channel="channelOther"
ref="OtherBU" method="doSomething" output-channel="responseChannel">
</int:service-activator>
I need to change output channel from both firstBU and otherBU activator to call web service which is send a paremeter to that service(paremeter type is Hashmap) and receive same type response.
I don't know how to call web service by using ws:outbound-gateway.Since I have only known to call web service using java way by generate client java class and may be i'll call service in method doSomething.
In my case,Do you think which way is better?
And I still want to know how to solve this by use ws:outbound-gateway too.
thank you.
As far as it is SOAP, so you get deal with XML. And your WSDL provides you the contract - an XSD which XML should be sent to the service and which will be returned as a response.
So, your task to configure <int-ws:outbound-gateway> and provide correct XML as a message payload to the request-channel of that component.
The same is about a response: you get an XML as payload.
However, it is for simple WS Outbound Gateway. You can configure it with marshaller and send to the request-channel some domain POJO and that marshaller takes care about converting that POJO to the XML representation for the SOAP request.
Show, your config, please, and maybe we can help more with your concreate issues.

wso2 esb mtom attachment

I am currently playing around with the WSO2 enterprise service bus, some cxf based webservices and mtom attachments.
Using SoapUI (MTOM enabled), I submit the following request to one backend service:
...
<incident>
....
<attachmentList>
<attachment>
<contentID>cid:soapui32.png</contentID>
</attachment>
</attachmentList>
</incident>
...
With MTOM enabled Raw data is
...
<attachmentList>
<attachment>
<contentID>
<inc:Include href="cid:soapui32.png" xmlns:inc="http://www.w3.org/2004/08/xop/include"/>
</contentID>
</attachment>
</attachmentList>
...
------=_Part_0_22113723.1360006252844
Content-Type: image/x-png; name=soapui32.png
Content-Transfer-Encoding: binary
Content-ID: <soapui32.png>
Content-Disposition: attachment; name="soapui32.png"; filename="soapui32.png"
......
So far, so good.
Now, as the next step, I create a WSDL based proxy service (WSO2 ESB 4.5.1) for this webservice.
<proxy xmlns="http://ws.apache.org/ns/synapse" name="testService" transports="https,http" statistics="enable" trace="enable" startOnLoad="true">
<target>
<outSequence>
<send/>
</outSequence>
<endpoint>
<wsdl service="IncidentService" port="IncidentServicePort" uri="uri2myservicewsdl"/>
</endpoint>
</target>
<publishWSDL uri="uri2myservicewsdl"/>
<description></description>
</proxy>
enableMTOM is set to true in the axis2.xml, MTOM is enabled for the proxy service.
If I submit exactly the same request with the same attachment via SoapUI, the esb transforms the attachment to inline content (debug log):
DEBUG - Starting Activation Handler invocation. Incoming Message:
......
<incident>
<attachmentList>
<attachment>
<contentID>iVBORw0KGgoAAAANSUh.....</contentID>
</attachment>
</attachmentList>
</incident>
.....
</soapenv:Body></soapenv:Envelope>
{org.wso2.carbon.activation.module.ActivationHandler}
Where can I enable MTOM, so that the proxy doesnt transform it to inline content?
Many thanks in advance.
Workaround
Maybe someone is interested, even if it's just a workaround:
I had enabled MTOM and SwA attachments in the axis2.xml (wso2 esb conf directory).
As soon as I disabled SwA and only left MTOM enabled, attachments are not transformed to inline content any more.
Now SwA is disabled for all proxy services, but that's ok for the moment.
I will have another look at it later, maybe it's a bug.

Resources