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 <woj...@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-unsubscr...@james.apache.org For additional commands, e-mail: notifications-h...@james.apache.org