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 877e361c3e4348445c2cb54ba9a2b63d22390389 Author: Benoit TELLIER <btell...@linagora.com> AuthorDate: Tue Dec 19 18:13:25 2023 +0100 [FIX] Set up JMX auth for Spring This prevents un-authenticated user from triggering deserialization exploits which could be exploited for privilege escalation. --- .../src/main/java/org/apache/james/cli/ServerCmd.java | 12 +++++++++++- .../spring-app/src/main/resources/jmxremote.access | 1 + .../spring-app/src/main/resources/jmxremote.password | 1 + .../james/app/spring/JamesAppSpringMainTest.java | 17 +++++++++++++++++ .../james/app/spring/JamesSpringContextTest.java | 18 +++++++++++++++++- .../META-INF/org/apache/james/spring-server.xml | 7 +++++++ upgrade-instructions.md | 8 ++++++++ 7 files changed, 62 insertions(+), 2 deletions(-) diff --git a/server/apps/cli/src/main/java/org/apache/james/cli/ServerCmd.java b/server/apps/cli/src/main/java/org/apache/james/cli/ServerCmd.java index aa25f95de3..b1f4058791 100644 --- a/server/apps/cli/src/main/java/org/apache/james/cli/ServerCmd.java +++ b/server/apps/cli/src/main/java/org/apache/james/cli/ServerCmd.java @@ -121,7 +121,7 @@ public class ServerCmd { public static void executeAndOutputToStream(String[] args, PrintStream printStream) throws Exception { Stopwatch stopWatch = Stopwatch.createStarted(); CommandLine cmd = parseCommandLine(args); - JmxConnection jmxConnection = new JmxConnection(getHost(cmd), getPort(cmd), getAuthCredential(cmd, JMX_PASSWORD_FILE_PATH_DEFAULT)); + JmxConnection jmxConnection = new JmxConnection(getHost(cmd), getPort(cmd), getAuthCredential(cmd, locateJmxConfiguration())); CmdType cmdType = new ServerCmd( new JmxDataProbe().connect(jmxConnection), @@ -135,6 +135,16 @@ public class ServerCmd { stopWatch.stop(); } + private static String locateJmxConfiguration() { + if (!new File(JMX_PASSWORD_FILE_PATH_DEFAULT).exists()) { + return JMX_PASSWORD_FILE_PATH_DEFAULT; + } + if (!new File("conf/jmxremote.password").exists()) { + return "conf/jmxremote.password"; + } + return "../conf/jmxremote.password"; + } + private final JmxDataProbe probe; private final JmxMailboxProbe mailboxProbe; private final JmxQuotaProbe quotaProbe; diff --git a/server/apps/spring-app/src/main/resources/jmxremote.access b/server/apps/spring-app/src/main/resources/jmxremote.access new file mode 100644 index 0000000000..09a7b6612a --- /dev/null +++ b/server/apps/spring-app/src/main/resources/jmxremote.access @@ -0,0 +1 @@ +james-admin readwrite \ No newline at end of file diff --git a/server/apps/spring-app/src/main/resources/jmxremote.password b/server/apps/spring-app/src/main/resources/jmxremote.password new file mode 100644 index 0000000000..f2ad9e9aee --- /dev/null +++ b/server/apps/spring-app/src/main/resources/jmxremote.password @@ -0,0 +1 @@ +james-admin changeme \ No newline at end of file diff --git a/server/apps/spring-app/src/test/java/org/apache/james/app/spring/JamesAppSpringMainTest.java b/server/apps/spring-app/src/test/java/org/apache/james/app/spring/JamesAppSpringMainTest.java index 3acc3a596d..52726603ee 100644 --- a/server/apps/spring-app/src/test/java/org/apache/james/app/spring/JamesAppSpringMainTest.java +++ b/server/apps/spring-app/src/test/java/org/apache/james/app/spring/JamesAppSpringMainTest.java @@ -18,11 +18,28 @@ ****************************************************************/ package org.apache.james.app.spring; +import java.io.File; +import java.io.FileOutputStream; + import org.junit.jupiter.api.Test; class JamesAppSpringMainTest { @Test void testServer() throws Exception { + File accessFile = new File("../conf/jmxremote.access"); + accessFile.getParentFile().mkdirs(); + accessFile.createNewFile(); + try (FileOutputStream out = new FileOutputStream(accessFile)) { + out.write("james-admin readwrite\r\n".getBytes()); + out.flush(); + } + File passwordFile = new File("../conf/jmxremote.password"); + passwordFile.createNewFile(); + try (FileOutputStream out = new FileOutputStream(passwordFile)) { + out.write("james-admin changeme\r\n".getBytes()); + out.flush(); + } + JamesAppSpringMain.main(null); } } diff --git a/server/apps/spring-app/src/test/java/org/apache/james/app/spring/JamesSpringContextTest.java b/server/apps/spring-app/src/test/java/org/apache/james/app/spring/JamesSpringContextTest.java index 8d2560a1fa..b65462d8cf 100644 --- a/server/apps/spring-app/src/test/java/org/apache/james/app/spring/JamesSpringContextTest.java +++ b/server/apps/spring-app/src/test/java/org/apache/james/app/spring/JamesSpringContextTest.java @@ -21,6 +21,9 @@ package org.apache.james.app.spring; import static org.assertj.core.api.Assertions.assertThat; +import java.io.File; +import java.io.FileOutputStream; + import org.apache.james.container.spring.context.JamesServerApplicationContext; import org.apache.james.events.InVMEventBus; import org.apache.james.mailbox.lucene.search.LuceneMessageSearchIndex; @@ -34,7 +37,20 @@ class JamesSpringContextTest { private JamesServerApplicationContext context; @BeforeEach - void setup() { + void setup() throws Exception { + File accessFile = new File("../conf/jmxremote.access"); + accessFile.getParentFile().mkdirs(); + accessFile.createNewFile(); + try (FileOutputStream out = new FileOutputStream(accessFile)) { + out.write("james-admin readwrite\r\n".getBytes()); + out.flush(); + } + File passwordFile = new File("../conf/jmxremote.password"); + passwordFile.createNewFile(); + try (FileOutputStream out = new FileOutputStream(passwordFile)) { + out.write("james-admin changeme\r\n".getBytes()); + out.flush(); + } context = new JamesServerApplicationContext(new String[] { "META-INF/org/apache/james/spring-server.xml" }); context.registerShutdownHook(); context.start(); diff --git a/server/container/spring/src/main/resources/META-INF/org/apache/james/spring-server.xml b/server/container/spring/src/main/resources/META-INF/org/apache/james/spring-server.xml index 7e68e89591..27ab76901e 100644 --- a/server/container/spring/src/main/resources/META-INF/org/apache/james/spring-server.xml +++ b/server/container/spring/src/main/resources/META-INF/org/apache/james/spring-server.xml @@ -219,6 +219,13 @@ <property name="objectName" value="connector:name=rmi"/> <property name="serviceUrl" value="service:jmx:rmi://${jmx.address}/jndi/rmi://${jmx.address}:${jmx.port}/jmxrmi"/> + <property name="environment"> + <map> + <entry key="jmx.remote.x.password.file" value="../conf/jmxremote.password" /> + <entry key="jmx.remote.x.access.file" value="../conf/jmxremote.access" /> + <entry key="jmx.remote.rmi.server.credentials.filter.pattern" value="java.lang.String;!*"/> + </map> + </property> </bean> <bean id="registry" class="org.springframework.remoting.rmi.RmiRegistryFactoryBean"> diff --git a/upgrade-instructions.md b/upgrade-instructions.md index f9d0669b7f..a713e73113 100644 --- a/upgrade-instructions.md +++ b/upgrade-instructions.md @@ -25,6 +25,14 @@ Change list: - [Set up TTL on the mailbox_change and email_change tables](#set-up-ttl-on-the-mailboxchange-and-emailchange-tables) - [Change compaction strategy of blob_cache table](#change-compaction-strategy-of-blobcache-table) - [RRT forwards now rewrite senders](#rrt-forwards-now-rewrite-senders) + - [Increase RabbitMQ consumer timeout on the task queue](#increase-rabbitmq-consumer-timeout-on-the-task-queue) + - [JMX authentication for Spring](#jmx-authentication-for-spring) + +### JMX authentication for Spring + +Date: 19/12/2023 + +Spring distribution now requires `jmxremote.access` and `jmxremote.password` files within the `/conf` folder in order to start. ### Increase RabbitMQ consumer timeout on the task queue --------------------------------------------------------------------- To unsubscribe, e-mail: notifications-unsubscr...@james.apache.org For additional commands, e-mail: notifications-h...@james.apache.org