11package org .testcontainers .cassandra ;
22
33import com .datastax .oss .driver .api .core .CqlSession ;
4+ import com .datastax .oss .driver .api .core .CqlSessionBuilder ;
5+ import com .datastax .oss .driver .api .core .config .DefaultDriverOption ;
6+ import com .datastax .oss .driver .api .core .config .DriverConfigLoader ;
7+ import com .datastax .oss .driver .api .core .config .ProgrammaticDriverConfigLoaderBuilder ;
8+ import com .datastax .oss .driver .api .core .context .DriverContext ;
49import com .datastax .oss .driver .api .core .cql .ResultSet ;
510import com .datastax .oss .driver .api .core .cql .Row ;
11+ import com .datastax .oss .driver .api .core .session .ProgrammaticArguments ;
12+ import com .datastax .oss .driver .internal .core .context .DefaultDriverContext ;
13+ import com .datastax .oss .driver .internal .core .ssl .DefaultSslEngineFactory ;
614import org .junit .jupiter .api .Test ;
15+ import org .testcontainers .containers .Container ;
716import org .testcontainers .containers .ContainerLaunchException ;
817import org .testcontainers .utility .DockerImageName ;
918
19+ import java .net .URL ;
20+
1021import static org .assertj .core .api .Assertions .assertThat ;
1122import static org .assertj .core .api .Assertions .assertThatThrownBy ;
23+ import static org .assertj .core .api .Assertions .fail ;
1224
1325class CassandraContainerTest {
1426
15- private static final String CASSANDRA_IMAGE = "cassandra:3.11.2 " ;
27+ private static final String CASSANDRA_IMAGE = "cassandra:3.11.15 " ;
1628
1729 private static final String TEST_CLUSTER_NAME_IN_CONF = "Test Cluster Integration Test" ;
1830
@@ -21,7 +33,7 @@ class CassandraContainerTest {
2133 @ Test
2234 void testSimple () {
2335 try ( // container-definition {
24- CassandraContainer cassandraContainer = new CassandraContainer ("cassandra:3.11.2" )
36+ CassandraContainer cassandraContainer = new CassandraContainer (CASSANDRA_IMAGE )
2537 // }
2638 ) {
2739 cassandraContainer .start ();
@@ -61,6 +73,69 @@ void testConfigurationOverride() {
6173 }
6274 }
6375
76+ @ Test
77+ public void testWithSslClientConfig () {
78+ /*
79+ Commands executed to generate certificates in 'cassandra-ssl-configuration' directory:
80+ keytool -genkey -keyalg RSA -validity 36500 -alias localhost -keystore keystore.p12 -storepass cassandra \
81+ -keypass cassandra -dname "CN=localhost, OU=Testcontainers, O=Testcontainers, L=None, C=None"
82+ keytool -export -alias localhost -file cassandra.cer -keystore keystore.p12
83+ keytool -import -v -trustcacerts -alias localhost -file cassandra.cer -keystore truststore.p12
84+
85+ Commands executed to generate the client certificate and key in 'client-ssl' directory:
86+ keytool -importkeystore -srckeystore keystore.p12 -destkeystore test_node.p12 -deststoretype PKCS12 \
87+ -srcstorepass cassandra -deststorepass cassandra
88+ openssl pkcs12 -in test_node.p12 -nokeys -out cassandra.cer.pem -passin pass:cassandra
89+ openssl pkcs12 -in test_node.p12 -nodes -nocerts -out cassandra.key.pem -passin pass:cassandra
90+
91+ Reference:
92+ https://docs.datastax.com/en/cassandra-oss/3.x/cassandra/configuration/secureSSLCertificates.html
93+ https://docs.datastax.com/en/cassandra-oss/3.x/cassandra/configuration/secureCqlshSSL.html
94+ */
95+ try (
96+ // with-ssl-config {
97+ CassandraContainer cassandraContainer = new CassandraContainer (CASSANDRA_IMAGE )
98+ .withConfigurationOverride ("cassandra-ssl-configuration" )
99+ .withSsl ("client-ssl/cassandra.cer.pem" , "client-ssl/cassandra.key.pem" )
100+ // }
101+ ) {
102+ cassandraContainer .start ();
103+ try {
104+ ResultSet resultSet = performQueryWithSslClientConfig (
105+ cassandraContainer ,
106+ "SELECT cluster_name FROM system.local"
107+ );
108+ assertThat (resultSet .wasApplied ()).as ("Query was applied" ).isTrue ();
109+ assertThat (resultSet .one ().getString (0 ))
110+ .as ("Cassandra configuration is configured with secured connection" )
111+ .isEqualTo (TEST_CLUSTER_NAME_IN_CONF );
112+ } catch (Exception e ) {
113+ fail (e );
114+ }
115+ }
116+ }
117+
118+ @ Test
119+ public void testSimpleSslCqlsh () {
120+ try (
121+ CassandraContainer cassandraContainer = new CassandraContainer (CASSANDRA_IMAGE )
122+ .withConfigurationOverride ("cassandra-ssl-configuration" )
123+ .withSsl ("client-ssl/cassandra.cer.pem" , "client-ssl/cassandra.key.pem" )
124+ ) {
125+ cassandraContainer .start ();
126+
127+ Container .ExecResult execResult = cassandraContainer .execInContainer (
128+ "cqlsh" ,
129+ "--ssl" ,
130+ "-e" ,
131+ "SELECT * FROM system_schema.keyspaces;"
132+ );
133+ assertThat (execResult .getStdout ()).contains ("keyspace_name" );
134+ } catch (Exception e ) {
135+ fail (e );
136+ }
137+ }
138+
64139 @ Test
65140 void testEmptyConfigurationOverride () {
66141 try (
@@ -164,6 +239,31 @@ private ResultSet performQueryWithAuth(CassandraContainer cassandraContainer, St
164239 return performQuery (cqlSession , cql );
165240 }
166241
242+ private ResultSet performQueryWithSslClientConfig (CassandraContainer cassandraContainer , String cql ) {
243+ final ProgrammaticDriverConfigLoaderBuilder driverConfigLoaderBuilder = DriverConfigLoader .programmaticBuilder ();
244+ driverConfigLoaderBuilder .withBoolean (DefaultDriverOption .SSL_HOSTNAME_VALIDATION , false );
245+ final URL trustStoreUrl =
246+ this .getClass ().getClassLoader ().getResource ("cassandra-ssl-configuration/truststore.p12" );
247+ driverConfigLoaderBuilder .withString (DefaultDriverOption .SSL_TRUSTSTORE_PATH , trustStoreUrl .getFile ());
248+ driverConfigLoaderBuilder .withString (DefaultDriverOption .SSL_TRUSTSTORE_PASSWORD , "cassandra" );
249+ final URL keyStoreUrl =
250+ this .getClass ().getClassLoader ().getResource ("cassandra-ssl-configuration/keystore.p12" );
251+ driverConfigLoaderBuilder .withString (DefaultDriverOption .SSL_KEYSTORE_PATH , keyStoreUrl .getFile ());
252+ driverConfigLoaderBuilder .withString (DefaultDriverOption .SSL_KEYSTORE_PASSWORD , "cassandra" );
253+ final DriverContext driverContext = new DefaultDriverContext (
254+ driverConfigLoaderBuilder .build (),
255+ ProgrammaticArguments .builder ().build ()
256+ );
257+
258+ final CqlSessionBuilder sessionBuilder = CqlSession .builder ();
259+ final CqlSession cqlSession = sessionBuilder
260+ .addContactPoint (cassandraContainer .getContactPoint ())
261+ .withLocalDatacenter (cassandraContainer .getLocalDatacenter ())
262+ .withSslEngineFactory (new DefaultSslEngineFactory (driverContext ))
263+ .build ();
264+ return performQuery (cqlSession , cql );
265+ }
266+
167267 private ResultSet performQuery (CqlSession session , String cql ) {
168268 final ResultSet rs = session .execute (cql );
169269 session .close ();
0 commit comments