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

brusdev pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/activemq-artemis.git


The following commit(s) were added to refs/heads/main by this push:
     new a79685e0b8 ARTEMIS-5683 properly convert wildcards in 
LegacyLDAPSecuritySettingPlugin
a79685e0b8 is described below

commit a79685e0b88fe0faa702856a4af43d7ee89dc423
Author: Justin Bertram <[email protected]>
AuthorDate: Thu Oct 2 10:47:47 2025 -0500

    ARTEMIS-5683 properly convert wildcards in LegacyLDAPSecuritySettingPlugin
---
 .../impl/LegacyLDAPSecuritySettingPlugin.java      |  69 ++++-
 .../impl/LegacyLDAPSecuritySettingPluginTest.java  | 119 +++++++++
 docs/user-manual/security.adoc                     |  15 ++
 ...egacyLDAPSecuritySettingPluginWildcardTest.java | 291 +++++++++++++++++++++
 .../src/test/resources/AMQauthWildcard.ldif        | 148 +++++++++++
 5 files changed, 641 insertions(+), 1 deletion(-)

diff --git 
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/LegacyLDAPSecuritySettingPlugin.java
 
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/LegacyLDAPSecuritySettingPlugin.java
index e9942c48ec..b361a98397 100644
--- 
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/LegacyLDAPSecuritySettingPlugin.java
+++ 
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/LegacyLDAPSecuritySettingPlugin.java
@@ -40,6 +40,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import org.apache.activemq.artemis.core.config.WildcardConfiguration;
 import org.apache.activemq.artemis.core.security.Role;
 import org.apache.activemq.artemis.core.server.ActiveMQServerLogger;
 import org.apache.activemq.artemis.core.server.SecuritySettingPlugin;
@@ -52,10 +53,14 @@ import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.TimeUnit;
 
+import static 
org.apache.activemq.artemis.core.config.WildcardConfiguration.DEFAULT_WILDCARD_CONFIGURATION;
+
 public class LegacyLDAPSecuritySettingPlugin implements SecuritySettingPlugin {
 
    private static final Logger logger = 
LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
+   private static final WildcardConfiguration OPENWIRE_WILDCARD = new 
WildcardConfiguration().setDelimiter('.').setAnyWords('>').setSingleWord('*');
+
    private static final long serialVersionUID = 4793109879399750045L;
 
    public static final String INITIAL_CONTEXT_FACTORY = 
"initialContextFactory";
@@ -74,6 +79,9 @@ public class LegacyLDAPSecuritySettingPlugin implements 
SecuritySettingPlugin {
    public static final String REFRESH_INTERVAL = "refreshInterval";
    public static final String MAP_ADMIN_TO_MANAGE = "mapAdminToManage";
    public static final String ALLOW_QUEUE_ADMIN_ON_READ = 
"allowQueueAdminOnRead";
+   public static final String ANY_WORDS_WILDCARD_CONVERSION = 
"anyWordsWildcardConversion";
+   public static final String SINGLE_WORD_WILDCARD_CONVERSION = 
"singleWordWildcardConversion";
+   public static final String DELIMITER_WILDCARD_CONVERSION = 
"delimiterWildcardConversion";
 
    private String initialContextFactory = "com.sun.jndi.ldap.LdapCtxFactory";
    private String connectionURL = "ldap://localhost:1024";;
@@ -91,6 +99,10 @@ public class LegacyLDAPSecuritySettingPlugin implements 
SecuritySettingPlugin {
    private int refreshInterval = 0;
    private boolean mapAdminToManage = false;
    private boolean allowQueueAdminOnRead = false;
+   private WildcardConfiguration wildcardConfiguration = new 
WildcardConfiguration()
+      .setAnyWords(DEFAULT_WILDCARD_CONFIGURATION.getAnyWords())
+      .setSingleWord(DEFAULT_WILDCARD_CONFIGURATION.getSingleWord())
+      .setDelimiter(DEFAULT_WILDCARD_CONFIGURATION.getDelimiter());
 
    private DirContext context;
    private EventDirContext eventContext;
@@ -118,6 +130,9 @@ public class LegacyLDAPSecuritySettingPlugin implements 
SecuritySettingPlugin {
          refreshInterval = Integer.parseInt(getOption(options, 
REFRESH_INTERVAL, Integer.valueOf(refreshInterval).toString()));
          mapAdminToManage = getOption(options, MAP_ADMIN_TO_MANAGE, 
Boolean.FALSE.toString()).equalsIgnoreCase(Boolean.TRUE.toString());
          allowQueueAdminOnRead = getOption(options, ALLOW_QUEUE_ADMIN_ON_READ, 
Boolean.FALSE.toString()).equalsIgnoreCase(Boolean.TRUE.toString());
+         wildcardConfiguration.setAnyWords(getCharOption(options, 
ANY_WORDS_WILDCARD_CONVERSION, 
String.valueOf(DEFAULT_WILDCARD_CONFIGURATION.getAnyWords())));
+         wildcardConfiguration.setSingleWord(getCharOption(options, 
SINGLE_WORD_WILDCARD_CONVERSION, 
String.valueOf(DEFAULT_WILDCARD_CONFIGURATION.getSingleWord())));
+         wildcardConfiguration.setDelimiter(getCharOption(options, 
DELIMITER_WILDCARD_CONVERSION, 
String.valueOf(DEFAULT_WILDCARD_CONFIGURATION.getDelimiter())));
       }
 
       if (refreshInterval > 0) {
@@ -138,6 +153,14 @@ public class LegacyLDAPSecuritySettingPlugin implements 
SecuritySettingPlugin {
       return this;
    }
 
+   private char getCharOption(Map<String, String> options, String key, String 
defaultValue) {
+      String result = getOption(options, key, defaultValue);
+      if (result.length() != 1) {
+         throw new IllegalArgumentException("Value for " + key + " is longer 
than 1 character: " + result);
+      }
+      return result.charAt(0);
+   }
+
    private String getOption(Map<String, String> options, String key, String 
defaultValue) {
       String result = options.get(key);
       if (result == null) {
@@ -264,6 +287,15 @@ public class LegacyLDAPSecuritySettingPlugin implements 
SecuritySettingPlugin {
       return this;
    }
 
+   public int getRefreshInterval() {
+      return refreshInterval;
+   }
+
+   public LegacyLDAPSecuritySettingPlugin setRefreshInterval(int 
refreshInterval) {
+      this.refreshInterval = refreshInterval;
+      return this;
+   }
+
    public boolean isMapAdminToManage() {
       return mapAdminToManage;
    }
@@ -282,6 +314,33 @@ public class LegacyLDAPSecuritySettingPlugin implements 
SecuritySettingPlugin {
       return this;
    }
 
+   public char getAnyWordsWildcardConversion() {
+      return this.wildcardConfiguration.getAnyWords();
+   }
+
+   public LegacyLDAPSecuritySettingPlugin setAnyWordsWildcardConversion(char 
anyWordsWildcardConversion) {
+      this.wildcardConfiguration.setAnyWords(anyWordsWildcardConversion);
+      return this;
+   }
+
+   public char getSingleWordWildcardConversion() {
+      return this.wildcardConfiguration.getSingleWord();
+   }
+
+   public LegacyLDAPSecuritySettingPlugin setSingleWordWildcardConversion(char 
singleWordWildcardConversion) {
+      this.wildcardConfiguration.setSingleWord(singleWordWildcardConversion);
+      return this;
+   }
+
+   public char getDelimiterWildcardConversion() {
+      return this.wildcardConfiguration.getDelimiter();
+   }
+
+   public LegacyLDAPSecuritySettingPlugin setDelimiterWildcardConversion(char 
delimiterWildcardConversion) {
+      this.wildcardConfiguration.setDelimiter(delimiterWildcardConversion);
+      return this;
+   }
+
    protected boolean isContextAlive() {
       boolean alive = false;
       if (context != null) {
@@ -415,7 +474,7 @@ public class LegacyLDAPSecuritySettingPlugin implements 
SecuritySettingPlugin {
       if (prepareDebugLog) {
          logMessage.append("\n\tDestination name: ").append(rdn.getValue());
       }
-      String destination = rdn.getValue().toString();
+      String destination = 
convertDestinationWildcards(rdn.getValue().toString());
 
       rdn = rdns.get(rdns.size() - 1);
       if (prepareDebugLog) {
@@ -482,6 +541,14 @@ public class LegacyLDAPSecuritySettingPlugin implements 
SecuritySettingPlugin {
       }
    }
 
+   private String convertDestinationWildcards(String destination) {
+      // Convert the OpenWire wildcard syntax to the corresponding Artemis 
syntax
+      destination = OPENWIRE_WILDCARD.convert(destination, 
wildcardConfiguration);
+      // The '$' character was used previously in LDAP entries to represent 
the '>' character
+      destination = destination.replace('$', 
wildcardConfiguration.getAnyWords());
+      return destination;
+   }
+
    @Override
    public SecuritySettingPlugin stop() {
       if (scheduledFuture != null) {
diff --git 
a/artemis-server/src/test/java/org/apache/activemq/artemis/core/server/impl/LegacyLDAPSecuritySettingPluginTest.java
 
b/artemis-server/src/test/java/org/apache/activemq/artemis/core/server/impl/LegacyLDAPSecuritySettingPluginTest.java
new file mode 100644
index 0000000000..14a0440c50
--- /dev/null
+++ 
b/artemis-server/src/test/java/org/apache/activemq/artemis/core/server/impl/LegacyLDAPSecuritySettingPluginTest.java
@@ -0,0 +1,119 @@
+/*
+ * 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.core.server.impl;
+
+import java.util.Map;
+
+import org.apache.activemq.artemis.utils.RandomUtil;
+import org.junit.Test;
+
+import static java.util.Map.entry;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+public class LegacyLDAPSecuritySettingPluginTest {
+
+   @Test
+   public void testBlankParameterMap() throws Exception {
+      new LegacyLDAPSecuritySettingPlugin().init(Map.of());
+   }
+
+   @Test
+   public void testFullParameterMap() throws Exception {
+      final String initialContextFactoryValue = RandomUtil.randomUUIDString();
+      final String connectionURLValue = RandomUtil.randomUUIDString();
+      final String connectionUsernameValue = RandomUtil.randomUUIDString();
+      final String connectionPasswordValue = RandomUtil.randomUUIDString();
+      final String connectionProtocolValue = RandomUtil.randomUUIDString();
+      final String authenticationValue = RandomUtil.randomUUIDString();
+      final String roleAttributeValue = RandomUtil.randomUUIDString();
+      final String filterValue = RandomUtil.randomUUIDString();
+      final String destinationBaseValue = RandomUtil.randomUUIDString();
+      final String adminPermissionValueValue = RandomUtil.randomUUIDString();
+      final String readPermissionValueValue = RandomUtil.randomUUIDString();
+      final String writePermissionValueValue = RandomUtil.randomUUIDString();
+      final String enableListenerValue = 
String.valueOf(RandomUtil.randomBoolean());
+      final String refreshIntervalValue = 
String.valueOf(RandomUtil.randomInt());
+      final String mapAdminToManageValue = 
String.valueOf(RandomUtil.randomBoolean());
+      final String allowQueueAdminOnReadValue = 
String.valueOf(RandomUtil.randomBoolean());
+      final String anyWordsWildcardConversionValue = 
String.valueOf(RandomUtil.randomChar());
+      final String singleWordWildcardConversionValue = 
String.valueOf(RandomUtil.randomChar());
+      final String delimiterWildcardConversionValue = 
String.valueOf(RandomUtil.randomChar());
+
+      LegacyLDAPSecuritySettingPlugin plugin = new 
LegacyLDAPSecuritySettingPlugin().init(Map.ofEntries(
+         entry("initialContextFactory", initialContextFactoryValue),
+         entry("connectionURL", connectionURLValue),
+         entry("connectionUsername", connectionUsernameValue),
+         entry("connectionPassword", connectionPasswordValue),
+         entry("connectionProtocol", connectionProtocolValue),
+         entry("authentication", authenticationValue),
+         entry("roleAttribute", roleAttributeValue),
+         entry("filter", filterValue),
+         entry("destinationBase", destinationBaseValue),
+         entry("adminPermissionValue", adminPermissionValueValue),
+         entry("readPermissionValue", readPermissionValueValue),
+         entry("writePermissionValue", writePermissionValueValue),
+         entry("enableListener", enableListenerValue),
+         entry("refreshInterval", refreshIntervalValue),
+         entry("mapAdminToManage", mapAdminToManageValue),
+         entry("allowQueueAdminOnRead", allowQueueAdminOnReadValue),
+         entry("anyWordsWildcardConversion", anyWordsWildcardConversionValue),
+         entry("singleWordWildcardConversion", 
singleWordWildcardConversionValue),
+         entry("delimiterWildcardConversion", delimiterWildcardConversionValue)
+      ));
+      assertEquals(initialContextFactoryValue, 
plugin.getInitialContextFactory());
+      assertEquals(connectionURLValue, plugin.getConnectionURL());
+      assertEquals(connectionUsernameValue, plugin.getConnectionUsername());
+      assertEquals(connectionPasswordValue, plugin.getConnectionPassword());
+      assertEquals(connectionProtocolValue, plugin.getConnectionProtocol());
+      assertEquals(authenticationValue, plugin.getAuthentication());
+      assertEquals(roleAttributeValue, plugin.getRoleAttribute());
+      assertEquals(filterValue, plugin.getFilter());
+      assertEquals(destinationBaseValue, plugin.getDestinationBase());
+      assertEquals(adminPermissionValueValue, 
plugin.getAdminPermissionValue());
+      assertEquals(readPermissionValueValue, plugin.getReadPermissionValue());
+      assertEquals(writePermissionValueValue, 
plugin.getWritePermissionValue());
+      assertEquals(enableListenerValue, 
String.valueOf(plugin.isEnableListener()));
+      assertEquals(refreshIntervalValue, 
String.valueOf(plugin.getRefreshInterval()));
+      assertEquals(mapAdminToManageValue, 
String.valueOf(plugin.isMapAdminToManage()));
+      assertEquals(allowQueueAdminOnReadValue, 
String.valueOf(plugin.isAllowQueueAdminOnRead()));
+      assertEquals(anyWordsWildcardConversionValue, 
String.valueOf(plugin.getAnyWordsWildcardConversion()));
+      assertEquals(singleWordWildcardConversionValue, 
String.valueOf(plugin.getSingleWordWildcardConversion()));
+      assertEquals(delimiterWildcardConversionValue, 
String.valueOf(plugin.getDelimiterWildcardConversion()));
+   }
+
+   @Test
+   public void testLongAnyWords() throws Exception {
+      assertThrows(IllegalArgumentException.class, () -> {
+         new 
LegacyLDAPSecuritySettingPlugin().init(Map.of(LegacyLDAPSecuritySettingPlugin.ANY_WORDS_WILDCARD_CONVERSION,
 "xxx"));
+      });
+   }
+
+   @Test
+   public void testLongSingleWord() throws Exception {
+      assertThrows(IllegalArgumentException.class, () -> {
+         new 
LegacyLDAPSecuritySettingPlugin().init(Map.of(LegacyLDAPSecuritySettingPlugin.SINGLE_WORD_WILDCARD_CONVERSION,
 "xxx"));
+      });
+   }
+
+   @Test
+   public void testLongDelimiter() throws Exception {
+      assertThrows(IllegalArgumentException.class, () -> {
+         new 
LegacyLDAPSecuritySettingPlugin().init(Map.of(LegacyLDAPSecuritySettingPlugin.DELIMITER_WILDCARD_CONVERSION,
 "xxx"));
+      });
+   }
+}
diff --git a/docs/user-manual/security.adoc b/docs/user-manual/security.adoc
index 281f18640e..2298c7994c 100644
--- a/docs/user-manual/security.adoc
+++ b/docs/user-manual/security.adoc
@@ -349,6 +349,21 @@ Whether or not to map the legacy `read` permission to the 
`createDurableQueue`,
 This was allowed in ActiveMQ Classic.
 The default value is `false`.
 
+anyWordsWildcardConversion::
+This is a 1-character value that should match the `any-words` 
xref:wildcard-syntax.adoc#customizing-the-syntax[wildcard syntax] setting 
defined for the broker.
+The plugin will translate any `<` or `$` character to this value in an LDAP 
entry defining a destination name.
+The default value is `#`.
+
+singleWordWildcardConversion::
+This is a 1-character value that should match the `single-word` 
xref:wildcard-syntax.adoc#customizing-the-syntax[wildcard syntax] setting 
defined for the broker.
+The plugin will translate any `\*` character to this value in an LDAP entry 
defining a destination name.
+The default value is `*`.
+
+delimiterWildcardConversion::
+This is a 1-character value that should match the `delimiter` 
xref:wildcard-syntax.adoc#customizing-the-syntax[wildcard syntax] setting 
defined for the broker.
+The plugin will translate any `.` character to this value in an LDAP entry 
defining a destination name.
+The default value is `.`.
+
 The name of the queue or topic defined in LDAP will serve as the "match" for 
the security-setting, the permission value will be mapped from the ActiveMQ 
Classic type to the Artemis type, and the role will be mapped as-is.
 
 ActiveMQ Classic only has 3 permission types - `read`, `write`, and `admin`.
diff --git 
a/tests/integration-tests-isolated/src/test/java/org/apache/activemq/artemis/tests/integration/isolated/security/LegacyLDAPSecuritySettingPluginWildcardTest.java
 
b/tests/integration-tests-isolated/src/test/java/org/apache/activemq/artemis/tests/integration/isolated/security/LegacyLDAPSecuritySettingPluginWildcardTest.java
new file mode 100644
index 0000000000..0c1c1722af
--- /dev/null
+++ 
b/tests/integration-tests-isolated/src/test/java/org/apache/activemq/artemis/tests/integration/isolated/security/LegacyLDAPSecuritySettingPluginWildcardTest.java
@@ -0,0 +1,291 @@
+/*
+ * 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.isolated.security;
+
+import javax.naming.Context;
+import javax.naming.NameClassPair;
+import javax.naming.NamingEnumeration;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.InitialDirContext;
+import java.io.File;
+import java.lang.management.ManagementFactory;
+import java.net.URL;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Set;
+
+import org.apache.activemq.artemis.api.core.ActiveMQException;
+import org.apache.activemq.artemis.api.core.QueueConfiguration;
+import org.apache.activemq.artemis.api.core.TransportConfiguration;
+import org.apache.activemq.artemis.api.core.client.ActiveMQClient;
+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.config.Configuration;
+import org.apache.activemq.artemis.core.config.WildcardConfiguration;
+import org.apache.activemq.artemis.core.config.impl.ConfigurationImpl;
+import org.apache.activemq.artemis.core.remoting.impl.invm.InVMAcceptorFactory;
+import 
org.apache.activemq.artemis.core.remoting.impl.invm.InVMConnectorFactory;
+import org.apache.activemq.artemis.core.server.ActiveMQServer;
+import org.apache.activemq.artemis.core.server.ActiveMQServers;
+import 
org.apache.activemq.artemis.core.server.impl.LegacyLDAPSecuritySettingPlugin;
+import 
org.apache.activemq.artemis.spi.core.security.ActiveMQJAASSecurityManager;
+import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
+import org.apache.directory.server.annotations.CreateLdapServer;
+import org.apache.directory.server.annotations.CreateTransport;
+import org.apache.directory.server.core.annotations.ApplyLdifFiles;
+import org.apache.directory.server.core.integ.AbstractLdapTestUnit;
+import org.apache.directory.server.core.integ.FrameworkRunner;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.junit.runner.RunWith;
+
+import static 
org.apache.activemq.artemis.core.config.WildcardConfiguration.DEFAULT_WILDCARD_CONFIGURATION;
+
+@RunWith(FrameworkRunner.class)
+@CreateLdapServer(transports = {@CreateTransport(protocol = "LDAP", port = 
1024)})
+@ApplyLdifFiles("AMQauthWildcard.ldif")
+public class LegacyLDAPSecuritySettingPluginWildcardTest extends 
AbstractLdapTestUnit {
+
+   static {
+      String path = System.getProperty("java.security.auth.login.config");
+      if (path == null) {
+         URL resource = 
LegacyLDAPSecuritySettingPluginWildcardTest.class.getClassLoader().getResource("login.config");
+         if (resource != null) {
+            path = resource.getFile();
+            System.setProperty("java.security.auth.login.config", path);
+         }
+      }
+   }
+
+   ActiveMQServer server;
+   ActiveMQJAASSecurityManager securityManager;
+   Configuration configuration;
+   private ServerLocator locator;
+
+   public static final String TARGET_TMP = "./target/tmp";
+   private static final String PRINCIPAL = "uid=admin,ou=system";
+   private static final String CREDENTIALS = "secret";
+
+   // defined in LDIF
+   private static final String AUTHORIZED_USER = "authorizedUser";
+   private static final String UNAUTHORIZED_USER = "unauthorizedUser";
+
+   public LegacyLDAPSecuritySettingPluginWildcardTest() {
+      File parent = new File(TARGET_TMP);
+      parent.mkdirs();
+      temporaryFolder = new TemporaryFolder(parent);
+   }
+
+   @Rule
+   public TemporaryFolder temporaryFolder;
+   private String testDir;
+
+   @Before
+   public void setUp() throws Exception {
+      locator = ActiveMQClient.createServerLocatorWithoutHA(new 
TransportConfiguration(InVMConnectorFactory.class.getCanonicalName()));
+      testDir = temporaryFolder.getRoot().getAbsolutePath();
+
+      LegacyLDAPSecuritySettingPlugin legacyLDAPSecuritySettingPlugin = new 
LegacyLDAPSecuritySettingPlugin()
+         .setInitialContextFactory("com.sun.jndi.ldap.LdapCtxFactory")
+         .setConnectionURL("ldap://localhost:1024";)
+         .setConnectionUsername("uid=admin,ou=system")
+         .setConnectionPassword("secret")
+         .setConnectionProtocol("s")
+         .setAuthentication("simple");
+
+      securityManager = new ActiveMQJAASSecurityManager("LDAPLogin");
+      configuration = new ConfigurationImpl()
+         .setSecurityEnabled(true)
+         .setPersistenceEnabled(false)
+         .addAcceptorConfiguration(new 
TransportConfiguration(InVMAcceptorFactory.class.getCanonicalName()))
+         .setJournalDirectory(ActiveMQTestBase.getJournalDir(testDir, 0, 
false))
+         .setBindingsDirectory(ActiveMQTestBase.getBindingsDir(testDir, 0, 
false))
+         .setPagingDirectory(ActiveMQTestBase.getPageDir(testDir, 0, false))
+         
.setLargeMessagesDirectory(ActiveMQTestBase.getLargeMessagesDir(testDir, 0, 
false))
+         .addSecuritySettingPlugin(legacyLDAPSecuritySettingPlugin);
+   }
+
+   @After
+   public void tearDown() throws Exception {
+      locator.close();
+      if (server != null) {
+         server.stop();
+      }
+   }
+
+   @Test
+   public void testRunning() throws Exception {
+      Hashtable<String, String> env = new Hashtable<>();
+      env.put(Context.PROVIDER_URL, "ldap://localhost:1024";);
+      env.put(Context.INITIAL_CONTEXT_FACTORY, 
"com.sun.jndi.ldap.LdapCtxFactory");
+      env.put(Context.SECURITY_AUTHENTICATION, "simple");
+      env.put(Context.SECURITY_PRINCIPAL, PRINCIPAL);
+      env.put(Context.SECURITY_CREDENTIALS, CREDENTIALS);
+      DirContext ctx = new InitialDirContext(env);
+
+      Set<String> set = new HashSet<>();
+
+      NamingEnumeration<NameClassPair> list = ctx.list("ou=system");
+
+      while (list.hasMore()) {
+         NameClassPair ncp = list.next();
+         set.add(ncp.getName());
+      }
+
+      Assert.assertTrue(set.contains("uid=admin"));
+      Assert.assertTrue(set.contains("ou=users"));
+      Assert.assertTrue(set.contains("ou=groups"));
+      Assert.assertTrue(set.contains("ou=configuration"));
+      Assert.assertTrue(set.contains("prefNodeName=sysPrefRoot"));
+   }
+
+   @Test
+   public void 
testBasicPluginAuthorizationRightAngleBracketWithDefaultAnywords() throws 
Exception {
+      testBasicPluginAuthorization("A.A", DEFAULT_WILDCARD_CONFIGURATION, 
AUTHORIZED_USER);
+   }
+
+   @Test
+   public void 
testBasicPluginAuthorizationRightAngleBracketWithDefaultAnywordsNegative() 
throws Exception {
+      testBasicPluginAuthorization("A.A", DEFAULT_WILDCARD_CONFIGURATION, 
UNAUTHORIZED_USER);
+   }
+
+   @Test
+   public void 
testBasicPluginAuthorizationRightAngleBracketWithCustomAnywords() throws 
Exception {
+      testBasicPluginAuthorization("A.A", new 
WildcardConfiguration().setAnyWords('%'), AUTHORIZED_USER);
+   }
+
+   @Test
+   public void 
testBasicPluginAuthorizationRightAngleBracketWithCustomAnywordsNegative() 
throws Exception {
+      testBasicPluginAuthorization("A.A", new 
WildcardConfiguration().setAnyWords('%'), UNAUTHORIZED_USER);
+   }
+
+   @Test
+   public void 
testBasicPluginAuthorizationRightAngleBracketWithCustomDelimiter() throws 
Exception {
+      testBasicPluginAuthorization("A_A", new 
WildcardConfiguration().setDelimiter('_'), AUTHORIZED_USER);
+   }
+
+   @Test
+   public void 
testBasicPluginAuthorizationRightAngleBracketWithCustomDelimiterNegative() 
throws Exception {
+      testBasicPluginAuthorization("A_A", new 
WildcardConfiguration().setDelimiter('_'), UNAUTHORIZED_USER);
+   }
+
+   @Test
+   public void testBasicPluginAuthorizationDollarWithDefaultAnywords() throws 
Exception {
+      testBasicPluginAuthorization("B.B", DEFAULT_WILDCARD_CONFIGURATION, 
AUTHORIZED_USER);
+   }
+
+   @Test
+   public void testBasicPluginAuthorizationDollarWithDefaultAnywordsNegative() 
throws Exception {
+      testBasicPluginAuthorization("B.B", DEFAULT_WILDCARD_CONFIGURATION, 
UNAUTHORIZED_USER);
+   }
+
+   @Test
+   public void testBasicPluginAuthorizationDollarWithCustomAnywords() throws 
Exception {
+      testBasicPluginAuthorization("B.B", new 
WildcardConfiguration().setAnyWords('%'), AUTHORIZED_USER);
+   }
+
+   @Test
+   public void testBasicPluginAuthorizationDollarWithCustomAnywordsNegative() 
throws Exception {
+      testBasicPluginAuthorization("B.B", new 
WildcardConfiguration().setAnyWords('%'), UNAUTHORIZED_USER);
+   }
+
+   @Test
+   public void testBasicPluginAuthorizationDollarWithCustomDelimiter() throws 
Exception {
+      testBasicPluginAuthorization("B_B", new 
WildcardConfiguration().setDelimiter('_'), AUTHORIZED_USER);
+   }
+
+   @Test
+   public void testBasicPluginAuthorizationDollarWithCustomDelimiterNegative() 
throws Exception {
+      testBasicPluginAuthorization("B_B", new 
WildcardConfiguration().setDelimiter('_'), UNAUTHORIZED_USER);
+   }
+
+   @Test
+   public void testBasicPluginAuthorizationWithDefaultSingleWord() throws 
Exception {
+      testBasicPluginAuthorization("C.C.C", DEFAULT_WILDCARD_CONFIGURATION, 
AUTHORIZED_USER);
+   }
+
+   @Test
+   public void testBasicPluginAuthorizationWithDefaultSingleWordNegative() 
throws Exception {
+      testBasicPluginAuthorization("C.C.C", DEFAULT_WILDCARD_CONFIGURATION, 
UNAUTHORIZED_USER);
+   }
+
+   @Test
+   public void testBasicPluginAuthorizationCustomSingleWord() throws Exception 
{
+      testBasicPluginAuthorization("C.C.C", new 
WildcardConfiguration().setSingleWord('%'), AUTHORIZED_USER);
+   }
+
+   @Test
+   public void testBasicPluginAuthorizationCustomSingleWordNegative() throws 
Exception {
+      testBasicPluginAuthorization("C.C.C", new 
WildcardConfiguration().setSingleWord('%'), UNAUTHORIZED_USER);
+   }
+
+   private void testBasicPluginAuthorization(String name, 
WildcardConfiguration wildcardConfiguration, String username) throws Exception {
+      if (!wildcardConfiguration.equals(DEFAULT_WILDCARD_CONFIGURATION)) {
+         LegacyLDAPSecuritySettingPlugin plugin = 
(LegacyLDAPSecuritySettingPlugin) 
configuration.getSecuritySettingPlugins().iterator().next();
+         
plugin.setAnyWordsWildcardConversion(wildcardConfiguration.getAnyWords());
+         
plugin.setSingleWordWildcardConversion(wildcardConfiguration.getSingleWord());
+         
plugin.setDelimiterWildcardConversion(wildcardConfiguration.getDelimiter());
+         configuration.setWildCardConfiguration(wildcardConfiguration);
+      }
+      server = ActiveMQServers.newActiveMQServer(configuration, 
ManagementFactory.getPlatformMBeanServer(), securityManager, false);
+      server.start();
+
+      ClientSessionFactory cf = locator.createSessionFactory();
+
+      try {
+         ClientSession session = cf.createSession(username, "secret", false, 
true, true, false, 0);
+         session.createQueue(QueueConfiguration.of(name));
+         if (!username.equals(AUTHORIZED_USER)) {
+            Assert.fail("should throw exception here");
+         }
+         ClientProducer producer = session.createProducer();
+         producer.send(name, session.createMessage(false));
+         session.close();
+      } catch (ActiveMQException e) {
+         if (username.equals(AUTHORIZED_USER)) {
+            Assert.fail("should not throw exception");
+         }
+      }
+
+      cf.close();
+   }
+
+   @Test
+   public void testBasicPluginAuthorizationWithBadMatch() throws Exception {
+      final String name = "X.X";
+      server = ActiveMQServers.newActiveMQServer(configuration, 
ManagementFactory.getPlatformMBeanServer(), securityManager, false);
+      server.start();
+
+      ClientSessionFactory cf = locator.createSessionFactory();
+
+      try {
+         ClientSession session = cf.createSession(AUTHORIZED_USER, "secret", 
false, true, true, false, 0);
+         session.createQueue(QueueConfiguration.of(name));
+         Assert.fail("should throw exception here");
+      } catch (ActiveMQException e) {
+         // ignore
+      }
+
+      cf.close();
+   }
+}
diff --git 
a/tests/integration-tests-isolated/src/test/resources/AMQauthWildcard.ldif 
b/tests/integration-tests-isolated/src/test/resources/AMQauthWildcard.ldif
new file mode 100755
index 0000000000..097292292a
--- /dev/null
+++ b/tests/integration-tests-isolated/src/test/resources/AMQauthWildcard.ldif
@@ -0,0 +1,148 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+##########################
+## Define basic objects ##
+##########################
+
+dn: o=ActiveMQ,ou=system
+objectclass: organization
+objectclass: top
+o: ActiveMQ
+
+###################
+## Define roles ##
+###################
+
+dn: cn=role1,ou=system
+cn: role1
+member: uid=authorizedUser,ou=system
+objectClass: groupOfNames
+objectClass: top
+
+dn: cn=unauthorizedRole,ou=system
+cn: unauthorizedRole
+member: uid=unauthorizedUser,ou=system
+objectClass: groupOfNames
+objectClass: top
+
+##################
+## Define users ##
+##################
+
+dn: uid=authorizedUser,ou=system
+uid: authorizedUser
+userPassword: secret
+objectClass: account
+objectClass: simpleSecurityObject
+objectClass: top
+
+dn: uid=unauthorizedUser,ou=system
+uid: unauthorizedUser
+userPassword: secret
+objectClass: account
+objectClass: simpleSecurityObject
+objectClass: top
+
+#########################
+## Define destinations ##
+#########################
+
+dn: ou=destinations,o=ActiveMQ,ou=system
+objectclass: organizationalUnit
+objectclass: top
+ou: destinations
+
+dn: ou=queues,ou=destinations,o=ActiveMQ,ou=system
+objectclass: organizationalUnit
+objectclass: top
+ou: queues
+
+## A.>
+
+dn: cn=A.>,ou=queues,ou=destinations,o=ActiveMQ,ou=system
+objectClass: applicationProcess
+objectClass: top
+cn: A.>
+
+dn: cn=admin,cn=A.>,ou=queues,ou=destinations,o=ActiveMQ,ou=system
+objectclass: groupOfUniqueNames
+objectclass: top
+cn: admin
+uniquemember: cn=role1
+
+dn: cn=read,cn=A.>,ou=queues,ou=destinations,o=ActiveMQ,ou=system
+objectclass: groupOfUniqueNames
+objectclass: top
+cn: read
+uniquemember: cn=role1
+
+dn: cn=write,cn=A.>,ou=queues,ou=destinations,o=ActiveMQ,ou=system
+objectclass: groupOfUniqueNames
+objectclass: top
+cn: write
+uniquemember: cn=role1
+
+## B.$
+
+dn: cn=B.$,ou=queues,ou=destinations,o=ActiveMQ,ou=system
+objectClass: applicationProcess
+objectClass: top
+cn: B.$
+
+dn: cn=admin,cn=B.$,ou=queues,ou=destinations,o=ActiveMQ,ou=system
+objectclass: groupOfUniqueNames
+objectclass: top
+cn: admin
+uniquemember: cn=role1
+
+dn: cn=read,cn=B.$,ou=queues,ou=destinations,o=ActiveMQ,ou=system
+objectclass: groupOfUniqueNames
+objectclass: top
+cn: read
+uniquemember: cn=role1
+
+dn: cn=write,cn=B.$,ou=queues,ou=destinations,o=ActiveMQ,ou=system
+objectclass: groupOfUniqueNames
+objectclass: top
+cn: write
+uniquemember: cn=role1
+
+## C.*.C
+
+dn: cn=C.*.C,ou=queues,ou=destinations,o=ActiveMQ,ou=system
+objectClass: applicationProcess
+objectClass: top
+cn: C.*.C
+
+dn: cn=admin,cn=C.*.C,ou=queues,ou=destinations,o=ActiveMQ,ou=system
+objectclass: groupOfUniqueNames
+objectclass: top
+cn: admin
+uniquemember: cn=role1
+
+dn: cn=read,cn=C.*.C,ou=queues,ou=destinations,o=ActiveMQ,ou=system
+objectclass: groupOfUniqueNames
+objectclass: top
+cn: read
+uniquemember: cn=role1
+
+dn: cn=write,cn=C.*.C,ou=queues,ou=destinations,o=ActiveMQ,ou=system
+objectclass: groupOfUniqueNames
+objectclass: top
+cn: write
+uniquemember: cn=role1
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]
For further information, visit: https://activemq.apache.org/contact



Reply via email to