You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by bt...@apache.org on 2019/11/08 03:11:54 UTC
[james-project] 07/36: JAMES-2904 Cassandra session user password
and ssl configuration options
This is an automated email from the ASF dual-hosted git repository.
btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 03ac1aa6bd60d8a6460db72e88ccf69e27758f9c
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Tue Oct 1 16:43:40 2019 +0700
JAMES-2904 Cassandra session user password and ssl configuration options
---
.../backends/cassandra/init/ClusterBuilder.java | 24 ++++-
.../init/configuration/ClusterConfiguration.java | 72 +++++++++++++-
.../backends/cassandra/CassandraWaitStrategy.java | 2 +-
.../james/backends/cassandra/DockerCassandra.java | 14 ++-
.../DockerCassandraAuthenticatedSingleton.java | 44 ++-------
.../destination/conf/cassandra.properties | 3 +
.../destination/conf/cassandra.properties | 3 +
.../destination/conf/cassandra.properties | 3 +
.../destination/conf/cassandra.properties | 3 +
.../modules/mailbox/ResilientClusterProvider.java | 3 +
.../AuthenticatedCassandraJamesServerTest.java | 109 +++++++++++++++++++++
....java => CassandraAuthenticationExtension.java} | 46 ++++-----
...va => CassandraBadAuthenticationExtension.java} | 46 ++++-----
.../java/org/apache/james/CassandraExtension.java | 4 +
src/site/xdoc/server/config-cassandra.xml | 13 +++
15 files changed, 289 insertions(+), 100 deletions(-)
diff --git a/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/init/ClusterBuilder.java b/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/init/ClusterBuilder.java
index bc212b0..681992a 100644
--- a/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/init/ClusterBuilder.java
+++ b/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/init/ClusterBuilder.java
@@ -55,10 +55,12 @@ public class ClusterBuilder {
private Optional<Integer> readTimeoutMillis;
private Optional<Integer> connectTimeoutMillis;
private Optional<PoolingOptions> poolingOptions;
+ private Optional<Boolean> useSsl;
private ClusterBuilder() {
username = Optional.empty();
password = Optional.empty();
+ useSsl = Optional.empty();
host = Optional.empty();
port = Optional.empty();
@@ -71,13 +73,21 @@ public class ClusterBuilder {
}
public ClusterBuilder username(String username) {
- this.username = Optional.of(username);
+ return username(Optional.of(username));
+ }
+
+ public ClusterBuilder password(String password) {
+ return password(Optional.of(password));
+ }
+
+ public ClusterBuilder username(Optional<String> username) {
+ this.username = username;
return this;
}
- public ClusterBuilder password(String password) {
- this.password = Optional.of(password);
+ public ClusterBuilder password(Optional<String> password) {
+ this.password = password;
return this;
}
@@ -94,6 +104,12 @@ public class ClusterBuilder {
return this;
}
+ public ClusterBuilder useSsl(boolean useSsl) {
+ this.useSsl = Optional.of(useSsl);
+
+ return this;
+ }
+
public ClusterBuilder poolingOptions(PoolingOptions poolingOptions) {
this.poolingOptions = Optional.of(poolingOptions);
return this;
@@ -155,6 +171,8 @@ public class ClusterBuilder {
clusterBuilder.withSocketOptions(socketOptions);
poolingOptions.ifPresent(clusterBuilder::withPoolingOptions);
+ useSsl.filter(b -> b).ifPresent(any -> clusterBuilder.withSSL());
+
Cluster cluster = clusterBuilder.build();
try {
queryLogger.map(queryLoggerConfiguration ->
diff --git a/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/init/configuration/ClusterConfiguration.java b/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/init/configuration/ClusterConfiguration.java
index 5d832ca..0173373 100644
--- a/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/init/configuration/ClusterConfiguration.java
+++ b/backends-common/cassandra/src/main/java/org/apache/james/backends/cassandra/init/configuration/ClusterConfiguration.java
@@ -46,6 +46,9 @@ public class ClusterConfiguration {
private Optional<PoolingOptions> poolingOptions;
private Optional<Integer> readTimeoutMillis;
private Optional<Integer> connectTimeoutMillis;
+ private Optional<Boolean> useSsl;
+ private Optional<String> username;
+ private Optional<String> password;
public Builder() {
hosts = ImmutableList.builder();
@@ -57,6 +60,9 @@ public class ClusterConfiguration {
poolingOptions = Optional.empty();
readTimeoutMillis = Optional.empty();
connectTimeoutMillis = Optional.empty();
+ username = Optional.empty();
+ password = Optional.empty();
+ useSsl = Optional.empty();
}
public Builder host(Host host) {
@@ -138,6 +144,33 @@ public class ClusterConfiguration {
return this;
}
+ public Builder username(Optional<String> username) {
+ this.username = username;
+ return this;
+ }
+
+ public Builder username(String username) {
+ return username(Optional.of(username));
+ }
+
+ public Builder password(Optional<String> password) {
+ this.password = password;
+ return this;
+ }
+
+ public Builder password(String password) {
+ return password(Optional.of(password));
+ }
+
+ public Builder useSsl(boolean useSsl) {
+ this.useSsl = Optional.of(useSsl);
+ return this;
+ }
+
+ public Builder useSsl() {
+ return useSsl(true);
+ }
+
public Builder connectTimeoutMillis(int connectTimeoutMillis) {
return connectTimeoutMillis(Optional.of(connectTimeoutMillis));
}
@@ -152,12 +185,18 @@ public class ClusterConfiguration {
queryLoggerConfiguration.orElse(QueryLoggerConfiguration.DEFAULT),
poolingOptions,
readTimeoutMillis.orElse(DEFAULT_READ_TIMEOUT_MILLIS),
- connectTimeoutMillis.orElse(DEFAULT_CONNECT_TIMEOUT_MILLIS));
+ connectTimeoutMillis.orElse(DEFAULT_CONNECT_TIMEOUT_MILLIS),
+ useSsl.orElse(false),
+ username,
+ password);
}
}
private static final String CASSANDRA_NODES = "cassandra.nodes";
public static final String CASSANDRA_KEYSPACE = "cassandra.keyspace";
+ public static final String CASSANDRA_USER = "cassandra.user";
+ public static final String CASSANDRA_PASSWORD = "cassandra.password";
+ public static final String CASSANDRA_SSL = "cassandra.ssl";
public static final String REPLICATION_FACTOR = "cassandra.replication.factor";
public static final String READ_TIMEOUT_MILLIS = "cassandra.readTimeoutMillis";
public static final String CONNECT_TIMEOUT_MILLIS = "cassandra.connectTimeoutMillis";
@@ -170,6 +209,7 @@ public class ClusterConfiguration {
private static final int DEFAULT_CONNECTION_MIN_DELAY = 5000;
private static final int DEFAULT_READ_TIMEOUT_MILLIS = 5000;
private static final int DEFAULT_CONNECT_TIMEOUT_MILLIS = 5000;
+ private static final boolean DEFAULT_SSL = false;
public static Builder builder() {
return new Builder();
@@ -186,6 +226,9 @@ public class ClusterConfiguration {
.poolingOptions(readPoolingOptions(configuration))
.readTimeoutMillis(Optional.ofNullable(configuration.getInteger(READ_TIMEOUT_MILLIS, null)))
.connectTimeoutMillis(Optional.ofNullable(configuration.getInteger(CONNECT_TIMEOUT_MILLIS, null)))
+ .useSsl(configuration.getBoolean(CASSANDRA_SSL, false))
+ .username(Optional.ofNullable(configuration.getString(CASSANDRA_USER, null)))
+ .password(Optional.ofNullable(configuration.getString(CASSANDRA_PASSWORD, null)))
.build();
}
@@ -237,10 +280,13 @@ public class ClusterConfiguration {
private final Optional<PoolingOptions> poolingOptions;
private final int readTimeoutMillis;
private final int connectTimeoutMillis;
+ private final boolean useSsl;
+ private final Optional<String> username;
+ private final Optional<String> password;
public ClusterConfiguration(List<Host> hosts, String keyspace, int replicationFactor, int minDelay, int maxRetry,
QueryLoggerConfiguration queryLoggerConfiguration, Optional<PoolingOptions> poolingOptions,
- int readTimeoutMillis, int connectTimeoutMillis) {
+ int readTimeoutMillis, int connectTimeoutMillis, boolean useSsl, Optional<String> username, Optional<String> password) {
this.hosts = hosts;
this.keyspace = keyspace;
this.replicationFactor = replicationFactor;
@@ -250,6 +296,9 @@ public class ClusterConfiguration {
this.poolingOptions = poolingOptions;
this.readTimeoutMillis = readTimeoutMillis;
this.connectTimeoutMillis = connectTimeoutMillis;
+ this.useSsl = useSsl;
+ this.username = username;
+ this.password = password;
}
public List<Host> getHosts() {
@@ -288,6 +337,18 @@ public class ClusterConfiguration {
return connectTimeoutMillis;
}
+ public boolean isUseSsl() {
+ return useSsl;
+ }
+
+ public Optional<String> getUsername() {
+ return username;
+ }
+
+ public Optional<String> getPassword() {
+ return password;
+ }
+
@Override
public final boolean equals(Object o) {
if (o instanceof ClusterConfiguration) {
@@ -301,7 +362,10 @@ public class ClusterConfiguration {
&& Objects.equals(this.queryLoggerConfiguration, that.queryLoggerConfiguration)
&& Objects.equals(this.poolingOptions, that.poolingOptions)
&& Objects.equals(this.readTimeoutMillis, that.readTimeoutMillis)
- && Objects.equals(this.connectTimeoutMillis, that.connectTimeoutMillis);
+ && Objects.equals(this.connectTimeoutMillis, that.connectTimeoutMillis)
+ && Objects.equals(this.useSsl, that.useSsl)
+ && Objects.equals(this.username, that.username)
+ && Objects.equals(this.password, that.password);
}
return false;
}
@@ -309,6 +373,6 @@ public class ClusterConfiguration {
@Override
public final int hashCode() {
return Objects.hash(hosts, keyspace, replicationFactor, minDelay, maxRetry, queryLoggerConfiguration, poolingOptions,
- readTimeoutMillis, connectTimeoutMillis);
+ readTimeoutMillis, connectTimeoutMillis, username, useSsl, password);
}
}
diff --git a/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/CassandraWaitStrategy.java b/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/CassandraWaitStrategy.java
index bb47552..cbec58c 100644
--- a/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/CassandraWaitStrategy.java
+++ b/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/CassandraWaitStrategy.java
@@ -50,7 +50,7 @@ public class CassandraWaitStrategy implements WaitStrategy {
Unreliables.retryUntilTrue(Ints.checkedCast(timeout.getSeconds()), TimeUnit.SECONDS, () -> {
try {
return cassandraContainer
- .execInContainer("cqlsh", "-e", "show host")
+ .execInContainer("cqlsh", "-u", "cassandra", "-p", "cassandra", "-e", "show host")
.getStdout()
.contains("Connected to Test Cluster");
} catch (IOException | InterruptedException e) {
diff --git a/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/DockerCassandra.java b/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/DockerCassandra.java
index 688ed0e..58a9a08 100644
--- a/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/DockerCassandra.java
+++ b/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/DockerCassandra.java
@@ -19,6 +19,8 @@
package org.apache.james.backends.cassandra;
+import java.util.function.Function;
+
import org.apache.james.util.Host;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -26,6 +28,8 @@ import org.testcontainers.DockerClientFactory;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.output.OutputFrame;
import org.testcontainers.images.builder.ImageFromDockerfile;
+import org.testcontainers.images.builder.dockerfile.DockerfileBuilder;
+import org.testcontainers.images.builder.dockerfile.traits.RunStatementTrait;
import com.github.dockerjava.api.DockerClient;
import com.google.common.collect.ImmutableMap;
@@ -45,17 +49,21 @@ public class DockerCassandra {
@SuppressWarnings("resource")
public DockerCassandra() {
+ this("cassandra_3_11_3", Function.identity());
+ }
+
+ public DockerCassandra(String imageName, Function<DockerfileBuilder, DockerfileBuilder> additionalSteps) {
client = DockerClientFactory.instance().client();
boolean doNotDeleteImageAfterUsage = false;
cassandraContainer = new GenericContainer<>(
- new ImageFromDockerfile("cassandra_3_11_3", doNotDeleteImageAfterUsage)
+ new ImageFromDockerfile(imageName,doNotDeleteImageAfterUsage)
.withDockerfileFromBuilder(builder ->
- builder
+ additionalSteps.apply(builder
.from("cassandra:3.11.3")
.env("ENV CASSANDRA_CONFIG", "/etc/cassandra")
.run("echo \"-Xms" + CASSANDRA_MEMORY + "M\" >> " + JVM_OPTIONS)
.run("echo \"-Xmx" + CASSANDRA_MEMORY + "M\" >> " + JVM_OPTIONS)
- .run("sed", "-i", "s/auto_snapshot: true/auto_snapshot: false/g", "/etc/cassandra/cassandra.yaml")
+ .run("sed", "-i", "s/auto_snapshot: true/auto_snapshot: false/g", "/etc/cassandra/cassandra.yaml"))
.build()))
.withTmpFs(ImmutableMap.of("/var/lib/cassandra", "rw,noexec,nosuid,size=200m"))
.withExposedPorts(CASSANDRA_PORT)
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraExtension.java b/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/DockerCassandraAuthenticatedSingleton.java
similarity index 58%
copy from server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraExtension.java
copy to backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/DockerCassandraAuthenticatedSingleton.java
index a2750cc..e16f639 100644
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraExtension.java
+++ b/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/DockerCassandraAuthenticatedSingleton.java
@@ -17,44 +17,14 @@
* under the License. *
****************************************************************/
-package org.apache.james;
+package org.apache.james.backends.cassandra;
-import org.junit.jupiter.api.extension.ExtensionContext;
+public class DockerCassandraAuthenticatedSingleton {
+ public static final DockerCassandra singleton = new DockerCassandra("cassandra_3_11_3_auth",
+ dockerfileBuilder -> dockerfileBuilder
+ .run("echo 'authenticator: PasswordAuthenticator' >> /etc/cassandra/cassandra.yaml"));
-import com.google.inject.Module;
-
-public class CassandraExtension implements GuiceModuleTestExtension {
-
- private final DockerCassandraRule cassandra;
-
- public CassandraExtension() {
- this(new DockerCassandraRule());
- }
-
- public CassandraExtension(DockerCassandraRule cassandra) {
- this.cassandra = cassandra;
- }
-
- @Override
- public void beforeAll(ExtensionContext extensionContext) {
- cassandra.start();
- }
-
- @Override
- public void afterAll(ExtensionContext extensionContext) {
- cassandra.stop();
- }
-
- @Override
- public Module getModule() {
- return cassandra.getModule();
- }
-
- public void pause() {
- cassandra.pause();
- }
-
- public void unpause() {
- cassandra.unpause();
+ static {
+ singleton.start();
}
}
diff --git a/dockerfiles/run/guice/cassandra-ldap/destination/conf/cassandra.properties b/dockerfiles/run/guice/cassandra-ldap/destination/conf/cassandra.properties
index ea199db..cebfe65 100644
--- a/dockerfiles/run/guice/cassandra-ldap/destination/conf/cassandra.properties
+++ b/dockerfiles/run/guice/cassandra-ldap/destination/conf/cassandra.properties
@@ -3,6 +3,9 @@
cassandra.nodes=cassandra
cassandra.keyspace=apache_james
+#cassandra.user=cassandra
+#cassandra.password=cassandra
+#cassandra.ssl=false
cassandra.replication.factor=1
cassandra.retryConnection.maxRetries=200
cassandra.retryConnection.minDelay=5000
diff --git a/dockerfiles/run/guice/cassandra-rabbitmq-ldap/destination/conf/cassandra.properties b/dockerfiles/run/guice/cassandra-rabbitmq-ldap/destination/conf/cassandra.properties
index 1c63f7e..842f56d 100644
--- a/dockerfiles/run/guice/cassandra-rabbitmq-ldap/destination/conf/cassandra.properties
+++ b/dockerfiles/run/guice/cassandra-rabbitmq-ldap/destination/conf/cassandra.properties
@@ -3,6 +3,9 @@
cassandra.nodes=cassandra
cassandra.keyspace=apache_james
+#cassandra.user=cassandra
+#cassandra.password=cassandra
+#cassandra.ssl=false
cassandra.replication.factor=1
cassandra.retryConnection.maxRetries=200
cassandra.retryConnection.minDelay=5000
diff --git a/dockerfiles/run/guice/cassandra-rabbitmq/destination/conf/cassandra.properties b/dockerfiles/run/guice/cassandra-rabbitmq/destination/conf/cassandra.properties
index 1c63f7e..842f56d 100644
--- a/dockerfiles/run/guice/cassandra-rabbitmq/destination/conf/cassandra.properties
+++ b/dockerfiles/run/guice/cassandra-rabbitmq/destination/conf/cassandra.properties
@@ -3,6 +3,9 @@
cassandra.nodes=cassandra
cassandra.keyspace=apache_james
+#cassandra.user=cassandra
+#cassandra.password=cassandra
+#cassandra.ssl=false
cassandra.replication.factor=1
cassandra.retryConnection.maxRetries=200
cassandra.retryConnection.minDelay=5000
diff --git a/dockerfiles/run/guice/cassandra/destination/conf/cassandra.properties b/dockerfiles/run/guice/cassandra/destination/conf/cassandra.properties
index 2cf6a10..413a2ad 100644
--- a/dockerfiles/run/guice/cassandra/destination/conf/cassandra.properties
+++ b/dockerfiles/run/guice/cassandra/destination/conf/cassandra.properties
@@ -3,6 +3,9 @@
cassandra.nodes=cassandra
cassandra.keyspace=apache_james
+#cassandra.user=cassandra
+#cassandra.password=cassandra
+#cassandra.ssl=false
cassandra.replication.factor=1
cassandra.retryConnection.maxRetries=200
cassandra.retryConnection.minDelay=5000
diff --git a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/ResilientClusterProvider.java b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/ResilientClusterProvider.java
index e28e6a4..979aa57 100644
--- a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/ResilientClusterProvider.java
+++ b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/ResilientClusterProvider.java
@@ -64,6 +64,9 @@ public class ResilientClusterProvider implements Provider<Cluster> {
return () -> {
Cluster cluster = ClusterBuilder.builder()
.servers(configuration.getHosts())
+ .username(configuration.getUsername())
+ .password(configuration.getPassword())
+ .useSsl(configuration.isUseSsl())
.poolingOptions(configuration.getPoolingOptions())
.queryLoggerConfiguration(configuration.getQueryLoggerConfiguration())
.readTimeoutMillis(configuration.getReadTimeoutMillis())
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/AuthenticatedCassandraJamesServerTest.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/AuthenticatedCassandraJamesServerTest.java
new file mode 100644
index 0000000..130f4c9
--- /dev/null
+++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/AuthenticatedCassandraJamesServerTest.java
@@ -0,0 +1,109 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.james;
+
+import static org.apache.james.CassandraJamesServerMain.ALL_BUT_JMX_CASSANDRA_MODULE;
+import static org.apache.james.JamesServerContract.DOMAIN_LIST_CONFIGURATION_MODULE;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import org.apache.commons.lang3.NotImplementedException;
+import org.apache.james.backends.cassandra.DockerCassandraAuthenticatedSingleton;
+import org.apache.james.backends.cassandra.init.configuration.ClusterConfiguration;
+import org.apache.james.mailbox.extractor.TextExtractor;
+import org.apache.james.mailbox.store.search.PDFTextExtractor;
+import org.apache.james.modules.TestJMAPServerModule;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+import com.datastax.driver.core.exceptions.AuthenticationException;
+import com.google.inject.CreationException;
+
+class AuthenticatedCassandraJamesServerTest {
+ private static final int LIMIT_TO_10_MESSAGES = 10;
+
+ @Nested
+ class AuthenticationTest implements JamesServerContract {
+ @RegisterExtension
+ JamesServerExtension testExtension = new JamesServerBuilder()
+ .extension(new DockerElasticSearchExtension())
+ .extension(new CassandraAuthenticationExtension())
+ .server(configuration -> GuiceJamesServer.forConfiguration(configuration)
+ .combineWith(ALL_BUT_JMX_CASSANDRA_MODULE)
+ .overrideWith(binder -> binder.bind(TextExtractor.class).to(PDFTextExtractor.class))
+ .overrideWith(new TestJMAPServerModule(LIMIT_TO_10_MESSAGES))
+ .overrideWith(DOMAIN_LIST_CONFIGURATION_MODULE))
+ .build();
+ }
+
+ @Nested
+ class SslTest {
+ @RegisterExtension
+ JamesServerExtension testExtension = new JamesServerBuilder()
+ .extension(new DockerElasticSearchExtension())
+ .extension(new CassandraExtension())
+ .disableAutoStart()
+ .server(configuration -> GuiceJamesServer.forConfiguration(configuration)
+ .combineWith(ALL_BUT_JMX_CASSANDRA_MODULE)
+ .overrideWith(binder -> binder.bind(TextExtractor.class).to(PDFTextExtractor.class))
+ .overrideWith(new TestJMAPServerModule(LIMIT_TO_10_MESSAGES))
+ .overrideWith(DOMAIN_LIST_CONFIGURATION_MODULE))
+ .overrideServerModule(binder -> binder.bind(ClusterConfiguration.class)
+ .toInstance(ClusterConfiguration.builder()
+ .host(DockerCassandraAuthenticatedSingleton.singleton.getHost())
+ .keyspace("testing")
+ .replicationFactor(1)
+ .maxRetry(1)
+ .minDelay(100)
+ .useSsl()
+ .build()))
+ .build();
+
+ @Test
+ void startShouldFailWhenSslUsedAndNotSupportedByServer(GuiceJamesServer jamesServer) {
+ assertThatThrownBy(jamesServer::start)
+ .isInstanceOf(CreationException.class)
+ .hasStackTraceContaining("Caused by: com.datastax.driver.core.exceptions.NoHostAvailableException: All host(s) tried for query failed");
+ }
+ }
+
+ @Nested
+ class AuthenticationFailureTest {
+ @RegisterExtension
+ JamesServerExtension testExtension = new JamesServerBuilder()
+ .extension(new DockerElasticSearchExtension())
+ .extension(new CassandraBadAuthenticationExtension())
+ .disableAutoStart()
+ .server(configuration -> GuiceJamesServer.forConfiguration(configuration)
+ .combineWith(ALL_BUT_JMX_CASSANDRA_MODULE)
+ .overrideWith(binder -> binder.bind(TextExtractor.class).to(PDFTextExtractor.class))
+ .overrideWith(new TestJMAPServerModule(LIMIT_TO_10_MESSAGES))
+ .overrideWith(DOMAIN_LIST_CONFIGURATION_MODULE))
+ .build();
+
+ @Test
+ void startShouldFailOnBadPassword(GuiceJamesServer jamesServer) {
+ assertThatThrownBy(jamesServer::start)
+ .isInstanceOf(CreationException.class)
+ .hasStackTraceContaining("Caused by: com.datastax.driver.core.exceptions.AuthenticationException: Authentication error");
+ }
+ }
+}
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraExtension.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraAuthenticationExtension.java
similarity index 55%
copy from server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraExtension.java
copy to server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraAuthenticationExtension.java
index a2750cc..7528d6c 100644
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraExtension.java
+++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraAuthenticationExtension.java
@@ -19,42 +19,36 @@
package org.apache.james;
+import org.apache.james.backends.cassandra.DockerCassandraAuthenticatedSingleton;
+import org.apache.james.backends.cassandra.init.configuration.ClusterConfiguration;
+import org.apache.james.server.CassandraTruncateTableTask;
import org.junit.jupiter.api.extension.ExtensionContext;
import com.google.inject.Module;
+import com.google.inject.multibindings.Multibinder;
+import com.google.inject.util.Modules;
-public class CassandraExtension implements GuiceModuleTestExtension {
-
- private final DockerCassandraRule cassandra;
-
- public CassandraExtension() {
- this(new DockerCassandraRule());
- }
-
- public CassandraExtension(DockerCassandraRule cassandra) {
- this.cassandra = cassandra;
- }
+public class CassandraAuthenticationExtension implements GuiceModuleTestExtension {
@Override
public void beforeAll(ExtensionContext extensionContext) {
- cassandra.start();
- }
-
- @Override
- public void afterAll(ExtensionContext extensionContext) {
- cassandra.stop();
+ DockerCassandraAuthenticatedSingleton.singleton.start();
}
@Override
public Module getModule() {
- return cassandra.getModule();
- }
-
- public void pause() {
- cassandra.pause();
- }
-
- public void unpause() {
- cassandra.unpause();
+ return Modules.combine((binder) -> binder.bind(ClusterConfiguration.class)
+ .toInstance(ClusterConfiguration.builder()
+ .host(DockerCassandraAuthenticatedSingleton.singleton.getHost())
+ .keyspace("testing")
+ .username("cassandra")
+ .password("cassandra")
+ .replicationFactor(1)
+ .maxRetry(20)
+ .minDelay(5000)
+ .build()),
+ binder -> Multibinder.newSetBinder(binder, CleanupTasksPerformer.CleanupTask.class)
+ .addBinding()
+ .to(CassandraTruncateTableTask.class));
}
}
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraExtension.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraBadAuthenticationExtension.java
similarity index 56%
copy from server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraExtension.java
copy to server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraBadAuthenticationExtension.java
index a2750cc..a001393 100644
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraExtension.java
+++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraBadAuthenticationExtension.java
@@ -19,42 +19,36 @@
package org.apache.james;
+import org.apache.james.backends.cassandra.DockerCassandraAuthenticatedSingleton;
+import org.apache.james.backends.cassandra.init.configuration.ClusterConfiguration;
+import org.apache.james.server.CassandraTruncateTableTask;
import org.junit.jupiter.api.extension.ExtensionContext;
import com.google.inject.Module;
+import com.google.inject.multibindings.Multibinder;
+import com.google.inject.util.Modules;
-public class CassandraExtension implements GuiceModuleTestExtension {
-
- private final DockerCassandraRule cassandra;
-
- public CassandraExtension() {
- this(new DockerCassandraRule());
- }
-
- public CassandraExtension(DockerCassandraRule cassandra) {
- this.cassandra = cassandra;
- }
+public class CassandraBadAuthenticationExtension implements GuiceModuleTestExtension {
@Override
public void beforeAll(ExtensionContext extensionContext) {
- cassandra.start();
- }
-
- @Override
- public void afterAll(ExtensionContext extensionContext) {
- cassandra.stop();
+ DockerCassandraAuthenticatedSingleton.singleton.start();
}
@Override
public Module getModule() {
- return cassandra.getModule();
- }
-
- public void pause() {
- cassandra.pause();
- }
-
- public void unpause() {
- cassandra.unpause();
+ return Modules.combine((binder) -> binder.bind(ClusterConfiguration.class)
+ .toInstance(ClusterConfiguration.builder()
+ .host(DockerCassandraAuthenticatedSingleton.singleton.getHost())
+ .keyspace("testing")
+ .username("cassandra")
+ .password("bad")
+ .replicationFactor(1)
+ .maxRetry(1)
+ .minDelay(100)
+ .build()),
+ binder -> Multibinder.newSetBinder(binder, CleanupTasksPerformer.CleanupTask.class)
+ .addBinding()
+ .to(CassandraTruncateTableTask.class));
}
}
diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraExtension.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraExtension.java
index a2750cc..f7d1fc4 100644
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraExtension.java
+++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraExtension.java
@@ -50,6 +50,10 @@ public class CassandraExtension implements GuiceModuleTestExtension {
return cassandra.getModule();
}
+ public DockerCassandraRule getCassandra() {
+ return cassandra;
+ }
+
public void pause() {
cassandra.pause();
}
diff --git a/src/site/xdoc/server/config-cassandra.xml b/src/site/xdoc/server/config-cassandra.xml
index d951fe8..3511c87 100644
--- a/src/site/xdoc/server/config-cassandra.xml
+++ b/src/site/xdoc/server/config-cassandra.xml
@@ -38,6 +38,19 @@
<dt><strong>cassandra.keyspace</strong></dt>
<dd>Is the name of the keyspace used by James. Optional, default value: <b>apache_james</b></dd>
+ <dt><strong>cassandra.user</strong></dt>
+ <dd>Username used as a credential for contacting Cassandra cluster. Optional, default is absent,
+ required if <strong>cassandra.password</strong> is supplied</dd>
+
+ <dt><strong>cassandra.password</strong></dt>
+ <dd>Password used as a credential for contacting Cassandra cluster. Optional, default is absent,
+ required if <strong>cassandra.user</strong> is supplied</dd>
+
+ <dt><strong>cassandra.ssl</strong></dt>
+ <dd>Wether SSL should be enabled on the communications with Cassandra cluster. Optional, defaults to false.<br/>
+ The keystore used for trusting SLL server socket can be set via JSSE system properties as explained on
+ <a href="https://docs.datastax.com/en/developer/java-driver/3.7/manual/ssl/">Cassandra driver manual</a>.</dd>
+
<dt><strong>cassandra.replication.factor</strong></dt>
<dd>Is the replication factor used upon keyspace creation. Modifying this property while the keyspace already exists
will have no effect. Optional. Default value 1.</dd>
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org