How to use SSL Certificate with ActiveMQ without self signed certificate - java

The ActiveMQ SSL documentation states:
ActiveMQ includes key and trust stores that reference a dummy self signed cert
As per configuring SSL on ActiveMQ it is mentioned to provide the file url of broker keystore file.
<bean id="SecureConnector" class="org.eclipse.jetty.server.ssl.SslSelectChannelConnector">
<property name="port" value="8162" />
<property name="keystore" value="file:${activemq.conf}/broker.ks" />
<property name="password" value="password" />
</bean>
I have purchased an SSL certificate. How can i use that with ActiveMQ? The files I have are a .cer file and a .key file.
Should I first convert the .cer files to .jks file format and then configure it in ActiveMQ Jetty?
Is that how it is supposed to be done? Maybe I am missing something completely due to lack of knowledge in this area.
I cannot use the method explained by ActiveMQ because it requires both client and broker handshake and in this case the client is the 3rd party app and we have no control there.

The certificate definitely must be in JKS format as that is the format which Java uses (and ActiveMQ is written in Java). Once the certificate is converted just reference it in the ActiveMQ configuration as described in the documentation. It should be really straight-forward.
If your certificate is signed by a trusted authority then the client will trust it implicitly and won't need to import it into a truststore of some kind. Using a truststore is necessary for "self-signed" certificates (which are used in the ActiveMQ documentation) since they are not signed by a trusted authority.

Related

Wildfly does not pass intermediate certificate to HTTPS client

So I have this certificate chain made of 3 certificates:
Root cert (installed in all clients)
Intermediate cert (installed in my browser, but not in other clients/Java apps accessing webservices)
Domain wildcard certificate
Wildfly is configured to use a keystore that holds intermediate and domain certificates in JKS format, along with the private key for the domain cert. When I send a HTTPS request from my browser, the certificate is validated just fine and everything seems OK. But when the Java client application I am working on tries to establish a connection, it cannot build a valid certificate chain:
javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
I checked the certificates delivered by Wildfly using openssl (openssl s_client -showcerts -connect <servername>) and confirmed that the intermediate certificate is NOT transmitted even though it is present in the keystore. Now I can work around this in my development environment by adding the intermediate cert to my local trust store, however that is not an acceptable long-term solution for production.
In my Wildfly's standalone.xml I have specified the keystore and the alias of the wildcard certificate.
<server-identities>
<ssl>
<keystore path="/path/to/keytsore.jks" keystore-password="supersecure" alias="*.redacted.com"/>
</ssl>
</server-identities>
Searching through the Wildfly admin docs I saw no mention of intermediate certificates. I tried to add an additional element to the config (same path and password, but alias of the intermediate certificate), but Wildfly would not start up with that.
Any idea how I can get Wildfly to present the intermediate certificate to connecting clients? Does it need to have a specific alias name? Or is there another way to tell Wildfly the alias of any intermediate cert?

certificate mechanism between webservice provider and consumer

What are the exact steps done by server and client to place a ssl certificate mechanism in a webservice call? Who(client/server/both) will generate .keystore,.p7b/.cer files? I have googled a lot but couldn't find the answer to it.
In my case, i am the client running a java application which consumes a soap webservice call. I have a .p7b file given by WebService provider. I know where to place the files(.keystore, .cer) and how to use it in the application.
But, my questions are
Do i need to generate keystore file or should i get it from
webservice provider? If i need to generate, how? Do i need private
key/passphrase?
I need a .cer file, so how can i use keytool to convert .p7b to .cer
file?
Thank you for your help in advance.
It looks like you're calling a web service where the HTTP connection is protected by TLS/SSL using X509 certificates. That means the server has set up a keystore with those certificates as well as the corresponding private keys. When you call the web service, the server will retrieve from its keystore the certificate used for the trust establishment (that is, to protect the TLS connection to the web service) and sends it to the client. When the client receives the response from the server it will check the trust of that certificate. Now we have two scenarios:
If the server uses a self-signed certificate (can be used for developments and testing, but not in production), then the client won't recognize it as trusted because it's not stored in the client's truststore. By default, in a Java environment, the truststore is searched (by order) in the following two locations: $JAVA_HOME/lib/security/jssecacerts and $JAVA_HOME/lib/security/cacerts. A custom truststore can also be used by running the client with -Djavax.net.ssl.trustStore and -Djavax.net.ssl.trustStorePassword or by using a custom TrustManager. As such, if the server self-signed certificate is not stored in one of these locations, the secure connection will fail. So the client will have to import the certificate into its truststore. To circumvent the import of self-signed certificates into the client's truststore, you can create a custom X509TrustManager as stated here.
If the server uses a certificate signed by one of the recognized root CA authorities, then it'll be validated automagically because those CA's certificates are already installed in Java's default truststore. As such, the trusted TLS connection will be successful.
In the case where the server does not require client authentication the process is over (this is what happens when you connect to most HTTPS websites via browser).
If the server requires client authentication, then the client will need to provide its own certificate from its keystore to the server, and the server will need to have it installed in its truststore. The web service provider must provide to the client the specification for the certificate profile that the client should use.
Here you can find a good clarification to the keystore vs truststore terminology.
By default in Java environments, keystores and truststores are JKS files.
So you're saying you have a .p7b file provided by the web service provider. Quoting from this page:
PKCS#7/P7B Format
The PKCS#7 or P7B format is usually stored in Base64 ASCII format and has a file extention of .p7b or .p7c. P7B certificates contain "-----BEGIN PKCS7-----" and "-----END PKCS7-----" statements. A P7B file only contains certificates and chain certificates, not the private key. Several platforms support P7B files including Microsoft Windows and Java Tomcat.
So that P7B file contains the server certificate or certificate chain (more on this here).
I believe you're in a no-client-auth scenario. Therefore, you won't need your own keystore. You'll only need to import the server's certificate (P7B file) into the truststore you're using. You can directly import a P7B file without converting it to CER format:
keytool -import -trustcacerts -alias web_service -keystore my_truststore.jks -file web_service.p7b
In the case you still want a CER formatted certificate, you can convert from P7B to CER like this (to answer to your 2nd question):
openssl pkcs7 -print_certs -in certificate.p7b -out certificate.cer
If in fact client authentication is needed, then you'll need to create your keystore with your private key and public certificate and provide it to the connection by either the -Djavax.net.ssl.keyStore and -Djavax.net.ssl.keyStorePassword parameters or through a KeyManager. The same workflow previously explained applies now in the opposite direction.

How to switch SSL Verify off for Neo4j's RestGraphDatabase?

I'm running my NEO4j HA cluster behind SSL.
I'm writing a client in Java that manages some data. Now since I'm only using SSL to encrypt communication, I'm using a self-signed cert. But now I'm facing an
uglycom.sun.jersey.api.client.ClientHandlerException: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException
Any ideas how to tell Neo4J not to verify the cert?
You do not need to generate a self-signed certificate on your own, Neo4j will do that for you when configured to do so.
http://docs.neo4j.org/chunked/stable/security-server.html#_https_support
The Neo4j server includes built in support for SSL encrypted
communication over HTTPS. The first time the server starts, it
automatically generates a self-signed SSL certificate and a private
key. Because the certificate is self signed, it is not safe to rely on
for production use, instead, you should provide your own key and
certificate for the server to use.
In the case that you are using the Neo4j generated self-signed cert and you're still having issues, please update your question with your configuration details in the neo4j-server.properties file for each of your HA instances (if they aren't the same).

How can a Java app accepts a server certificate seamlessly?

Most Web browsers that support SSL have a list of CAs whose certificates they will automatically accept. If a browser encounters a certificate whose authorizing CA is in the list, the browser will automatically accept the certificate, and establish a SSL connection to the site.
There is a Java 1.6 client, running on JBoss 7, which is required to make SSL connection to LDAP server. Since the client is on production, if the LDAP server updates its certificate without notifying me to update the certificate accordingly on JBoss, the client will fail. My question is: how can I securely connect(ssl) to LDAP in a similar way the browser “accepts” the certificate seamlessly?
I don’t know if this is feasible in Java. But, any thoughts and feedbacks are all welcome.
Java has a default truststore that contains all the trusted certificates. This is under %JRE_HOME%\lib\security\cacert and has all the trusted CA certificates (Verisign etc).
So if your client https application tries to connect to a server that deploys a certificate signed by these issuers you would have no issue (same as happens with your browser).
Now to your problem. You don't mention enough information about your LDAP server.
I can think of the following:
The LDAP server deploys a certificate signed by some CA (not one of
the known ones).
The LDAP server deploys a self-signed certificate
For case (1) all you need to do is add the certificate of the signer to your truststore (i.e. the certificate of the issure that signed the certificate of your LDAP server). If the LDAP server changes certificate, you would be unaffected provided that it gets the certificate from the same CA which you would have set now as trusted. This trusted certificate could be added in cacerts but the recommended solution is to use your own separate truststore, import it and set it in JVM to override the default cacerts. Plenty of example in Google.
For case (2) this is a really bad setup and are in trouble as you would need to actually update the truststore manually each time the LDAP server changes certificate.
But in any case I can only assume that the certificate changes due to expiration? I can't think of another reason (except compromise of private key but this is not the problem here from your description)

using spring-ldap with ssl

I need to talk to an LDAP server via spring-ldap with SSL, and the other end has a self-signed certificate no less.
Can any kind soul please point me to some instructions for setting this up?
Check out Spring LDAP documentation for connecting to LDAP server over HTTP(S):
As far as self signed certificate is concerned, you can import certificate chain into a truststore and set the following VM arguments:
-Djavax.net.ssl.trustStore="<path to truststore file>"
-Djavax.net.ssl.trustStorePassword="<passphrase for truststore>"
or override the truststore at runtime like:
System.setProperty("javax.net.ssl.trustStore","<path to truststore file>");
System.setProperty("javax.net.ssl.trustStorePassword","<passphrase for truststore>");
Keep in mind that both options will override default JVM truststore. So if you are hitting different sites with different certs, you may want to import all of them into one truststore.
In case you need help creating truststore file, refer to this: Digital Certificate: How to import .cer file in to .truststore file using?
Note: If the other end is a trusted source then you might also skip the certification check, as I had to do because any few months the certificate was changed and I was constrained to import into my local truststore and the other environments' truststores, test, production, the new certificate, every single time.

Categories