I want the last of these lines in a standalone application to pass with no exceptions thrown:
Properties props = new Properties();
props.setProperty("java.naming.factory.initial",
"weblogic.jndi.WLInitialContextFactory");
props.setProperty("java.naming.provider.url",
"t3s://localhost:9002");
props.setProperty("java.naming.security.principal",
"<username>");
props.setProperty("java.naming.security.credentials",
"<password>");
Context ctx = new InitialContext(props);
...but I get this information in an exception:
Warning Security BEA-090542 Certificate chain received from localhost - 127.0.0.1 was not trusted causing SSL handshake failure. Check the certificate chain to determine if it should be trusted or not. If it should be trusted, then update the client trusted CA configuration to trust the CA certificate that signed the peer certificate chain. If you are connecting to a WLS server that is using demo certificates (the default WLS server behavior), and you want this client to trust demo certificates, then specify -Dweblogic.security.TrustKeyStore=DemoTrust on the command line for this client.
So, I created a keystore for the ca using this command:
keytool -keystore client.jks -importcert -file cacert.pem
...and referred to it using the property weblogic.security.TrustKeyStore=client.jks
This still doesn't work, most likely because I haven't supplied a password to the keystore. What have I missed? How can I supply this password? (or, how do I create the keystore without setting a password for it?)
Almost two months later, I returned to this issue. After finding this link, I found out that this works:
System.setProperty("weblogic.security.SSL.ignoreHostnameVerification","true");
System.setProperty("java.protocol.handler.pkgs", "weblogic.net");
System.setProperty("weblogic.security.TrustKeyStore","CustomTrust");
System.setProperty("weblogic.security.CustomTrustKeyStoreFileName", "<keystorelocation>");
System.setProperty("weblogic.security.CustomTrustKeyStorePassPhrase","<keystorepassword>");
System.setProperty("weblogic.security.CustomTrustKeyStoreType","JKS");
I only got it working using system properties.
Related
I have an instance of Apache ActiveMQ 5.16.3 with Java 8 in a Debian Docker container (Kubernetes).
It's configured to use mutual SSL in /opt/activemq/conf/activemq.xml:
<sslContext>
<sslContext
keyStore="/etc/data/my-bridge-broker.ks"
keyStorePassword="my-pass"
trustStore="/etc/data/broker_to_client.ts"
trustStorePassword="my-pass"
/>
</sslContext>
<!--- ... --->
<transportConnectors>
<transportConnector name="ssl" uri="ssl://0.0.0.0:61714?transport.enabledProtocols=TLSv1.2&transport.needClientAuth=true"/>
</transportConnectors>
The mutual SSL works properly, and I am able to connect from a sample Java client, using ActiveMQSslConnectionFactory providing the appropriate certificates in the truststore and keystore and passwords.
Next, while the broker was running I removed the client's certificate by its alias from the server's trust store:
cd /etc/data
keytool -delete -alias <client-cert-name> -keystore broker_to_client.ts -storepass my-pass
Surprisingly, the client is still able to connect. I restarted the server and the client can still connect and post messages on the queues. Any idea why? I thought the truststore defines which client certificates will be allowed?
Looking at the documentation they recommend using Certificate Revocation List (CRL) or Online Certificate Status Protocol (OCSP). They don't mention the option to remove from the truststore. Does this mean ActiveMQ doesn't use the truststore file?
If the client's certificate is issued from a trusted authority then it doesn't matter if the it's in the broker's truststore. The client's certificate will still be trusted because it's from a trusted authority. The broker's truststore is only there to include certificates that come from an untrusted authority or are self-signed.
A vendor have given me a .jks to connect to their mq via jms. I am using the following code as a template for my proof of concept.
Connecting to a Websphere MQ in Java with SSL/Keystore
The creation of the Keystore is fine, however when it attempts to create a Truststore it loads a new .jks file. Am i supposed to generate this file or should it have been provided as currently I am unable to create it.
// instantiate a KeyStore with type JKS
KeyStore ks = KeyStore.getInstance("JKS");
// load the contents of the KeyStore
ks.load(new FileInputStream("/home/hudo/hugo.jks"), KSPW);
System.out.println("Number of keys on JKS: "
+ Integer.toString(ks.size()));
// Create a keystore object for the truststore
KeyStore trustStore = KeyStore.getInstance("JKS");
// Open our file and read the truststore (no password)
trustStore.load(new FileInputStream("/home/xwgztu2/xwgztu2.jks"), null);
Thanks
There are a lot of assumptions in this answer (as the question does't provide much of information), but I as well assume it comes with the amount of experience.
To create an SSL connection, the server must have a keypair (private, public key and a certificate bount to the public key) and client must trust the certificate (or its issuer). There is as well an option for mutual SSL (aka client auth ssl), where the client needs its own keypair and certificate and the server needs to trust the client's certificate.
Truststore it loads a new .jks file. Am i supposed to generate this file or should it have been provided as currently I am unable to create it.
The truststore should effectively contain the issuer certificate of the server's certificate (if a self-signed certificate is used, it is the same one).
You can get the certificate by connecting to the service
openssl s_client -connect host:port -showcerts
and then import the returned certificate into a new keystore (using e.g. keytool -importcert command)
keytool -importcert -keystore mytruststore.jks -alias mqserver -file servercert.pem
If the server returns you multiple certificates (certificate chain), you may import them all.
If you are not able to do so, just ask the service provider (someone who deploys the MQ) to provide you the certificate or the truststore.
I need to integrate an application with external web service which forces to use https. Authors of this web service provided me with .crt file which I should use for making https requests. After some investigation I've found the following code which uses KeyStore class for secured https access:
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
FileInputStream instream = new FileInputStream(new File(file));
try {
trustStore.load(instream, password.toCharArray());
} finally {
instream.close();
}
SSLContext sslcontext =
SSLContexts.custom().loadTrustMaterial(trustStore, new TrustSelfSignedStrategy()).build();
SSLConnectionSocketFactory sslsf =
new SSLConnectionSocketFactory(sslcontext, new String[]{"TLSv1.2"}, null,
BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
HttpClients.custom().setSSLSocketFactory(sslsf).build();
In this code KeyStore requires input stream along with password trustStore.load(instream, password.toCharArray());. However, as I understand, we don't need password when using .crt file. So this way of loading certificate is not suitable for me. At the same time, from what I've discovered so far, the code I provided here is the only way to configure HttpClient for using SSL certificate. Is there any workaround to configure HttpClient for using .crt certificate?
Thanks,
Andrey
I assume the Web service is providing you with a self-signed certificate (i.e. not signed by a well-known CA). If it is already signed by a well-known CA that is in Java's cacerts file, then you don't need to do anything.
Otherwise, you have a couple of options:
Import the certificate into global cacerts keystore
Launch your application with application-specific keystore
In either case, you first need to convert crt file into jks keystore that Java uses. You can do this by:
$ keytool -import -keystore mykeystore.jks -storepass horsestaple
Note that keytool requires the password (horsestaple above) to be supplied for creating a jks store. You can put anything there; as you mention, public website certificates do not need password protection, they are public after all.
If you are doing option 1, make a backup of your cacerts and supply the cacerts file instead of mykeystore.jks. See the link below for the location of cacerts. For this option, you are all set, your application should be connecting to the Web service via HTTPS without any additional configuration, since Java loads cacerts by default.
If you are doing option 2, which is probably preferred at least for testing phase, you need to run your application with this parameter:
-Djavax.net.ssl.trustStore=mykeystore.jks
This is a JVM parameter, so supply it appropriately. This depends on how you are running you application.
Note that you will only have the imported certificate in this case, so your other HTTPS connections will not work. You can avoid this by first copying the standard cacerts to a temporary location, importing the key into it and using that in the command above. That will give you all the standard certificates, plus the one you need.
A slight downside of option 2 is that if new certificates are added or revoked, your application-specific keystore will not be updated. If this is a concern, you can merge keystores on the fly, for example:
Registering multiple keystores in JVM
In either case, you should now be able to just do a standard URL fetch, such as in example given here:
https://blogs.oracle.com/java-platform-group/entry/diagnosing_tls_ssl_and_https
i.e.:
final URL url = new URL("https://example.com");
try(final InputStream in = url.openStream()){
//…
}
More information here:
Keytool and general certificates info
https://docs.oracle.com/cd/E19830-01/819-4712/ablqw/index.html
Cacerts location
http://docs.oracle.com/javase/7/docs/technotes/tools/solaris/keytool.html
More options for importing self-signed certificates
How to properly import a selfsigned certificate into Java keystore that is available to all Java applications by default?
Unless they provided you with their .crt file which should be used for validating connections to them, which would indicate they are using a self-signed certificate, they haven't provided you with anything useful. If you need a certificate as a client, the first thing you need is a public/private key pair, from which you generate a CSR, which you get signed. Nobody else can securely provide any of that except the signed certificate.
If they've provided their own (self-signed?) certificate, you need to load it into a truststore, not a keystore, via the keytool with the -trustcacerts option, and then tell Java to use that truststore, either via the javax.net.ssl.trustStore system property or by constructing your own TrustManager and feeding it to a custom SSLContext, as described in the JSSE Reference Guide.
My Java application needs to authenticate to Google cloud Mysql instance with SSL client authentication. Its client-key and certificate are provided by Google. I also need to setup JMX agent with SSL on same application whose certificates are provided by a private CA.
How to prevent Mysql from presenting JMX certificate and vice-versa in case I add both private certificates into single keystore provided to JVM at startup
Is there any other way to authenticate SSL certificates with Mysql beside putting then in 'javax.net.ssl.keyStore'? If not, are there any aliases that Mysql or JMX agent prefer over other names?
You can look at using the Cloud SQL MySQL socket factory which uses temporary SSL certificates to authenticate to Cloud SQL (only supported for Second Generation instances):
https://github.com/GoogleCloudPlatform/cloud-sql-mysql-socket-factory
MySQL Connecting Securely Using SSL
For SSL support to work, you must have the following:
A JDK that includes JSSE (Java Secure Sockets Extension), like JDK-1.4.1 or newer. SSL does not currently work with a JDK that you can add JSSE to, like JDK-1.2.x or JDK-1.3.x due to the following JSSE bug: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4273544
A MySQL server that supports SSL and has been compiled and configured to do so, which is MySQL 4.0.4 or later. For more information, see Building MySQL with Support for Secure Connections.
A client certificate (covered in this section)
How to work with multiple keystore?
The test certificates reside in keystores named node1.keystore … node100.keystore, which were created following the steps described in Creating Self-Signed Test Certificates.
Export the test certificate for node1.example.com:
$ keytool -exportcert -keystore node1.keystore -alias node1 \
-storepass changeme -file node1.cer
Import the test certificate into the custom truststore:
keytool -importcert -keystore custom.truststore -alias node1 \
-storepass trustchangeme -file node1.cer -noprompt
Here we specify the -noprompt option to suppress the prompt asking
you to confirm that the certificate is trustworthy. Since you
created the certificate yourself, this confirmation is unnecessary.
Repeat Steps 1 and 2 for node2.keystore … node100.keystore.
Resource Link:
Creating Java Keystores and Truststores
Keystore and truststore details:
A keystore is used in one of two distinct ways:
The keystore contains private keys and certificates used by TLS/SSL servers to authenticate themselves to TLS/SSL clients. By convention, such files are referred to as keystores.
When used as a truststore, the file contains certificates of trusted TLS/SSL servers, or of Certificate Authorities trusted to identify servers. There are no private keys in the truststore.
Because keystores contain private keys, while truststores do not, the security requirements for keystores are more stringent. In particular:
Hadoop TLS/SSL requires that truststores and the truststore password be stored, in plaintext, in a configuration file that is readable by all.
Keystore and key passwords are stored, in plaintext, in a file that is readable only by members of the appropriate group.
These considerations should inform your choice of which keys and certificates to store in the keystores and truststores you will deploy across your cluster.
Keystores should contain a minimal set of keys and certificates. A reasonable strategy would be to create a unique keystore for each host, which would contain only the keys and certificates needed by the Hadoop TLS/SSL services running on the host. In most cases, the keystore would contain a single key/certificate entry.
Modifying Keystores: CDH services and processes must be restarted in case changes are made to a keystore. However, this is relatively rare since keystores do not need to be updated when hosts are added or deleted from a cluster.
Because truststores do not contain sensitive information, it is reasonable to create a single truststore for an entire cluster. On a production cluster, such a truststore would often contain a single CA certificate (or certificate chain), since you would typically choose to have all certificates issued by a single CA.
Important: Do not use the same password for truststores and keystores/keys.
Since truststore passwords are stored in the clear in files readable by all, doing so would compromise the security of the private keys in the keystore.
I am building a JAVA web service client in which i connect to a service.
This service has a ssl certificate verification.
How to call this service using ssl certificate verification.
I am using JAX-RPC implementation in client built using Eclipse.
An example would be appriciated.
I am able to do the web service connection...
I added the key store using the command:
keytool -import -trustcacerts -file <file path/filename.cer> -alias <aliasName> -keystore <JAVA_HOME/jre/lib/security/cacerts>
gave the password as "changeit" and added the certificate in keystore.
Now in code i added two lines:
System.setProperty("javax.net.ssl.trustStore", "<JAVA_HOME>/jre/lib/security/cacerts");
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
also added
_call.setUsername("username");
_call.setPassword("password");
where _call is the call object of Call Class.
And it worked!!!!!!
All you need to do is injecting the server root certificate to your JDK/JRE environments by using the following command line: -
keytool -importcerts -trustcacerts -file <path_to_root_cer_file> -alias <the_server_alias> -keystore <your_keystore>
The default [your_keystore] is
1. <JDK_HOME>/jre/lib/security/cacerts
2. <JRE_HOME>/lib/security/cacerts
The default password is changeit.
When you call the web service, just mention the
"https://<host>:<SSL_port>/Path/To/Services"
I hope this may help to achieve your requirement.
Regards,
Charlee Ch.
You mean your web service is protected with a "client certificate"? If yes, get the certificate in either a .p12 (PFX) or keystore format from the service provider and use the following System properties to set it before your call:
javax.net.ssl.keyStore - Path to the keystore on your server
javax.net.ssl.keyStorePassword - passphrase for that keystore
javax.net.ssl.keyStoreType - Set it to "pkcs12" is the client certificate provided to you is .p12
If you application is client to only one web service provider, set these properties as VM arguments, if not, you may need to create specific SSLConnectionFactory for each secured endpoint. Refer to my response on this post for details on creating custom SSL Socket Factories.