We're maintaining a Java application with a JAX-WS SOAP API for external systems running on WildFly 14 application server. The external systems currently connect using common one-way SSL. Our goal is to switch communication to mutual authentication, so two-way SSL.
Not all of the external systems can make the switch at the same time though, so simply enforcing two-way SSL is not an option. We need to migrate them step-by-step during a transition phase. That why I've been wondering: Is there a possibility to enable two-way SSL on a WildFly HTTPS interface for specific caller IPs only?
I have based my tests on the official documentation on setting up regular two-way SSL. Following these steps, every caller needs to provide a client certificate. Modifying that example configuration to use want-client-auth instead of need-client-auth softens the checks to support two-way SSL but not require it. Unfortunately that is not enough in our case, because it does not imply guarantees about whether a particular external system is consistently using two-way SSL or not. A system could send some of its requests providing a client certificate, and some without. In other words, business requires a way to say "From this day on, external system Foo may only use the API with a client certificate. All the other external systems are unaffected, for now."
To implement this - preferably without application code changes -
I've been reading the documentation of the new WildFly security module Elytron. It seems quite extensible, but details on custom components are sparse and I haven't found an extension point that sounds like it would help in my case.
The only solution approach I have right now is configuring a separate set of socket-binding and https-listener for Wildfly, similar to what is described here. That means we would have two HTTPS ports: One with one-way SSL, and another one with mandatory two-way SSL. As external systems are completing their migration steps, they switch the port used for invoking our API. Forcing them to only use the two-way SSL port from then on would require specific firewall rules, but should be possible.
So, this solution is rather simple in technical implementation but leads to overhead for re-configuring the external systems and adapting firewall rules. That's why I'd be happy about any suggestions for a solution that is more elegant, or hints how to use Elytron for that.
Thanks in advance!
I think you came to best conclusion. Elytron does not have possibility to choose SSL Context based on client parameters (What would that be? Client IP address? That can change when behind the load balancer.)
So I think only way is to have different SSLContext configured on different ports (or hostnames).
Regarding extending server. I guess SSL handshake is very early step and after that different customisation points take part. I thought about some Undertow custom handler, something similar to [1], but as I said that would be too late.
[1] http://undertow.io/undertow-docs/undertow-docs-2.0.0/index.html#redirect-handler
Related
Is there any possibility to:
Connect Spring, Feign, any Load Balancer with working SSL together?
See any working example?
Read explanation about how features?
Spring Feign with SSL and Load Balancer
I couldn't find out comprehensive source of knowledge about creating modern Spring Client based on interfaces, without writing much boilerplate code. Now, I have learned a lot and I want to share with my little project about creating such a thing, without cracking Your head against the wall, but let's start from the beggining.
Prerequisite
We need some features like:
Java 11 or higher.
Maven (3.6.3 is enough).
Spring (2.6.5 is my starter version).
Minimal knowledge about SSL.
TL;DR Gimme some code
You can download whole project from this repository. All dependencies, files, configuration is included and is ready to start as it is. You just need to specify client, two instances of one kind and two of another API to see the proof of working load balancing. Just follow instruction.
Introduction
Nowadays, we expect high avaliable, very efficient and complex infrastructure on many instances. Furthermore, everything should be encrypted over HTTPS protocol, increasing the level of security. From hundreds of different libraries I decided to do something with Feign Client and check the posibilities.
Why Feign?
It is oficially part of a Spring Cloud components.
Multiple implementations like OkHttpClient or ApacheHttpClient.
Configuration over implementation in out of a box style, like Retryer or ErrorDecoder.
It can be easly bound with Spring Load Balancer.
In my example I have used both implementation of Client to show differences in configuration, e.g. the way we can add truststore to our API client. Probably the biggest pros is fact, that we can configure our clients totally dependant from themselves. In inner traffic, between our own components, we have possibility to turn of SSL and set less timeouts, quite the opposite to outer traffic with TLS and longer timeouts.
Configuration over Implementation
As I said, we have many implementations as out of a box, ready to use with a little dose of magic. Default configuration provide us possibility to attempt max 5 times any endpoint, when it fail to response with any reason. In a simply way we can change it by creating #Bean in EndpointConfiguration.class. The most important thing is to bind our configuration with appropriate #LoadBalancerClient and #FeignClient, because It's not bean, thus we manually point at configuration.
SSL
It is important to provide truststore and build SSLContext/SSLFactory with TrustManager to work with SSL. We must override default client with our proposition of Bean, of course we can inject any other bean by constructor. Alternatively we can use default client and install certificate in JDK truststore or override javax.net.ssl.trustStore and javax.net.ssl.trustStorePassword. Very usefull is to use JVM argument -Djavax.net.debug=all during connection tests to check if our certificates are properly loaded and connection ends up with success. Of course You should not keep password in clear text format in Your production environment. It is a way better to keep encrypted format of our secret and decrypt it during application start.
Load Balancer
The most important thing that I have done is load balancer configuration with pointers to the service and configuration. We can decide current load balancing strategy defining ReactorLoadBalancer<ServiceInstance> #Bean, default one is round robin, also we can choose random way. Another challange is to provide our instances of nodes to load balancer. Every client should implement it own ServiceInstanceListSupplier with serviceId bound to the service name and list of actual instances, that specify host, port or protocol (HTTP/HTTPS).
All that glitters is not gold
Patience is the key to success. Spring, Feign and Load Balancer specification is really good, but at this moment I have not seen good working example with all those things linked up together. A lot of beans are marked as #ConditionalOnMissingBean even with combined property. It is a bit messy to see currently bean, especially client, so you have to work with debugger.
I'm upgrading java xmlrpc from 2.0.1 (org: xmlrpc; module: xmlrpc) to 3.1.3 (org: org.apache.xmlrpc; modules: xmlrpc-client, xmlrpc-server, xmlrpc-commons) in preparation of a migration to JDK 11. Because this project has been split into separate modules for client and server and, I have to fix about three dozen compilation errors. Most of these aren't a big problem. However, I've run into a bit of a roadblock in that there are a number of classes related to secured XMLRPC connections that have been removed in version 3.0:
org.apache.xmlrpc.secure.SecureWebServer; // including setParanoid(boolean), acceptClient(String) and addHandler(string, Handler)
org.apache.xmlrpc.AuthenticatedXmlRpcHandler;
org.apache.xmlrpc.secure.SecureXmlRpcClient; // including setBasicAuthentication(username, password)
We use these in the following ways:
We have a SecureWebServer class that extends from the Apache SecureWebServer, though I don't know if we need this anymore because it appears like the only reason we overrode this was for improved shutdown logic, which seems to be improved already in the 3.1.3 release.
We have a custom Handler class that extends from AuthenticatedXmlRpcHandler. This handler uses a custom ValueProvider for additional logic related to Timestamps and other types that weren't supported in 2.0.1. I don't know if we need this ValueProvider anymore either.
We have a client/server architecture and allow our users to optionally encrypt the communication between the server and the client. Because of this, we have a bunch of logic to configure a SecureXmlRpcClient if necessary.
I've tried to find a migration guide for migrating from 2.X to 3.X versions, and while the Apache site on XMLRPC does contain explanations to some extent, it's not quite the same as a migration guide. Best I can tell, you should now use a config class? It's somewhat confusing, and I'm wondering if it's still necessary to use separate secure and insecure classes.
The above might be more detail than is necessary for the question, which is: How do I handle the removal of separate servers and clients for secure xmlrpc calls in XMLRPC 3.0? Like, do I still need to create separate secure and insecure clients and servers in code, or can everything now use the default XMLRPC server and client with no differentiation between secure and insecure servers and clients?
Like, do I still need to create separate secure and insecure clients
and servers in code, or can everything now use the default XMLRPC
server and client with no differentiation between secure and insecure
servers and clients?
Yes you still need the separate implementations. In 3.x it is up to clients to provide secure set up.
There are couple of ways
On server side you will need to override createServerSocket to substitute for secure SSLServerSocket similar to what 2.x had.
On client side you have initialize with SSLServerSocketFactory on the XmlRpcCommonsTransportFactory to create ssl factory.
Basic Auth can be configured using XmlRpcHttpClientConfig.
Alternatively on server side you could use the full blown servlet container like tomcat or jetty which comes up its own ssl factory.
For client side you can use Httpcient to cover ssl.
You can find some details on how to configure the XmlRpcServlet and client
https://ws.apache.org/xmlrpc/server.html
https://ws.apache.org/xmlrpc/client.html
I feel I should offer some explanation of why I want to implement what seems like a bad solution....
I'm a systems admin, not a java programmer, and have inherited a large and diverse estate of applications running Java 1.7 in Tomcat.
While I am keen to get these all upgraded, this requires the time and cooperation of the development team. My biggest concern (rather topically) is removal of SSLv3, TLS/1.0 and TLS/1.1 from the network. SSL termination for incoming connections is handled by proxy so I can (in principle) stop exposing the vulnerabilities in the services there, however that will break the integration between components running in seperate JVMs and communicating via HTTPS (e.g. CAS authentication).
(yes I could run separate internal/external proxies or use direct addressing bypassing the proxy....but this seems even more of a hack)
Which brings me to my question....
Does BouncyCastle only provide ciphersuites or does it provide TLS?
If I install bouncycastle as a provider will these older java applications be able to make HTTPS client requests using TLS/1.2 or are further code changes required?
BouncyCastle provider will allow you to use ciphers not supported by the jvm. However, depending on your jvm version, the tls 1.2 protocol might not be supported. It appears java 7 should be able to support it.
Either way, to enforce the use of tls1.2, you need further configuration, but not necesserally code changes. You servers must be configured to use it exclusively (configuration may be vendor-specific). Your clients may be configured to use tls1.2 only as well (using -Dhttps.protocols for instance).
See https://blogs.oracle.com/java-platform-group/diagnosing-tls,-ssl,-and-https for more information.
By default, the Java web apps that I develop runs on http.
Suppose, if I want my web app to run on https, is there something specific that I should do as a developer? Or it it totally a network-guy task and un-related to developer?
Basically I want to know the steps to host a Java web application on https.
You don't need any programmatic changes in your web-application, You need to configure SSL with your web/app server
Glassfish SSL Conf
Tomcat SSL Conf
Jetty SSL Conf
JBoss SSL Conf
It depends on what J2EE(Web Container) you are using,
But there should be no developer changes required.
For tomcat you can click here.
The other answers are correct, but I want to add just one tip: sometimes a website serves some pages as http and others as https, usually in the mistaken belief that this will somehow improve performance since https is supposedly harder on the server, best to serve as much un-encrypted http as possible.
Don't do this! It's such a waste of developer effort since you now have to plan all your http -> https transitions, and perhaps even your https -> http transitions. You risk introducing security holes with the transitions (oops, anyone with session cookie can make the transition!). I recommend just doing all 100% https in this scenario. Crypto will never be a significant performance bottleneck, since it's perfectly scalable (more servers, more processors, more threads, etc, always help crypto, you won't be so lucky with the database!).
To enable HTTPS on sever and to make specific application accessible only through secured mode i.e https please do following
Create KeyStores and Add Certificates to the key store [ Links can be found from above answer :) ]
Add the following to your web.xml
Restricted URLs
/appname/*
CONFIDENTIAL
you can add various patterns like /appname/login*,/appname/service* etc..
I'm in the process of writing a client/server application which should work message based. I would like re-use as much as possible instead of writing another implementation and curious what others are using.
Features the library should offer:
client and server side functionality
should work message based
support multi-threading
should work behind load balancer / firewalls
I did several tests with HTTPCore, but the bottom line is that one has to implement both client and server, only the transport layer would be covered. RMI is not an option either due to the network related requirements.
Any ideas are highly appreciated.
Details
My idea is to implement a client/server wrapper which handles the client communication (including user/password validation) and writes incoming requests to a JMS queue:
#1 User --> Wrapper (Check for user/password) --> JMS --> "Server"
#2 User polls Wrapper which polls JMS
Separate processes will handle the requests and can reply via wrapper to the clients. I'd like to use JMS because:
it handles persistence quite well
load balancing - it's easy to handle peaks by adding additional servers as consumer
JMSTimeToLive comes in handy too
Unfortunately I don't see a way to use JMS on it's own, because clients should only have access to their messages and the setup of different users on JMS side doesn't sound feasible either.
Well, HTTP is probably the best supported in terms of client and server code implementing it - but it may well be completely inappropriate based on your requirements. We'll need to actually see some requirements (or at least a vague idea of what the application is like) before we can really advise you properly.
RMI works nicely for us. There are limitations, such as not being able to call back to the client unless you can connect directly to that computer (does not work if client is behind a firewall). You can also easily wrap your communication in SSL or tunnel it over HTTP which can be wrapped in SSL.
If you do end up using this remember to always set the serial version of a class that is distributed to the client. You can set it to 1L when you create it, or if the client already has the class use serialver.exe to discover the existing class's serial. Otherwise as soon as you change or add a public method or variable compatibility with existing clients will break.
static final long serialVersionUID = 1L
EDIT: Each RMI request that comes into the server gets its own thread. You don't have to handle this yourself.
EDIT: I think some details were added later in the question. You can tunnel RMI over HTTP, then you could use a load balancer with it.
I've recently started playing with Hessian and it shows a lot of promise. It natively uses HTTP which makes it simpler than RMI over HTTP and it's a binary protocol which means it's faster than all the XML-based protocols. It's very easy to get Hessian going. I recently did this by embedding Jetty in our app, configuring the Hessian Servlet and making it implement our API interface. The great thing about Hessian is it's simplicity... nothing like JMS or RMI over HTTP. There are also libraries for Hessian in other languages.
I'd say the best-supported, if not best-implemented, client/server communications package for Java is Sun's RMI (Remote Method Invocation). It's included with the standard Java class library, and gets the job done, even if it's not the fastest option out there. And, of course, it's supported by Sun. I implemented a turn-based gaming framework with it several years ago, and it was quite stable.
It is difficult to make a suggestion based on the information given but possibly the use of TemporaryQueues e.g. dynamically created PTP destinations on a per client basis might fit the problem?
Here is a reasonable overview.
Did you tried RMI or CORBA? With both of them you can distribute your logic and create Sessions
Use Spring....Then pick and choose the protocol.
We're standardizing on Adobe's AMF as we're using Adobe Flex/AIR in the client-tier and Java6/Tomcat6/BlazeDS/Spring-Framework2.5/iBATIS2.3.4/ActiveMQ-JMS5.2 in our middle-tier stack (Oracle 10g back-end).
Because we're standardizing on Flex client-side development, AMF and BlazeDS (now better coupled to Spring thanks to Adobe and SpringSource cooperating on the integration), are the most efficient and convenient means we can employ to interact with the server-side.
We also heavily build on JMS messaging in the data center - BlazeDS enables us to bridge our Flex clients as JMS topic subscribers. That is extremely powerful and effective.
Our Flex .swf and Java .class code is bundled into the same .jar file for deployment. That way the correct version of the client code will be deployed to interact with the corresponding middle-tier java code that will process client service calls (or messaging operations). That has always been a bane of client-server computing - making sure the correct versions of the respective tiers are hooked up to each other. We've effectively solved that age-old problem with our particular approach to packaging and deployment.
All of our client-server interactions work over HTTP/HTTPS ports 80 and 443. Even the server-side messaging push we do with BlazeDS bridged to our ActiveMQ JMS message broker.