The scenario is around calling an external SSL SOAP web service from within Mirth. The web service is requires an SSL/TLS connection along with a client certificate.
The intention is to use the built-in SOAP Sender Destination to call the remote secure web service, and somehow include that client certificate.
I understand that you first need to install that client certificate into the Java runtime. This may be within the Java runtime's certificate store or the Jetty certstore.
The platform:
Windows 2003 SP2
Mirth 1.8
Java jre1.5.0_09
Question: what configuration steps (Mirth, JRE certificate stores, etc.) would you suggest to successfully have a Mirth SOAP Sender include a client certificate (*.cer) when calling a web service secured by SSL?
The Java runtime, or more specifically, the Sun JSSE provider, will present a client certificate if some system properties are set. You can read details in the JSSE Reference Guide, but the important properties are javax.net.ssl.keyStore and javax.net.ssl.keyStorePassword.
There are a few drawbacks to this approach. First, setting the key store password as a system property makes it accessible to any code running in that process—although this can be controlled if a SecurityManager is installed. Second, these settings will be used for any SSL sockets created through the "default" SSLContext. If you need different credentials for different endpoints, you'll need a Mirth-specific solution.
No starting point was specified in the question, but if starting from scratch, the easiest approach is to create a new Java Key Store ("JKS" format) and generate a new key pair and a CSR. After sending the CSR to the CA and getting a certificate back, import it into the same key store. That key store is ready to use.
If a certificate is already available, it is likely to be in a stored with its corresponding private key in PKCS #12 format (.p12 or .pfx file). These can be used directly by a Java application, but the javax.net.ssl.keyStoreType property will need to be set to "PKCS12"
Mirth 1.8 cannot send a client cert when calling a SOAP web service.
I'm late a bit here for this but actually there is a possibility that it could. By sending a few config parameters to the JVM you could get the underlying SOAP engine to switch to HTTPs and provide the proper certificate.
refer to this question for details on which parameters to set for configuring the VM
Java HTTPS client certificate authentication
you will notice there are quite a few things to take care of. Normally HTTPs and client authentication should "just work" once you configured your certificates appropriately. BUT there are some servers out there that are not so friendly to B2B style clients so you have to watch out.
Using JDK 6_21 and a few tweaks with the certificate I was able to get one of them servers to behave but it was long and painful on our side for something that takes about 15 minutes to configure properly on the server.
here is another question that address this very issue (client side authentication towards unfriendly servers).
Client SSL authentication causing 403.7 error from IIS
Related
this question might sound I bit dummy but I have researched many questions/answers here and can't find the answer for my case.
Currently I am using RestTemplate library to make HTTP requests for my java library that I am currently working on. In order to have successful HTTP call to HTTPS URLs i needed to add a SSL configuration for my HTTP client. Something like this:
clientBuilder
.disableCookieManagement()
.setDefaultRequestConfig(requestConfig)
.setSSLSocketFactory(new SSLConnectionSocketFactory(SSLContexts.custom()
.loadTrustMaterial(null, new TrustSelfSignedStrategy())
.build()));
So this library is supposed to be shipped to the user as a jar executable application and I know that using self-signed SSL certificates is not a good idea for general usage since there might have web servers that do not acknowledge it. I read that If I get a signed SSL certificate then I should save the proper keys on Keystore and also use Trustore to acknowledge the server's certificate. I do not think I can just pass Keystore and Trustore to the client who executes my java library, so my question here is, does Java has a built-in SSL certificate, so I could somehow just do some configuration on HTTP client and the built-in certificates would be used. As far as I know, node.js offers something like that.
Could anyone just give me a explanation of how this works for java spring-boot?
There are two separate certificate verifications that could be happening. To connect to a server using https, you need to receive the server's certificate and validate it using a truststore.
In addition, it is possible for you to have a client certificate, and to pass that to the server so it can authenticate your client. Unless you have been told you need to do that, you don't. Unless the server has been specifically configured to do it, it isn't possible. If it is what you need to do, you need to obtain a client certificate, install it into a keystore and use that keystore in your client.
So for normal https, you do not need a keystore.
Whether you need "TrustSelfSignedStrategy" depends on the server.
If the server has a valid signed SSL certificate, you do not need to do anything special, RestTemplate will just work.
If the server has a self-signed certificate, you need to either configure the client to accept any self-signed certificate, or load the server's certificate into a truststore so the client knows to accept that specific certificate.
When I run NiFI 1.8 on my local machine (http://localhost:8080/nifi) I am able to interact with the application through the API using Java. I can start and stop processors, and I get a 200 response code everytime.
When I use the same code to interact with a remote NiFI instance (which uses authentication) I get a SocketException, with the message "Unexpected end of file from server"
I tried setting credentials of the HttpURLConnection but it made no difference. Is this an issue with a certificate? If it is I'm not sure how to obtain and set the correct one.
Any clues?
There are multiple ways to authenticate against NiFi. All secure instances can accept client certificates by default, so if you have a user entity configured for some identity nifi_client, you can issue a certificate with that CN and use it when invoking the API from your Java client. Generally this involves putting the key and certificate in a Java Keystore (*.jks) and having a truststore that contains the public certificate of the NiFi server. There are specific instructions for handling certificate authentication in the NiFi Admin Guide, and you can look at the NiFi CLI as an example of an authenticated client.
I want to use certificates from Let's Encrypt with a large count of Jetty servers. One of the problems is that the certificates from Let's Encrypt has a lifetime of 90 days.
To handle this the Jetty server or some extra code must renew the certificate frequently.
Can Jetty handle this self? If yes how can I enable this?
If I need to implement it self with a Java client then how can I replace the certificate dynamically via Jetty API without a restart of the Jetty server?
Edit: Some related and partial helpful links:
setting ssl keystore at runtime in Jetty
Changing Jetty SSL server certificate on-the-fly
Since version 9.3.15 you can use:
SslContextFactory.reload(Consumer<SslContextFactory>)
For details see at: https://github.com/eclipse/jetty.project/issues/918
The Blog site (Client-Auth REQUESTED in GlassFish) reads:
In domain.xml, please add the following property to http-listener element
<property name="com.sun.grizzly.ssl.auth" value="want"/>
However, when adding this to my GlassFish v3 domain.xml, the existing browser client certificate is not requested. The GlassFish server is properly set up, i.e., requires client certificates with the option "client-auth-enabled" set to true.
The GlassFish bugtracker (1) mentions a different version:
* client-auth: want/need/<blank>
However, this property doesn't get accepted either.
Others have the same problem (2).
How can I enable an optional client certificate request in GlassFish? Are there alternatives?
(1) http://java.net/jira/browse/GLASSFISH-6935
(2) https://stackoverflow.com/questions/3634129/configure-glassfish-v3-client-auth-requested-to-want
Probably because it doesn't exist.
*When you deal with client certificates in HTTPS, keep in mind your HTTPS listener configurations. The SSLv3/TLS protocol allows three modes for an HTTPS socket.
* The traditional mode requires a single server certificate. An HTTPS client (typically a web browser) validates the server identity by matching the certificate to a list, or truststore, of Certificate Authorities. You probably use this mode every day during typical log-in activity.
* Another mode requires both client and server certificates. The client certificate is validated by the server side, and the server certificate is validated by the client side.
* The third mode requires a server certificate, but the client certificate is optional.
*In the real world, you want to use the same HTTPS URL whether a user is authenticated by password or certificate. This approach requires a server that supports the third, optional client certificate mode. At this writing, the GlassFish application server does not support this mode. Fortunately, the Apache Tomcat web server, supported by OpenSSO, is available as an alternative. For Reference
We have to create a web service client using Apache CXF in Java. The thing is I cannot seem to get the SSL session to properly engage. Either it fails altogether, the server fails to decipher what is sent to it once the application data is transmitted or I fail to read the responses from the server.
However when trying the same transaction using a simple soap test client built in .NET everything runs smoothly.
Server is using double authentication.
Everything is certificate based (x509) stored in the windows certificate store (windows-MY and windows-ROOT)
edit
yes, double authentication is indeed client AND server authentication.
Thus far using the bountyCastle provider instead of SunMSCAPI seems to get further but still cannot get the client authentication to work.
PLatform of client CXF 2.2.9, Sun JDK 1.6_21
server IIS 6 ASP.NET unfortunately is all I could gather, I have no control over the server and must use it as-is.
update
I am using a JKS keystore now but still am getting the problem. It seems the client is not sending his certificate to the server as part of the authentication process. As a result I get a 403.7 error from the server.
Funny thing is that I receive this error message as an HTML page that must first be decrypted before it is readable !
Presumably, by double authentication, you mean you're using client-certificate authentication in addition to server-certificate authentication (which is more common).
It would be useful to know which versions of the platforms are used on either side, and which patches have been applied.
It's possible that some of the problem come from the re-negotiation fix to CVE-2009-3555 (or lack of fix).
The problem is a flaw in the initial design of the re-negotiation in TLS, which is what was used to re-negotiate a client-certificate. There are two ways of getting a client-certificate: either the server asks for it during the initial TLS handshake, or it asks for it during a subsequent handshake (for example, once it has figured out what the request was aimed for and/or when trying to access a certain restricted area). The second method is the re-negotiation. Unfortunately, there was a security flaw in the design of the TLS protocol in that respect, which has since been fixed thanks to a TLS extension described in RFC 5746.
When the flaw was initially disclosed (around November 2009), some platforms and libraries such as Sun Java or OpenSSL rolled out a quick fix which simply disallowed any re-negotiation (so only initial negotiation of the client-certificate would work). Later on, once RFC 5746 was written, these libraries started to roll out implementations supporting this extension.
As far as I'm aware, Microsoft's default in IIS and its web framework was to use re-negotiation and not initial negotiation. In addition, it didn't roll out the initial fix to disable re-negotiation (effectively keeping the known vulnerability). It only rolled out a patch (still tolerant to old implementations by default) quite recently: Microsoft Security Bulletin MS10-049 - Critical.
There is also an explanation of the problem on this Microsoft security blog:
http://blogs.technet.com/b/srd/archive/2010/08/10/ms10-049-an-inside-look-at-cve-2009-3555-the-tls-renegotiation-vulnerability.aspx
Essentially, if you're trying to talk to a server that only supports the old negotiation style from a stack that only has the new re-negotiation style or no renegotiation at all, it's not going to work.
If your server is running using IIS or similar environment, you might be able to turn on initial client-certificate negotiation using netsh and its clientcertnegotiation=enable option.
Java doesn't rely on the OS certificate store and needs to use its own.
This will import your self-signed certificates.
cd JAVA_HOME/jre/lib/security
keytool -import -file server_cert.cer -keystore cacerts
I post this as an answer though I realize now the question was not formulated properly as I got thrown in a loop because the .NET example I had was actually performing a hack to get around the problem.
The proper question should have been
How to get Java to perform Client side Authentication on a server that does not ask for Ask for certificates ?
the answer is actually under our very noses, however to get to the answer one needs the correct question !!
Great thanks to Bruno who provided some very helpful information.
the solution can pretty much be summed up in these two questions :
Java HTTPS client certificate authentication
Client SSL authentication causing 403.7 error from IIS
Although the client is "not supposed" to send a certificate if not asked I found that by tweaking the client certificate in the keystore to contain the following :
Client certificate with all extensions
Client Private key
A concatenation of the client's complete certification chain.
push all this in the same certificate store and use it as keystore. Then load again the certification chain as a trust store. From there it should just work. This being said there is still a possibility for failure. the safest way to solve this particular issue is to have the server actively ask for a authentication certificate from the client by providing a list of accepted CA.
Hope this helps anyone else that can be stuck in the same problem, sure tooke me for a spin for a while before I reach the root of evil.