From 2c86afd7127922b111bd54b6a7876d541881db92 Mon Sep 17 00:00:00 2001 From: Madhavan Sridharan Date: Tue, 11 May 2021 18:16:03 -0400 Subject: [PATCH] Assist with https://github.com/ing-bank/cassandra-jdbc-wrapper/discussions/1 by providing the initial changes required to connect to the Apache Cassandra(R) DBaaS cluster --- README.md | 21 +++++++++++- pom.xml | 2 +- .../cassandra/jdbc/CassandraDataSource.java | 2 +- .../data/cassandra/jdbc/SessionHolder.java | 33 +++++++++++++------ .../com/ing/data/cassandra/jdbc/Utils.java | 8 +++++ .../data/cassandra/jdbc/UtilsUnitTest.java | 7 ++++ 6 files changed, 60 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 2cc1a19..faa8621 100644 --- a/README.md +++ b/README.md @@ -162,7 +162,7 @@ jdbc:cassandra://host1--host2--host3:9042/keyspace?consistency=LOCAL_QUORUM ``` Consistency level defaults to `ONE` if not specified (see -[Consistency levels](https://docs.datastax.com/en/ddac/doc/datastax_enterprise/dbInternals/dbIntConfigConsistency.html) +[Consistency levels](https://docs.datastax.com/en/dse/6.8/dse-arch/datastax_enterprise/dbInternals/dbIntConfigConsistency.html) documentation for further details about the valid values for this argument). ### Secure connection with SSL @@ -183,6 +183,24 @@ The argument `sslEngineFactory` will be ignored if the argument `enableSsl` is ` For further information about custom implementations of `SslEngineFactory`, see [SSL](https://docs.datastax.com/en/developer/java-driver/latest/manual/core/ssl/) documentation. +### Connecting to DBaaS + +In order to connect to the cloud [Cassandra DBaaS](www.datastax.com/astra) cluster, one would need to specify: +* `secureconnectbundle`: the fully qualified path of the cloud secure connect bundle file +* `keyspace`: the keyspace to connect to +* `user`: the username +* `password`: the password + +For example, + +``` +jdbc:cassandra://localhost:9042/keyspace?consistency=LOCAL_QUORUM&secureconnectbundle=/path/to/location/secure-connect-bundle-cluster.zip +``` + +*Note*: whatever the host(s) given here will be ignored and will be fetched from the cloud secure connect bundle, but it is required to pass in something in here to make this work at the moment. + +For further information about connecting to DBaaS, see [cloud documentation](https://docs.datastax.com/en/developer/java-driver/latest/manual/cloud/). + ### Using simple statements To issue a simple select and get data from it: @@ -462,6 +480,7 @@ We use [SemVer](http://semver.org/) for versioning. ## Authors * Maxime Wiewiora - **[@maximevw](https://github.com/maximevw)** +* Madhavan - **[@msmygit](https://github.com/msmygit)** And special thanks to the developer of the original project on which is based this one: * Alexander Dejanovski - **[@adejanovski](https://github.com/adejanovski)** diff --git a/pom.xml b/pom.xml index 40d1226..911c687 100644 --- a/pom.xml +++ b/pom.xml @@ -71,7 +71,7 @@ 3.11.9 3.11 - 4.10.0 + 4.11.1 0.13.0 6.0.4 diff --git a/src/main/java/com/ing/data/cassandra/jdbc/CassandraDataSource.java b/src/main/java/com/ing/data/cassandra/jdbc/CassandraDataSource.java index 5348e08..d09c3ad 100644 --- a/src/main/java/com/ing/data/cassandra/jdbc/CassandraDataSource.java +++ b/src/main/java/com/ing/data/cassandra/jdbc/CassandraDataSource.java @@ -87,7 +87,7 @@ public class CassandraDataSource implements ConnectionPoolDataSource, DataSource /** * The consistency level. *

- * See + * See * consistency level documentation for further details. *

*/ diff --git a/src/main/java/com/ing/data/cassandra/jdbc/SessionHolder.java b/src/main/java/com/ing/data/cassandra/jdbc/SessionHolder.java index 7dd6301..1200ff2 100644 --- a/src/main/java/com/ing/data/cassandra/jdbc/SessionHolder.java +++ b/src/main/java/com/ing/data/cassandra/jdbc/SessionHolder.java @@ -160,6 +160,7 @@ boolean acquire() { private Session createSession(final Properties properties) throws SQLException { final String hosts = properties.getProperty(Utils.TAG_SERVER_NAME); final int port = Integer.parseInt(properties.getProperty(Utils.TAG_PORT_NUMBER)); + final String cloudSecureConnectBundle = properties.getProperty(Utils.TAG_CLOUD_SECURE_CONNEC_BUNDLE); final String keyspace = properties.getProperty(Utils.TAG_DATABASE_NAME); final String username = properties.getProperty(Utils.TAG_USER, StringUtils.EMPTY); final String password = properties.getProperty(Utils.TAG_PASSWORD, StringUtils.EMPTY); @@ -180,10 +181,17 @@ private Session createSession(final Properties properties) throws SQLException { final ProgrammaticDriverConfigLoaderBuilder driverConfigLoaderBuilder = DriverConfigLoader.programmaticBuilder(); driverConfigLoaderBuilder.withBoolean(DefaultDriverOption.SOCKET_KEEP_ALIVE, true); - builder.addContactPoints(Arrays.stream(hosts.split("--")) - .map(host -> InetSocketAddress.createUnresolved(host, port)) - .collect(Collectors.toList()) - ); + if(StringUtils.isNotBlank(cloudSecureConnectBundle)) { + driverConfigLoaderBuilder.withString(DefaultDriverOption.CLOUD_SECURE_CONNECT_BUNDLE, + cloudSecureConnectBundle); + log.info(String.format("Cloud secure connect bundle used. Host(s) %s will be ignored.", + hosts)); + } else { + builder.addContactPoints(Arrays.stream(hosts.split("--")) + .map(host -> InetSocketAddress.createUnresolved(host, port)) + .collect(Collectors.toList()) + ); + } // Set credentials when applicable. if (username.length() > 0) { @@ -262,12 +270,17 @@ private Session createSession(final Properties properties) throws SQLException { builder.withConfigLoader(driverConfigLoaderBuilder.build()); // SSL configuration. - if (sslEnabled) { - if (StringUtils.isNotEmpty(sslEngineFactoryClassName)) { - configureSslEngineFactory(builder, sslEngineFactoryClassName); - } else { - configureDefaultSslEngineFactory(builder, driverConfigLoaderBuilder); - } + if(StringUtils.isBlank(cloudSecureConnectBundle)) { + if (sslEnabled) { + if (StringUtils.isNotEmpty(sslEngineFactoryClassName)) { + configureSslEngineFactory(builder, sslEngineFactoryClassName); + } else { + configureDefaultSslEngineFactory(builder, driverConfigLoaderBuilder); + } + } + } else { + log.info("Cloud secure connect bundle used. SSL will always be enabled. All manual SSL" + + " configuration(s) will be ignored."); } try { diff --git a/src/main/java/com/ing/data/cassandra/jdbc/Utils.java b/src/main/java/com/ing/data/cassandra/jdbc/Utils.java index c495403..a646464 100644 --- a/src/main/java/com/ing/data/cassandra/jdbc/Utils.java +++ b/src/main/java/com/ing/data/cassandra/jdbc/Utils.java @@ -98,6 +98,10 @@ public final class Utils { * JDBC URL parameter key for the custom SSL engine factory ({@link SslEngineFactory}). */ public static final String KEY_SSL_ENGINE_FACTORY = "sslenginefactory"; + /** + * JDBC URL parameter key for the cloud secure connect bundle. + */ + public static final String KEY_CLOUD_SECURE_CONNEC_BUNDLE = "secureconnectbundle"; public static final String TAG_USER = "user"; public static final String TAG_PASSWORD = "password"; @@ -117,6 +121,7 @@ public final class Utils { public static final String TAG_CONNECTION_RETRIES = "retries"; public static final String TAG_ENABLE_SSL = "enableSsl"; public static final String TAG_SSL_ENGINE_FACTORY = "sslEngineFactory"; + public static final String TAG_CLOUD_SECURE_CONNEC_BUNDLE = "secureConnectBundle"; public static final String JSSE_TRUSTSTORE_PROPERTY = "javax.net.ssl.trustStore"; public static final String JSSE_TRUSTSTORE_PASSWORD_PROPERTY = "javax.net.ssl.trustStorePassword"; @@ -264,6 +269,9 @@ public static Properties parseURL(final String url) throws SQLException { if (params.containsKey(KEY_SSL_ENGINE_FACTORY)) { props.setProperty(TAG_SSL_ENGINE_FACTORY, params.get(KEY_SSL_ENGINE_FACTORY)); } + if (params.containsKey(KEY_CLOUD_SECURE_CONNEC_BUNDLE) ) { + props.setProperty(TAG_CLOUD_SECURE_CONNEC_BUNDLE, params.get(KEY_CLOUD_SECURE_CONNEC_BUNDLE)); + } } } diff --git a/src/test/java/com/ing/data/cassandra/jdbc/UtilsUnitTest.java b/src/test/java/com/ing/data/cassandra/jdbc/UtilsUnitTest.java index 4357a28..5870546 100644 --- a/src/test/java/com/ing/data/cassandra/jdbc/UtilsUnitTest.java +++ b/src/test/java/com/ing/data/cassandra/jdbc/UtilsUnitTest.java @@ -45,6 +45,13 @@ class UtilsUnitTest { static Stream buildUrlParsingTestCases() { return Stream.of( + Arguments.of("jdbc:cassandra://localhost:9042/astra?secureconnectbundle=/path/to/location/filename.extn", + new HashMap() {{ + put(Utils.TAG_SERVER_NAME, "localhost"); + put(Utils.TAG_PORT_NUMBER, "9042"); + put(Utils.TAG_DATABASE_NAME, "astra"); + put(Utils.TAG_CLOUD_SECURE_CONNEC_BUNDLE, "/path/to/location/filename.extn"); + }}), Arguments.of("jdbc:cassandra://localhost:9042/Keyspace1?version=3.0.0&consistency=QUORUM", new HashMap() {{ put(Utils.TAG_SERVER_NAME, "localhost");