Dynamically switch http:listener-config configuration in mule - mule

I would like to have the ability to switch listener configuration easily in Mule (CE-3.6.1) from http to https (with basic autentication). I've created a variable in the mule-project.xml 'mule.protocol' and two properties files http.properties and https.properties with some data like port (the same port in http and https), host, password, etc.
in config.xml I have:
<context:property-placeholder location="${mule.protocol}.properties" />
<http:listener-config name="HTTP_Listener_Configuration" host="${host}" port="${port}" doc:name="HTTP Listener Configuration" protocol="${protocol}">
<tls:context>
<tls:key-store type="${keystore.type}" path="${keystore.path}" keyPassword="${keystore.keyPassword}" password="${keystore.password}" />
</tls:context>
</http:listener-config>
but I have two problems.
First, I get a message: Value '${protocol}' is not man-valid with respect to enumeration '[HTTP, HTTPS]'
and the second, section 'tls:context' is permitted only in https case, so I would have to hide it dynamically. How to solve these problems or whether there is another way to easily switch between the configuration of http and https? I'm using HTTP_Listener_Configuration in many services.

Unfortunately, this was only added for Mule 3.8.0 (coming soon). In older versions the protocol attribute does not support properties. You could use a Spring profile as a workaround. You can find more data in the JIRA ticket for this.

Related

Https soap service in mule

I have a requirement where soap based service needs to be consumed and in order to achieve that I had used WSConsumer component in Mule.
Where we give the service URL in the properties file and refer to it.
<ws:consumer-config name="Web_Service_Consumer" wsdlLocation="serviceApi.wsdl"
service="serviceAPI" port="serviceApiSoap12Port" serviceAddress="${serviceurl}"
doc:name="Web Service Consumer"/>
Now after the development we came to know that QA web service is a HTTPS web service and while hitting the service following exception is received
SSLHandshakeException: General SSLEngine problem
I'm able to hit the service with Http:request connector as following
<http:request-config name="HTTP_Request_Configuration" host="${host}" port="${port}"
doc:name="HTTP Request Configuration" protocol="HTTPS">
<tls:context>
<tls:trust-store insecure="true" />
</tls:context>
</http:request-config>
But the issue with above config is it won't work for HTTP configuration.
I should be able to connect to both HTTP & HTTPS as I have different environments.
Is there a way where I can achieve this with ws:consumer??
I assume the HTTP connector configuration shown is the one queried by your WS Consumer connector. A simple solution would be to configure the protocol of your HTTP config via property file but Mule doesn't play well with it because you may end-up with a TLS Context configured with HTTP and your connector won't work. There is a little trick you can do however: create 2 HTTP configurations - one for HTTP and one for HTTPS:
<http:listener-config name="HTTPS_Config"
protocol="HTTPS"
host="${host}"
port="${port}"
doc:name="HTTPS Config" >
<tls:context>
<tls:key-store type="${keystore.type}"
path="${keystore.path}"
keyPassword="${keystore.keyPassword}"
password="${keystore.password}"/>
</tls:context>
</http:listener-config>
<http:listener-config name="HTTP_Config"
host="${host}"
port="${port}"
doc:name="HTTP Config" >
</http:listener-config>
In a property file, define which configuration (i.e. which protocol) should be used:
host=localhost
port=443
protocol=HTTPS # or HTTP
And finally in your flow, use your property to reference the proper HTTP(S) config:
<flow name="http-testFlow">
<http:listener config-ref="${protocol}_Config" path="/test" doc:name="HTTP"/>
...
</flow>
The trick is to name your configuration ${protocol}_Config such as HTTP_Config and HTTPS_Config so the proper one is used at runtime via config-ref="${protocol}_Config". Mule will then dynamically use the proper configuration when your app is launched. This is entirely transparent for the user as only the protocol (HTTP vs. HTTPS) needs to be configured, and it can be used in any environment.
You can use this differently, the idea is to have Mule pick your HTTP or HTTPS dynamically at runtime.
EDIT: to configure your WS Consumer with HTTPS you'll need to reference a proper HTTP Requester Configuration such as:
<ws:consumer-config name="Web_Service_Consumer"
...
connectorConfig="HTTP_Request_Configuration"/>
<http:request-config name="HTTP_Request_Configuration"
...
<tls:context>
...
</tls:context>
...
/>
See Web Service Consumer documentation for details.
Note: though this solution works I would recommend using HTTPS all the time, for security reasons and to have less differences between your dev/QA/Prod/... environments - among other things.
I faced similar issues, we finally chose to have only an HTTPS config and define via property which keystore to use at runtime. In dev we would use a self-signed certificate and a proper keystore in environments requiring proper security.
Hope this helps.

Mule HTTP transport deprecated

I use the new HTTP Connector as mentioned in the online documentation:
<http:listener-config name="HTTP_Listener_Configuration" host="localhost" port="8081"/>
<flow name="test_flow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/" doc:name="NEW HTTP Connector"/>
<...>
</flow>
Yet, when deploying in DEV on Cloudhub, I still get the message:
HTTP transport is deprecated and will be removed in Mule 4.0. Use HTTP
module instead.
I'm not sure what to look for. Is this a known issue?
While deploying to mule cloudhub, please change the host in listener config from local host to the default All interfaces [0.0.0.0].
Change your HTTP Connector to use "0.0.0.0" instead of your CloudHub domain name and redeploy.

Mule 2 Way HTTPS Authentication

I have a Mule application which needs to talk an external server over HTTPS using 2 way SSL authentication.
My question is: How to enable Server Certificate verification in Mule ? It seems, by default Mule doesn't verify Server's Cert. I am using Mule v 3.3.0.
For example: '-k' option in curl disables server's cert verification.
In similar way, is there any configuration parameter by which I can enable/disable Server's cert verification ?
Thanks
Jai
For Mule versions before 3.6, the HTTP transport supports configuration of the trust store used by the HTTP outbound endpoint to determine whether the certificate presented by an HTTPS server should be trusted.
To provide a key store that contains the certificates of servers you need to trust, provide the <https:tls-server /> to the <https:connector />, and reference that connector in your <https:outbound-endpoint />:
<https:connector name="myHttpsConnector">
<https:tls-server path="truststore.jks" storePassword="supersecure" />
</https:connector>
<flow name="someFlow">
<https:outbound-endpoint host="remote-host" port="443" path="/api" connector-ref="myHttpsConnector" />
</flow>
The blog post linked in clare's answer explains this a bit, from both the server side and the client side. You can also refer to the HTTPS Transport Reference, although it doesn't explain the use of tls-server vs. tls-client.
You can check out this blogpost. It will show you how you can configure mutual authentication in Mule. HTH.
You can configure the HTTP Request connector in Mule >= 3.6.0 to use a trust store you create that contains the certificate(s) of the server(s) you need to trust using TLS Configuration.
It might look something like this:
<tls:context name="tlsContextForServiceFoo">
<tls:trust-store path="serviceFooServerCertificates.jks" password="supersecure"/>
<tls:key-store path="myClientCertificates.jks" keyPassword="extrasecure" password="ultrasecure"/>
</tls:context>
<http:request-config name="twoWayAuthServiceFooConfig"
protocol="HTTPS"
host="services.pentagon.gov"
port="443"
tlsContext-ref="tlsContextForServiceFoo" />
<flow name="useServiceFoo">
<http:request config-ref="twoWayAuthServiceFooConfig" path="/api/doStuff" method="POST" />
</flow>

hostName in webservice endpoint in mule config?

I have a mule application which needs to be deployed in different servers. I have question for setting the hostname for HTTP based endpoint address
Should host name come from properties file, replacing it at build time based on the environment for which the application is being built --
Example --
http:inbound-endpoint address="http://${host.name}:61005/my/service" exchange-pattern="request-response"
Or is it possible to build the deployable app with hostname as localhost and replace it at deployment time
Example --
http:inbound-endpoint address="http://localhost:61005/my/service" exchange-pattern="request-response"
Thanks in advance.
You could use 0.0.0.0 as the host and it will listen on every network interface of the server:
<http:inbound-endpoint address="http://0.0.0.0:61005/my/service" exchange-pattern="request-response" />
It means that if, for example, your server has the IP 192.168.0.1, it will automatically server requests at http://192.168.0.1:61005/my/service/
It will save you from configuring a deployment file.
A properties file would work fine but keep in mind Spring's Property Placeholder Resolver can also get values from Java system properties so you could provide a value for ${host.name} at start-up with:
mule -M-Dhost.name=$HOSTNAME

remove server header tomcat

I am able to rename the value of org.apache.coyote.http11.Http11Protocol.SERVER to anything else, so the HTTP-Response-Header contains something like:
Server:Apache
instead of the default
Server:Apache-Coyote/1.1
Using a empty value for org.apache.coyote.http11.Http11Protocol.SERVER does not remove the Server-Header.
How can I remove the Server-Header from my responses?
You can modify your tomcat server.xml and add a "server" option and set it to whatever you want. The server option should be set for any http or ssl connectors that you have running. For example, below is a sample HTTP Connector configuration from an example server.xml file
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" enableLookups="false" xpoweredby="false" server="Web"/>
Short answer - you can't remove the header, but you should modify it (see other answers).
The server header is defined in the RFC and it is mandatory. (not defined as optional in the spec)
Taken from http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.38
14.38 Server
The Server response-header field contains information about the software used by the origin server to handle the request.
The field can contain multiple product tokens (section 3.8) and
comments identifying the server and any significant subproducts. The
product tokens are listed in order of their significance for
identifying the application.
If the response is being forwarded through a proxy, the proxy application MUST NOT modify the Server
response-header. Instead, it SHOULD include a Via field (as described
in section 14.45).
Note: Revealing the specific software version of the server might
allow the server machine to become more vulnerable to attacks
against software that is known to contain security holes. Server
implementors are encouraged to make this field a configurable
option.
It should be possible since Tomcat 5.5. Check out this discussion: https://mail-archives.apache.org/mod_mbox/tomcat-users/200508.mbox/%3C42FBE8AA.1060401#joedog.org%3E
and this link:
https://tomcat.apache.org/tomcat-4.1-doc/config/coyote.html
Accordingly the following should set the server header to TEST. Empty should make it empty.
<Connector className="org.apache.coyote.tomcat4.CoyoteConnector" port="8180" inProcessors="5" maxProcessors="75" enableLookups="true" acceptCount="10" debug="0" connectionTimeout="20000" useURIValidationHack="false" server="TEST"/>
Setting the Server header to Apache should security-wise be good enough in most cases. Just from that it won't be possible to infer which OS nor which exact version with which modules and the versions of the modules running.
if you are using embedded tomcat then you can try below code.
import org.apache.catalina.startup.Tomcat;
final Tomcat server = new Tomcat();
server.getConnector().setXpoweredBy(false);
server.getConnector().setAttribute("server", "");
For Web application.
Set Server header from the code.
It worked for me in Java Spring boot project.
response.setHeader("Server", "none");
Try adding from code if it is deployed in tomcat.