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/06/17 11:04:32 UTC

[james-project] branch master updated (ace9f15 -> 860f726)

This is an automated email from the ASF dual-hosted git repository.

btellier pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git.


    from ace9f15  Revert "JAMES-2777 fix too strong expectation about task cancellation"
     new 74988eb  MAILET-136 James SMTP doesn't create new user or mailbox when doing domain re routing
     new d81197b  MAILET-136 James JMAP doesn't create new user or mailbox when doing domain re routing
     new c3876cf  JAMES-2146 a new component dedicated to load java security keys from configuration
     new d3c90a9  JAMES-2146 StartUpCheck for Jmap security configuration
     new 41553be  JAMES-2146 Refactor Jmap signature handler
     new 263f7cf  JAMES-2146 Move FileSystemFixture to file api module
     new 2fc2a8b  JAMES-2146 Reuse FileSystemFixture in jmap tests
     new aafeb6f  JAMES-2146 Add a test of loading keystore in different versions
     new 860f726  JAMES-2146 Allow JamesServerBuilder to override guice modules

The 9 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../james/filesystem/api}/FileSystemFixture.java   |  17 +-
 .../org/apache/james/CassandraNodeConfTest.java    |  52 ++---
 .../CassandraRabbitMQLdapJmapJamesServerTest.java  |  29 ++-
 .../java/org/apache/james/JamesServerBuilder.java  |  10 +-
 server/container/guice/mailet/pom.xml              |   6 +
 .../apache/james/utils/GuiceMailetLoaderTest.java  |   6 +-
 .../apache/james/utils/GuiceMatcherLoaderTest.java |   6 +-
 .../james/GuiceJamesServerStartUpCheckTest.java    |  51 ++---
 .../org/apache/james/GuiceJamesServerTest.java     |  29 ++-
 .../apache/james/GuiceLifecycleHeathCheckTest.java |  28 ++-
 .../apache/james/MemoryJmapJamesServerTest.java    |  87 +++++++-
 .../src/test/resources/badAliasKeystore            | Bin
 .../org/apache/james/jmap/JMAPCommonModule.java    |   7 +
 .../james/jmap/JMAPConfigurationStartUpCheck.java} |  61 +++---
 .../apache/james/modules/TestJMAPServerModule.java |  17 +-
 .../RecipientRewriteTableIntegrationTest.java      |  30 ++-
 ...> CassandraSetMessagesMethodReRoutingTest.java} |   7 +-
 .../org/apache/james/jmap/JmapCommonRequests.java  |  36 +++
 .../integration/GetMessageListMethodTest.java      |  34 +--
 .../SetMessagesMethodReRoutingTest.java            | 242 +++++++++++++++++++++
 .../methods/integration/SetMessagesMethodTest.java |  12 +-
 ...a => MemorySetMessagesMethodReRoutingTest.java} |   4 +-
 ...bbitMQAwsS3SetMessagesMethodReRoutingTest.java} |   5 +-
 server/protocols/jmap/pom.xml                      |   6 +
 .../{SignatureHandler.java => AsymmetricKeys.java} |  22 +-
 .../james/jmap/crypto/JamesSignatureHandler.java   |  44 +---
 ...ignatureHandler.java => SecurityKeyLoader.java} |  62 +-----
 ...ider.java => JamesSignatureHandlerFixture.java} |  49 +----
 .../jmap/crypto/JamesSignatureHandlerTest.java     |  18 +-
 .../james/jmap/crypto/SecurityKeyLoaderTest.java   | 131 +++++++++++
 .../james/jmap/crypto/SignedTokenFactoryTest.java  |   3 +-
 .../james/jmap/crypto/SignedTokenManagerTest.java  |   3 +-
 .../jmap/src/test/resources/keystoreJava11         | Bin 0 -> 2581 bytes
 .../jmap/src/test/resources/keystoreJava7          | Bin 0 -> 2239 bytes
 34 files changed, 750 insertions(+), 364 deletions(-)
 rename server/container/{guice/mailet/src/test/java/org/apache/james/utils => filesystem-api/src/test/java/org/apache/james/filesystem/api}/FileSystemFixture.java (86%)
 copy server/{protocols/jmap => container/guice/memory-guice}/src/test/resources/badAliasKeystore (100%)
 copy server/container/guice/{cassandra-guice/src/main/java/org/apache/james/modules/mailbox/ElasticSearchStartUpCheck.java => protocols/jmap/src/main/java/org/apache/james/jmap/JMAPConfigurationStartUpCheck.java} (53%)
 copy server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/java/org/apache/james/jmap/cassandra/{CassandraSetMailboxesMethodTest.java => CassandraSetMessagesMethodReRoutingTest.java} (91%)
 create mode 100644 server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/SetMessagesMethodReRoutingTest.java
 copy server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/java/org/apache/james/jmap/memory/{MemorySetMailboxesMethodTest.java => MemorySetMessagesMethodReRoutingTest.java} (90%)
 copy server/protocols/jmap-integration-testing/rabbitmq-jmap-integration-testing/src/test/java/org/apache/james/jmap/rabbitmq/{RabbitMQAwsS3VacationIntegrationTest.java => RabbitMQAwsS3SetMessagesMethodReRoutingTest.java} (91%)
 copy server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/{SignatureHandler.java => AsymmetricKeys.java} (73%)
 copy server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/{JamesSignatureHandler.java => SecurityKeyLoader.java} (54%)
 rename server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/{JamesSignatureHandlerProvider.java => JamesSignatureHandlerFixture.java} (58%)
 create mode 100644 server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SecurityKeyLoaderTest.java
 create mode 100644 server/protocols/jmap/src/test/resources/keystoreJava11
 create mode 100644 server/protocols/jmap/src/test/resources/keystoreJava7


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[james-project] 08/09: JAMES-2146 Add a test of loading keystore in different versions

Posted by bt...@apache.org.
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 aafeb6f63f59ee14328bc822e08a15ca6ca69458
Author: Tran Tien Duc <dt...@linagora.com>
AuthorDate: Fri Jun 7 10:16:14 2019 +0700

    JAMES-2146 Add a test of loading keystore in different versions
---
 .../james/jmap/crypto/SecurityKeyLoaderTest.java   |  25 +++++++++++++++++++++
 .../jmap/src/test/resources/keystoreJava11         | Bin 0 -> 2581 bytes
 .../jmap/src/test/resources/keystoreJava7          | Bin 0 -> 2239 bytes
 3 files changed, 25 insertions(+)

diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SecurityKeyLoaderTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SecurityKeyLoaderTest.java
index c47f33f..8c5675a 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SecurityKeyLoaderTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SecurityKeyLoaderTest.java
@@ -30,6 +30,8 @@ import java.util.Optional;
 import org.apache.james.filesystem.api.FileSystemFixture;
 import org.apache.james.jmap.JMAPConfiguration;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
 
 class SecurityKeyLoaderTest {
 
@@ -85,4 +87,27 @@ class SecurityKeyLoaderTest {
         assertThat(loader.load())
             .isNotNull();
     }
+
+    @ParameterizedTest
+    @ValueSource(strings = {
+        "keystoreJava7",
+        "keystoreJava11",
+    })
+    void loadShouldReturnSecurityKeysWhenUsingKeyStoreGeneratedByDifferentJavaVersions(
+        String keyStoreInDifferentVersion) throws Exception {
+
+        JMAPConfiguration jmapConfiguration = JMAPConfiguration.builder()
+            .enable()
+            .jwtPublicKeyPem(Optional.of(JWT_PUBLIC_KEY))
+            .keystore(keyStoreInDifferentVersion)
+            .secret("james72laBalle")
+            .build();
+
+        SecurityKeyLoader loader = new SecurityKeyLoader(
+            FileSystemFixture.CLASSPATH_FILE_SYSTEM,
+            jmapConfiguration);
+
+        assertThat(loader.load())
+            .isNotNull();
+    }
 }
\ No newline at end of file
diff --git a/server/protocols/jmap/src/test/resources/keystoreJava11 b/server/protocols/jmap/src/test/resources/keystoreJava11
new file mode 100644
index 0000000..e4492c3
Binary files /dev/null and b/server/protocols/jmap/src/test/resources/keystoreJava11 differ
diff --git a/server/protocols/jmap/src/test/resources/keystoreJava7 b/server/protocols/jmap/src/test/resources/keystoreJava7
new file mode 100644
index 0000000..aa45ad0
Binary files /dev/null and b/server/protocols/jmap/src/test/resources/keystoreJava7 differ


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[james-project] 06/09: JAMES-2146 Move FileSystemFixture to file api module

Posted by bt...@apache.org.
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 263f7cfcf1d4382de93d9d92ed2dd535db6ded13
Author: Tran Tien Duc <dt...@linagora.com>
AuthorDate: Thu Jun 6 12:09:28 2019 +0700

    JAMES-2146 Move FileSystemFixture to file api module
    
    to be used in other places
---
 .../apache/james/filesystem/api}/FileSystemFixture.java | 17 +++++++----------
 server/container/guice/mailet/pom.xml                   |  6 ++++++
 .../org/apache/james/utils/GuiceMailetLoaderTest.java   |  6 +++---
 .../org/apache/james/utils/GuiceMatcherLoaderTest.java  |  6 +++---
 4 files changed, 19 insertions(+), 16 deletions(-)

diff --git a/server/container/guice/mailet/src/test/java/org/apache/james/utils/FileSystemFixture.java b/server/container/filesystem-api/src/test/java/org/apache/james/filesystem/api/FileSystemFixture.java
similarity index 86%
rename from server/container/guice/mailet/src/test/java/org/apache/james/utils/FileSystemFixture.java
rename to server/container/filesystem-api/src/test/java/org/apache/james/filesystem/api/FileSystemFixture.java
index fa6c580..b9d4cc2 100644
--- a/server/container/guice/mailet/src/test/java/org/apache/james/utils/FileSystemFixture.java
+++ b/server/container/filesystem-api/src/test/java/org/apache/james/filesystem/api/FileSystemFixture.java
@@ -17,22 +17,19 @@
  * under the License.                                           *
  ****************************************************************/
 
-package org.apache.james.utils;
+package org.apache.james.filesystem.api;
 
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
 
-import org.apache.commons.lang.NotImplementedException;
-import org.apache.james.filesystem.api.FileSystem;
-
 public class FileSystemFixture {
 
     public static final FileSystem THROWING_FILE_SYSTEM = new FileSystem() {
         @Override
         public InputStream getResource(String url) throws IOException {
-            throw new NotImplementedException();
+            throw new UnsupportedOperationException();
         }
 
         @Override
@@ -42,14 +39,14 @@ public class FileSystemFixture {
 
         @Override
         public File getBasedir() throws FileNotFoundException {
-            throw new NotImplementedException();
+            throw new UnsupportedOperationException();
         }
     };
 
     public static final FileSystem CLASSPATH_FILE_SYSTEM = new FileSystem() {
         @Override
         public InputStream getResource(String url) throws IOException {
-            throw new NotImplementedException();
+            return ClassLoader.getSystemResourceAsStream(url);
         }
 
         @Override
@@ -59,14 +56,14 @@ public class FileSystemFixture {
 
         @Override
         public File getBasedir() throws FileNotFoundException {
-            throw new NotImplementedException();
+            throw new UnsupportedOperationException();
         }
     };
 
     public static final FileSystem RECURSIVE_CLASSPATH_FILE_SYSTEM = new FileSystem() {
         @Override
         public InputStream getResource(String url) throws IOException {
-            throw new NotImplementedException();
+            throw new UnsupportedOperationException();
         }
 
         @Override
@@ -76,7 +73,7 @@ public class FileSystemFixture {
 
         @Override
         public File getBasedir() throws FileNotFoundException {
-            throw new NotImplementedException();
+            throw new UnsupportedOperationException();
         }
     };
 }
diff --git a/server/container/guice/mailet/pom.xml b/server/container/guice/mailet/pom.xml
index b2a260b..71f324f 100644
--- a/server/container/guice/mailet/pom.xml
+++ b/server/container/guice/mailet/pom.xml
@@ -43,6 +43,12 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>james-server-filesystem-api</artifactId>
+            <scope>test</scope>
+            <type>test-jar</type>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>james-server-guice-configuration</artifactId>
         </dependency>
         <dependency>
diff --git a/server/container/guice/mailet/src/test/java/org/apache/james/utils/GuiceMailetLoaderTest.java b/server/container/guice/mailet/src/test/java/org/apache/james/utils/GuiceMailetLoaderTest.java
index b0cfae0..129f8e7 100644
--- a/server/container/guice/mailet/src/test/java/org/apache/james/utils/GuiceMailetLoaderTest.java
+++ b/server/container/guice/mailet/src/test/java/org/apache/james/utils/GuiceMailetLoaderTest.java
@@ -19,9 +19,9 @@
 
 package org.apache.james.utils;
 
-import static org.apache.james.utils.FileSystemFixture.CLASSPATH_FILE_SYSTEM;
-import static org.apache.james.utils.FileSystemFixture.RECURSIVE_CLASSPATH_FILE_SYSTEM;
-import static org.apache.james.utils.FileSystemFixture.THROWING_FILE_SYSTEM;
+import static org.apache.james.filesystem.api.FileSystemFixture.CLASSPATH_FILE_SYSTEM;
+import static org.apache.james.filesystem.api.FileSystemFixture.RECURSIVE_CLASSPATH_FILE_SYSTEM;
+import static org.apache.james.filesystem.api.FileSystemFixture.THROWING_FILE_SYSTEM;
 import static org.assertj.core.api.Assertions.assertThat;
 
 import javax.mail.MessagingException;
diff --git a/server/container/guice/mailet/src/test/java/org/apache/james/utils/GuiceMatcherLoaderTest.java b/server/container/guice/mailet/src/test/java/org/apache/james/utils/GuiceMatcherLoaderTest.java
index 01e709b..319fb7a 100644
--- a/server/container/guice/mailet/src/test/java/org/apache/james/utils/GuiceMatcherLoaderTest.java
+++ b/server/container/guice/mailet/src/test/java/org/apache/james/utils/GuiceMatcherLoaderTest.java
@@ -19,9 +19,9 @@
 
 package org.apache.james.utils;
 
-import static org.apache.james.utils.FileSystemFixture.CLASSPATH_FILE_SYSTEM;
-import static org.apache.james.utils.FileSystemFixture.RECURSIVE_CLASSPATH_FILE_SYSTEM;
-import static org.apache.james.utils.FileSystemFixture.THROWING_FILE_SYSTEM;
+import static org.apache.james.filesystem.api.FileSystemFixture.CLASSPATH_FILE_SYSTEM;
+import static org.apache.james.filesystem.api.FileSystemFixture.RECURSIVE_CLASSPATH_FILE_SYSTEM;
+import static org.apache.james.filesystem.api.FileSystemFixture.THROWING_FILE_SYSTEM;
 import static org.assertj.core.api.Assertions.assertThat;
 
 import javax.mail.MessagingException;


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[james-project] 09/09: JAMES-2146 Allow JamesServerBuilder to override guice modules

Posted by bt...@apache.org.
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 860f7266a377da4c4944cc8a1cf786e3467432e2
Author: Tran Tien Duc <dt...@linagora.com>
AuthorDate: Fri Jun 7 10:41:09 2019 +0700

    JAMES-2146 Allow JamesServerBuilder to override guice modules
---
 .../org/apache/james/CassandraNodeConfTest.java    | 52 +++++++++-------------
 .../CassandraRabbitMQLdapJmapJamesServerTest.java  | 29 ++++++------
 .../java/org/apache/james/JamesServerBuilder.java  | 10 ++++-
 .../james/GuiceJamesServerStartUpCheckTest.java    | 51 ++++++++-------------
 .../org/apache/james/GuiceJamesServerTest.java     | 29 ++++++------
 .../apache/james/GuiceLifecycleHeathCheckTest.java | 28 ++++++------
 .../apache/james/MemoryJmapJamesServerTest.java    | 50 +++++++++------------
 .../james/jmap/JMAPConfigurationStartUpCheck.java  | 15 ++++++-
 .../james/jmap/crypto/SecurityKeyLoader.java       |  3 ++
 .../james/jmap/crypto/SecurityKeyLoaderTest.java   | 22 ++++++++-
 10 files changed, 145 insertions(+), 144 deletions(-)

diff --git a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraNodeConfTest.java b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraNodeConfTest.java
index 2444764..53aedfb 100644
--- a/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraNodeConfTest.java
+++ b/server/container/guice/cassandra-guice/src/test/java/org/apache/james/CassandraNodeConfTest.java
@@ -44,6 +44,16 @@ class CassandraNodeConfTest {
     private static final int CASSANDRA_PORT = 9042;
     private static final int LIMIT_TO_10_MESSAGES = 10;
 
+    private static JamesServerBuilder extensionBuilder() {
+        return new JamesServerBuilder()
+            .extension(new DockerElasticSearchExtension())
+            .extension(new CassandraExtension())
+            .server(configuration -> GuiceJamesServer.forConfiguration(configuration)
+                .combineWith(ALL_BUT_JMX_CASSANDRA_MODULE)
+                .overrideWith(new TestJMAPServerModule(LIMIT_TO_10_MESSAGES)))
+            .disableAutoStart();
+    }
+
     private static String getDockerHostIp() {
         DockerClientFactory clientFactory = DockerClientFactory.instance();
         clientFactory.client();
@@ -65,15 +75,7 @@ class CassandraNodeConfTest {
     @Nested
     class NormalBehaviour {
         @RegisterExtension
-        JamesServerExtension testExtension = new JamesServerBuilder()
-            .extension(new DockerElasticSearchExtension())
-            .extension(new CassandraExtension())
-            .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)))
-            .disableAutoStart()
-            .build();
+        JamesServerExtension testExtension = extensionBuilder().build();
 
         @Test
         void serverShouldStartServiceWhenNodeIsReachable(GuiceJamesServer server) throws Exception {
@@ -88,18 +90,11 @@ class CassandraNodeConfTest {
         private final DockerCassandraRule cassandra = new DockerCassandraRule();
 
         @RegisterExtension
-        JamesServerExtension testExtension = new JamesServerBuilder()
-            .extension(new DockerElasticSearchExtension())
-            .extension(new CassandraExtension(cassandra))
-            .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(binder -> binder.bind(ClusterConfiguration.class)
-                    .toInstance(clusterWithHosts(
-                        Host.from(unreachableNode, 9042),
-                        cassandra.getHost()))))
-            .disableAutoStart()
+        JamesServerExtension testExtension = extensionBuilder()
+            .overrideServerModule(binder -> binder.bind(ClusterConfiguration.class)
+                .toInstance(clusterWithHosts(
+                    Host.from(unreachableNode, 9042),
+                    cassandra.getHost())))
             .build();
 
         @Test
@@ -113,17 +108,10 @@ class CassandraNodeConfTest {
         private final DockerCassandraRule cassandra = new DockerCassandraRule();
 
         @RegisterExtension
-        JamesServerExtension testExtension = new JamesServerBuilder()
-            .extension(new DockerElasticSearchExtension())
-            .extension(new CassandraExtension(cassandra))
-            .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(binder -> binder.bind(ClusterConfiguration.class)
-                    .toInstance(clusterWithHosts(
-                        Host.from(getDockerHostIp(), cassandra.getMappedPort(CASSANDRA_PORT))))))
-            .disableAutoStart()
+        JamesServerExtension testExtension =  extensionBuilder()
+            .overrideServerModule(binder -> binder.bind(ClusterConfiguration.class)
+                .toInstance(clusterWithHosts(
+                    Host.from(getDockerHostIp(), cassandra.getMappedPort(CASSANDRA_PORT)))))
             .build();
 
         @Test
diff --git a/server/container/guice/cassandra-rabbitmq-ldap-guice/src/test/java/org/apache/james/CassandraRabbitMQLdapJmapJamesServerTest.java b/server/container/guice/cassandra-rabbitmq-ldap-guice/src/test/java/org/apache/james/CassandraRabbitMQLdapJmapJamesServerTest.java
index 1867638..0e4edaa 100644
--- a/server/container/guice/cassandra-rabbitmq-ldap-guice/src/test/java/org/apache/james/CassandraRabbitMQLdapJmapJamesServerTest.java
+++ b/server/container/guice/cassandra-rabbitmq-ldap-guice/src/test/java/org/apache/james/CassandraRabbitMQLdapJmapJamesServerTest.java
@@ -33,7 +33,6 @@ import org.apache.james.modules.SwiftBlobStoreExtension;
 import org.apache.james.modules.TestJMAPServerModule;
 import org.apache.james.modules.blobstore.BlobStoreChoosingConfiguration;
 import org.apache.james.modules.protocols.ImapGuiceProbe;
-import org.apache.james.server.core.configuration.Configuration;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.TestInstance;
@@ -61,7 +60,8 @@ class CassandraRabbitMQLdapJmapJamesServerTest {
         @RegisterExtension
         JamesServerExtension testExtension = baseJamesServerExtensionBuilder()
             .extension(new SwiftBlobStoreExtension())
-            .server(configuration -> buildGuiceServer(configuration, BlobStoreChoosingConfiguration.objectStorage()))
+            .overrideServerModule(binder -> binder.bind(BlobStoreChoosingConfiguration.class)
+                .toInstance(BlobStoreChoosingConfiguration.objectStorage()))
             .build();
     }
 
@@ -70,9 +70,10 @@ class CassandraRabbitMQLdapJmapJamesServerTest {
     class WithAwsS3 implements ContractSuite {
         @RegisterExtension
         JamesServerExtension testExtension = baseJamesServerExtensionBuilder()
-                .extension(new AwsS3BlobStoreExtension())
-                .server(configuration -> buildGuiceServer(configuration, BlobStoreChoosingConfiguration.objectStorage()))
-                .build();
+            .extension(new AwsS3BlobStoreExtension())
+            .overrideServerModule(binder -> binder.bind(BlobStoreChoosingConfiguration.class)
+                .toInstance(BlobStoreChoosingConfiguration.objectStorage()))
+            .build();
     }
 
     @Nested
@@ -80,7 +81,8 @@ class CassandraRabbitMQLdapJmapJamesServerTest {
     class WithoutSwiftOrAwsS3 implements ContractSuite {
         @RegisterExtension
         JamesServerExtension testExtension = baseJamesServerExtensionBuilder()
-            .server(configuration -> buildGuiceServer(configuration, BlobStoreChoosingConfiguration.cassandra()))
+            .overrideServerModule(binder -> binder.bind(BlobStoreChoosingConfiguration.class)
+                .toInstance(BlobStoreChoosingConfiguration.cassandra()))
             .build();
     }
 
@@ -89,15 +91,10 @@ class CassandraRabbitMQLdapJmapJamesServerTest {
             .extension(new DockerElasticSearchExtension())
             .extension(new CassandraExtension())
             .extension(new RabbitMQExtension())
-            .extension(new LdapTestExtension());
-    }
-
-    GuiceJamesServer buildGuiceServer(Configuration configuration, BlobStoreChoosingConfiguration choosingConfiguration) {
-        return GuiceJamesServer.forConfiguration(configuration)
-            .combineWith(CassandraRabbitMQLdapJamesServerMain.MODULES)
-            .overrideWith(binder -> binder.bind(BlobStoreChoosingConfiguration.class)
-                .toInstance(choosingConfiguration))
-            .overrideWith(new TestJMAPServerModule(LIMIT_TO_10_MESSAGES))
-            .overrideWith(JmapJamesServerContract.DOMAIN_LIST_CONFIGURATION_MODULE);
+            .extension(new LdapTestExtension())
+            .server(configuration -> GuiceJamesServer.forConfiguration(configuration)
+                .combineWith(CassandraRabbitMQLdapJamesServerMain.MODULES)
+                .overrideWith(new TestJMAPServerModule(LIMIT_TO_10_MESSAGES))
+                .overrideWith(JmapJamesServerContract.DOMAIN_LIST_CONFIGURATION_MODULE));
     }
 }
diff --git a/server/container/guice/guice-common/src/test/java/org/apache/james/JamesServerBuilder.java b/server/container/guice/guice-common/src/test/java/org/apache/james/JamesServerBuilder.java
index 8f38e5b..dfed2b0 100644
--- a/server/container/guice/guice-common/src/test/java/org/apache/james/JamesServerBuilder.java
+++ b/server/container/guice/guice-common/src/test/java/org/apache/james/JamesServerBuilder.java
@@ -45,6 +45,7 @@ public class JamesServerBuilder {
 
     private final ImmutableList.Builder<GuiceModuleTestExtension> extensions;
     private final TemporaryFolderRegistrableExtension folderRegistrableExtension;
+    private final ImmutableList.Builder<Module> overrideModules;
     private ServerProvider server;
     private Optional<ConfigurationProvider> configuration;
     private Optional<Boolean> autoStart;
@@ -54,6 +55,7 @@ public class JamesServerBuilder {
         extensions = ImmutableList.builder();
         folderRegistrableExtension = new TemporaryFolderRegistrableExtension();
         autoStart = Optional.empty();
+        overrideModules = ImmutableList.builder();
     }
 
     public JamesServerBuilder extensions(GuiceModuleTestExtension... extensions) {
@@ -75,6 +77,11 @@ public class JamesServerBuilder {
         return this;
     }
 
+    public JamesServerBuilder overrideServerModule(Module module) {
+        this.overrideModules.add(module);
+        return this;
+    }
+
     public JamesServerBuilder disableAutoStart() {
         this.autoStart = Optional.of(false);
         return this;
@@ -115,7 +122,8 @@ public class JamesServerBuilder {
         return server
             .buildServer(configurationProvider.buildConfiguration(file))
             .overrideWith(modules)
-            .overrideWith((binder -> binder.bind(CleanupTasksPerformer.class).asEagerSingleton()));
+            .overrideWith((binder -> binder.bind(CleanupTasksPerformer.class).asEagerSingleton()))
+            .overrideWith(overrideModules.build());
     }
 
 }
diff --git a/server/container/guice/memory-guice/src/test/java/org/apache/james/GuiceJamesServerStartUpCheckTest.java b/server/container/guice/memory-guice/src/test/java/org/apache/james/GuiceJamesServerStartUpCheckTest.java
index 1301a25..ad40b24 100644
--- a/server/container/guice/memory-guice/src/test/java/org/apache/james/GuiceJamesServerStartUpCheckTest.java
+++ b/server/container/guice/memory-guice/src/test/java/org/apache/james/GuiceJamesServerStartUpCheckTest.java
@@ -115,19 +115,21 @@ class GuiceJamesServerStartUpCheckTest {
         }
     }
 
+    private static JamesServerBuilder extensionBuilder() {
+        return new JamesServerBuilder()
+            .server(configuration -> GuiceJamesServer.forConfiguration(configuration)
+                .combineWith(MemoryJamesServerMain.IN_MEMORY_SERVER_AGGREGATE_MODULE)
+                .overrideWith(new TestJMAPServerModule(LIMIT_TO_10_MESSAGES)))
+            .disableAutoStart();
+    }
+
     @Nested
     class WithStartUpCheckDoesntRequireGuiceComponents implements StartUpCheckSuccessContract {
 
         @RegisterExtension
-        JamesServerExtension jamesServerExtension = new JamesServerBuilder()
-            .server(configuration -> GuiceJamesServer.forConfiguration(configuration)
-                .combineWith(MemoryJamesServerMain.IN_MEMORY_SERVER_AGGREGATE_MODULE)
-                .overrideWith(new TestJMAPServerModule(LIMIT_TO_10_MESSAGES))
-                .overrideWith(binder -> binder.bind(TextExtractor.class).to(PDFTextExtractor.class))
-                .overrideWith(binder -> Multibinder
-                    .newSetBinder(binder, StartUpCheck.class)
-                    .addBinding().to(NoopStartUpCheck.class)))
-            .disableAutoStart()
+        JamesServerExtension jamesServerExtension = extensionBuilder()
+            .overrideServerModule(binder -> Multibinder.newSetBinder(binder, StartUpCheck.class)
+                .addBinding().to(NoopStartUpCheck.class))
             .build();
     }
 
@@ -135,15 +137,9 @@ class GuiceJamesServerStartUpCheckTest {
     class WithStartUpCheckRequireGuiceComponents implements StartUpCheckSuccessContract {
 
         @RegisterExtension
-        JamesServerExtension jamesServerExtension = new JamesServerBuilder()
-            .server(configuration -> GuiceJamesServer.forConfiguration(configuration)
-                .combineWith(MemoryJamesServerMain.IN_MEMORY_SERVER_AGGREGATE_MODULE)
-                .overrideWith(new TestJMAPServerModule(LIMIT_TO_10_MESSAGES))
-                .overrideWith(binder -> binder.bind(TextExtractor.class).to(PDFTextExtractor.class))
-                .overrideWith(binder -> Multibinder
-                    .newSetBinder(binder, StartUpCheck.class)
-                    .addBinding().to(TestBlobExportMechanismStartUpCheck.class)))
-            .disableAutoStart()
+        JamesServerExtension jamesServerExtension = extensionBuilder()
+            .overrideServerModule(binder -> Multibinder.newSetBinder(binder, StartUpCheck.class)
+                .addBinding().to(TestBlobExportMechanismStartUpCheck.class))
             .build();
     }
 
@@ -151,32 +147,21 @@ class GuiceJamesServerStartUpCheckTest {
     class WithNoStartUpCheck implements StartUpCheckSuccessContract {
 
         @RegisterExtension
-        JamesServerExtension jamesServerExtension = new JamesServerBuilder()
-            .server(configuration -> GuiceJamesServer.forConfiguration(configuration)
-                .combineWith(MemoryJamesServerMain.IN_MEMORY_SERVER_AGGREGATE_MODULE)
-                .overrideWith(new TestJMAPServerModule(LIMIT_TO_10_MESSAGES))
-                .overrideWith(binder -> binder.bind(TextExtractor.class).to(PDFTextExtractor.class)))
-            .disableAutoStart()
-            .build();
+        JamesServerExtension jamesServerExtension = extensionBuilder().build();
     }
 
     @Nested
     class StartUpCheckFails {
 
         @RegisterExtension
-        JamesServerExtension jamesServerExtension = new JamesServerBuilder()
-            .server(configuration -> GuiceJamesServer.forConfiguration(configuration)
-                .combineWith(MemoryJamesServerMain.IN_MEMORY_SERVER_AGGREGATE_MODULE)
-                .overrideWith(new TestJMAPServerModule(LIMIT_TO_10_MESSAGES))
-                .overrideWith(binder -> binder.bind(TextExtractor.class).to(PDFTextExtractor.class))
-                .overrideWith(binder -> {
+        JamesServerExtension jamesServerExtension = extensionBuilder()
+            .overrideServerModule(binder -> {
                     Multibinder<StartUpCheck> setBinder = Multibinder
                         .newSetBinder(binder, StartUpCheck.class);
 
                     setBinder.addBinding().to(NoopStartUpCheck.class);
                     setBinder.addBinding().to(FailingStartUpCheck.class);
-                }))
-            .disableAutoStart()
+                })
             .build();
 
         @Test
diff --git a/server/container/guice/memory-guice/src/test/java/org/apache/james/GuiceJamesServerTest.java b/server/container/guice/memory-guice/src/test/java/org/apache/james/GuiceJamesServerTest.java
index 7c9831a..6e49658 100644
--- a/server/container/guice/memory-guice/src/test/java/org/apache/james/GuiceJamesServerTest.java
+++ b/server/container/guice/memory-guice/src/test/java/org/apache/james/GuiceJamesServerTest.java
@@ -24,16 +24,18 @@ class GuiceJamesServerTest {
 
     private static final int LIMIT_TO_10_MESSAGES = 10;
 
+    private static JamesServerBuilder extensionBuilder() {
+        return new JamesServerBuilder()
+            .server(configuration -> GuiceJamesServer.forConfiguration(configuration)
+                .combineWith(MemoryJamesServerMain.IN_MEMORY_SERVER_AGGREGATE_MODULE)
+                .overrideWith(new TestJMAPServerModule(LIMIT_TO_10_MESSAGES)))
+            .disableAutoStart();
+    }
+
     @Nested
     class NormalBehaviour {
         @RegisterExtension
-        JamesServerExtension jamesServerExtension = new JamesServerBuilder()
-            .server(configuration -> GuiceJamesServer.forConfiguration(configuration)
-                .combineWith(MemoryJamesServerMain.IN_MEMORY_SERVER_AGGREGATE_MODULE)
-                .overrideWith(new TestJMAPServerModule(LIMIT_TO_10_MESSAGES))
-                .overrideWith(binder -> binder.bind(TextExtractor.class).to(PDFTextExtractor.class)))
-            .disableAutoStart()
-            .build();
+        JamesServerExtension jamesServerExtension = extensionBuilder().build();
 
         @Test
         void serverShouldBeStartedAfterCallingStart(GuiceJamesServer server) throws Exception {
@@ -72,15 +74,10 @@ class GuiceJamesServerTest {
         };
 
         @RegisterExtension
-        JamesServerExtension jamesServerExtension = new JamesServerBuilder()
-            .server(configuration -> GuiceJamesServer.forConfiguration(configuration)
-                .combineWith(MemoryJamesServerMain.IN_MEMORY_SERVER_AGGREGATE_MODULE)
-                .overrideWith(new TestJMAPServerModule(LIMIT_TO_10_MESSAGES))
-                .overrideWith(binder -> binder.bind(TextExtractor.class).to(PDFTextExtractor.class))
-                .overrideWith(binder -> Multibinder.newSetBinder(binder, ConfigurationPerformer.class)
-                    .addBinding()
-                    .toInstance(throwingConfigurationPerformer)))
-            .disableAutoStart()
+        JamesServerExtension jamesServerExtension = extensionBuilder()
+            .overrideServerModule(binder -> Multibinder.newSetBinder(binder, ConfigurationPerformer.class)
+                .addBinding()
+                .toInstance(throwingConfigurationPerformer))
             .build();
 
         @Test
diff --git a/server/container/guice/memory-guice/src/test/java/org/apache/james/GuiceLifecycleHeathCheckTest.java b/server/container/guice/memory-guice/src/test/java/org/apache/james/GuiceLifecycleHeathCheckTest.java
index aeff8dd..7e3878c 100644
--- a/server/container/guice/memory-guice/src/test/java/org/apache/james/GuiceLifecycleHeathCheckTest.java
+++ b/server/container/guice/memory-guice/src/test/java/org/apache/james/GuiceLifecycleHeathCheckTest.java
@@ -50,6 +50,15 @@ import reactor.core.scheduler.Schedulers;
 class GuiceLifecycleHeathCheckTest {
     private static final int LIMIT_TO_10_MESSAGES = 10;
 
+    private static JamesServerBuilder extensionBuilder() {
+        return new JamesServerBuilder()
+            .server(configuration -> GuiceJamesServer.forConfiguration(configuration)
+                .combineWith(MemoryJamesServerMain.IN_MEMORY_SERVER_AGGREGATE_MODULE)
+                .overrideWith(new TestJMAPServerModule(LIMIT_TO_10_MESSAGES))
+                .overrideWith(binder -> binder.bind(WebAdminConfiguration.class)
+                    .toInstance(WebAdminConfiguration.TEST_CONFIGURATION)));
+    }
+
     private static void configureRequestSpecification(GuiceJamesServer server) {
         WebAdminGuiceProbe webAdminGuiceProbe = server.getProbe(WebAdminGuiceProbe.class);
 
@@ -64,13 +73,7 @@ class GuiceLifecycleHeathCheckTest {
     @Nested
     class Healthy {
         @RegisterExtension
-        JamesServerExtension jamesServerExtension = new JamesServerBuilder()
-            .server(configuration -> GuiceJamesServer.forConfiguration(configuration)
-                .combineWith(MemoryJamesServerMain.IN_MEMORY_SERVER_AGGREGATE_MODULE)
-                .overrideWith(new TestJMAPServerModule(LIMIT_TO_10_MESSAGES))
-                .overrideWith(binder -> binder.bind(TextExtractor.class).to(PDFTextExtractor.class))
-                .overrideWith(binder -> binder.bind(WebAdminConfiguration.class).toInstance(WebAdminConfiguration.TEST_CONFIGURATION)))
-            .build();
+        JamesServerExtension jamesServerExtension = extensionBuilder().build();
 
         @Test
         void startedJamesServerShouldBeHealthy(GuiceJamesServer server) {
@@ -108,14 +111,9 @@ class GuiceLifecycleHeathCheckTest {
         CountDownLatch latch = new CountDownLatch(1);
 
         @RegisterExtension
-        JamesServerExtension jamesServerExtension = new JamesServerBuilder()
-            .server(configuration -> GuiceJamesServer.forConfiguration(configuration)
-                .combineWith(MemoryJamesServerMain.IN_MEMORY_SERVER_AGGREGATE_MODULE)
-                .overrideWith(new TestJMAPServerModule(LIMIT_TO_10_MESSAGES))
-                .overrideWith(binder -> binder.bind(TextExtractor.class).to(PDFTextExtractor.class))
-                .overrideWith(binder -> binder.bind(WebAdminConfiguration.class).toInstance(WebAdminConfiguration.TEST_CONFIGURATION))
-                .overrideWith(binder -> binder.bind(CountDownLatch.class).toInstance(latch))
-                .overrideWith(binder -> binder.bind(DestroyedBeforeWebAdmin.class).asEagerSingleton()))
+        JamesServerExtension jamesServerExtension = extensionBuilder()
+            .overrideServerModule(binder -> binder.bind(CountDownLatch.class).toInstance(latch))
+            .overrideServerModule(binder -> binder.bind(DestroyedBeforeWebAdmin.class).asEagerSingleton())
             .build();
 
         @Test
diff --git a/server/container/guice/memory-guice/src/test/java/org/apache/james/MemoryJmapJamesServerTest.java b/server/container/guice/memory-guice/src/test/java/org/apache/james/MemoryJmapJamesServerTest.java
index 2b0469a..26eae94 100644
--- a/server/container/guice/memory-guice/src/test/java/org/apache/james/MemoryJmapJamesServerTest.java
+++ b/server/container/guice/memory-guice/src/test/java/org/apache/james/MemoryJmapJamesServerTest.java
@@ -34,16 +34,18 @@ class MemoryJmapJamesServerTest {
 
     private static final int LIMIT_TO_10_MESSAGES = 10;
 
-    @Nested
-    class JmapJamesServerTest implements JmapJamesServerContract {
-
-        @RegisterExtension
-        JamesServerExtension jamesServerExtension = new JamesServerBuilder()
+    private static JamesServerBuilder extensionBuilder() {
+        return new JamesServerBuilder()
             .server(configuration -> GuiceJamesServer.forConfiguration(configuration)
                 .combineWith(MemoryJamesServerMain.IN_MEMORY_SERVER_AGGREGATE_MODULE)
                 .overrideWith(new TestJMAPServerModule(LIMIT_TO_10_MESSAGES))
-                .overrideWith(DOMAIN_LIST_CONFIGURATION_MODULE))
-            .build();
+                .overrideWith(DOMAIN_LIST_CONFIGURATION_MODULE));
+    }
+
+    @Nested
+    class JmapJamesServerTest implements JmapJamesServerContract {
+        @RegisterExtension
+        JamesServerExtension jamesServerExtension = extensionBuilder().build();
     }
 
     @Nested
@@ -53,18 +55,14 @@ class MemoryJmapJamesServerTest {
         class BadAliasKeyStore {
 
             @RegisterExtension
-            JamesServerExtension jamesServerExtension = new JamesServerBuilder()
-                .server(configuration -> GuiceJamesServer.forConfiguration(configuration)
-                    .combineWith(MemoryJamesServerMain.IN_MEMORY_SERVER_AGGREGATE_MODULE)
-                    .overrideWith(new TestJMAPServerModule(LIMIT_TO_10_MESSAGES))
-                    .overrideWith(DOMAIN_LIST_CONFIGURATION_MODULE)
-                    .overrideWith(binder -> binder.bind(JMAPConfiguration.class)
-                        .toInstance(TestJMAPServerModule
-                            .jmapConfigurationBuilder()
-                            .keystore("badAliasKeystore")
-                            .secret("password")
-                            .build())))
+            JamesServerExtension jamesServerExtension = extensionBuilder()
                 .disableAutoStart()
+                .overrideServerModule(binder -> binder.bind(JMAPConfiguration.class)
+                    .toInstance(TestJMAPServerModule
+                        .jmapConfigurationBuilder()
+                        .keystore("badAliasKeystore")
+                        .secret("password")
+                        .build()))
                 .build();
 
             @Test
@@ -82,17 +80,13 @@ class MemoryJmapJamesServerTest {
         class BadSecretKeyStore {
 
             @RegisterExtension
-            JamesServerExtension jamesServerExtension = new JamesServerBuilder()
-                .server(configuration -> GuiceJamesServer.forConfiguration(configuration)
-                    .combineWith(MemoryJamesServerMain.IN_MEMORY_SERVER_AGGREGATE_MODULE)
-                    .overrideWith(new TestJMAPServerModule(LIMIT_TO_10_MESSAGES))
-                    .overrideWith(DOMAIN_LIST_CONFIGURATION_MODULE)
-                    .overrideWith(binder -> binder.bind(JMAPConfiguration.class)
-                        .toInstance(TestJMAPServerModule
-                            .jmapConfigurationBuilder()
-                            .secret("WrongSecret")
-                            .build())))
+            JamesServerExtension jamesServerExtension = extensionBuilder()
                 .disableAutoStart()
+                .overrideServerModule(binder -> binder.bind(JMAPConfiguration.class)
+                    .toInstance(TestJMAPServerModule
+                        .jmapConfigurationBuilder()
+                        .secret("WrongSecret")
+                        .build()))
                 .build();
 
             @Test
diff --git a/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPConfigurationStartUpCheck.java b/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPConfigurationStartUpCheck.java
index 158d4fc..765b723 100644
--- a/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPConfigurationStartUpCheck.java
+++ b/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPConfigurationStartUpCheck.java
@@ -32,14 +32,27 @@ public class JMAPConfigurationStartUpCheck implements StartUpCheck {
     public static final String CHECK_NAME = "JMAPConfigurationStartUpCheck";
 
     private final SecurityKeyLoader securityKeyLoader;
+    private final JMAPConfiguration jmapConfiguration;
 
     @Inject
-    JMAPConfigurationStartUpCheck(SecurityKeyLoader securityKeyLoader) {
+    JMAPConfigurationStartUpCheck(SecurityKeyLoader securityKeyLoader, JMAPConfiguration jmapConfiguration) {
         this.securityKeyLoader = securityKeyLoader;
+        this.jmapConfiguration = jmapConfiguration;
     }
 
     @Override
     public CheckResult check() {
+        if (jmapConfiguration.isEnabled()) {
+            return checkSecurityKey();
+        }
+
+        return CheckResult.builder()
+            .checkName(checkName())
+            .resultType(ResultType.GOOD)
+            .build();
+    }
+
+    private CheckResult checkSecurityKey() {
         try {
             securityKeyLoader.load();
             return CheckResult.builder()
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/SecurityKeyLoader.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/SecurityKeyLoader.java
index 0bb359c..4ec4ab6 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/SecurityKeyLoader.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/SecurityKeyLoader.java
@@ -34,6 +34,7 @@ import org.apache.james.filesystem.api.FileSystem;
 import org.apache.james.jmap.JMAPConfiguration;
 
 import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
 
 public class SecurityKeyLoader {
 
@@ -51,6 +52,8 @@ public class SecurityKeyLoader {
     }
 
     public AsymmetricKeys load() throws Exception {
+        Preconditions.checkState(jmapConfiguration.isEnabled(), "JMAP is not enabled");
+
         KeyStore keystore = KeyStore.getInstance(JKS);
         InputStream fis = fileSystem.getResource(jmapConfiguration.getKeystore());
         char[] secret = jmapConfiguration.getSecret().toCharArray();
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SecurityKeyLoaderTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SecurityKeyLoaderTest.java
index 8c5675a..8eccdaa 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SecurityKeyLoaderTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SecurityKeyLoaderTest.java
@@ -36,6 +36,24 @@ import org.junit.jupiter.params.provider.ValueSource;
 class SecurityKeyLoaderTest {
 
     @Test
+    void loadShouldThrowWhenJMAPIsNotEnabled() throws Exception {
+        JMAPConfiguration jmapConfiguration = JMAPConfiguration.builder()
+            .disable()
+            .jwtPublicKeyPem(Optional.of(JWT_PUBLIC_KEY))
+            .keystore("keystore")
+            .secret("james72laBalle")
+            .build();
+
+        SecurityKeyLoader loader = new SecurityKeyLoader(
+            FileSystemFixture.CLASSPATH_FILE_SYSTEM,
+            jmapConfiguration);
+
+        assertThatThrownBy(loader::load)
+            .isInstanceOf(RuntimeException.class)
+            .hasMessage("JMAP is not enabled");
+    }
+
+    @Test
     void loadShouldThrowWhenWrongKeystore() throws Exception {
         JMAPConfiguration jmapConfiguration = JMAPConfiguration.builder()
             .enable()
@@ -72,7 +90,7 @@ class SecurityKeyLoaderTest {
     }
 
     @Test
-    void loadShouldReturnSecurityKeysWhenCorrectPassword() throws Exception {
+    void loadShouldReturnAsymmetricKeysWhenCorrectPassword() throws Exception {
         JMAPConfiguration jmapConfiguration = JMAPConfiguration.builder()
             .enable()
             .jwtPublicKeyPem(Optional.of(JWT_PUBLIC_KEY))
@@ -93,7 +111,7 @@ class SecurityKeyLoaderTest {
         "keystoreJava7",
         "keystoreJava11",
     })
-    void loadShouldReturnSecurityKeysWhenUsingKeyStoreGeneratedByDifferentJavaVersions(
+    void loadShouldReturnAsymmetricKeysWhenUsingKeyStoreGeneratedByDifferentJavaVersions(
         String keyStoreInDifferentVersion) throws Exception {
 
         JMAPConfiguration jmapConfiguration = JMAPConfiguration.builder()


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[james-project] 01/09: MAILET-136 James SMTP doesn't create new user or mailbox when doing domain re routing

Posted by bt...@apache.org.
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 74988eb7e7cb8f48c7b1a336162ba833cb0ada50
Author: Tran Tien Duc <dt...@linagora.com>
AuthorDate: Wed Jun 5 15:39:36 2019 +0700

    MAILET-136 James SMTP doesn't create new user or mailbox when doing domain re routing
---
 .../RecipientRewriteTableIntegrationTest.java      | 30 +++++++++++++++++++++-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/server/mailet/integration-testing/src/test/java/org/apache/james/mailets/RecipientRewriteTableIntegrationTest.java b/server/mailet/integration-testing/src/test/java/org/apache/james/mailets/RecipientRewriteTableIntegrationTest.java
index 34cd1d2..0a12f0a 100644
--- a/server/mailet/integration-testing/src/test/java/org/apache/james/mailets/RecipientRewriteTableIntegrationTest.java
+++ b/server/mailet/integration-testing/src/test/java/org/apache/james/mailets/RecipientRewriteTableIntegrationTest.java
@@ -25,6 +25,7 @@ import static org.apache.james.mailets.configuration.Constants.PASSWORD;
 import static org.apache.james.mailets.configuration.Constants.awaitAtMostOneMinute;
 import static org.assertj.core.api.Assertions.assertThat;
 
+import org.apache.james.modules.MailboxProbeImpl;
 import org.apache.james.modules.protocols.ImapGuiceProbe;
 import org.apache.james.modules.protocols.SmtpGuiceProbe;
 import org.apache.james.probe.DataProbe;
@@ -176,7 +177,6 @@ public class RecipientRewriteTableIntegrationTest {
     @Test
     public void messageShouldNotSendToRecipientWhenDomainMapping() throws Exception {
         dataProbe.addDomainAliasMapping(DEFAULT_DOMAIN, JAMES_ANOTHER_DOMAIN);
-        dataProbe.addUser(ANY_AT_ANOTHER_DOMAIN, PASSWORD);
 
         messageSender.connect(LOCALHOST_IP, jamesServer.getProbe(SmtpGuiceProbe.class).getSmtpPort())
             .sendMessage(FROM, ANY_AT_JAMES);
@@ -222,4 +222,32 @@ public class RecipientRewriteTableIntegrationTest {
             .awaitMessage(awaitAtMostOneMinute);
         assertThat(imapMessageReader.readFirstMessage()).isNotNull();
     }
+
+    @Test
+    public void domainAliasMappingShouldNotCreateNonExistedUserWhenReRouting() throws Exception {
+        dataProbe.addDomain("domain1.com");
+        dataProbe.addDomain("domain2.com");
+
+        // domain2 as the source, domain1 as the destination
+        dataProbe.addDomainAliasMapping("domain2.com", "domain1.com");
+
+        dataProbe.addUser("user@domain1.com", PASSWORD);
+
+        messageSender.connect(LOCALHOST_IP, jamesServer.getProbe(SmtpGuiceProbe.class).getSmtpPort())
+            .sendMessage(FROM, "user@domain2.com");
+
+        imapMessageReader.connect(LOCALHOST_IP, jamesServer.getProbe(ImapGuiceProbe.class).getImapPort())
+            .login("user@domain1.com", PASSWORD)
+            .select(IMAPMessageReader.INBOX)
+            .awaitMessage(awaitAtMostOneMinute);
+
+        // assert user  non existence
+        assertThat(dataProbe.listUsers())
+            .doesNotContain("user@domain2.com");
+
+        // assert alias address has no mailbox
+        assertThat(jamesServer.getProbe(MailboxProbeImpl.class)
+            .listUserMailboxes("user@doamin2.com"))
+            .isEmpty();
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[james-project] 05/09: JAMES-2146 Refactor Jmap signature handler

Posted by bt...@apache.org.
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 41553be8cde4501ce16de1bced01e9359d68e61e
Author: Tran Tien Duc <dt...@linagora.com>
AuthorDate: Thu Jun 6 11:05:11 2019 +0700

    JAMES-2146 Refactor Jmap signature handler
---
 .../james/jmap/crypto/JamesSignatureHandler.java   | 42 ++++---------------
 ...ider.java => JamesSignatureHandlerFixture.java} | 48 +++++-----------------
 .../jmap/crypto/JamesSignatureHandlerTest.java     | 18 +-------
 .../james/jmap/crypto/SecurityKeyLoaderTest.java   | 11 +----
 .../james/jmap/crypto/SignedTokenFactoryTest.java  |  3 +-
 .../james/jmap/crypto/SignedTokenManagerTest.java  |  3 +-
 6 files changed, 24 insertions(+), 101 deletions(-)

diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/JamesSignatureHandler.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/JamesSignatureHandler.java
index 82ee210..69b2441 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/JamesSignatureHandler.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/JamesSignatureHandler.java
@@ -19,24 +19,14 @@
 
 package org.apache.james.jmap.crypto;
 
-import java.io.InputStream;
 import java.security.InvalidKeyException;
-import java.security.Key;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
 import java.security.NoSuchAlgorithmException;
-import java.security.PrivateKey;
-import java.security.PublicKey;
 import java.security.Signature;
 import java.security.SignatureException;
-import java.security.cert.Certificate;
 import java.util.Base64;
-import java.util.Optional;
 
 import javax.inject.Inject;
 
-import org.apache.james.filesystem.api.FileSystem;
-import org.apache.james.jmap.JMAPConfiguration;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -47,39 +37,21 @@ public class JamesSignatureHandler implements SignatureHandler {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(JamesSignatureHandler.class);
 
-    public static final String ALIAS = "james";
     public static final String ALGORITHM = "SHA1withRSA";
-    public static final String JKS = "JKS";
 
-    private final FileSystem fileSystem;
-    private final JMAPConfiguration jmapConfiguration;
+    private final SecurityKeyLoader keyLoader;
 
-    private PrivateKey privateKey;
-    private PublicKey publicKey;
+    private AsymmetricKeys securityKeys;
 
 
     @Inject
-    @VisibleForTesting JamesSignatureHandler(FileSystem fileSystem, JMAPConfiguration jmapConfiguration) {
-        this.fileSystem = fileSystem;
-        this.jmapConfiguration = jmapConfiguration;
+    @VisibleForTesting JamesSignatureHandler(SecurityKeyLoader keyLoader) {
+        this.keyLoader = keyLoader;
     }
 
     @Override
     public void init() throws Exception {
-        KeyStore keystore = KeyStore.getInstance(JKS);
-        InputStream fis = fileSystem.getResource(jmapConfiguration.getKeystore());
-        char[] secret = jmapConfiguration.getSecret().toCharArray();
-        keystore.load(fis, secret);
-        Certificate aliasCertificate = Optional
-                .ofNullable(keystore.getCertificate(ALIAS))
-                .orElseThrow(() -> new KeyStoreException("Alias '" + ALIAS + "' keystore can't be found"));
-
-        publicKey = aliasCertificate.getPublicKey();
-        Key key = keystore.getKey(ALIAS, secret);
-        if (! (key instanceof PrivateKey)) {
-            throw new KeyStoreException("Provided key is not a PrivateKey");
-        }
-        privateKey = (PrivateKey) key;
+        securityKeys = keyLoader.load();
     }
 
     @Override
@@ -87,7 +59,7 @@ public class JamesSignatureHandler implements SignatureHandler {
         Preconditions.checkNotNull(source);
         try {
             Signature javaSignature = Signature.getInstance(ALGORITHM);
-            javaSignature.initSign(privateKey);
+            javaSignature.initSign(securityKeys.getPrivateKey());
             javaSignature.update(source.getBytes());
             return Base64.getEncoder().encodeToString(javaSignature.sign());
         } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) {
@@ -101,7 +73,7 @@ public class JamesSignatureHandler implements SignatureHandler {
         Preconditions.checkNotNull(signature);
         try {
             Signature javaSignature = Signature.getInstance(ALGORITHM);
-            javaSignature.initVerify(publicKey);
+            javaSignature.initVerify(securityKeys.getPublicKey());
             javaSignature.update(source.getBytes());
             return javaSignature.verify(Base64.getDecoder().decode(signature));
         } catch (NoSuchAlgorithmException | InvalidKeyException e) {
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/JamesSignatureHandlerProvider.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/JamesSignatureHandlerFixture.java
similarity index 58%
rename from server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/JamesSignatureHandlerProvider.java
rename to server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/JamesSignatureHandlerFixture.java
index c531581..392f50f 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/JamesSignatureHandlerProvider.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/JamesSignatureHandlerFixture.java
@@ -19,19 +19,13 @@
 
 package org.apache.james.jmap.crypto;
 
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
 import java.util.Optional;
 
-import org.apache.james.filesystem.api.FileSystem;
 import org.apache.james.jmap.JMAPConfiguration;
-import org.apache.james.jmap.JMAPConfiguration.Builder;
 
-public class JamesSignatureHandlerProvider {
+class JamesSignatureHandlerFixture {
 
-    private static final String JWT_PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----\n" +
+    static final String JWT_PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----\n" +
         "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtlChO/nlVP27MpdkG0Bh\n" +
         "16XrMRf6M4NeyGa7j5+1UKm42IKUf3lM28oe82MqIIRyvskPc11NuzSor8HmvH8H\n" +
         "lhDs5DyJtx2qp35AT0zCqfwlaDnlDc/QDlZv1CoRZGpQk1Inyh6SbZwYpxxwh0fi\n" +
@@ -41,41 +35,19 @@ public class JamesSignatureHandlerProvider {
         "kwIDAQAB\n" +
         "-----END PUBLIC KEY-----";
 
-    public JamesSignatureHandlerProvider() {
-    }
-
-    public JamesSignatureHandler provide() throws Exception {
-        JamesSignatureHandler signatureHandler = new JamesSignatureHandler(newFileSystem(),
-                newConfigurationBuilder().build());
-        signatureHandler.init();
-        return signatureHandler;
-    }
+    static JamesSignatureHandler defaultSignatureHandler() {
 
-    public static Builder newConfigurationBuilder() {
-        return JMAPConfiguration.builder()
+        JMAPConfiguration jmapConfiguration = JMAPConfiguration.builder()
             .enable()
+            .jwtPublicKeyPem(Optional.of(JWT_PUBLIC_KEY))
             .keystore("keystore")
             .secret("james72laBalle")
-            .jwtPublicKeyPem(Optional.of(JWT_PUBLIC_KEY));
-    }
-
-    public static FileSystem newFileSystem() {
-        return new FileSystem() {
-            @Override
-            public InputStream getResource(String url) throws IOException {
-                return ClassLoader.getSystemResourceAsStream(url);
-            }
+            .build();
 
-            @Override
-            public File getFile(String fileURL) throws FileNotFoundException {
-                return null;
-            }
+        SecurityKeyLoader loader = new SecurityKeyLoader(
+            new ClassLoaderFileSystem(),
+            jmapConfiguration);
 
-            @Override
-            public File getBasedir() throws FileNotFoundException {
-                return null;
-            }
-        };
+        return new JamesSignatureHandler(loader);
     }
-
 }
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/JamesSignatureHandlerTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/JamesSignatureHandlerTest.java
index 8dc44de..5b3e4a2 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/JamesSignatureHandlerTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/JamesSignatureHandlerTest.java
@@ -21,9 +21,6 @@ package org.apache.james.jmap.crypto;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
-import java.security.KeyStoreException;
-
-import org.apache.james.jmap.JMAPConfiguration;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -37,19 +34,8 @@ public class JamesSignatureHandlerTest {
 
     @Before
     public void setUp() throws Exception {
-       signatureHandler = new JamesSignatureHandlerProvider().provide();
-    }
-
-    @Test(expected = KeyStoreException.class)
-    public void initShouldThrowOnUnknownKeystore() throws Exception {
-        JMAPConfiguration jmapConfiguration = JamesSignatureHandlerProvider.newConfigurationBuilder()
-            .keystore("badAliasKeystore")
-            .secret("password")
-            .build();
-
-        JamesSignatureHandler signatureHandler = new JamesSignatureHandler(JamesSignatureHandlerProvider.newFileSystem(),
-                jmapConfiguration);
-        signatureHandler.init();
+       signatureHandler = JamesSignatureHandlerFixture.defaultSignatureHandler();
+       signatureHandler.init();
     }
 
     @Test
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SecurityKeyLoaderTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SecurityKeyLoaderTest.java
index 63c1acb..152f672 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SecurityKeyLoaderTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SecurityKeyLoaderTest.java
@@ -19,6 +19,7 @@
 
 package org.apache.james.jmap.crypto;
 
+import static org.apache.james.jmap.crypto.JamesSignatureHandlerFixture.JWT_PUBLIC_KEY;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
@@ -31,16 +32,6 @@ import org.junit.jupiter.api.Test;
 
 class SecurityKeyLoaderTest {
 
-    private static final String JWT_PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----\n" +
-        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtlChO/nlVP27MpdkG0Bh\n" +
-        "16XrMRf6M4NeyGa7j5+1UKm42IKUf3lM28oe82MqIIRyvskPc11NuzSor8HmvH8H\n" +
-        "lhDs5DyJtx2qp35AT0zCqfwlaDnlDc/QDlZv1CoRZGpQk1Inyh6SbZwYpxxwh0fi\n" +
-        "+d/4RpE3LBVo8wgOaXPylOlHxsDizfkL8QwXItyakBfMO6jWQRrj7/9WDhGf4Hi+\n" +
-        "GQur1tPGZDl9mvCoRHjFrD5M/yypIPlfMGWFVEvV5jClNMLAQ9bYFuOc7H1fEWw6\n" +
-        "U1LZUUbJW9/CH45YXz82CYqkrfbnQxqRb2iVbVjs/sHopHd1NTiCfUtwvcYJiBVj\n" +
-        "kwIDAQAB\n" +
-        "-----END PUBLIC KEY-----";
-
     @Test
     void loadShouldThrowWhenWrongKeystore() throws Exception {
         JMAPConfiguration jmapConfiguration = JMAPConfiguration.builder()
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SignedTokenFactoryTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SignedTokenFactoryTest.java
index dfe8c18..12d8aa9 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SignedTokenFactoryTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SignedTokenFactoryTest.java
@@ -39,7 +39,8 @@ public class SignedTokenFactoryTest {
 
     @Before
     public void setUp() throws Exception {
-        JamesSignatureHandler signatureHandler = new JamesSignatureHandlerProvider().provide();
+        JamesSignatureHandler signatureHandler = JamesSignatureHandlerFixture.defaultSignatureHandler();
+        signatureHandler.init();
         zonedDateTimeProvider = new FixedDateZonedDateTimeProvider();
         toKenFactory = new SignedTokenFactory(signatureHandler, zonedDateTimeProvider);
     }
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SignedTokenManagerTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SignedTokenManagerTest.java
index b31f0df..6614fde 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SignedTokenManagerTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SignedTokenManagerTest.java
@@ -44,7 +44,8 @@ public class SignedTokenManagerTest {
 
     @Before
     public void setUp() throws Exception {
-        JamesSignatureHandler signatureHandler = new JamesSignatureHandlerProvider().provide();
+        JamesSignatureHandler signatureHandler = JamesSignatureHandlerFixture.defaultSignatureHandler();
+        signatureHandler.init();
         zonedDateTimeProvider = new FixedDateZonedDateTimeProvider();
         tokenManager = new SignedTokenManager(signatureHandler, zonedDateTimeProvider);
         tokenFactory = new SignedTokenFactory(signatureHandler, zonedDateTimeProvider);


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[james-project] 07/09: JAMES-2146 Reuse FileSystemFixture in jmap tests

Posted by bt...@apache.org.
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 2fc2a8ba61567096b9011e6791c745fcca53d630
Author: Tran Tien Duc <dt...@linagora.com>
AuthorDate: Thu Jun 6 12:13:43 2019 +0700

    JAMES-2146 Reuse FileSystemFixture in jmap tests
---
 server/protocols/jmap/pom.xml                      |  6 +++
 .../james/jmap/crypto/ClassLoaderFileSystem.java   | 45 ----------------------
 .../jmap/crypto/JamesSignatureHandlerFixture.java  |  3 +-
 .../james/jmap/crypto/SecurityKeyLoaderTest.java   |  7 ++--
 4 files changed, 12 insertions(+), 49 deletions(-)

diff --git a/server/protocols/jmap/pom.xml b/server/protocols/jmap/pom.xml
index fb6df6a..eb622e6 100644
--- a/server/protocols/jmap/pom.xml
+++ b/server/protocols/jmap/pom.xml
@@ -115,6 +115,12 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>james-server-filesystem-api</artifactId>
+            <scope>test</scope>
+            <type>test-jar</type>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>james-server-jetty</artifactId>
         </dependency>
         <dependency>
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/ClassLoaderFileSystem.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/ClassLoaderFileSystem.java
deleted file mode 100644
index 43687e4..0000000
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/ClassLoaderFileSystem.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/****************************************************************
- * 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.jmap.crypto;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.apache.james.filesystem.api.FileSystem;
-
-class ClassLoaderFileSystem implements FileSystem {
-
-    @Override
-    public InputStream getResource(String url) throws IOException {
-        return ClassLoader.getSystemResourceAsStream(url);
-    }
-
-    @Override
-    public File getFile(String fileURL) throws FileNotFoundException {
-        return null;
-    }
-
-    @Override
-    public File getBasedir() throws FileNotFoundException {
-        return null;
-    }
-}
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/JamesSignatureHandlerFixture.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/JamesSignatureHandlerFixture.java
index 392f50f..8becead 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/JamesSignatureHandlerFixture.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/JamesSignatureHandlerFixture.java
@@ -21,6 +21,7 @@ package org.apache.james.jmap.crypto;
 
 import java.util.Optional;
 
+import org.apache.james.filesystem.api.FileSystemFixture;
 import org.apache.james.jmap.JMAPConfiguration;
 
 class JamesSignatureHandlerFixture {
@@ -45,7 +46,7 @@ class JamesSignatureHandlerFixture {
             .build();
 
         SecurityKeyLoader loader = new SecurityKeyLoader(
-            new ClassLoaderFileSystem(),
+            FileSystemFixture.CLASSPATH_FILE_SYSTEM,
             jmapConfiguration);
 
         return new JamesSignatureHandler(loader);
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SecurityKeyLoaderTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SecurityKeyLoaderTest.java
index 152f672..c47f33f 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SecurityKeyLoaderTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SecurityKeyLoaderTest.java
@@ -27,6 +27,7 @@ import java.io.IOException;
 import java.security.KeyStoreException;
 import java.util.Optional;
 
+import org.apache.james.filesystem.api.FileSystemFixture;
 import org.apache.james.jmap.JMAPConfiguration;
 import org.junit.jupiter.api.Test;
 
@@ -42,7 +43,7 @@ class SecurityKeyLoaderTest {
             .build();
 
         SecurityKeyLoader loader = new SecurityKeyLoader(
-            new ClassLoaderFileSystem(),
+            FileSystemFixture.CLASSPATH_FILE_SYSTEM,
             jmapConfiguration);
 
         assertThatThrownBy(loader::load)
@@ -60,7 +61,7 @@ class SecurityKeyLoaderTest {
             .build();
 
         SecurityKeyLoader loader = new SecurityKeyLoader(
-            new ClassLoaderFileSystem(),
+            FileSystemFixture.CLASSPATH_FILE_SYSTEM,
             jmapConfiguration);
 
         assertThatThrownBy(loader::load)
@@ -78,7 +79,7 @@ class SecurityKeyLoaderTest {
             .build();
 
         SecurityKeyLoader loader = new SecurityKeyLoader(
-            new ClassLoaderFileSystem(),
+            FileSystemFixture.CLASSPATH_FILE_SYSTEM,
             jmapConfiguration);
 
         assertThat(loader.load())


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[james-project] 04/09: JAMES-2146 StartUpCheck for Jmap security configuration

Posted by bt...@apache.org.
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 d3c90a9e2551e43b79ae8e7605cfa232dc2f9628
Author: Tran Tien Duc <dt...@linagora.com>
AuthorDate: Thu Jun 6 10:56:41 2019 +0700

    JAMES-2146 StartUpCheck for Jmap security configuration
---
 .../apache/james/MemoryJmapJamesServerTest.java    |  93 ++++++++++++++++++---
 .../src/test/resources/badAliasKeystore            | Bin 0 -> 2246 bytes
 .../org/apache/james/jmap/JMAPCommonModule.java    |   5 ++
 .../james/jmap/JMAPConfigurationStartUpCheck.java  |  63 ++++++++++++++
 .../apache/james/modules/TestJMAPServerModule.java |  17 ++--
 5 files changed, 160 insertions(+), 18 deletions(-)

diff --git a/server/container/guice/memory-guice/src/test/java/org/apache/james/MemoryJmapJamesServerTest.java b/server/container/guice/memory-guice/src/test/java/org/apache/james/MemoryJmapJamesServerTest.java
index 47afa30..2b0469a 100644
--- a/server/container/guice/memory-guice/src/test/java/org/apache/james/MemoryJmapJamesServerTest.java
+++ b/server/container/guice/memory-guice/src/test/java/org/apache/james/MemoryJmapJamesServerTest.java
@@ -19,20 +19,91 @@
 
 package org.apache.james;
 
-import org.apache.james.mailbox.extractor.TextExtractor;
-import org.apache.james.mailbox.store.search.PDFTextExtractor;
+import static org.apache.james.JmapJamesServerContract.DOMAIN_LIST_CONFIGURATION_MODULE;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import org.apache.james.jmap.JMAPConfiguration;
+import org.apache.james.jmap.JMAPConfigurationStartUpCheck;
 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;
 
-class MemoryJmapJamesServerTest implements JmapJamesServerContract {
+class MemoryJmapJamesServerTest {
+
     private static final int LIMIT_TO_10_MESSAGES = 10;
 
-    @RegisterExtension
-    static JamesServerExtension jamesServerExtension = new JamesServerBuilder()
-        .server(configuration -> GuiceJamesServer.forConfiguration(configuration)
-            .combineWith(MemoryJamesServerMain.IN_MEMORY_SERVER_AGGREGATE_MODULE)
-            .overrideWith(new TestJMAPServerModule(LIMIT_TO_10_MESSAGES))
-            .overrideWith(binder -> binder.bind(TextExtractor.class).to(PDFTextExtractor.class))
-            .overrideWith(DOMAIN_LIST_CONFIGURATION_MODULE))
-        .build();
+    @Nested
+    class JmapJamesServerTest implements JmapJamesServerContract {
+
+        @RegisterExtension
+        JamesServerExtension jamesServerExtension = new JamesServerBuilder()
+            .server(configuration -> GuiceJamesServer.forConfiguration(configuration)
+                .combineWith(MemoryJamesServerMain.IN_MEMORY_SERVER_AGGREGATE_MODULE)
+                .overrideWith(new TestJMAPServerModule(LIMIT_TO_10_MESSAGES))
+                .overrideWith(DOMAIN_LIST_CONFIGURATION_MODULE))
+            .build();
+    }
+
+    @Nested
+    class JamesServerJmapConfigurationTest {
+
+        @Nested
+        class BadAliasKeyStore {
+
+            @RegisterExtension
+            JamesServerExtension jamesServerExtension = new JamesServerBuilder()
+                .server(configuration -> GuiceJamesServer.forConfiguration(configuration)
+                    .combineWith(MemoryJamesServerMain.IN_MEMORY_SERVER_AGGREGATE_MODULE)
+                    .overrideWith(new TestJMAPServerModule(LIMIT_TO_10_MESSAGES))
+                    .overrideWith(DOMAIN_LIST_CONFIGURATION_MODULE)
+                    .overrideWith(binder -> binder.bind(JMAPConfiguration.class)
+                        .toInstance(TestJMAPServerModule
+                            .jmapConfigurationBuilder()
+                            .keystore("badAliasKeystore")
+                            .secret("password")
+                            .build())))
+                .disableAutoStart()
+                .build();
+
+            @Test
+            void jamesShouldNotStartWhenBadAliasKeyStore(GuiceJamesServer server) {
+                assertThatThrownBy(server::start)
+                    .isInstanceOfSatisfying(
+                        StartUpChecksPerformer.StartUpChecksException.class,
+                        ex -> assertThat(ex.badCheckNames())
+                            .containsOnly(JMAPConfigurationStartUpCheck.CHECK_NAME))
+                    .hasMessageContaining("Alias 'james' keystore can't be found");
+            }
+        }
+
+        @Nested
+        class BadSecretKeyStore {
+
+            @RegisterExtension
+            JamesServerExtension jamesServerExtension = new JamesServerBuilder()
+                .server(configuration -> GuiceJamesServer.forConfiguration(configuration)
+                    .combineWith(MemoryJamesServerMain.IN_MEMORY_SERVER_AGGREGATE_MODULE)
+                    .overrideWith(new TestJMAPServerModule(LIMIT_TO_10_MESSAGES))
+                    .overrideWith(DOMAIN_LIST_CONFIGURATION_MODULE)
+                    .overrideWith(binder -> binder.bind(JMAPConfiguration.class)
+                        .toInstance(TestJMAPServerModule
+                            .jmapConfigurationBuilder()
+                            .secret("WrongSecret")
+                            .build())))
+                .disableAutoStart()
+                .build();
+
+            @Test
+            void jamesShouldNotStartWhenBadSecret(GuiceJamesServer server) {
+                assertThatThrownBy(server::start)
+                    .isInstanceOfSatisfying(
+                        StartUpChecksPerformer.StartUpChecksException.class,
+                        ex -> assertThat(ex.badCheckNames())
+                            .containsOnly(JMAPConfigurationStartUpCheck.CHECK_NAME))
+                    .hasMessageContaining("Keystore was tampered with, or password was incorrect");
+            }
+        }
+    }
 }
diff --git a/server/container/guice/memory-guice/src/test/resources/badAliasKeystore b/server/container/guice/memory-guice/src/test/resources/badAliasKeystore
new file mode 100644
index 0000000..0a4de22
Binary files /dev/null and b/server/container/guice/memory-guice/src/test/resources/badAliasKeystore differ
diff --git a/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPCommonModule.java b/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPCommonModule.java
index 9a44d3a..792b1e3 100644
--- a/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPCommonModule.java
+++ b/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPCommonModule.java
@@ -36,6 +36,7 @@ import org.apache.james.jmap.model.MessageFactory;
 import org.apache.james.jmap.model.MessagePreviewGenerator;
 import org.apache.james.jmap.send.MailSpool;
 import org.apache.james.jmap.utils.HeadersAuthenticationExtractor;
+import org.apache.james.lifecycle.api.StartUpCheck;
 import org.apache.james.util.date.DefaultZonedDateTimeProvider;
 import org.apache.james.util.date.ZonedDateTimeProvider;
 import org.apache.james.util.mime.MessageContentExtractor;
@@ -46,6 +47,7 @@ import com.google.common.collect.ImmutableList;
 import com.google.inject.AbstractModule;
 import com.google.inject.Provides;
 import com.google.inject.Scopes;
+import com.google.inject.multibindings.Multibinder;
 import com.google.inject.name.Names;
 
 public class JMAPCommonModule extends AbstractModule {
@@ -75,6 +77,9 @@ public class JMAPCommonModule extends AbstractModule {
 
         bindConstant().annotatedWith(Names.named(AccessTokenRepository.TOKEN_EXPIRATION_IN_MS)).to(DEFAULT_TOKEN_EXPIRATION_IN_MS);
         bind(AccessTokenManager.class).to(AccessTokenManagerImpl.class);
+
+        Multibinder.newSetBinder(binder(), StartUpCheck.class)
+            .addBinding().to(JMAPConfigurationStartUpCheck.class);
     }
 
     @Provides
diff --git a/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPConfigurationStartUpCheck.java b/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPConfigurationStartUpCheck.java
new file mode 100644
index 0000000..158d4fc
--- /dev/null
+++ b/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPConfigurationStartUpCheck.java
@@ -0,0 +1,63 @@
+/****************************************************************
+ * 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.jmap;
+
+import javax.inject.Inject;
+
+import org.apache.james.jmap.crypto.SecurityKeyLoader;
+import org.apache.james.lifecycle.api.StartUpCheck;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class JMAPConfigurationStartUpCheck implements StartUpCheck {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(JMAPConfigurationStartUpCheck.class);
+    public static final String CHECK_NAME = "JMAPConfigurationStartUpCheck";
+
+    private final SecurityKeyLoader securityKeyLoader;
+
+    @Inject
+    JMAPConfigurationStartUpCheck(SecurityKeyLoader securityKeyLoader) {
+        this.securityKeyLoader = securityKeyLoader;
+    }
+
+    @Override
+    public CheckResult check() {
+        try {
+            securityKeyLoader.load();
+            return CheckResult.builder()
+                .checkName(checkName())
+                .resultType(ResultType.GOOD)
+                .build();
+        } catch (Exception e) {
+            LOGGER.error("Cannot load security key from jmap configuration", e);
+            return CheckResult.builder()
+                .checkName(checkName())
+                .resultType(ResultType.BAD)
+                .description(e.getMessage())
+                .build();
+        }
+    }
+
+    @Override
+    public String checkName() {
+        return CHECK_NAME;
+    }
+}
diff --git a/server/container/guice/protocols/jmap/src/test/java/org/apache/james/modules/TestJMAPServerModule.java b/server/container/guice/protocols/jmap/src/test/java/org/apache/james/modules/TestJMAPServerModule.java
index a2f9313..ba78607 100644
--- a/server/container/guice/protocols/jmap/src/test/java/org/apache/james/modules/TestJMAPServerModule.java
+++ b/server/container/guice/protocols/jmap/src/test/java/org/apache/james/modules/TestJMAPServerModule.java
@@ -45,6 +45,15 @@ public class TestJMAPServerModule extends AbstractModule {
         + "kwIDAQAB\n"
         + "-----END PUBLIC KEY-----";
 
+    public static JMAPConfiguration.Builder jmapConfigurationBuilder() {
+        return JMAPConfiguration.builder()
+                .enable()
+                .keystore("keystore")
+                .secret("james72laBalle")
+                .jwtPublicKeyPem(Optional.of(PUBLIC_PEM_KEY))
+                .randomPort();
+    }
+
     private final long maximumLimit;
 
     public TestJMAPServerModule(long maximumLimit) {
@@ -59,12 +68,6 @@ public class TestJMAPServerModule extends AbstractModule {
     @Provides
     @Singleton
     JMAPConfiguration provideConfiguration() throws FileNotFoundException, ConfigurationException {
-        return JMAPConfiguration.builder()
-                .enable()
-                .keystore("keystore")
-                .secret("james72laBalle")
-                .jwtPublicKeyPem(Optional.of(PUBLIC_PEM_KEY))
-                .randomPort()
-                .build();
+        return jmapConfigurationBuilder().build();
     }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[james-project] 02/09: MAILET-136 James JMAP doesn't create new user or mailbox when doing domain re routing

Posted by bt...@apache.org.
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 d81197b9555ed2f48cdcf3650ad733fde275312b
Author: Tran Tien Duc <dt...@linagora.com>
AuthorDate: Tue Jun 11 11:24:01 2019 +0700

    MAILET-136 James JMAP doesn't create new user or mailbox when doing domain re routing
---
 .../CassandraSetMessagesMethodReRoutingTest.java   |  47 ++++
 .../org/apache/james/jmap/JmapCommonRequests.java  |  36 +++
 .../integration/GetMessageListMethodTest.java      |  34 +--
 .../SetMessagesMethodReRoutingTest.java            | 242 +++++++++++++++++++++
 .../methods/integration/SetMessagesMethodTest.java |  12 +-
 .../MemorySetMessagesMethodReRoutingTest.java      |  42 ++++
 ...abbitMQAwsS3SetMessagesMethodReRoutingTest.java |  48 ++++
 7 files changed, 438 insertions(+), 23 deletions(-)

diff --git a/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraSetMessagesMethodReRoutingTest.java b/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraSetMessagesMethodReRoutingTest.java
new file mode 100644
index 0000000..02dcbf8
--- /dev/null
+++ b/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraSetMessagesMethodReRoutingTest.java
@@ -0,0 +1,47 @@
+/****************************************************************
+ * 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.jmap.cassandra;
+
+import java.io.IOException;
+
+import org.apache.james.CassandraJmapTestRule;
+import org.apache.james.DockerCassandraRule;
+import org.apache.james.GuiceJamesServer;
+import org.apache.james.jmap.methods.integration.SetMessagesMethodReRoutingTest;
+import org.junit.Rule;
+
+public class CassandraSetMessagesMethodReRoutingTest extends SetMessagesMethodReRoutingTest {
+
+    @Rule
+    public DockerCassandraRule cassandra = new DockerCassandraRule();
+
+    @Rule
+    public CassandraJmapTestRule rule = CassandraJmapTestRule.defaultTestRule();
+
+    @Override
+    protected GuiceJamesServer createJmapServer() throws IOException {
+        return rule.jmapServer(cassandra.getModule());
+    }
+
+    @Override
+    protected void await() {
+        rule.await();
+    }
+}
diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/JmapCommonRequests.java b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/JmapCommonRequests.java
index 85e241f..7dd4c14 100644
--- a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/JmapCommonRequests.java
+++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/JmapCommonRequests.java
@@ -36,6 +36,7 @@ import org.apache.james.mailbox.Role;
 import org.apache.james.mailbox.model.MailboxId;
 
 import io.restassured.builder.ResponseSpecBuilder;
+import io.restassured.path.json.JsonPath;
 import io.restassured.specification.ResponseSpecification;
 
 public class JmapCommonRequests {
@@ -131,6 +132,41 @@ public class JmapCommonRequests {
                 .path(ARGUMENTS + ".messageIds[0]");
     }
 
+    public static String getLatestMessageId(AccessToken accessToken, Role mailbox) {
+        String inboxId = getMailboxId(accessToken, mailbox);
+        return with()
+                .header("Authorization", accessToken.serialize())
+                .body("[[\"getMessageList\", {\"filter\":{\"inMailboxes\":[\"" + inboxId + "\"]}, \"sort\":[\"date desc\"]}, \"#0\"]]")
+                .post("/jmap")
+            .then()
+                .extract()
+                .path(ARGUMENTS + ".messageIds[0]");
+    }
+
+    public static String bodyOfMessage(AccessToken accessToken, String messageId) {
+        return getMessageContent(accessToken, messageId)
+                .get(ARGUMENTS + ".list[0].textBody");
+    }
+
+    public static List<String> receiversOfMessage(AccessToken accessToken, String messageId) {
+        return getMessageContent(accessToken, messageId)
+                .getList(ARGUMENTS + ".list[0].to.email");
+    }
+
+    private static JsonPath getMessageContent(AccessToken accessToken, String messageId) {
+        return with()
+                .header("Authorization", accessToken.serialize())
+                .body("[[\"getMessages\", {\"ids\": [\"" + messageId + "\"]}, \"#0\"]]")
+            .when()
+                .post("/jmap")
+            .then()
+                .statusCode(200)
+                .body(NAME, equalTo("messages"))
+                .body(ARGUMENTS + ".list", hasSize(1))
+            .extract()
+                .jsonPath();
+    }
+
     public static List<String> listMessageIdsInMailbox(AccessToken accessToken, String mailboxId) {
         return with()
                 .header("Authorization", accessToken.serialize())
diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/GetMessageListMethodTest.java b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/GetMessageListMethodTest.java
index 1ac3d65..3c38c11 100644
--- a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/GetMessageListMethodTest.java
+++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/GetMessageListMethodTest.java
@@ -107,7 +107,7 @@ public abstract class GetMessageListMethodTest {
     private GuiceJamesServer jmapServer;
     private MailboxProbeImpl mailboxProbe;
     private DataProbe dataProbe;
-    
+
     @Before
     public void setup() throws Throwable {
         jmapServer = createJmapServer();
@@ -346,7 +346,7 @@ public abstract class GetMessageListMethodTest {
             .body(NAME, equalTo("messageList"))
             .body(ARGUMENTS + ".messageIds", hasSize(1));
     }
-    
+
     @Test
     public void getMessageListSetFlaggedFilterShouldResultFlaggedMessages() throws Exception {
         mailboxProbe.createMailbox(MailboxConstants.USER_NAMESPACE, ALICE, "mailbox");
@@ -367,7 +367,7 @@ public abstract class GetMessageListMethodTest {
             .statusCode(200)
             .body(NAME, equalTo("messageList"))
             .body(ARGUMENTS + ".messageIds", allOf(
-                    containsInAnyOrder(messageFlagged.getMessageId().serialize()), 
+                    containsInAnyOrder(messageFlagged.getMessageId().serialize()),
                     not(containsInAnyOrder(messageNotFlagged.getMessageId().serialize()))));
     }
 
@@ -391,7 +391,7 @@ public abstract class GetMessageListMethodTest {
             .statusCode(200)
             .body(NAME, equalTo("messageList"))
             .body(ARGUMENTS + ".messageIds", allOf(
-                    containsInAnyOrder(messageNotFlagged.getMessageId().serialize()), 
+                    containsInAnyOrder(messageNotFlagged.getMessageId().serialize()),
                     not(containsInAnyOrder(messageFlagged.getMessageId().serialize()))));
     }
 
@@ -415,7 +415,7 @@ public abstract class GetMessageListMethodTest {
             .statusCode(200)
             .body(NAME, equalTo("messageList"))
             .body(ARGUMENTS + ".messageIds", allOf(
-                    containsInAnyOrder(messageRead.getMessageId().serialize()), 
+                    containsInAnyOrder(messageRead.getMessageId().serialize()),
                     not(containsInAnyOrder(messageNotRead.getMessageId().serialize()))));
     }
 
@@ -439,7 +439,7 @@ public abstract class GetMessageListMethodTest {
             .statusCode(200)
             .body(NAME, equalTo("messageList"))
             .body(ARGUMENTS + ".messageIds", allOf(
-                    containsInAnyOrder(messageNotRead.getMessageId().serialize()), 
+                    containsInAnyOrder(messageNotRead.getMessageId().serialize()),
                     not(containsInAnyOrder(messageRead.getMessageId().serialize()))));
     }
 
@@ -463,7 +463,7 @@ public abstract class GetMessageListMethodTest {
             .statusCode(200)
             .body(NAME, equalTo("messageList"))
             .body(ARGUMENTS + ".messageIds", allOf(
-                    containsInAnyOrder(messageDraft.getMessageId().serialize()), 
+                    containsInAnyOrder(messageDraft.getMessageId().serialize()),
                     not(containsInAnyOrder(messageNotDraft.getMessageId().serialize()))));
     }
 
@@ -487,7 +487,7 @@ public abstract class GetMessageListMethodTest {
             .statusCode(200)
             .body(NAME, equalTo("messageList"))
             .body(ARGUMENTS + ".messageIds", allOf(
-                    containsInAnyOrder(messageNotDraft.getMessageId().serialize()), 
+                    containsInAnyOrder(messageNotDraft.getMessageId().serialize()),
                     not(containsInAnyOrder(messageDraft.getMessageId().serialize()))));
     }
 
@@ -511,7 +511,7 @@ public abstract class GetMessageListMethodTest {
             .statusCode(200)
             .body(NAME, equalTo("messageList"))
             .body(ARGUMENTS + ".messageIds", allOf(
-                    containsInAnyOrder(messageAnswered.getMessageId().serialize()), 
+                    containsInAnyOrder(messageAnswered.getMessageId().serialize()),
                     not(containsInAnyOrder(messageNotAnswered.getMessageId().serialize()))));
     }
 
@@ -535,7 +535,7 @@ public abstract class GetMessageListMethodTest {
             .statusCode(200)
             .body(NAME, equalTo("messageList"))
             .body(ARGUMENTS + ".messageIds", allOf(
-                    containsInAnyOrder(messageNotAnswered.getMessageId().serialize()), 
+                    containsInAnyOrder(messageNotAnswered.getMessageId().serialize()),
                     not(containsInAnyOrder(messageAnswered.getMessageId().serialize()))));
     }
 
@@ -612,7 +612,7 @@ public abstract class GetMessageListMethodTest {
             .statusCode(200)
             .body(NAME, equalTo("messageList"))
             .body(ARGUMENTS + ".messageIds", allOf(
-                    containsInAnyOrder(messageNotSeenFlagged.getMessageId().serialize()), 
+                    containsInAnyOrder(messageNotSeenFlagged.getMessageId().serialize()),
                     not(containsInAnyOrder(messageNotSeenNotFlagged.getMessageId().serialize(),
                             messageSeenNotFlagged.getMessageId().serialize(),
                             messageSeenFlagged.getMessageId().serialize()))));
@@ -644,7 +644,7 @@ public abstract class GetMessageListMethodTest {
             .body(ARGUMENTS + ".messageIds", allOf(
                     containsInAnyOrder(messageNotSeenFlagged.getMessageId().serialize(),
                             messageSeenFlagged.getMessageId().serialize(),
-                            messageNotSeenNotFlagged.getMessageId().serialize()), 
+                            messageNotSeenNotFlagged.getMessageId().serialize()),
                     not(containsInAnyOrder(messageSeenNotFlagged.getMessageId().serialize()))));
     }
 
@@ -672,7 +672,7 @@ public abstract class GetMessageListMethodTest {
             .statusCode(200)
             .body(NAME, equalTo("messageList"))
             .body(ARGUMENTS + ".messageIds", allOf(
-                    containsInAnyOrder(messageSeenNotFlagged.getMessageId().serialize()), 
+                    containsInAnyOrder(messageSeenNotFlagged.getMessageId().serialize()),
                     not(containsInAnyOrder(messageNotSeenFlagged.getMessageId().serialize(),
                             messageSeenFlagged.getMessageId().serialize(),
                             messageNotSeenNotFlagged.getMessageId().serialize()))));
@@ -706,7 +706,7 @@ public abstract class GetMessageListMethodTest {
             .body(NAME, equalTo("messageList"))
             .body(ARGUMENTS + ".messageIds", allOf(
                     containsInAnyOrder(messageSeenFlagged.getMessageId().serialize(),
-                            messageNotSeenFlagged.getMessageId().serialize()), 
+                            messageNotSeenFlagged.getMessageId().serialize()),
                     not(containsInAnyOrder(messageNotSeenNotFlagged.getMessageId().serialize(),
                             messageSeenNotFlagged.getMessageId().serialize()))));
     }
@@ -916,7 +916,7 @@ public abstract class GetMessageListMethodTest {
                 new ByteArrayInputStream("Subject: test\r\n\r\ntestmail".getBytes()), new Date(), false, new Flags());
 
         await();
-        
+
         given()
             .header("Authorization", aliceAccessToken.serialize())
             .body(String.format("[[\"getMessageList\", {\"filter\":{\"notInMailboxes\":[\"%s\"]}}, \"#0\"]]", mailboxId.serialize()))
@@ -1643,7 +1643,7 @@ public abstract class GetMessageListMethodTest {
             .statusCode(200)
             .body(NAME, equalTo("messageList"));
     }
-    
+
     @Test
     public void getMessageListShouldWorkWhenCollapseThreadIsTrue() {
         given()
@@ -1655,7 +1655,7 @@ public abstract class GetMessageListMethodTest {
             .statusCode(200)
             .body(NAME, equalTo("messageList"));
     }
-    
+
     @Test
     public void getMessageListShouldReturnAllMessagesWhenPositionIsNotGiven() throws Exception {
         mailboxProbe.createMailbox(MailboxConstants.USER_NAMESPACE, ALICE, "mailbox");
diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/SetMessagesMethodReRoutingTest.java b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/SetMessagesMethodReRoutingTest.java
new file mode 100644
index 0000000..d60bf21
--- /dev/null
+++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/SetMessagesMethodReRoutingTest.java
@@ -0,0 +1,242 @@
+/****************************************************************
+ * 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.jmap.methods.integration;
+
+import static io.restassured.RestAssured.given;
+import static io.restassured.config.EncoderConfig.encoderConfig;
+import static io.restassured.config.RestAssuredConfig.newConfig;
+import static org.apache.james.jmap.HttpJmapAuthentication.authenticateJamesUser;
+import static org.apache.james.jmap.JmapCommonRequests.bodyOfMessage;
+import static org.apache.james.jmap.JmapCommonRequests.getLatestMessageId;
+import static org.apache.james.jmap.JmapCommonRequests.getOutboxId;
+import static org.apache.james.jmap.JmapCommonRequests.receiversOfMessage;
+import static org.apache.james.jmap.JmapURIBuilder.baseUri;
+import static org.apache.james.jmap.TestingConstants.ARGUMENTS;
+import static org.apache.james.jmap.TestingConstants.NAME;
+import static org.apache.james.jmap.TestingConstants.calmlyAwait;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.collection.IsMapWithSize.aMapWithSize;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.james.GuiceJamesServer;
+import org.apache.james.jmap.api.access.AccessToken;
+import org.apache.james.mailbox.Role;
+import org.apache.james.mailbox.probe.MailboxProbe;
+import org.apache.james.modules.MailboxProbeImpl;
+import org.apache.james.probe.DataProbe;
+import org.apache.james.utils.DataProbeImpl;
+import org.apache.james.utils.JmapGuiceProbe;
+import org.awaitility.Duration;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import io.restassured.RestAssured;
+import io.restassured.builder.RequestSpecBuilder;
+import io.restassured.http.ContentType;
+import io.restassured.parsing.Parser;
+
+public abstract class SetMessagesMethodReRoutingTest {
+    private static final String PASSWORD = "password";
+
+    private static final String DESTINATION_DOMAIN = "domain1.com";
+    private static final String ALIAS_DOMAIN = "domain2.com";
+    private static final String RECEIVER_AT_DESTINATION_DOMAIN = "user@domain1.com";
+    private static final String RECEIVER_AT_ALIAS_DOMAIN = "user@domain2.com";
+    private static final String SENDER_AT_DESTINATION_DOMAIN = "sender@domain1.com";
+
+    private AccessToken receiverAtDestinationDomainToken;
+    private AccessToken senderAtDestinationDomainToken;
+
+    protected abstract GuiceJamesServer createJmapServer() throws IOException;
+
+    protected abstract void await();
+
+    private GuiceJamesServer jmapServer;
+    private MailboxProbe mailboxProbe;
+    private DataProbe dataProbe;
+
+    @Before
+    public void setup() throws Throwable {
+        jmapServer = createJmapServer();
+        jmapServer.start();
+        mailboxProbe = jmapServer.getProbe(MailboxProbeImpl.class);
+        dataProbe = jmapServer.getProbe(DataProbeImpl.class);
+
+        RestAssured.requestSpecification = new RequestSpecBuilder()
+                .setContentType(ContentType.JSON)
+                .setAccept(ContentType.JSON)
+                .setConfig(newConfig().encoderConfig(encoderConfig().defaultContentCharset(StandardCharsets.UTF_8)))
+                .setPort(jmapServer.getProbe(JmapGuiceProbe.class).getJmapPort())
+                .build();
+        RestAssured.enableLoggingOfRequestAndResponseIfValidationFails();
+        RestAssured.defaultParser = Parser.JSON;
+
+        dataProbe.addDomain(DESTINATION_DOMAIN);
+        dataProbe.addDomain(ALIAS_DOMAIN);
+        dataProbe.addUser(RECEIVER_AT_DESTINATION_DOMAIN, PASSWORD);
+        dataProbe.addUser(SENDER_AT_DESTINATION_DOMAIN, PASSWORD);
+        receiverAtDestinationDomainToken = authenticateJamesUser(baseUri(jmapServer), RECEIVER_AT_DESTINATION_DOMAIN, PASSWORD);
+        senderAtDestinationDomainToken = authenticateJamesUser(baseUri(jmapServer), SENDER_AT_DESTINATION_DOMAIN, PASSWORD);
+    }
+
+    @After
+    public void teardown() {
+        jmapServer.stop();
+    }
+
+    @Test // MAILET-136
+    public void sendShouldReRouteMailToDestinationAddressWhenDomainAliasMapping() throws Exception {
+        dataProbe.addDomainAliasMapping(ALIAS_DOMAIN, DESTINATION_DOMAIN);
+
+        String messageContent = "content content";
+        String sendMessageBody =
+            "[" +
+            "  [" +
+            "    \"setMessages\"," +
+            "    {" +
+            "      \"create\": { \"creationId1337\" : {" +
+            "        \"from\": { \"name\": \"Sender\", \"email\": \"" + SENDER_AT_DESTINATION_DOMAIN + "\"}," +
+            "        \"to\": [{ \"name\": \"User\", \"email\": \"" + RECEIVER_AT_ALIAS_DOMAIN + "\"}]," +
+            "        \"subject\": \"Thank you for joining example.com!\"," +
+            "        \"textBody\": \"" + messageContent + "\"," +
+            "        \"mailboxIds\": [\"" + getOutboxId(senderAtDestinationDomainToken) + "\"]" +
+            "      }}" +
+            "    }," +
+            "    \"#0\"" +
+            "  ]" +
+            "]";
+        given()
+            .header("Authorization", senderAtDestinationDomainToken.serialize())
+            .body(sendMessageBody)
+        .when()
+            .post("/jmap")
+        .then()
+            .statusCode(200)
+            .body(NAME, equalTo("messagesSet"))
+            .body(ARGUMENTS + ".notCreated", aMapWithSize(0))
+            .body(ARGUMENTS + ".created", aMapWithSize(1));
+
+        calmlyAwait
+            .pollDelay(Duration.FIVE_HUNDRED_MILLISECONDS)
+            .atMost(30, TimeUnit.SECONDS)
+            .untilAsserted(() ->
+                assertThat(getLatestMessageId(receiverAtDestinationDomainToken, Role.INBOX))
+                    .isNotNull());
+
+        String inboxMessageId = getLatestMessageId(receiverAtDestinationDomainToken, Role.INBOX);
+        assertThat(bodyOfMessage(receiverAtDestinationDomainToken, inboxMessageId))
+            .isEqualTo(messageContent);
+    }
+
+    @Test // MAILET-136
+    public void sendShouldNotCreateNewUserOrMailboxOfAliasAddressWhenDomainAliasMapping() throws Exception {
+        dataProbe.addDomainAliasMapping(ALIAS_DOMAIN, DESTINATION_DOMAIN);
+
+        String messageContent = "content content";
+        String sendMessageBody =
+            "[" +
+            "  [" +
+            "    \"setMessages\"," +
+            "    {" +
+            "      \"create\": { \"creationId1337\" : {" +
+            "        \"from\": { \"name\": \"Sender\", \"email\": \"" + SENDER_AT_DESTINATION_DOMAIN + "\"}," +
+            "        \"to\": [{ \"name\": \"User\", \"email\": \"" + RECEIVER_AT_ALIAS_DOMAIN + "\"}]," +
+            "        \"subject\": \"Thank you for joining example.com!\"," +
+            "        \"textBody\": \"" + messageContent + "\"," +
+            "        \"mailboxIds\": [\"" + getOutboxId(senderAtDestinationDomainToken) + "\"]" +
+            "      }}" +
+            "    }," +
+            "    \"#0\"" +
+            "  ]" +
+            "]";
+        given()
+            .header("Authorization", senderAtDestinationDomainToken.serialize())
+            .body(sendMessageBody)
+        .when()
+            .post("/jmap")
+        .then()
+            .statusCode(200)
+            .body(NAME, equalTo("messagesSet"))
+            .body(ARGUMENTS + ".notCreated", aMapWithSize(0))
+            .body(ARGUMENTS + ".created", aMapWithSize(1));
+
+        calmlyAwait
+            .pollDelay(Duration.FIVE_HUNDRED_MILLISECONDS)
+            .atMost(30, TimeUnit.SECONDS)
+            .untilAsserted(() ->
+                assertThat(getLatestMessageId(receiverAtDestinationDomainToken, Role.INBOX))
+                    .isNotNull());
+
+        assertThat(dataProbe.listUsers())
+            .doesNotContain("user@domain2.com");
+        assertThat(mailboxProbe.listUserMailboxes("user@domain2.com"))
+            .isEmpty();
+    }
+
+
+    @Test // MAILET-136
+    public void sendShouldSaveToAsTheAliasAddressWhenDomainAliasMapping() throws Exception {
+        dataProbe.addDomainAliasMapping(ALIAS_DOMAIN, DESTINATION_DOMAIN);
+
+        String messageContent = "content content";
+        String sendMessageBody =
+            "[" +
+            "  [" +
+            "    \"setMessages\"," +
+            "    {" +
+            "      \"create\": { \"creationId1337\" : {" +
+            "        \"from\": { \"name\": \"Sender\", \"email\": \"" + SENDER_AT_DESTINATION_DOMAIN + "\"}," +
+            "        \"to\": [{ \"name\": \"User\", \"email\": \"" + RECEIVER_AT_ALIAS_DOMAIN + "\"}]," +
+            "        \"subject\": \"Thank you for joining example.com!\"," +
+            "        \"textBody\": \"" + messageContent + "\"," +
+            "        \"mailboxIds\": [\"" + getOutboxId(senderAtDestinationDomainToken) + "\"]" +
+            "      }}" +
+            "    }," +
+            "    \"#0\"" +
+            "  ]" +
+            "]";
+        given()
+            .header("Authorization", senderAtDestinationDomainToken.serialize())
+            .body(sendMessageBody)
+        .when()
+            .post("/jmap")
+        .then()
+            .statusCode(200)
+            .body(NAME, equalTo("messagesSet"))
+            .body(ARGUMENTS + ".notCreated", aMapWithSize(0))
+            .body(ARGUMENTS + ".created", aMapWithSize(1));
+
+        calmlyAwait
+            .pollDelay(Duration.FIVE_HUNDRED_MILLISECONDS)
+            .atMost(30, TimeUnit.SECONDS)
+            .untilAsserted(() ->
+                assertThat(getLatestMessageId(senderAtDestinationDomainToken, Role.SENT))
+                    .isNotNull());
+
+        String sentMessageId = getLatestMessageId(senderAtDestinationDomainToken, Role.SENT);
+        assertThat(receiversOfMessage(senderAtDestinationDomainToken, sentMessageId))
+            .containsOnly(RECEIVER_AT_ALIAS_DOMAIN);
+    }
+}
diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/SetMessagesMethodTest.java b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/SetMessagesMethodTest.java
index 03ad0b0..a58c3d0 100644
--- a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/SetMessagesMethodTest.java
+++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/SetMessagesMethodTest.java
@@ -2198,7 +2198,7 @@ public abstract class SetMessagesMethodTest {
             "    \"#0\"" +
             "  ]" +
             "]";
-        
+
         given()
             .header("Authorization", accessToken.serialize())
             .body(copyDraftToOutBox)
@@ -2529,7 +2529,7 @@ public abstract class SetMessagesMethodTest {
         String outboxId = getMailboxId(accessToken, Role.OUTBOX);
         assertThat(hasNoMessageIn(bobAccessToken, outboxId)).isTrue();
     }
-    
+
     private boolean hasNoMessageIn(AccessToken accessToken, String mailboxId) {
         try {
             with()
@@ -2544,7 +2544,7 @@ public abstract class SetMessagesMethodTest {
             return true;
         } catch (AssertionError e) {
             return false;
-        } 
+        }
     }
 
     @Test
@@ -4388,7 +4388,7 @@ public abstract class SetMessagesMethodTest {
 
         checkBlobContent(blobId, rawBytes);
     }
-    
+
     @Test
     public void setMessagesShouldVerifyHeaderOfMessageInInbox() throws Exception {
         String toUsername = "username1@" + DOMAIN;
@@ -4702,7 +4702,7 @@ public abstract class SetMessagesMethodTest {
     @Test
     public void setMessagesShouldUpdateIsAnsweredWhenInReplyToHeaderSentViaDraft() throws Exception {
         OriginalMessage firstMessage = receiveFirstMessage();
-        
+
         String draftCreationId = "creationId1337";
         String createDraft = "[" +
             "  [" +
@@ -4770,7 +4770,7 @@ public abstract class SetMessagesMethodTest {
     @Test
     public void setMessagesShouldUpdateIsForwardedWhenXForwardedHeaderSentViaDraft() throws Exception {
         OriginalMessage firstMessage = receiveFirstMessage();
-        
+
         String draftCreationId = "creationId1337";
         String createDraft = "[" +
             "  [" +
diff --git a/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/java/org/apache/james/jmap/memory/MemorySetMessagesMethodReRoutingTest.java b/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/java/org/apache/james/jmap/memory/MemorySetMessagesMethodReRoutingTest.java
new file mode 100644
index 0000000..e30e4c7
--- /dev/null
+++ b/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/java/org/apache/james/jmap/memory/MemorySetMessagesMethodReRoutingTest.java
@@ -0,0 +1,42 @@
+/****************************************************************
+ * 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.jmap.memory;
+
+import java.io.IOException;
+
+import org.apache.james.GuiceJamesServer;
+import org.apache.james.MemoryJmapTestRule;
+import org.apache.james.jmap.methods.integration.SetMessagesMethodReRoutingTest;
+import org.junit.Rule;
+
+public class MemorySetMessagesMethodReRoutingTest extends SetMessagesMethodReRoutingTest {
+
+    @Rule
+    public MemoryJmapTestRule memoryJmap = new MemoryJmapTestRule();
+
+    @Override
+    protected GuiceJamesServer createJmapServer() throws IOException {
+        return memoryJmap.jmapServer();
+    }
+    
+    @Override
+    protected void await() {
+    }
+}
diff --git a/server/protocols/jmap-integration-testing/rabbitmq-jmap-integration-testing/src/test/java/org/apache/james/jmap/rabbitmq/RabbitMQAwsS3SetMessagesMethodReRoutingTest.java b/server/protocols/jmap-integration-testing/rabbitmq-jmap-integration-testing/src/test/java/org/apache/james/jmap/rabbitmq/RabbitMQAwsS3SetMessagesMethodReRoutingTest.java
new file mode 100644
index 0000000..12da9b1
--- /dev/null
+++ b/server/protocols/jmap-integration-testing/rabbitmq-jmap-integration-testing/src/test/java/org/apache/james/jmap/rabbitmq/RabbitMQAwsS3SetMessagesMethodReRoutingTest.java
@@ -0,0 +1,48 @@
+/****************************************************************
+ * 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.jmap.rabbitmq;
+
+import java.io.IOException;
+
+import org.apache.james.CassandraRabbitMQAwsS3JmapTestRule;
+import org.apache.james.DockerCassandraRule;
+import org.apache.james.GuiceJamesServer;
+import org.apache.james.jmap.methods.integration.SetMessagesMethodReRoutingTest;
+import org.junit.Rule;
+
+public class RabbitMQAwsS3SetMessagesMethodReRoutingTest extends SetMessagesMethodReRoutingTest {
+
+    @Rule
+    public DockerCassandraRule cassandra = new DockerCassandraRule();
+
+    @Rule
+    public CassandraRabbitMQAwsS3JmapTestRule rule = CassandraRabbitMQAwsS3JmapTestRule.defaultTestRule();
+
+    @Override
+    protected GuiceJamesServer createJmapServer() throws IOException {
+        return rule.jmapServer(cassandra.getModule());
+    }
+
+    @Override
+    protected void await() {
+        rule.await();
+    }
+}
+


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[james-project] 03/09: JAMES-2146 a new component dedicated to load java security keys from configuration

Posted by bt...@apache.org.
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 c3876cf57482e186b47a3f300237c0436638cb13
Author: Tran Tien Duc <dt...@linagora.com>
AuthorDate: Thu Jun 6 10:21:20 2019 +0700

    JAMES-2146 a new component dedicated to load java security keys from configuration
    
    And later, use it in new KeyStore StartUpCheck
---
 .../org/apache/james/jmap/JMAPCommonModule.java    |  2 +
 .../apache/james/jmap/crypto/AsymmetricKeys.java   | 42 ++++++++++
 .../james/jmap/crypto/JamesSignatureHandler.java   |  2 +-
 ...ignatureHandler.java => SecurityKeyLoader.java} | 61 ++------------
 .../james/jmap/crypto/ClassLoaderFileSystem.java   | 45 ++++++++++
 .../james/jmap/crypto/SecurityKeyLoaderTest.java   | 96 ++++++++++++++++++++++
 6 files changed, 194 insertions(+), 54 deletions(-)

diff --git a/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPCommonModule.java b/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPCommonModule.java
index c562d60..9a44d3a 100644
--- a/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPCommonModule.java
+++ b/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPCommonModule.java
@@ -27,6 +27,7 @@ import org.apache.james.jmap.api.SimpleTokenManager;
 import org.apache.james.jmap.api.access.AccessTokenRepository;
 import org.apache.james.jmap.crypto.AccessTokenManagerImpl;
 import org.apache.james.jmap.crypto.JamesSignatureHandler;
+import org.apache.james.jmap.crypto.SecurityKeyLoader;
 import org.apache.james.jmap.crypto.SignatureHandler;
 import org.apache.james.jmap.crypto.SignedTokenFactory;
 import org.apache.james.jmap.crypto.SignedTokenManager;
@@ -64,6 +65,7 @@ public class JMAPCommonModule extends AbstractModule {
         bind(MessagePreviewGenerator.class).in(Scopes.SINGLETON);
         bind(MessageContentExtractor.class).in(Scopes.SINGLETON);
         bind(HeadersAuthenticationExtractor.class).in(Scopes.SINGLETON);
+        bind(SecurityKeyLoader.class).in(Scopes.SINGLETON);
 
         bind(SignatureHandler.class).to(JamesSignatureHandler.class);
         bind(ZonedDateTimeProvider.class).to(DefaultZonedDateTimeProvider.class);
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/AsymmetricKeys.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/AsymmetricKeys.java
new file mode 100644
index 0000000..301fd4e
--- /dev/null
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/AsymmetricKeys.java
@@ -0,0 +1,42 @@
+/****************************************************************
+ * 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.jmap.crypto;
+
+import java.security.PrivateKey;
+import java.security.PublicKey;
+
+class AsymmetricKeys {
+
+    private final PrivateKey privateKey;
+    private final PublicKey publicKey;
+
+    AsymmetricKeys(PrivateKey privateKey, PublicKey publicKey) {
+        this.privateKey = privateKey;
+        this.publicKey = publicKey;
+    }
+
+    PrivateKey getPrivateKey() {
+        return privateKey;
+    }
+
+    PublicKey getPublicKey() {
+        return publicKey;
+    }
+}
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/JamesSignatureHandler.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/JamesSignatureHandler.java
index 37d3456..82ee210 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/JamesSignatureHandler.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/JamesSignatureHandler.java
@@ -50,7 +50,7 @@ public class JamesSignatureHandler implements SignatureHandler {
     public static final String ALIAS = "james";
     public static final String ALGORITHM = "SHA1withRSA";
     public static final String JKS = "JKS";
-    
+
     private final FileSystem fileSystem;
     private final JMAPConfiguration jmapConfiguration;
 
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/JamesSignatureHandler.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/SecurityKeyLoader.java
similarity index 53%
copy from server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/JamesSignatureHandler.java
copy to server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/SecurityKeyLoader.java
index 37d3456..0bb359c 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/JamesSignatureHandler.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/SecurityKeyLoader.java
@@ -20,52 +20,37 @@
 package org.apache.james.jmap.crypto;
 
 import java.io.InputStream;
-import java.security.InvalidKeyException;
 import java.security.Key;
 import java.security.KeyStore;
 import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
 import java.security.PrivateKey;
 import java.security.PublicKey;
-import java.security.Signature;
-import java.security.SignatureException;
 import java.security.cert.Certificate;
-import java.util.Base64;
 import java.util.Optional;
 
 import javax.inject.Inject;
 
 import org.apache.james.filesystem.api.FileSystem;
 import org.apache.james.jmap.JMAPConfiguration;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Preconditions;
 
-public class JamesSignatureHandler implements SignatureHandler {
+public class SecurityKeyLoader {
 
-    private static final Logger LOGGER = LoggerFactory.getLogger(JamesSignatureHandler.class);
+    private static final String ALIAS = "james";
+    private static final String JKS = "JKS";
 
-    public static final String ALIAS = "james";
-    public static final String ALGORITHM = "SHA1withRSA";
-    public static final String JKS = "JKS";
-    
     private final FileSystem fileSystem;
     private final JMAPConfiguration jmapConfiguration;
 
-    private PrivateKey privateKey;
-    private PublicKey publicKey;
-
-
+    @VisibleForTesting
     @Inject
-    @VisibleForTesting JamesSignatureHandler(FileSystem fileSystem, JMAPConfiguration jmapConfiguration) {
+    SecurityKeyLoader(FileSystem fileSystem, JMAPConfiguration jmapConfiguration) {
         this.fileSystem = fileSystem;
         this.jmapConfiguration = jmapConfiguration;
     }
 
-    @Override
-    public void init() throws Exception {
+    public AsymmetricKeys load() throws Exception {
         KeyStore keystore = KeyStore.getInstance(JKS);
         InputStream fis = fileSystem.getResource(jmapConfiguration.getKeystore());
         char[] secret = jmapConfiguration.getSecret().toCharArray();
@@ -74,41 +59,11 @@ public class JamesSignatureHandler implements SignatureHandler {
                 .ofNullable(keystore.getCertificate(ALIAS))
                 .orElseThrow(() -> new KeyStoreException("Alias '" + ALIAS + "' keystore can't be found"));
 
-        publicKey = aliasCertificate.getPublicKey();
+        PublicKey publicKey = aliasCertificate.getPublicKey();
         Key key = keystore.getKey(ALIAS, secret);
         if (! (key instanceof PrivateKey)) {
             throw new KeyStoreException("Provided key is not a PrivateKey");
         }
-        privateKey = (PrivateKey) key;
-    }
-
-    @Override
-    public String sign(String source) {
-        Preconditions.checkNotNull(source);
-        try {
-            Signature javaSignature = Signature.getInstance(ALGORITHM);
-            javaSignature.initSign(privateKey);
-            javaSignature.update(source.getBytes());
-            return Base64.getEncoder().encodeToString(javaSignature.sign());
-        } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    @Override
-    public boolean verify(String source, String signature) {
-        Preconditions.checkNotNull(source);
-        Preconditions.checkNotNull(signature);
-        try {
-            Signature javaSignature = Signature.getInstance(ALGORITHM);
-            javaSignature.initVerify(publicKey);
-            javaSignature.update(source.getBytes());
-            return javaSignature.verify(Base64.getDecoder().decode(signature));
-        } catch (NoSuchAlgorithmException | InvalidKeyException e) {
-            throw new RuntimeException(e);
-        } catch (SignatureException e) {
-            LOGGER.warn("Attempt to use a malformed signature '{}' for source '{}'", signature, source, e);
-            return false;
-        }
+        return new AsymmetricKeys((PrivateKey) key, publicKey);
     }
 }
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/ClassLoaderFileSystem.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/ClassLoaderFileSystem.java
new file mode 100644
index 0000000..43687e4
--- /dev/null
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/ClassLoaderFileSystem.java
@@ -0,0 +1,45 @@
+/****************************************************************
+ * 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.jmap.crypto;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.james.filesystem.api.FileSystem;
+
+class ClassLoaderFileSystem implements FileSystem {
+
+    @Override
+    public InputStream getResource(String url) throws IOException {
+        return ClassLoader.getSystemResourceAsStream(url);
+    }
+
+    @Override
+    public File getFile(String fileURL) throws FileNotFoundException {
+        return null;
+    }
+
+    @Override
+    public File getBasedir() throws FileNotFoundException {
+        return null;
+    }
+}
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SecurityKeyLoaderTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SecurityKeyLoaderTest.java
new file mode 100644
index 0000000..63c1acb
--- /dev/null
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/SecurityKeyLoaderTest.java
@@ -0,0 +1,96 @@
+/****************************************************************
+ * 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.jmap.crypto;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import java.io.IOException;
+import java.security.KeyStoreException;
+import java.util.Optional;
+
+import org.apache.james.jmap.JMAPConfiguration;
+import org.junit.jupiter.api.Test;
+
+class SecurityKeyLoaderTest {
+
+    private static final String JWT_PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----\n" +
+        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtlChO/nlVP27MpdkG0Bh\n" +
+        "16XrMRf6M4NeyGa7j5+1UKm42IKUf3lM28oe82MqIIRyvskPc11NuzSor8HmvH8H\n" +
+        "lhDs5DyJtx2qp35AT0zCqfwlaDnlDc/QDlZv1CoRZGpQk1Inyh6SbZwYpxxwh0fi\n" +
+        "+d/4RpE3LBVo8wgOaXPylOlHxsDizfkL8QwXItyakBfMO6jWQRrj7/9WDhGf4Hi+\n" +
+        "GQur1tPGZDl9mvCoRHjFrD5M/yypIPlfMGWFVEvV5jClNMLAQ9bYFuOc7H1fEWw6\n" +
+        "U1LZUUbJW9/CH45YXz82CYqkrfbnQxqRb2iVbVjs/sHopHd1NTiCfUtwvcYJiBVj\n" +
+        "kwIDAQAB\n" +
+        "-----END PUBLIC KEY-----";
+
+    @Test
+    void loadShouldThrowWhenWrongKeystore() throws Exception {
+        JMAPConfiguration jmapConfiguration = JMAPConfiguration.builder()
+            .enable()
+            .jwtPublicKeyPem(Optional.of(JWT_PUBLIC_KEY))
+            .keystore("badAliasKeystore")
+            .secret("password")
+            .build();
+
+        SecurityKeyLoader loader = new SecurityKeyLoader(
+            new ClassLoaderFileSystem(),
+            jmapConfiguration);
+
+        assertThatThrownBy(loader::load)
+            .isInstanceOf(KeyStoreException.class)
+            .hasMessage("Alias 'james' keystore can't be found");
+    }
+
+    @Test
+    void loadShouldThrowWhenWrongPassword() throws Exception {
+        JMAPConfiguration jmapConfiguration = JMAPConfiguration.builder()
+            .enable()
+            .jwtPublicKeyPem(Optional.of(JWT_PUBLIC_KEY))
+            .keystore("keystore")
+            .secret("WrongPassword")
+            .build();
+
+        SecurityKeyLoader loader = new SecurityKeyLoader(
+            new ClassLoaderFileSystem(),
+            jmapConfiguration);
+
+        assertThatThrownBy(loader::load)
+            .isInstanceOf(IOException.class)
+            .hasMessage("Keystore was tampered with, or password was incorrect");
+    }
+
+    @Test
+    void loadShouldReturnSecurityKeysWhenCorrectPassword() throws Exception {
+        JMAPConfiguration jmapConfiguration = JMAPConfiguration.builder()
+            .enable()
+            .jwtPublicKeyPem(Optional.of(JWT_PUBLIC_KEY))
+            .keystore("keystore")
+            .secret("james72laBalle")
+            .build();
+
+        SecurityKeyLoader loader = new SecurityKeyLoader(
+            new ClassLoaderFileSystem(),
+            jmapConfiguration);
+
+        assertThat(loader.load())
+            .isNotNull();
+    }
+}
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org