You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@james.apache.org by bt...@apache.org on 2023/06/01 08:50:33 UTC

[james-project] 07/09: JAMES-3906 Tests (and fix) for certificate reload

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 7d2d167d56f4021dc4e2f514d0823d96d4721f5d
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Thu May 25 17:55:49 2023 +0700

    JAMES-3906 Tests (and fix) for certificate reload
---
 .../AbstractSSLAwareChannelPipelineFactory.java    |  12 +-
 .../apache/james/protocols/netty/NettyServer.java  |   2 +-
 .../apache/james/JamesServerConcreteContract.java  |   2 +-
 .../apache/james/JamesServerConcreteContract.java  |   2 +-
 .../org/apache/james/CertificateReloadTest.java    | 218 +++++++++++++++++++++
 .../org/apache/james/MemoryJamesServerTest.java    |   2 +-
 .../memory-app/src/test/resources/imapserver2.xml  |  73 +++++++
 .../memory-app/src/test/resources/jwt_publickey    |   9 +
 .../apps/memory-app/src/test/resources/keystore2   | Bin 0 -> 2726 bytes
 .../memory-app/src/test/resources/smtpserver2.xml  | 136 +++++++++++++
 .../org/apache/james/TemporaryJamesServer.java     |  18 +-
 .../james/modules/protocols/ImapGuiceProbe.java    |   7 +-
 .../james/modules/protocols/SmtpGuiceProbe.java    |   7 +
 .../lib/netty/AbstractConfigurableAsyncServer.java |   2 +-
 14 files changed, 468 insertions(+), 22 deletions(-)

diff --git a/protocols/netty/src/main/java/org/apache/james/protocols/netty/AbstractSSLAwareChannelPipelineFactory.java b/protocols/netty/src/main/java/org/apache/james/protocols/netty/AbstractSSLAwareChannelPipelineFactory.java
index 8152aaeeed..dc7e4330a4 100644
--- a/protocols/netty/src/main/java/org/apache/james/protocols/netty/AbstractSSLAwareChannelPipelineFactory.java
+++ b/protocols/netty/src/main/java/org/apache/james/protocols/netty/AbstractSSLAwareChannelPipelineFactory.java
@@ -18,6 +18,8 @@
  ****************************************************************/
 package org.apache.james.protocols.netty;
 
+import java.util.function.Supplier;
+
 import io.netty.channel.ChannelHandler;
 import io.netty.channel.ChannelPipeline;
 import io.netty.channel.socket.SocketChannel;
@@ -30,7 +32,7 @@ import io.netty.util.concurrent.EventExecutorGroup;
 @ChannelHandler.Sharable
 public abstract class AbstractSSLAwareChannelPipelineFactory<C extends SocketChannel> extends AbstractChannelPipelineFactory<C> {
     private final boolean proxyRequired;
-    private Encryption secure;
+    private Supplier<Encryption> secure;
 
     public AbstractSSLAwareChannelPipelineFactory(int timeout,
                                                   int maxConnections, int maxConnectsPerIp,
@@ -42,7 +44,7 @@ public abstract class AbstractSSLAwareChannelPipelineFactory<C extends SocketCha
     }
 
     public AbstractSSLAwareChannelPipelineFactory(int timeout,
-            int maxConnections, int maxConnectsPerIp, boolean proxyRequired, Encryption secure,
+            int maxConnections, int maxConnectsPerIp, boolean proxyRequired, Supplier<Encryption> secure,
             ChannelHandlerFactory frameHandlerFactory, EventExecutorGroup eventExecutorGroup) {
         this(timeout, maxConnections, maxConnectsPerIp, proxyRequired, frameHandlerFactory, eventExecutorGroup);
 
@@ -55,9 +57,9 @@ public abstract class AbstractSSLAwareChannelPipelineFactory<C extends SocketCha
 
         if (isSSLSocket()) {
             if (proxyRequired) {
-                channel.pipeline().addAfter("proxyInformationHandler", HandlerConstants.SSL_HANDLER, secure.sslHandler());
+                channel.pipeline().addAfter("proxyInformationHandler", HandlerConstants.SSL_HANDLER, secure.get().sslHandler());
             } else {
-                channel.pipeline().addFirst(HandlerConstants.SSL_HANDLER, secure.sslHandler());
+                channel.pipeline().addFirst(HandlerConstants.SSL_HANDLER, secure.get().sslHandler());
             }
         }
     }
@@ -66,6 +68,6 @@ public abstract class AbstractSSLAwareChannelPipelineFactory<C extends SocketCha
      * Return if the socket is using SSL/TLS
      */
     protected boolean isSSLSocket() {
-        return secure != null && secure.supportsEncryption() && !secure.isStartTLS();
+        return secure != null && secure.get().supportsEncryption() && !secure.get().isStartTLS();
     }
 }
diff --git a/protocols/netty/src/main/java/org/apache/james/protocols/netty/NettyServer.java b/protocols/netty/src/main/java/org/apache/james/protocols/netty/NettyServer.java
index d6c16e4537..e36f086801 100644
--- a/protocols/netty/src/main/java/org/apache/james/protocols/netty/NettyServer.java
+++ b/protocols/netty/src/main/java/org/apache/james/protocols/netty/NettyServer.java
@@ -126,7 +126,7 @@ public class NettyServer extends AbstractAsyncServer {
             maxCurConnections,
             maxCurConnectionsPerIP,
             proxyRequired,
-            secure,
+            () -> secure,
             getFrameHandlerFactory(),
             new DefaultEventLoopGroup(16)) {
 
diff --git a/server/apps/cassandra-app/src/test/java/org/apache/james/JamesServerConcreteContract.java b/server/apps/cassandra-app/src/test/java/org/apache/james/JamesServerConcreteContract.java
index ee6b338e87..3ac19242ee 100644
--- a/server/apps/cassandra-app/src/test/java/org/apache/james/JamesServerConcreteContract.java
+++ b/server/apps/cassandra-app/src/test/java/org/apache/james/JamesServerConcreteContract.java
@@ -32,7 +32,7 @@ public interface JamesServerConcreteContract extends JamesServerContract {
 
     @Override
     default int imapsPort(GuiceJamesServer server) {
-        return server.getProbe(ImapGuiceProbe.class).getImapsPort();
+        return server.getProbe(ImapGuiceProbe.class).getImapStartTLSPort();
     }
 
     @Override
diff --git a/server/apps/jpa-app/src/test/java/org/apache/james/JamesServerConcreteContract.java b/server/apps/jpa-app/src/test/java/org/apache/james/JamesServerConcreteContract.java
index ee6b338e87..3ac19242ee 100644
--- a/server/apps/jpa-app/src/test/java/org/apache/james/JamesServerConcreteContract.java
+++ b/server/apps/jpa-app/src/test/java/org/apache/james/JamesServerConcreteContract.java
@@ -32,7 +32,7 @@ public interface JamesServerConcreteContract extends JamesServerContract {
 
     @Override
     default int imapsPort(GuiceJamesServer server) {
-        return server.getProbe(ImapGuiceProbe.class).getImapsPort();
+        return server.getProbe(ImapGuiceProbe.class).getImapStartTLSPort();
     }
 
     @Override
diff --git a/server/apps/memory-app/src/test/java/org/apache/james/CertificateReloadTest.java b/server/apps/memory-app/src/test/java/org/apache/james/CertificateReloadTest.java
new file mode 100644
index 0000000000..8de9a48892
--- /dev/null
+++ b/server/apps/memory-app/src/test/java/org/apache/james/CertificateReloadTest.java
@@ -0,0 +1,218 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james;
+
+import static io.restassured.RestAssured.given;
+import static org.apache.james.MemoryJamesServerMain.IN_MEMORY_SERVER_AGGREGATE_MODULE;
+import static org.apache.james.jmap.JMAPTestingConstants.LOCALHOST_IP;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Path;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+
+import org.apache.james.data.UsersRepositoryModuleChooser;
+import org.apache.james.modules.data.MemoryUsersRepositoryModule;
+import org.apache.james.modules.protocols.ImapGuiceProbe;
+import org.apache.james.modules.protocols.SmtpGuiceProbe;
+import org.apache.james.utils.WebAdminGuiceProbe;
+import org.apache.james.webadmin.WebAdminConfiguration;
+import org.apache.james.webadmin.WebAdminUtils;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+import com.google.common.collect.ImmutableList;
+
+import io.restassured.RestAssured;
+
+class CertificateReloadTest {
+
+    public static class BlindTrustManager implements X509TrustManager {
+        public X509Certificate[] getAcceptedIssuers() {
+            return null;
+        }
+
+        public void checkClientTrusted(X509Certificate[] chain, String authType) {
+
+        }
+
+        public void checkServerTrusted(X509Certificate[] chain, String authType) {
+
+
+        }
+    }
+
+    private static final List<String> BASE_CONFIGURATION_FILE_NAMES = ImmutableList.of("dnsservice.xml",
+        "dnsservice.xml",
+        "imapserver.xml",
+        "imapserver2.xml",
+        "jwt_publickey",
+        "lmtpserver.xml",
+        "keystore",
+        "mailetcontainer.xml",
+        "mailrepositorystore.xml",
+        "managesieveserver.xml",
+        "pop3server.xml",
+        "smtpserver.xml",
+        "smtpserver2.xml");
+
+    private GuiceJamesServer jamesServer;
+    private TemporaryJamesServer temporaryJamesServer;
+
+    @BeforeEach
+    void beforeEach(@TempDir Path workingPath) {
+        temporaryJamesServer = new TemporaryJamesServer(workingPath.toFile(), BASE_CONFIGURATION_FILE_NAMES);
+
+        jamesServer = temporaryJamesServer.getJamesServer()
+            .combineWith(IN_MEMORY_SERVER_AGGREGATE_MODULE)
+            .combineWith(new UsersRepositoryModuleChooser(new MemoryUsersRepositoryModule())
+                .chooseModules(UsersRepositoryModuleChooser.Implementation.DEFAULT))
+            .overrideWith(binder -> binder.bind(WebAdminConfiguration.class).toInstance(WebAdminConfiguration.TEST_CONFIGURATION));
+
+    }
+
+    @AfterEach
+    void afterEach() {
+        if (jamesServer != null && jamesServer.isStarted()) {
+            jamesServer.stop();
+        }
+    }
+
+    @Test
+    void subjectShouldBeKeptWhenNoRestart() throws Exception {
+        temporaryJamesServer.copyResources("smtpserver2.xml", "smtpserver.xml");
+        jamesServer.start();
+
+        assertThat(getServerCertificate(jamesServer.getProbe(SmtpGuiceProbe.class).getSmtpSslPort().getValue()).getSubjectX500Principal().getName())
+            .isEqualTo("CN=Benoit Tellier,OU=Linagora,O=James,L=Puteaux,ST=Unknown,C=FR");
+    }
+
+    private X509Certificate getServerCertificate(int port) throws NoSuchAlgorithmException, KeyManagementException, IOException {
+        SSLSocket clientConnection = openSSLConnection(port);
+
+        return Arrays.stream(clientConnection.getSession()
+            .getPeerCertificates())
+            .filter(X509Certificate.class::isInstance)
+            .map(X509Certificate.class::cast)
+            .findFirst()
+            .orElseThrow();
+    }
+
+    private SSLSocket openSSLConnection(int port) throws NoSuchAlgorithmException, KeyManagementException, IOException {
+        SSLContext ctx = SSLContext.getInstance("TLS");
+        ctx.init(null, new TrustManager[]{new BlindTrustManager()}, null);
+        SSLSocket clientConnection = (SSLSocket) ctx.getSocketFactory().createSocket(LOCALHOST_IP, port);
+        return clientConnection;
+    }
+
+    @Test
+    void reloadShouldUpdateCertificates() throws Exception {
+        temporaryJamesServer.copyResources("smtpserver2.xml", "smtpserver.xml");
+        jamesServer.start();
+
+        temporaryJamesServer.copyResources("keystore2", "keystore");
+
+        WebAdminGuiceProbe webAdminGuiceProbe = jamesServer.getProbe(WebAdminGuiceProbe.class);
+        RestAssured.requestSpecification = WebAdminUtils.buildRequestSpecification(webAdminGuiceProbe.getWebAdminPort())
+            .build();
+
+        int port = jamesServer.getProbe(SmtpGuiceProbe.class).getSmtpSslPort().getValue();
+        given()
+            .queryParam("reload-certificate")
+            .queryParam("port", port)
+        .when()
+            .post("/servers")
+        .then()
+            .statusCode(204);
+
+        assertThat(getServerCertificate(port).getSubjectX500Principal().getName())
+            .isEqualTo("CN=Testing,OU=Testing,O=Testing,L=Testing,ST=Testing,C=Te");
+    }
+
+    @Test
+    void reloadShouldUpdateCertificatesForImap() throws Exception {
+        temporaryJamesServer.copyResources("imapserver2.xml", "imapserver.xml");
+        jamesServer.start();
+
+        temporaryJamesServer.copyResources("keystore2", "keystore");
+
+        WebAdminGuiceProbe webAdminGuiceProbe = jamesServer.getProbe(WebAdminGuiceProbe.class);
+        RestAssured.requestSpecification = WebAdminUtils.buildRequestSpecification(webAdminGuiceProbe.getWebAdminPort())
+            .build();
+
+        int port = jamesServer.getProbe(ImapGuiceProbe.class).getImapSSLPort();
+        given()
+            .queryParam("reload-certificate")
+            .queryParam("port", port)
+        .when()
+            .post("/servers")
+        .then()
+            .statusCode(204);
+
+        assertThat(getServerCertificate(port).getSubjectX500Principal().getName())
+            .isEqualTo("CN=Testing,OU=Testing,O=Testing,L=Testing,ST=Testing,C=Te");
+    }
+
+    @Test
+    void reloadShouldNotAbortExistingConnections() throws Exception {
+        temporaryJamesServer.copyResources("smtpserver2.xml", "smtpserver.xml");
+        jamesServer.start();
+        int port = jamesServer.getProbe(SmtpGuiceProbe.class).getSmtpSslPort().getValue();
+        SSLSocket channel = openSSLConnection(port);
+
+        temporaryJamesServer.copyResources("keystore2", "keystore");
+
+        WebAdminGuiceProbe webAdminGuiceProbe = jamesServer.getProbe(WebAdminGuiceProbe.class);
+        RestAssured.requestSpecification = WebAdminUtils.buildRequestSpecification(webAdminGuiceProbe.getWebAdminPort())
+            .build();
+
+        given()
+            .queryParam("reload-certificate")
+            .queryParam("port", jamesServer.getProbe(SmtpGuiceProbe.class).getSmtpSslPort().getValue())
+        .when()
+            .post("/servers")
+        .then()
+            .statusCode(204);
+
+        System.out.println(readBytes(channel));
+        channel.getOutputStream().write("EHLO toto.com\r\n".getBytes(StandardCharsets.UTF_8));
+        assertThat(readBytes(channel))
+            .contains("250 8BITMIME");
+    }
+
+    private String readBytes(SSLSocket sslSocket) throws IOException {
+        byte[] bline = new byte[1024];
+        final int read = sslSocket.getInputStream().read(bline);
+        return new String(bline, 0, read);
+    }
+
+}
diff --git a/server/apps/memory-app/src/test/java/org/apache/james/MemoryJamesServerTest.java b/server/apps/memory-app/src/test/java/org/apache/james/MemoryJamesServerTest.java
index 74245c157f..da68ed1af5 100644
--- a/server/apps/memory-app/src/test/java/org/apache/james/MemoryJamesServerTest.java
+++ b/server/apps/memory-app/src/test/java/org/apache/james/MemoryJamesServerTest.java
@@ -36,7 +36,7 @@ class MemoryJamesServerTest implements JamesServerContract {
 
     @Override
     public int imapsPort(GuiceJamesServer server) {
-        return server.getProbe(ImapGuiceProbe.class).getImapsPort();
+        return server.getProbe(ImapGuiceProbe.class).getImapStartTLSPort();
     }
 
     @Override
diff --git a/server/apps/memory-app/src/test/resources/imapserver2.xml b/server/apps/memory-app/src/test/resources/imapserver2.xml
new file mode 100644
index 0000000000..067bd16190
--- /dev/null
+++ b/server/apps/memory-app/src/test/resources/imapserver2.xml
@@ -0,0 +1,73 @@
+<?xml version="1.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.
+-->
+
+
+<imapservers>
+    <imapserver enabled="true">
+        <jmxName>imapserver</jmxName>
+        <bind>0.0.0.0:0</bind>
+        <connectionBacklog>200</connectionBacklog>
+        <tls socketTLS="false" startTLS="false">
+            <!-- To create a new keystore execute:
+            keytool -genkey -alias james -keyalg RSA -keystore /path/to/james/conf/keystore
+              -->
+            <keystore>classpath://keystore</keystore>
+            <secret>james72laBalle</secret>
+            <provider>org.bouncycastle.jce.provider.BouncyCastleProvider</provider>
+        </tls>
+        <connectionLimit>0</connectionLimit>
+        <connectionLimitPerIP>0</connectionLimitPerIP>
+        <plainAuthDisallowed>false</plainAuthDisallowed>
+        <gracefulShutdown>false</gracefulShutdown>
+    </imapserver>
+    <imapserver enabled="true">
+        <jmxName>imapserver-ssl</jmxName>
+        <bind>0.0.0.0:0</bind>
+        <connectionBacklog>200</connectionBacklog>
+        <tls socketTLS="false" startTLS="true">
+            <!-- To create a new keystore execute:
+              keytool -genkey -alias james -keyalg RSA -keystore /path/to/james/conf/keystore
+             -->
+            <keystore>classpath://keystore</keystore>
+            <secret>james72laBalle</secret>
+            <provider>org.bouncycastle.jce.provider.BouncyCastleProvider</provider>
+        </tls>
+        <connectionLimit>0</connectionLimit>
+        <connectionLimitPerIP>0</connectionLimitPerIP>
+        <gracefulShutdown>false</gracefulShutdown>
+    </imapserver>
+    <imapserver enabled="true">
+        <jmxName>imapserver-ssl2</jmxName>
+        <bind>0.0.0.0:0</bind>
+        <connectionBacklog>200</connectionBacklog>
+        <tls socketTLS="true" startTLS="false">
+            <!-- To create a new keystore execute:
+              keytool -genkey -alias james -keyalg RSA -keystore /path/to/james/conf/keystore
+             -->
+            <keystore>file://conf/keystore</keystore>
+            <secret>james72laBalle</secret>
+            <provider>org.bouncycastle.jce.provider.BouncyCastleProvider</provider>
+        </tls>
+        <connectionLimit>0</connectionLimit>
+        <connectionLimitPerIP>0</connectionLimitPerIP>
+        <gracefulShutdown>false</gracefulShutdown>
+    </imapserver>
+</imapservers>
diff --git a/server/apps/memory-app/src/test/resources/jwt_publickey b/server/apps/memory-app/src/test/resources/jwt_publickey
new file mode 100644
index 0000000000..53914e0533
--- /dev/null
+++ b/server/apps/memory-app/src/test/resources/jwt_publickey
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtlChO/nlVP27MpdkG0Bh
+16XrMRf6M4NeyGa7j5+1UKm42IKUf3lM28oe82MqIIRyvskPc11NuzSor8HmvH8H
+lhDs5DyJtx2qp35AT0zCqfwlaDnlDc/QDlZv1CoRZGpQk1Inyh6SbZwYpxxwh0fi
++d/4RpE3LBVo8wgOaXPylOlHxsDizfkL8QwXItyakBfMO6jWQRrj7/9WDhGf4Hi+
+GQur1tPGZDl9mvCoRHjFrD5M/yypIPlfMGWFVEvV5jClNMLAQ9bYFuOc7H1fEWw6
+U1LZUUbJW9/CH45YXz82CYqkrfbnQxqRb2iVbVjs/sHopHd1NTiCfUtwvcYJiBVj
+kwIDAQAB
+-----END PUBLIC KEY-----
diff --git a/server/apps/memory-app/src/test/resources/keystore2 b/server/apps/memory-app/src/test/resources/keystore2
new file mode 100644
index 0000000000..0b343bbc21
Binary files /dev/null and b/server/apps/memory-app/src/test/resources/keystore2 differ
diff --git a/server/apps/memory-app/src/test/resources/smtpserver2.xml b/server/apps/memory-app/src/test/resources/smtpserver2.xml
new file mode 100644
index 0000000000..713a16d893
--- /dev/null
+++ b/server/apps/memory-app/src/test/resources/smtpserver2.xml
@@ -0,0 +1,136 @@
+<?xml version="1.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.
+ -->
+
+<smtpservers>
+    <smtpserver enabled="true">
+        <jmxName>smtpserver-global</jmxName>
+        <bind>0.0.0.0:0</bind>
+        <connectionBacklog>200</connectionBacklog>
+        <tls socketTLS="false" startTLS="false">
+            <keystore>file://conf/keystore</keystore>
+            <secret>james72laBalle</secret>
+            <provider>org.bouncycastle.jce.provider.BouncyCastleProvider</provider>
+            <algorithm>SunX509</algorithm>
+        </tls>
+        <connectiontimeout>360</connectiontimeout>
+        <connectionLimit>0</connectionLimit>
+        <connectionLimitPerIP>0</connectionLimitPerIP>
+        <auth>
+            <announce>never</announce>
+            <requireSSL>false</requireSSL>
+        </auth>
+        <verifyIdentity>false</verifyIdentity>
+        <maxmessagesize>0</maxmessagesize>
+        <addressBracketsEnforcement>true</addressBracketsEnforcement>
+        <smtpGreeting>Apache JAMES awesome SMTP Server</smtpGreeting>
+        <handlerchain>
+            <handler class="org.apache.james.smtpserver.fastfail.ValidRcptHandler"/>
+            <handler class="org.apache.james.smtpserver.CoreCmdHandlerLoader"/>
+        </handlerchain>
+        <gracefulShutdown>false</gracefulShutdown>
+    </smtpserver>
+    <smtpserver enabled="true">
+        <jmxName>smtpserver-TLS</jmxName>
+        <bind>0.0.0.0:0</bind>
+        <connectionBacklog>200</connectionBacklog>
+        <tls socketTLS="false" startTLS="false">
+            <keystore>file://conf/keystore</keystore>
+            <secret>james72laBalle</secret>
+            <provider>org.bouncycastle.jce.provider.BouncyCastleProvider</provider>
+            <algorithm>SunX509</algorithm>
+        </tls>
+        <connectiontimeout>360</connectiontimeout>
+        <connectionLimit>0</connectionLimit>
+        <connectionLimitPerIP>0</connectionLimitPerIP>
+        <auth>
+            <announce>forUnauthorizedAddresses</announce>
+            <requireSSL>false</requireSSL>
+        </auth>
+        <!-- Trust authenticated users -->
+        <verifyIdentity>false</verifyIdentity>
+        <maxmessagesize>0</maxmessagesize>
+        <addressBracketsEnforcement>true</addressBracketsEnforcement>
+        <smtpGreeting>Apache JAMES awesome SMTP Server</smtpGreeting>
+        <handlerchain>
+            <handler class="org.apache.james.smtpserver.fastfail.ValidRcptHandler"/>
+            <handler class="org.apache.james.smtpserver.CoreCmdHandlerLoader"/>
+        </handlerchain>
+        <gracefulShutdown>false</gracefulShutdown>
+    </smtpserver>
+    <smtpserver enabled="true">
+        <jmxName>smtpserver-authenticated</jmxName>
+        <bind>0.0.0.0:0</bind>
+        <connectionBacklog>200</connectionBacklog>
+        <tls socketTLS="false" startTLS="false">
+            <keystore>file://conf/keystore</keystore>
+            <secret>james72laBalle</secret>
+            <provider>org.bouncycastle.jce.provider.BouncyCastleProvider</provider>
+            <algorithm>SunX509</algorithm>
+        </tls>
+        <connectiontimeout>360</connectiontimeout>
+        <connectionLimit>0</connectionLimit>
+        <connectionLimitPerIP>0</connectionLimitPerIP>
+        <auth>
+            <announce>forUnauthorizedAddresses</announce>
+            <requireSSL>false</requireSSL>
+        </auth>
+        <!-- Trust authenticated users -->
+        <verifyIdentity>false</verifyIdentity>
+        <maxmessagesize>0</maxmessagesize>
+        <addressBracketsEnforcement>true</addressBracketsEnforcement>
+        <smtpGreeting>Apache JAMES awesome SMTP Server</smtpGreeting>
+        <handlerchain>
+            <handler class="org.apache.james.smtpserver.fastfail.ValidRcptHandler"/>
+            <handler class="org.apache.james.smtpserver.CoreCmdHandlerLoader"/>
+        </handlerchain>
+        <gracefulShutdown>false</gracefulShutdown>
+    </smtpserver>
+    <smtpserver enabled="true">
+        <jmxName>smtpserver-ssl</jmxName>
+        <bind>0.0.0.0:0</bind>
+        <connectionBacklog>200</connectionBacklog>
+        <tls socketTLS="true" startTLS="false">
+            <keystore>file://conf/keystore</keystore>
+            <secret>james72laBalle</secret>
+            <provider>org.bouncycastle.jce.provider.BouncyCastleProvider</provider>
+            <algorithm>SunX509</algorithm>
+        </tls>
+        <connectiontimeout>360</connectiontimeout>
+        <connectionLimit>0</connectionLimit>
+        <connectionLimitPerIP>0</connectionLimitPerIP>
+        <auth>
+            <announce>forUnauthorizedAddresses</announce>
+            <requireSSL>false</requireSSL>
+        </auth>
+        <!-- Trust authenticated users -->
+        <verifyIdentity>false</verifyIdentity>
+        <maxmessagesize>0</maxmessagesize>
+        <addressBracketsEnforcement>true</addressBracketsEnforcement>
+        <smtpGreeting>Apache JAMES awesome SMTP Server</smtpGreeting>
+        <handlerchain>
+            <handler class="org.apache.james.smtpserver.fastfail.ValidRcptHandler"/>
+            <handler class="org.apache.james.smtpserver.CoreCmdHandlerLoader"/>
+        </handlerchain>
+        <gracefulShutdown>false</gracefulShutdown>
+    </smtpserver>
+</smtpservers>
+
+
diff --git a/server/container/guice/common/src/main/java/org/apache/james/TemporaryJamesServer.java b/server/container/guice/common/src/main/java/org/apache/james/TemporaryJamesServer.java
index 231d3586c2..ed4f330123 100644
--- a/server/container/guice/common/src/main/java/org/apache/james/TemporaryJamesServer.java
+++ b/server/container/guice/common/src/main/java/org/apache/james/TemporaryJamesServer.java
@@ -25,12 +25,10 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.URL;
-import java.nio.charset.StandardCharsets;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.List;
 
-import org.apache.commons.io.IOUtils;
 import org.apache.james.server.core.configuration.Configuration;
 
 import com.google.common.collect.ImmutableList;
@@ -77,19 +75,17 @@ public class TemporaryJamesServer {
         return jamesServer;
     }
 
-    public void appendConfigurationFile(String configurationData, String configurationFileName) throws IOException {
-        try (OutputStream outputStream = new FileOutputStream(Paths.get(configurationFolder.getAbsolutePath(), configurationFileName).toFile())) {
-            IOUtils.write(configurationData, outputStream, StandardCharsets.UTF_8);
-        }
-    }
-
     private void copyResources(Path resourcesFolder) {
         configurationFileNames
-            .forEach(resourceName -> copyResource(resourcesFolder, resourceName));
+            .forEach(resourceName -> copyResource(resourcesFolder, resourceName, resourceName));
+    }
+
+    public void copyResources(String resourceName, String targetName) {
+        copyResource(Paths.get(configurationFolder.getAbsolutePath()), resourceName, targetName);
     }
 
-    public static void copyResource(Path resourcesFolder, String resourceName) {
-        var resolvedResource = resourcesFolder.resolve(resourceName);
+    public static void copyResource(Path resourcesFolder, String resourceName, String targetName) {
+        var resolvedResource = resourcesFolder.resolve(targetName);
         try (OutputStream outputStream = new FileOutputStream(resolvedResource.toFile())) {
             URL resource = ClassLoader.getSystemClassLoader().getResource(resourceName);
             if (resource != null) {
diff --git a/server/container/guice/protocols/imap/src/main/java/org/apache/james/modules/protocols/ImapGuiceProbe.java b/server/container/guice/protocols/imap/src/main/java/org/apache/james/modules/protocols/ImapGuiceProbe.java
index a9bc25a856..5be2ebcae8 100644
--- a/server/container/guice/protocols/imap/src/main/java/org/apache/james/modules/protocols/ImapGuiceProbe.java
+++ b/server/container/guice/protocols/imap/src/main/java/org/apache/james/modules/protocols/ImapGuiceProbe.java
@@ -49,11 +49,16 @@ public class ImapGuiceProbe implements GuiceProbe {
             .orElseThrow(() -> new IllegalStateException("IMAP server not defined"));
     }
 
-    public int getImapsPort() {
+    public int getImapStartTLSPort() {
         return getPort(AbstractConfigurableAsyncServer::getStartTLSSupported)
             .orElseThrow(() -> new IllegalStateException("IMAPS server not defined"));
     }
 
+    public int getImapSSLPort() {
+        return getPort(server -> server.getSocketType().equals("secure"))
+            .orElseThrow(() -> new IllegalStateException("IMAPS server not defined"));
+    }
+
     private Optional<Integer> getPort(Predicate<? super AbstractConfigurableAsyncServer> filter) {
         return imapServerFactory.getServers().stream()
             .filter(filter)
diff --git a/server/container/guice/protocols/smtp/src/main/java/org/apache/james/modules/protocols/SmtpGuiceProbe.java b/server/container/guice/protocols/smtp/src/main/java/org/apache/james/modules/protocols/SmtpGuiceProbe.java
index 4c8ebaf0ed..ed07df2af4 100644
--- a/server/container/guice/protocols/smtp/src/main/java/org/apache/james/modules/protocols/SmtpGuiceProbe.java
+++ b/server/container/guice/protocols/smtp/src/main/java/org/apache/james/modules/protocols/SmtpGuiceProbe.java
@@ -64,6 +64,13 @@ public class SmtpGuiceProbe implements GuiceProbe {
         return getPort(AbstractConfigurableAsyncServer::getStartTLSSupported);
     }
 
+    public Port getSmtpSslPort() {
+        return getPort(server -> {
+            System.out.println(server.getServiceType());
+            return server.getSocketType().equals("secure");
+        });
+    }
+
     public Port getSmtpAuthRequiredPort() {
         return getPort(server -> ((SMTPServer) server).getAuthRequired().equals(FOR_UNAUTHORIZED_ADDRESSES));
     }
diff --git a/server/protocols/protocols-library/src/main/java/org/apache/james/protocols/lib/netty/AbstractConfigurableAsyncServer.java b/server/protocols/protocols-library/src/main/java/org/apache/james/protocols/lib/netty/AbstractConfigurableAsyncServer.java
index b6ded174ed..777026bab2 100644
--- a/server/protocols/protocols-library/src/main/java/org/apache/james/protocols/lib/netty/AbstractConfigurableAsyncServer.java
+++ b/server/protocols/protocols-library/src/main/java/org/apache/james/protocols/lib/netty/AbstractConfigurableAsyncServer.java
@@ -463,7 +463,7 @@ public abstract class AbstractConfigurableAsyncServer
     protected AbstractChannelPipelineFactory createPipelineFactory() {
         return new AbstractSSLAwareChannelPipelineFactory<>(getTimeout(), connectionLimit, connPerIP,
             proxyRequired,
-            getEncryption(), getFrameHandlerFactory(), getExecutorGroup()) {
+            this::getEncryption, getFrameHandlerFactory(), getExecutorGroup()) {
 
             @Override
             protected ChannelInboundHandlerAdapter createHandler() {


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