diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/config/ActiveMQDefaultConfiguration.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/config/ActiveMQDefaultConfiguration.java
index 8547414abb..543dff0070 100644
--- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/config/ActiveMQDefaultConfiguration.java
+++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/config/ActiveMQDefaultConfiguration.java
@@ -421,6 +421,9 @@ public final class ActiveMQDefaultConfiguration {
// Will the broker populate the message with the name of the validated user
private static boolean DEFAULT_POPULATE_VALIDATED_USER = false;
+ // Will the broker allow messages with no validated user
+ private static boolean DEFAULT_REJECT_EMPTY_VALIDATED_USER = false;
+
// its possible that you only want a server to partake in scale down as a receiver, via a group. In this case set scale-down to false
private static boolean DEFAULT_SCALE_DOWN_ENABLED = true;
@@ -1252,6 +1255,10 @@ public final class ActiveMQDefaultConfiguration {
return DEFAULT_POPULATE_VALIDATED_USER;
}
+ public static boolean isDefaultRejectEmptyValidatedUser() {
+ return DEFAULT_REJECT_EMPTY_VALIDATED_USER;
+ }
+
/**
* its possible that you only want a server to partake in scale down as a receiver, via a group. In this case set scale-down to false
*/
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/Configuration.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/Configuration.java
index 783adcaa76..04a95cbe01 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/Configuration.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/Configuration.java
@@ -1090,6 +1090,10 @@ public interface Configuration {
Configuration setPopulateValidatedUser(boolean populateValidatedUser);
+ boolean isRejectEmptyValidatedUser();
+
+ Configuration setRejectEmptyValidatedUser(boolean rejectEmptyValidatedUser);
+
/**
* It will return all the connectors in a toString manner for debug purposes.
*/
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/impl/ConfigurationImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/impl/ConfigurationImpl.java
index 7df8fb1bff..a6ece62798 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/impl/ConfigurationImpl.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/impl/ConfigurationImpl.java
@@ -289,6 +289,8 @@ public class ConfigurationImpl implements Configuration, Serializable {
protected boolean populateValidatedUser = ActiveMQDefaultConfiguration.isDefaultPopulateValidatedUser();
+ protected boolean rejectEmptyValidatedUser = ActiveMQDefaultConfiguration.isDefaultRejectEmptyValidatedUser();
+
private long connectionTtlCheckInterval = ActiveMQDefaultConfiguration.getDefaultConnectionTtlCheckInterval();
private URL configurationUrl;
@@ -1734,6 +1736,17 @@ public class ConfigurationImpl implements Configuration, Serializable {
return this;
}
+ @Override
+ public boolean isRejectEmptyValidatedUser() {
+ return rejectEmptyValidatedUser;
+ }
+
+ @Override
+ public Configuration setRejectEmptyValidatedUser(boolean rejectEmptyValidatedUser) {
+ this.rejectEmptyValidatedUser = rejectEmptyValidatedUser;
+ return this;
+ }
+
@Override
public long getConnectionTtlCheckInterval() {
return connectionTtlCheckInterval;
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/deployers/impl/FileConfigurationParser.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/deployers/impl/FileConfigurationParser.java
index 637e3ac7de..edd667b93f 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/deployers/impl/FileConfigurationParser.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/deployers/impl/FileConfigurationParser.java
@@ -373,6 +373,8 @@ public final class FileConfigurationParser extends XMLConfigurationUtil {
config.setPopulateValidatedUser(getBoolean(e, "populate-validated-user", config.isPopulateValidatedUser()));
+ config.setRejectEmptyValidatedUser(getBoolean(e, "reject-empty-validated-user", config.isRejectEmptyValidatedUser()));
+
config.setConnectionTtlCheckInterval(getLong(e, "connection-ttl-check-interval", config.getConnectionTtlCheckInterval(), Validators.GT_ZERO));
config.setConfigurationFileRefreshPeriod(getLong(e, "configuration-file-refresh-period", config.getConfigurationFileRefreshPeriod(), Validators.GT_ZERO));
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQMessageBundle.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQMessageBundle.java
index ff92501382..930c236bba 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQMessageBundle.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQMessageBundle.java
@@ -470,4 +470,7 @@ public interface ActiveMQMessageBundle {
@Message(id = 229224, value = "User {0} does not exist", format = Message.Format.MESSAGE_FORMAT)
IllegalArgumentException userDoesNotExist(String user);
+
+ @Message(id = 229225, value = "Validated User is not set", format = Message.Format.MESSAGE_FORMAT)
+ ActiveMQIllegalStateException rejectEmptyValidatedUser();
}
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerSessionImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerSessionImpl.java
index 4f8e514631..bcedd1fef4 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerSessionImpl.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerSessionImpl.java
@@ -2023,6 +2023,10 @@ public class ServerSessionImpl implements ServerSession, FailureListener {
msg.setValidatedUserID(validatedUser);
}
+ if (server.getConfiguration().isRejectEmptyValidatedUser() && msg.getValidatedUserID() == null) {
+ throw ActiveMQMessageBundle.BUNDLE.rejectEmptyValidatedUser();
+ }
+
if (tx == null || autoCommitSends) {
routingContext.setTransaction(null);
} else {
diff --git a/artemis-server/src/main/resources/schema/artemis-configuration.xsd b/artemis-server/src/main/resources/schema/artemis-configuration.xsd
index 957f8b4e6a..8fc8216a2c 100644
--- a/artemis-server/src/main/resources/schema/artemis-configuration.xsd
+++ b/artemis-server/src/main/resources/schema/artemis-configuration.xsd
@@ -396,6 +396,14 @@
+
+
+
+ true means that the server will not allow any message that doesn't have a validated user, in JMS this is JMSXUserID
+
+
+
+
diff --git a/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/FileConfigurationTest.java b/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/FileConfigurationTest.java
index 2e6dd88ef1..f7b558524b 100644
--- a/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/FileConfigurationTest.java
+++ b/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/FileConfigurationTest.java
@@ -139,6 +139,7 @@ public class FileConfigurationTest extends ConfigurationImplTest {
Assert.assertEquals(true, conf.isGracefulShutdownEnabled());
Assert.assertEquals(12345, conf.getGracefulShutdownTimeout());
Assert.assertEquals(true, conf.isPopulateValidatedUser());
+ Assert.assertEquals(false, conf.isRejectEmptyValidatedUser());
Assert.assertEquals(98765, conf.getConnectionTtlCheckInterval());
Assert.assertEquals(1234567, conf.getConfigurationFileRefreshPeriod());
diff --git a/artemis-server/src/test/resources/ConfigurationTest-full-config.xml b/artemis-server/src/test/resources/ConfigurationTest-full-config.xml
index d27e7f4288..4bc7679679 100644
--- a/artemis-server/src/test/resources/ConfigurationTest-full-config.xml
+++ b/artemis-server/src/test/resources/ConfigurationTest-full-config.xml
@@ -53,6 +53,7 @@
false
true
true
+ false
98765
1234567
1234567
diff --git a/artemis-server/src/test/resources/ConfigurationTest-xinclude-config.xml b/artemis-server/src/test/resources/ConfigurationTest-xinclude-config.xml
index bd647d61d1..9eef2acc90 100644
--- a/artemis-server/src/test/resources/ConfigurationTest-xinclude-config.xml
+++ b/artemis-server/src/test/resources/ConfigurationTest-xinclude-config.xml
@@ -54,6 +54,7 @@
false
true
true
+ false
98765
1234567
1234567
diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/security/JMSXUserIDPluginTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/security/JMSXUserIDPluginTest.java
new file mode 100644
index 0000000000..fef28748de
--- /dev/null
+++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/security/JMSXUserIDPluginTest.java
@@ -0,0 +1,138 @@
+/*
+ * 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.activemq.artemis.tests.integration.security;
+
+
+import org.apache.activemq.artemis.api.core.ActiveMQException;
+import org.apache.activemq.artemis.api.core.RoutingType;
+import org.apache.activemq.artemis.api.core.SimpleString;
+import org.apache.activemq.artemis.api.core.client.ClientConsumer;
+import org.apache.activemq.artemis.api.core.client.ClientMessage;
+import org.apache.activemq.artemis.api.core.client.ClientProducer;
+import org.apache.activemq.artemis.api.core.client.ClientSession;
+import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
+import org.apache.activemq.artemis.api.core.client.ServerLocator;
+import org.apache.activemq.artemis.core.server.ActiveMQServer;
+import org.apache.activemq.artemis.core.server.ActiveMQServers;
+import org.apache.activemq.artemis.core.server.ServerSession;
+import org.apache.activemq.artemis.core.server.plugin.ActiveMQServerPlugin;
+import org.apache.activemq.artemis.core.transaction.Transaction;
+import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
+import org.apache.qpid.jms.JmsConnectionFactory;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import javax.jms.Connection;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Session;
+import java.util.Map;
+
+public class JMSXUserIDPluginTest extends ActiveMQTestBase {
+
+ private ActiveMQServer server;
+ private SimpleString ADDRESS = new SimpleString("TestQueue");
+
+ @Override
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+
+ server = addServer(ActiveMQServers.newActiveMQServer(createDefaultNettyConfig(), true));
+
+ JMSXUserIDPlugin plugin = new JMSXUserIDPlugin();
+ plugin.setPopulateValidatedUser("testuser");
+
+ server.registerBrokerPlugin(plugin);
+ server.start();
+ server.createQueue(ADDRESS, RoutingType.ANYCAST, ADDRESS, null, true, false);
+ }
+
+ @Test
+ public void testAddValidatedUserCore() throws Exception {
+ ServerLocator locator = createNettyNonHALocator();
+ ClientSessionFactory sf = createSessionFactory(locator);
+ ClientSession session = sf.createSession(false, true, true);
+ ClientProducer producer = session.createProducer(ADDRESS.toString());
+ producer.send(session.createMessage(true));
+ ClientConsumer consumer = session.createConsumer(ADDRESS.toString());
+ session.start();
+ ClientMessage clientMessage = consumer.receiveImmediate();
+ Assert.assertNotNull(clientMessage);
+ Assert.assertEquals(clientMessage.getValidatedUserID(), "testuser");
+ }
+
+ @Test
+ public void testAddValidatedUserAMQP() throws Exception {
+ JmsConnectionFactory factory = new JmsConnectionFactory("amqp://127.0.0.1:61616");
+ Connection connection = factory.createConnection();
+ Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ javax.jms.Queue queue = session.createQueue(ADDRESS.toString());
+ MessageProducer producer = session.createProducer(queue);
+ producer.send(session.createMessage());
+ connection.close();
+
+ server.stop();
+ server.start();
+
+ connection = factory.createConnection();
+ session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ connection.start();
+ MessageConsumer consumer = session.createConsumer(queue);
+ Message message = consumer.receive(5000);
+ Assert.assertNotNull(message);
+ Assert.assertEquals(message.getStringProperty("_AMQ_VALIDATED_USER"), "testuser");
+ connection.close();
+ }
+
+
+ private static class JMSXUserIDPlugin implements ActiveMQServerPlugin {
+
+ private static String POPULATE_VALIDATED_USER = "POPULATE_VALIDATED_USER";
+
+ private String populateValidatedUser;
+
+ /**
+ * used to pass configured properties to Plugin
+ *
+ * @param properties
+ */
+ @Override
+ public void init(Map properties) {
+ populateValidatedUser = properties.getOrDefault(POPULATE_VALIDATED_USER, null);
+ }
+
+ @Override
+ public void beforeSend(ServerSession session, Transaction tx, org.apache.activemq.artemis.api.core.Message message, boolean direct, boolean noAutoCreateQueue) throws ActiveMQException {
+ if (populateValidatedUser != null && !message.containsProperty(org.apache.activemq.artemis.api.core.Message.HDR_VALIDATED_USER)) {
+ message.messageChanged();
+ message.putStringProperty(org.apache.activemq.artemis.api.core.Message.HDR_VALIDATED_USER, populateValidatedUser);
+ }
+ }
+
+ public String getPopulateValidatedUser() {
+ return populateValidatedUser;
+ }
+
+ public void setPopulateValidatedUser(String populateValidatedUser) {
+ this.populateValidatedUser = populateValidatedUser;
+ }
+ }
+
+}
diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/security/RejectValidatedUserTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/security/RejectValidatedUserTest.java
new file mode 100644
index 0000000000..996bea4dc2
--- /dev/null
+++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/security/RejectValidatedUserTest.java
@@ -0,0 +1,90 @@
+/*
+ * 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.activemq.artemis.tests.integration.security;
+
+import org.apache.activemq.artemis.api.core.ActiveMQIllegalStateException;
+import org.apache.activemq.artemis.api.core.client.ClientMessage;
+import org.apache.activemq.artemis.api.core.client.ClientProducer;
+import org.apache.activemq.artemis.api.core.client.ClientSession;
+import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
+import org.apache.activemq.artemis.api.core.client.ServerLocator;
+import org.apache.activemq.artemis.api.jms.ActiveMQJMSClient;
+import org.apache.activemq.artemis.core.server.ActiveMQServer;
+import org.apache.activemq.artemis.core.server.ActiveMQServers;
+import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
+import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
+import org.junit.Assert;
+import org.junit.Test;
+
+import javax.jms.Connection;
+import javax.jms.Message;
+import javax.jms.MessageProducer;
+import javax.jms.Queue;
+import javax.jms.Session;
+
+public class RejectValidatedUserTest extends ActiveMQTestBase {
+
+ private static final String ADDRESS = "TestQueue";
+ private ActiveMQServer server;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ server = addServer(ActiveMQServers.newActiveMQServer(createDefaultInVMConfig(), false));
+ server.getConfiguration().setRejectEmptyValidatedUser(true);
+ server.start();
+ }
+
+ @Test
+ public void testRejectException() throws Exception {
+ ServerLocator locator = createInVMNonHALocator();
+ ClientSessionFactory sessionFactory = locator.createSessionFactory();
+ ClientSession session = sessionFactory.createSession();
+ ClientProducer producer = session.createProducer(ADDRESS);
+ try {
+ producer.send(session.createMessage(true));
+ Assert.fail("Should throw exception");
+ } catch (ActiveMQIllegalStateException e) {
+ //pass
+ }
+ locator.close();
+ }
+
+ @Test
+ public void testAcceptException() throws Exception {
+ ServerLocator locator = createInVMNonHALocator();
+ ClientSessionFactory sessionFactory = locator.createSessionFactory();
+ ClientSession session = sessionFactory.createSession();
+ ClientProducer producer = session.createProducer(ADDRESS);
+ ClientMessage message = session.createMessage(true);
+ message.setValidatedUserID("testuser");
+ producer.send(message);
+ locator.close();
+ }
+
+ @Test
+ public void testAcceptJMSException() throws Exception {
+ ActiveMQConnectionFactory connectionFactory = ActiveMQJMSClient.createConnectionFactory("vm://0", "0");
+ Connection connection = connectionFactory.createConnection();
+ Session session = connection.createSession();
+ Queue queue = session.createQueue(ADDRESS.toString());
+ MessageProducer producer = session.createProducer(queue);
+ Message message = session.createMessage();
+ message.setStringProperty("JMSXUserID", "testuser");
+ producer.send(message);
+ }
+}