SSL Connection with java client 3.5.0

We are using Couchbase Enterprise Edition 7.1.4 and Java client 3.5.0.
Currently there is default unencrypted connection and now we are going to secure the connection using TLS. For that I am following below link:
Secure Connection

As mentioned in the link, I have performed below steps but those are not working:

  1. Get the CA certificate from the cluster and save it in a text file.
    (Copied CA certificate from admin UI Security-> Certificates)

  2. Enable encryption on the client side and point it to the file containing the certificate.

My Code :

public CouchbaseEncryption() {
    initCluster();
    PasswordAuthenticator passwordAuthenticator = PasswordAuthenticator.builder().username("test").password("test").build();
    couchbaseCluster = Cluster.connect("10.7.xxx.xxx", ClusterOptions.clusterOptions(passwordAuthenticator).environment(couchbaseEnvironment));
}

private static synchronized void initCluster() {
    if(couchbaseEnvironment == null) {           
        try {
        couchbaseEnvironment = ClusterEnvironment.builder()
                .securityConfig(SecurityConfig
                        .enableTls(true)
                        .trustCertificate(Paths.get("/path/to/cluster.cert"))
                .build();
        } catch (URISyntaxException e) {
           throw new RuntimeException(e);
        }
    }
}

As I am new to SSL not sure If I am missing anything. So my question is, for testing purpose can we use default CA certificate (enterprise edition) for java client connection?

“use couchbases:// in your connection string”

Also - when you reach out for help with an error, it helps to show the error.

Hi @atul! Welcome, and thanks for joining the Couchbase Forum.

Some general code review notes:

Unless you are creating many Cluster objects, I’d recommend letting the cluster manage the ClusterEnvironment instead of building your own. That way you don’t need to remember to shut down the environment after it’s no longer needed.

Here’s what it would look like to let the Cluster manage its own environment:

public CouchbaseEncryption() {
  String connectionString = "10.7.xxx.xxx";
  String username = "test";
  String password = "test";

  couchbaseCluster = Cluster.connect(
    connectionString,
    ClusterOptions.clusterOptions(username, password)
      // Instead of passing a pre-built ClusterEnvironment,
      // pass a callback that configures a ClusterEnvironment.Builder.
      .environment(env -> env
        .securityConfig(security -> security
          .enableTls(true)
          .trustCertificate(Paths.get("/path/to/cluster.cert"))
        )
      )
  );
}

You could simplify this further by using the connection string to customize the environment. Here’s an example that enables TLS by using the couchbases:// scheme, and configures the trusted CA certificate using the “certpath” parameter:

public CouchbaseEncryption() {
  String username = "test";
  String password = "test";
  couchbaseCluster = Cluster.connect(
    "couchbases://10.7.xxx.xxx?certpath=/path/to/cluster.cert",
    username,
    password
  );
}

With that out of the way, let’s think about the problem you’re facing. The Couchbase SDK verifies that the certificate presented by the server is associated with the address used to connect to the server. It’s possible the certificate requires you to use a hostname (like couchbase.example.com) instead of an IP address (like 10.7.xxx.xxx). If you look at the server list in the Couchbase Admin UI, how does that page display the addresses? Does changing the connection string to use those addresses help?

If that doesn’t solve the problem, please share the error you’re seeing so we can try to help diagnose it.

Thanks,
David

In a self-hosted deployment, each cluster generates a unique root certificate, so there isn’t really a concept of a “default certificate.” If you want, you can configure the server to use a specific certificate. See Configure Server Certificates | Couchbase Docs

Alternatively, in your dev environment you could configure the client to skip certificate verification. This is not secure, but can be a useful tool for diagnosing whether a connection failure is due to certificate issues. To try it, include the tls_verify=none parameter in your connection string. Just be extra careful not to use this feature in a production environment.

Thanks,
David

Thanks @david.nault @mreiche for prompt response, here is my CB connection code as per suggestion,

String username = “test”;
String password = “test”;
couchbaseCluster = Cluster.connect(
“couchbases://10.7.xxx.xxx?certpath=/path/to/cluster.cert”,
username,
password
);

But it is throwing exception:
“sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested”

I tried to resolve it by following ways:

  1. Added certificate to default Java Truststore - cacerts :
  • keytool -import -alias myCert -file C://certificate.cert -keystore $JAVA_HOME/lib/security/cacerts
  1. Created a Trust Store and passed it as JVM argument:
  • keytool -import -alias myCert -file C://certificate.cert -keystore myTrustStore
  • -Djavax.net.ssl.trustStore=C://myTrustStore
    -Djavax.net.ssl.trustStorePassword=changeit

Could you please help on this?

Connection is working with tls_verify=none that means connection failure is due to certificate issues.

start over from the beginning and follow the documentation exactly.

  1. make sure you are specifying the root certificate

  2. use only the option trustCertificate(path) mechanism. Mixing multiple mechanisms makes it difficult to determine what is wring.

  3. the openssl command can be used to troubleshoot ssl issues. Google “Troubleshooting SSL”

^-- Did you try this?

@david.nault
For development/test environment we have only one node as below,

In Code, my connection string is “couchbases://10.7.200.139”

Getting below error while connecting to CB

[com.couchbase.io][SecureConnectionFailedEvent] Detected a TLS problem in the IO layer: javax.net.ssl.SSLHandshakeException: General OpenSslEngine problem, Cause: java.security.cert.CertificateException: No subject alternative names matching IP address 10.7.200.139 found {“coreId”:“0xd15b7f7b00000003”,“local”:“/172.22.0.3:46678”,“remote”:“10.7.200.139/10.7.200.139:11207”}
2024-01-29T13:38:01,515 WARN [cb-events ] c.c.endpoint : [com.couchbase.endpoint][EndpointConnectionFailedEvent][13ms] Connect attempt 1 failed because of DecoderException: javax.net.ssl.SSLHandshakeException: General OpenSslEngine problem {“circuitBreaker”:“DISABLED”,“coreId”:“0xd15b7f7b00000003”,“remote”:“10.7.200.139:11207”,“type”:“KV”}

com.couchbase.client.core.deps.io.netty.handler.codec.DecoderException: javax.net.ssl.SSLHandshakeException: General OpenSslEngine problem
at java.lang.Thread.run(Unknown Source) ~[?:?]
Caused by: javax.net.ssl.SSLHandshakeException: General OpenSslEngine problem
at javax.net.ssl.SSLEngine.wrap(Unknown Source) ~[?:?]
… 1 more
Caused by: java.security.cert.CertificateException: No subject alternative names matching IP address 10.7.200.139 found
at sun.security.util.HostnameChecker.matchIP(Unknown Source) ~[?:?]
at sun.security.util.HostnameChecker.match(Unknown Source) ~[?:?]
at sun.security.ssl.X509TrustManagerImpl.checkIdentity(Unknown Source) ~[?:?]
at sun.security.ssl.X509TrustManagerImpl.checkIdentity(Unknown Source) ~[?:?]
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(Unknown Source) ~[?:?]
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source) ~[?:?]
… 1 more

HI @atul ,

My guess is that the server is presenting a certificate for 127.0.0.1 (because that’s the address it was configured to use during cluster setup), but the client requires a certificate for 10.7.200.139.

Since this is a single-node cluster, you can use the REST API to rename the node to give it its true name of 10.7.200.139. See Naming a Node | Couchbase Docs

I’m optimistic this will cause the server to present a certificate for the new name. If I’m wrong about that, something that would definitely work would be to take down the current cluster, and create a new one configured to use the correct name from the start. If that’s not an option, you could ask the folks in the Couchbase Server part of the forum for advice about configuring the server certificate.

Thanks,
David

2 Likes