SSL with no trusted certificate

Hi, guys, just a question about SSL connection between java client and couchbase server.

According to the official encryption instruction (http://developer.couchbase.com/documentation/server/4.0/sdks/java-2.2/managing-connections.html), I set up my code but I get an unwanted result.

An exception has been thrown out say “No trusted certificate found”

Here is my connection set up. Can anyone pitch some ideas?

	CouchbaseEnvironment environment = DefaultCouchbaseEnvironment
			.builder()
			.sslEnabled(true)
			.sslKeystoreFile("C:\\Program Files\\Java\\jdk1.7.0_75\\jre\\lib\\security\\cacerts")
			.sslKeystorePassword("changeit")
			.build();

The server side is 4.0 enterprise edition, and client side is JAVA SDK 2.1

hi @Hanwen,

the use of SSL and certificates depends on the correct configuration of the JVM. By default, Java will refuse to use certificates that are not signed by a CA (Certificate Authority) not listed in the JVM’s list of trusted CAs, but the Couchbase Server-generated certificate is self-signed…

Have you made sure you followed all the steps in the documentation correctly?

  • Your configuration should point to the keyStore, here it seems it points to the trustStore
  • You should make sure to add the server’s certificate using keytool and answering yes when it asks if the certificate should be trusted.
  • Probably best practice to change the truststore and keystore passwords in production :wink:

Actually, after reading through the keytool help page from Oracle I can see where your confusion can come from… By default, keytool will create or update “.keystore” in the user’s home directory:

-keystore keystore
The keystore location.
If the JKS storetype is used and a keystore file does not yet exist, then certain keytool commands may result in a new keystore file being created. For example, if keytool -genkeypair is invoked and the -keystore option is not specified, the default keystore file named .keystore in the user’s home directory will be created if it does not already exist. Similarly, if the -keystore ks_file option is specified but ks_file does not exist, then it will be created

So following the documentation you should check that:

  • you have a .keystore file in the app’s home folder
  • you see the Couchbase Server’s certificate when invoking keytool -list (probably the only certificate there?)
  • the certificate’s entry is of type trustedCertEntry

Then point the SDK config to the keystore and voilà :thumbsup:

In production you may want to consider putting the keystore in a more secure location though. I think you can just move it then make sure permission are securely set, but if cb’s certificate is the only one in there (see keytool -list) you can safely redo the import step with the -keystore pathToKeystoreFile and delete the old keystore.

Hi Simon,

Thanks very much. With some modification, I guess the secured connection is established. However, the performace is still not perfect.

Reading data into Couchbase is okay, but querying is always experiencing Timeout issue. I guess this is due to the security verfication on either or both client and server side.

Can you please suggest some best practices. Here is my code, where I have setup the connection time as MAX as I thought it would be.

	CouchbaseEnvironment environment = DefaultCouchbaseEnvironment
			.builder()
			.sslEnabled(true)
			.sslKeystoreFile("path of keystore file")
			.sslKeystorePassword("password")
			.connectTimeout(2000000)
			.managementTimeout(2000000)
			.kvTimeout(2000000)
			.queryTimeout(200000)
			.bootstrapCarrierEnabled(false)
			.build();

And the exception I encountered were

Oct 27, 2015 10:50:31 AM com.couchbase.client.core.endpoint.AbstractEndpoint$2 operationComplete
WARNING: [null][QueryEndpoint]: Could not connect to endpoint, retrying with delay 32 MILLISECONDS:
java.net.ConnectException: Connection timed out: no further information: some.web.site/xxx.xxx.xx.xx:18093

One thing I found is that, there is a port numbered as 18092 which is instructed after the installation and official website. But the JAVA API told me the 18093. Can some one clearfy this? Many thanks.

Many thanks.

Ok so first, notice there are now (as of Couchbase Server v4.0) 3 main services in Couchbase:

  • main communication with the cluster, to an extent key/value data service, on port 8091
  • views (map/reduce) on port 8092
  • N1QL (query service) on port 8093

When you use SSL, the ports change accordingly. By default they follow a similar progression so 18091, 18092 and 18903.

Since you didn’t explicitly force query service in your env yet the SDK tries to connect to it, that means that query service presence was advertised by the cluster itself, so I’m guessing you are indeed running CB 4.0?
Did you have to open port 18092 in a firewall or something similar? If so, you’ll need to follow the same steps for port 18093, on each node of the cluster.

Hi,

With 4.5 Developer Preview now available, we have introduced X.509 certificate support.

Looking forward to your feedback on this new improvement. For more information check - http://developer.couchbase.com/documentation/server/4.5-dp/security-x509.html

Thank you,
Don Pinto
Product Manager, Couchbase

Hi… I am trying to use the DefaultCouchbaseEnvironment and pass the .pem file as part of the:

.sslKeystoreFile(“path of keystore file”)
.sslKeystorePassword("password”)

I see this exception:

Caused by: java.io.IOException: Invalid keystore format
at sun.security.provider.JavaKeyStore.engineLoad(JavaKeyStore.java:663) ~[na:1.8.0_212]
at sun.security.provider.JavaKeyStore$JKS.engineLoad(JavaKeyStore.java:56) ~[na:1.8.0_212]
at sun.security.provider.KeyStoreDelegator.engineLoad(KeyStoreDelegator.java:224) ~[na:1.8.0_212]
at sun.security.provider.JavaKeyStore$DualFormatJKS.engineLoad(JavaKeyStore.java:70) ~[na:1.8.0_212]
at java.security.KeyStore.load(KeyStore.java:1445) ~[na:1.8.0_212]
at com.couchbase.client.core.endpoint.SSLEngineFactory.get(SSLEngineFactory.java:99) ~[core-io-1.7.11.jar!/:na]

Hi @siddique . It looks like you’re using Couchbase Java SDK 2.7.11, so you’ll need to convert the PEM file into a Java keystore file before you can use it. Here’s how to import the CA certificate into a new keystore file:

keytool -importcert -keystore truststore.jks -file certificate.pem

Couchbase Java SDK 2 has reached end of life, and is no longer maintained. Please upgrade to SDK 3 at the first opportunity.

In SDK 3, you don’t need to put the certificate in a Java keystore file; you can reference it directly, like this:

Cluster cluster = Cluster.connect(
  connectionString,
  ClusterOptions.clusterOptions(username, password)
    .environment(env -> env
      .securityConfig(security -> security
        .trustCertificate(Paths.get("path/to/certificate.pem"))
      )
    )
);

Thank you David for the reply. If I have to use the following code:

.sslKeystoreFile(“path of keystore file”)
.sslKeystorePassword("password”)

what will be the path to be mentioned?

Can you share a document to migrate from SDK 2.x to 3.x? Note ours is a springboot micro service.

Hi @siddique,

The path is the full filesystem path to the truststore.jks file you created using the keytool command.

Thanks,
David

Hi @david.nault ,

What dependency package should I be using for the following class:

class CouchbasePagingAndSortingRepository

I have included this in the pom.xml

<dependency >

<groupId>org.springframework.data</groupId>

<artifactId>spring-data-couchbase</artifactId>

<version>4.0.0.RELEASE</version>

</dependency >

When I perform a Maven build, I see this error:

cannot find symbol
[ERROR] symbol: class CouchbasePagingAndSortingRepository

Thanks,
Siddique

Hi @siddique,

That’s completely unrelated to SSL. Please could you start a new topic?

Thanks,
David