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/14 06:59:34 UTC

[james-project] 12/28: JAMES-3906 Add hot reloading/updating of the certificate: new interface with reloadSSLCertificate() method; new abstract class AbstractServerRoutes with implementation for all available/known servers; fix issue with `ManageSieveServerFactory` not being singleton causing issues

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

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

commit 666e32e275a1c7d80800eb9f48a5c2c0ed2df659
Author: Wojciech Kapcia <wo...@tigase.org>
AuthorDate: Thu May 11 17:35:22 2023 -0400

    JAMES-3906 Add hot reloading/updating of the certificate: new interface with reloadSSLCertificate() method; new abstract class AbstractServerRoutes with implementation for all available/known servers; fix issue with `ManageSieveServerFactory` not being singleton causing issues
---
 .../james/modules/protocols/IMAPServerModule.java  |  4 +++
 .../james/modules/protocols/LMTPServerModule.java  |  4 +++
 .../modules/protocols/ManageSieveServerModule.java |  4 +++
 .../james/modules/protocols/POP3ServerModule.java  |  4 +++
 .../james/modules/protocols/SMTPServerModule.java  |  4 +++
 .../james/imapserver/webadmin/ImapRoutes.java      | 22 ++++++++++++
 server/protocols/protocols-library/pom.xml         |  4 +++
 .../lib/netty/AbstractConfigurableAsyncServer.java |  9 ++++-
 .../protocols/lib/netty/AbstractServerFactory.java |  2 ++
 .../protocols/lib/netty/CertificateReloadable.java |  6 ++++
 .../lib/webadmin/AbstractServerRoutes.java         | 42 ++++++++++++++++++++++
 .../james/lmtpserver/webadmin/LMTPRoutes.java      | 21 +++++++++++
 .../webadmin/ManageSieveRoutes.java                | 21 +++++++++++
 .../james/pop3server/webadmin/POP3Routes.java      | 21 +++++++++++
 .../james/smtpserver/webadmin/SmtpRoutes.java      | 21 +++++++++++
 15 files changed, 188 insertions(+), 1 deletion(-)

diff --git a/server/container/guice/protocols/imap/src/main/java/org/apache/james/modules/protocols/IMAPServerModule.java b/server/container/guice/protocols/imap/src/main/java/org/apache/james/modules/protocols/IMAPServerModule.java
index 082240b01e..0d84991d97 100644
--- a/server/container/guice/protocols/imap/src/main/java/org/apache/james/modules/protocols/IMAPServerModule.java
+++ b/server/container/guice/protocols/imap/src/main/java/org/apache/james/modules/protocols/IMAPServerModule.java
@@ -57,6 +57,7 @@ import org.apache.james.imap.processor.SelectProcessor;
 import org.apache.james.imap.processor.base.AbstractProcessor;
 import org.apache.james.imap.processor.base.UnknownRequestProcessor;
 import org.apache.james.imapserver.netty.IMAPServerFactory;
+import org.apache.james.imapserver.webadmin.ImapRoutes;
 import org.apache.james.lifecycle.api.ConfigurationSanitizer;
 import org.apache.james.metrics.api.GaugeRegistry;
 import org.apache.james.metrics.api.MetricFactory;
@@ -67,6 +68,7 @@ import org.apache.james.utils.GuiceProbe;
 import org.apache.james.utils.InitializationOperation;
 import org.apache.james.utils.InitilizationOperationBuilder;
 import org.apache.james.utils.KeystoreCreator;
+import org.apache.james.webadmin.Routes;
 
 import com.github.fge.lambdas.Throwing;
 import com.google.common.collect.ImmutableList;
@@ -99,6 +101,8 @@ public class IMAPServerModule extends AbstractModule {
         bind(MailboxTyper.class).to(DefaultMailboxTyper.class).in(Scopes.SINGLETON);
 
         Multibinder.newSetBinder(binder(), GuiceProbe.class).addBinding().to(ImapGuiceProbe.class);
+
+        Multibinder.newSetBinder(binder(), Routes.class).addBinding().to(ImapRoutes.class);
     }
 
     @Provides
diff --git a/server/container/guice/protocols/lmtp/src/main/java/org/apache/james/modules/protocols/LMTPServerModule.java b/server/container/guice/protocols/lmtp/src/main/java/org/apache/james/modules/protocols/LMTPServerModule.java
index 60ed8c28fd..168d2f7027 100644
--- a/server/container/guice/protocols/lmtp/src/main/java/org/apache/james/modules/protocols/LMTPServerModule.java
+++ b/server/container/guice/protocols/lmtp/src/main/java/org/apache/james/modules/protocols/LMTPServerModule.java
@@ -24,12 +24,14 @@ import org.apache.james.RunArguments;
 import org.apache.james.filesystem.api.FileSystem;
 import org.apache.james.lifecycle.api.ConfigurationSanitizer;
 import org.apache.james.lmtpserver.netty.LMTPServerFactory;
+import org.apache.james.lmtpserver.webadmin.LMTPRoutes;
 import org.apache.james.server.core.configuration.ConfigurationProvider;
 import org.apache.james.util.LoggingLevel;
 import org.apache.james.utils.GuiceProbe;
 import org.apache.james.utils.InitializationOperation;
 import org.apache.james.utils.InitilizationOperationBuilder;
 import org.apache.james.utils.KeystoreCreator;
+import org.apache.james.webadmin.Routes;
 
 import com.google.inject.AbstractModule;
 import com.google.inject.Scopes;
@@ -42,6 +44,8 @@ public class LMTPServerModule extends AbstractModule {
         bind(LMTPServerFactory.class).in(Scopes.SINGLETON);
 
         Multibinder.newSetBinder(binder(), GuiceProbe.class).addBinding().to(LmtpGuiceProbe.class);
+
+        Multibinder.newSetBinder(binder(), Routes.class).addBinding().to(LMTPRoutes.class);
     }
 
     @ProvidesIntoSet
diff --git a/server/container/guice/protocols/managedsieve/src/main/java/org/apache/james/modules/protocols/ManageSieveServerModule.java b/server/container/guice/protocols/managedsieve/src/main/java/org/apache/james/modules/protocols/ManageSieveServerModule.java
index 8c983e46da..9ec6101d8e 100644
--- a/server/container/guice/protocols/managedsieve/src/main/java/org/apache/james/modules/protocols/ManageSieveServerModule.java
+++ b/server/container/guice/protocols/managedsieve/src/main/java/org/apache/james/modules/protocols/ManageSieveServerModule.java
@@ -25,12 +25,14 @@ import org.apache.james.lifecycle.api.ConfigurationSanitizer;
 import org.apache.james.managesieve.api.commands.CoreCommands;
 import org.apache.james.managesieve.core.CoreProcessor;
 import org.apache.james.managesieveserver.netty.ManageSieveServerFactory;
+import org.apache.james.managesieveserver.webadmin.ManageSieveRoutes;
 import org.apache.james.server.core.configuration.ConfigurationProvider;
 import org.apache.james.util.LoggingLevel;
 import org.apache.james.utils.GuiceProbe;
 import org.apache.james.utils.InitializationOperation;
 import org.apache.james.utils.InitilizationOperationBuilder;
 import org.apache.james.utils.KeystoreCreator;
+import org.apache.james.webadmin.Routes;
 
 import com.google.inject.AbstractModule;
 import com.google.inject.multibindings.Multibinder;
@@ -43,6 +45,8 @@ public class ManageSieveServerModule extends AbstractModule {
         install(new SieveModule());
         bind(CoreCommands.class).to(CoreProcessor.class);
         Multibinder.newSetBinder(binder(), GuiceProbe.class).addBinding().to(SieveProbeImpl.class);
+
+        Multibinder.newSetBinder(binder(), Routes.class).addBinding().to(ManageSieveRoutes.class);
     }
 
     @ProvidesIntoSet
diff --git a/server/container/guice/protocols/pop/src/main/java/org/apache/james/modules/protocols/POP3ServerModule.java b/server/container/guice/protocols/pop/src/main/java/org/apache/james/modules/protocols/POP3ServerModule.java
index bc00a306da..e22859ff34 100644
--- a/server/container/guice/protocols/pop/src/main/java/org/apache/james/modules/protocols/POP3ServerModule.java
+++ b/server/container/guice/protocols/pop/src/main/java/org/apache/james/modules/protocols/POP3ServerModule.java
@@ -26,11 +26,13 @@ import org.apache.james.lifecycle.api.ConfigurationSanitizer;
 import org.apache.james.pop3server.mailbox.DefaultMailboxAdapterFactory;
 import org.apache.james.pop3server.mailbox.MailboxAdapterFactory;
 import org.apache.james.pop3server.netty.POP3ServerFactory;
+import org.apache.james.pop3server.webadmin.POP3Routes;
 import org.apache.james.server.core.configuration.ConfigurationProvider;
 import org.apache.james.utils.GuiceProbe;
 import org.apache.james.utils.InitializationOperation;
 import org.apache.james.utils.InitilizationOperationBuilder;
 import org.apache.james.utils.KeystoreCreator;
+import org.apache.james.webadmin.Routes;
 
 import com.google.inject.AbstractModule;
 import com.google.inject.Scopes;
@@ -46,6 +48,8 @@ public class POP3ServerModule extends AbstractModule {
         bind(MailboxAdapterFactory.class).to(DefaultMailboxAdapterFactory.class);
 
         Multibinder.newSetBinder(binder(), GuiceProbe.class).addBinding().to(Pop3GuiceProbe.class);
+
+        Multibinder.newSetBinder(binder(), Routes.class).addBinding().to(POP3Routes.class);
     }
 
     @ProvidesIntoSet
diff --git a/server/container/guice/protocols/smtp/src/main/java/org/apache/james/modules/protocols/SMTPServerModule.java b/server/container/guice/protocols/smtp/src/main/java/org/apache/james/modules/protocols/SMTPServerModule.java
index 22b541da5d..8ba9378900 100644
--- a/server/container/guice/protocols/smtp/src/main/java/org/apache/james/modules/protocols/SMTPServerModule.java
+++ b/server/container/guice/protocols/smtp/src/main/java/org/apache/james/modules/protocols/SMTPServerModule.java
@@ -26,10 +26,12 @@ import org.apache.james.lifecycle.api.ConfigurationSanitizer;
 import org.apache.james.server.core.configuration.ConfigurationProvider;
 import org.apache.james.smtpserver.SendMailHandler;
 import org.apache.james.smtpserver.netty.SMTPServerFactory;
+import org.apache.james.smtpserver.webadmin.SmtpRoutes;
 import org.apache.james.utils.GuiceProbe;
 import org.apache.james.utils.InitializationOperation;
 import org.apache.james.utils.InitilizationOperationBuilder;
 import org.apache.james.utils.KeystoreCreator;
+import org.apache.james.webadmin.Routes;
 
 import com.google.inject.AbstractModule;
 import com.google.inject.Scopes;
@@ -43,6 +45,8 @@ public class SMTPServerModule extends AbstractModule {
         bind(SMTPServerFactory.class).in(Scopes.SINGLETON);
 
         Multibinder.newSetBinder(binder(), GuiceProbe.class).addBinding().to(SmtpGuiceProbe.class);
+
+        Multibinder.newSetBinder(binder(), Routes.class).addBinding().to(SmtpRoutes.class);
     }
 
     @ProvidesIntoSet
diff --git a/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/webadmin/ImapRoutes.java b/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/webadmin/ImapRoutes.java
new file mode 100644
index 0000000000..843106583c
--- /dev/null
+++ b/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/webadmin/ImapRoutes.java
@@ -0,0 +1,22 @@
+package org.apache.james.imapserver.webadmin;
+
+import javax.inject.Inject;
+
+import org.apache.james.imapserver.netty.IMAPServerFactory;
+import org.apache.james.protocols.lib.webadmin.AbstractServerRoutes;
+
+public class ImapRoutes
+        extends AbstractServerRoutes {
+
+    public static final String BASE_PATH = "/imap";
+
+    @Inject
+    public ImapRoutes(IMAPServerFactory imapServerFactory) {
+        this.serverFactory = imapServerFactory;
+    }
+
+    @Override
+    public String getBasePath() {
+        return BASE_PATH;
+    }
+}
\ No newline at end of file
diff --git a/server/protocols/protocols-library/pom.xml b/server/protocols/protocols-library/pom.xml
index ffda3f0739..c527fe454d 100644
--- a/server/protocols/protocols-library/pom.xml
+++ b/server/protocols/protocols-library/pom.xml
@@ -52,6 +52,10 @@
                 </exclusion>
             </exclusions>
         </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
+            <artifactId>james-server-webadmin-core</artifactId>
+        </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
             <artifactId>metrics-api</artifactId>
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 76e8152a6b..b6ded174ed 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
@@ -61,7 +61,10 @@ import io.netty.util.concurrent.EventExecutorGroup;
 /**
  * Abstract base class for Servers for all James Servers
  */
-public abstract class AbstractConfigurableAsyncServer extends AbstractAsyncServer implements Configurable, ServerMBean {
+public abstract class AbstractConfigurableAsyncServer
+        extends AbstractAsyncServer
+        implements CertificateReloadable, Configurable, ServerMBean {
+
     private static final Logger LOGGER = LoggerFactory.getLogger(AbstractConfigurableAsyncServer.class);
 
     /** The default value for the connection backlog. */
@@ -360,6 +363,10 @@ public abstract class AbstractConfigurableAsyncServer extends AbstractAsyncServe
         }
     }
 
+    public void reloadSSLCertificate() throws Exception {
+        buildSSLContext();
+    }
+
     /**
      * Return the default port which will get used for this server if non is
      * specify in the configuration
diff --git a/server/protocols/protocols-library/src/main/java/org/apache/james/protocols/lib/netty/AbstractServerFactory.java b/server/protocols/protocols-library/src/main/java/org/apache/james/protocols/lib/netty/AbstractServerFactory.java
index bf672d5efa..1a9d3d202f 100644
--- a/server/protocols/protocols-library/src/main/java/org/apache/james/protocols/lib/netty/AbstractServerFactory.java
+++ b/server/protocols/protocols-library/src/main/java/org/apache/james/protocols/lib/netty/AbstractServerFactory.java
@@ -23,6 +23,7 @@ import java.util.List;
 
 import javax.annotation.PostConstruct;
 import javax.annotation.PreDestroy;
+import javax.inject.Singleton;
 
 import org.apache.commons.configuration2.HierarchicalConfiguration;
 import org.apache.commons.configuration2.tree.ImmutableNode;
@@ -31,6 +32,7 @@ import org.apache.james.lifecycle.api.Configurable;
 /**
  * Abstract base class for Factories that need to create {@link AbstractConfigurableAsyncServer}'s via configuration files
  */
+@Singleton
 public abstract class AbstractServerFactory implements Configurable {
 
     private List<AbstractConfigurableAsyncServer> servers;
diff --git a/server/protocols/protocols-library/src/main/java/org/apache/james/protocols/lib/netty/CertificateReloadable.java b/server/protocols/protocols-library/src/main/java/org/apache/james/protocols/lib/netty/CertificateReloadable.java
new file mode 100644
index 0000000000..7ac6f2a44b
--- /dev/null
+++ b/server/protocols/protocols-library/src/main/java/org/apache/james/protocols/lib/netty/CertificateReloadable.java
@@ -0,0 +1,6 @@
+package org.apache.james.protocols.lib.netty;
+
+public interface CertificateReloadable {
+
+    void reloadSSLCertificate() throws Exception;
+}
diff --git a/server/protocols/protocols-library/src/main/java/org/apache/james/protocols/lib/webadmin/AbstractServerRoutes.java b/server/protocols/protocols-library/src/main/java/org/apache/james/protocols/lib/webadmin/AbstractServerRoutes.java
new file mode 100644
index 0000000000..baaa2d4606
--- /dev/null
+++ b/server/protocols/protocols-library/src/main/java/org/apache/james/protocols/lib/webadmin/AbstractServerRoutes.java
@@ -0,0 +1,42 @@
+package org.apache.james.protocols.lib.webadmin;
+
+import org.apache.james.protocols.lib.netty.AbstractConfigurableAsyncServer;
+import org.apache.james.protocols.lib.netty.AbstractServerFactory;
+import org.apache.james.webadmin.Routes;
+import org.apache.james.webadmin.utils.ErrorResponder;
+import org.apache.james.webadmin.utils.Responses;
+import org.eclipse.jetty.http.HttpStatus;
+
+import com.google.common.base.Preconditions;
+
+import spark.Service;
+
+public abstract class AbstractServerRoutes
+        implements Routes {
+
+    protected AbstractServerFactory serverFactory;
+
+    @Override
+    public void define(Service service) {
+        service.post(getBasePath(), (request, response) -> {
+            Preconditions.checkArgument(request.queryParams().contains("reload-certificate"),
+                    "'reload-certificate' query parameter shall be specified");
+
+            if (serverFactory.getServers() == null
+                    || serverFactory.getServers().isEmpty()
+                    || serverFactory.getServers().stream().noneMatch(AbstractConfigurableAsyncServer::isEnabled)) {
+                return ErrorResponder.builder()
+                        .statusCode(HttpStatus.BAD_REQUEST_400)
+                        .type(ErrorResponder.ErrorType.NOT_FOUND)
+                        .message("No servers configured, nothing to reload")
+                        .haltError();
+            }
+
+            for (AbstractConfigurableAsyncServer server : serverFactory.getServers()) {
+                server.reloadSSLCertificate();
+            }
+
+            return Responses.returnNoContent(response);
+        });
+    }
+}
\ No newline at end of file
diff --git a/server/protocols/protocols-lmtp/src/main/java/org/apache/james/lmtpserver/webadmin/LMTPRoutes.java b/server/protocols/protocols-lmtp/src/main/java/org/apache/james/lmtpserver/webadmin/LMTPRoutes.java
new file mode 100644
index 0000000000..ac949aad95
--- /dev/null
+++ b/server/protocols/protocols-lmtp/src/main/java/org/apache/james/lmtpserver/webadmin/LMTPRoutes.java
@@ -0,0 +1,21 @@
+package org.apache.james.lmtpserver.webadmin;
+
+import javax.inject.Inject;
+
+import org.apache.james.lmtpserver.netty.LMTPServerFactory;
+import org.apache.james.protocols.lib.webadmin.AbstractServerRoutes;
+
+public class LMTPRoutes extends AbstractServerRoutes {
+
+    public static final String BASE_PATH = "/lmtp";
+
+    @Inject
+    public LMTPRoutes(LMTPServerFactory lmtpServerFactory) {
+        this.serverFactory = lmtpServerFactory;
+    }
+
+    @Override
+    public String getBasePath() {
+        return BASE_PATH;
+    }
+}
\ No newline at end of file
diff --git a/server/protocols/protocols-managesieve/src/main/java/org/apache/james/managesieveserver/webadmin/ManageSieveRoutes.java b/server/protocols/protocols-managesieve/src/main/java/org/apache/james/managesieveserver/webadmin/ManageSieveRoutes.java
new file mode 100644
index 0000000000..6aa01b7b27
--- /dev/null
+++ b/server/protocols/protocols-managesieve/src/main/java/org/apache/james/managesieveserver/webadmin/ManageSieveRoutes.java
@@ -0,0 +1,21 @@
+package org.apache.james.managesieveserver.webadmin;
+
+import javax.inject.Inject;
+
+import org.apache.james.managesieveserver.netty.ManageSieveServerFactory;
+import org.apache.james.protocols.lib.webadmin.AbstractServerRoutes;
+
+public class ManageSieveRoutes extends AbstractServerRoutes {
+
+    public static final String BASE_PATH = "/sieve";
+
+    @Inject
+    public ManageSieveRoutes(ManageSieveServerFactory manageSieveServerFactory) {
+        this.serverFactory = manageSieveServerFactory;
+    }
+
+    @Override
+    public String getBasePath() {
+        return BASE_PATH;
+    }
+}
\ No newline at end of file
diff --git a/server/protocols/protocols-pop3/src/main/java/org/apache/james/pop3server/webadmin/POP3Routes.java b/server/protocols/protocols-pop3/src/main/java/org/apache/james/pop3server/webadmin/POP3Routes.java
new file mode 100644
index 0000000000..7e41923ea4
--- /dev/null
+++ b/server/protocols/protocols-pop3/src/main/java/org/apache/james/pop3server/webadmin/POP3Routes.java
@@ -0,0 +1,21 @@
+package org.apache.james.pop3server.webadmin;
+
+import javax.inject.Inject;
+
+import org.apache.james.pop3server.netty.POP3ServerFactory;
+import org.apache.james.protocols.lib.webadmin.AbstractServerRoutes;
+
+public class POP3Routes extends AbstractServerRoutes {
+
+    public static final String BASE_PATH = "/pop3";
+
+    @Inject
+    public POP3Routes(POP3ServerFactory pop3ServerFactory) {
+        this.serverFactory = pop3ServerFactory;
+    }
+
+    @Override
+    public String getBasePath() {
+        return BASE_PATH;
+    }
+}
\ No newline at end of file
diff --git a/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/webadmin/SmtpRoutes.java b/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/webadmin/SmtpRoutes.java
new file mode 100644
index 0000000000..79d409cc86
--- /dev/null
+++ b/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/webadmin/SmtpRoutes.java
@@ -0,0 +1,21 @@
+package org.apache.james.smtpserver.webadmin;
+
+import javax.inject.Inject;
+
+import org.apache.james.protocols.lib.webadmin.AbstractServerRoutes;
+import org.apache.james.smtpserver.netty.SMTPServerFactory;
+
+public class SmtpRoutes extends AbstractServerRoutes {
+
+    public static final String BASE_PATH = "/smtp";
+
+    @Inject
+    public SmtpRoutes(SMTPServerFactory imapServerFactory) {
+        this.serverFactory = imapServerFactory;
+    }
+
+    @Override
+    public String getBasePath() {
+        return BASE_PATH;
+    }
+}
\ No newline at end of file


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