From 6efea5fcf9a64c67ac17c76ea1e5f52ce76e89f3 Mon Sep 17 00:00:00 2001 From: gchuf Date: Sat, 25 Apr 2026 09:06:22 +0200 Subject: [PATCH 1/9] exit early on operationName == null --- .../management/ArtemisMBeanServerGuard.java | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/ArtemisMBeanServerGuard.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/ArtemisMBeanServerGuard.java index f7cd7c3dc6d..6b3cdaf5213 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/ArtemisMBeanServerGuard.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/ArtemisMBeanServerGuard.java @@ -127,13 +127,7 @@ private boolean canBypassRBAC(ObjectName objectName) { @Override public boolean canInvoke(String object, String operationName) { - ObjectName objectName = null; - try { - objectName = ObjectName.getInstance(object); - } catch (MalformedObjectNameException e) { - logger.debug("can't check invoke rights as object name invalid: {}", object, e); - return false; - } + /* * HawtIO calls this with a null operationName as a coarse grained way of authenticating against all the * operations on an mbean. Until this addition this was throwing a null pointer on operationName later in this @@ -142,7 +136,19 @@ public boolean canInvoke(String object, String operationName) { * it. Since it is just an optimisation it is fine to always return true. Note that the alternative * ArtemisRbacInvocationHandler does allow the ability to restrict a whole mbean. */ - if (operationName == null || canBypassRBAC(objectName)) { + if (operationName == null) { + return true; + } + + ObjectName objectName = null; + try { + objectName = ObjectName.getInstance(object); + } catch (MalformedObjectNameException e) { + logger.debug("can't check invoke rights as object name invalid: {}", object, e); + return false; + } + + if (canBypassRBAC(objectName)) { return true; } From 768938e9b03db1b73126cc1e4c936f4210522e88 Mon Sep 17 00:00:00 2001 From: gchuf Date: Sun, 26 Apr 2026 13:52:56 +0200 Subject: [PATCH 2/9] pass currentUserRoles to jmxAccessControlList --- .../management/ArtemisMBeanServerGuard.java | 38 +++++++++++++--- .../management/JMXAccessControlList.java | 44 +++++++++++++++++++ 2 files changed, 75 insertions(+), 7 deletions(-) diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/ArtemisMBeanServerGuard.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/ArtemisMBeanServerGuard.java index 6b3cdaf5213..3d6e08857e2 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/ArtemisMBeanServerGuard.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/ArtemisMBeanServerGuard.java @@ -36,6 +36,9 @@ import java.lang.reflect.Method; import java.security.Principal; import java.util.List; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; public class ArtemisMBeanServerGuard implements GuardInvocationHandler { @@ -157,15 +160,18 @@ public boolean canInvoke(String object, String operationName) { if (paramListIndex > 0) { operationName = operationName.substring(0, paramListIndex); } + Set currentUserRoles = getCurrentUserRoles(); - List requiredRoles = getRequiredRoles(objectName, operationName); - for (String role : requiredRoles) { - if (currentUserHasRole(role)) { - return true; - } + boolean authorized = authorizeUserForMethod(objectName, operationName, currentUserRoles); + + if (authorized) { + logger.debug("{} {} true", object, operationName); + return true; + } else { + logger.debug("{} {} false", object, operationName); + return false; } - logger.debug("{} {} false", object, operationName); - return false; + } void handleInvoke(ObjectName objectName, String operationName) throws IOException { @@ -188,6 +194,10 @@ List getRequiredRoles(ObjectName objectName, String methodName) { return jmxAccessControlList.getRolesForObject(objectName, methodName); } + boolean authorizeUserForMethod(ObjectName objectName, String operationName, Set currentUserRoles) { + return jmxAccessControlList.authorizeUserForMethod(objectName, operationName, currentUserRoles); + } + public void setJMXAccessControlList(JMXAccessControlList JMXAccessControlList) { this.jmxAccessControlList = JMXAccessControlList; } @@ -216,4 +226,18 @@ public static boolean currentUserHasRole(String requestedRole) { } return false; } + + public static Set getCurrentUserRoles() { + Subject subject = SecurityManagerShim.currentSubject(); + if (subject == null) { + return Collections.emptySet(); + } + + Set roles = new HashSet<>(); + for (Principal p : subject.getPrincipals()) { + roles.add(p.getName()); + } + return roles; + } + } diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/JMXAccessControlList.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/JMXAccessControlList.java index bb6d18d444e..908e3fb7e35 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/JMXAccessControlList.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/JMXAccessControlList.java @@ -18,11 +18,13 @@ import javax.management.ObjectName; import java.util.ArrayList; +import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.TreeMap; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -81,6 +83,34 @@ public List getRolesForObject(ObjectName objectName, String methodName) return defaultAccess.getMatchingRolesForMethod(methodName); } + + public boolean authorizeUserForMethod(ObjectName objectName, String methodName, Set userRoles) { + TreeMap domainMap = domainAccess.get(objectName.getDomain()); + + if (domainMap != null) { + Map keyPropertyList = objectName.getKeyPropertyList(); + for (Map.Entry keyEntry : keyPropertyList.entrySet()) { + String key = normalizeKey(keyEntry.getKey() + "=" + keyEntry.getValue()); + for (Access accessEntry : domainMap.values()) { + boolean matches = accessEntry.getKeyPattern().matcher(key).matches(); + if (matches) { + boolean authorized = accessEntry.authorizeUserForMethod(methodName, userRoles); + return authorized; + } + } + } + + Access access = domainMap.get(""); + if (access != null) { + return access.authorizeUserForMethod(methodName, userRoles); + } + } + + return defaultAccess.authorizeUserForMethod(methodName, userRoles); + } + + + public boolean isInAllowList(ObjectName objectName) { TreeMap domainMap = allowList.get(objectName.getDomain()); @@ -223,6 +253,20 @@ public List getMatchingRolesForMethod(String methodName) { } return catchAllRoles; } + + public boolean authorizeUserForMethod(String methodName, Set userRoles) { + List roles = methodRoles.get(methodName); + if (roles != null) { + return !Collections.disjoint(roles, userRoles); + + } + for (Map.Entry> entry : methodPrefixRoles.entrySet()) { + if (methodName.startsWith(entry.getKey())) { + return !Collections.disjoint(entry.getValue(), userRoles); + } + } + return !Collections.disjoint(catchAllRoles, userRoles); + } } public static JMXAccessControlList createDefaultList() { From 1627207dd0b69a66b23fc4ee38ea78287031c173 Mon Sep 17 00:00:00 2001 From: gchuf Date: Mon, 27 Apr 2026 15:12:47 +0200 Subject: [PATCH 3/9] implement bypassRBAC cache --- .../core/server/management/ArtemisMBeanServerGuard.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/ArtemisMBeanServerGuard.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/ArtemisMBeanServerGuard.java index 3d6e08857e2..dc38a50dadf 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/ArtemisMBeanServerGuard.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/ArtemisMBeanServerGuard.java @@ -36,9 +36,11 @@ import java.lang.reflect.Method; import java.security.Principal; import java.util.List; +import java.util.Map; import java.util.Collections; import java.util.HashSet; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; public class ArtemisMBeanServerGuard implements GuardInvocationHandler { @@ -46,6 +48,8 @@ public class ArtemisMBeanServerGuard implements GuardInvocationHandler { private JMXAccessControlList jmxAccessControlList = JMXAccessControlList.createDefaultList(); + private final Map bypassRBACCache = new ConcurrentHashMap<>(); + public void init() { ArtemisMBeanServerBuilder.setGuard(this); } @@ -125,7 +129,7 @@ private void handleSetAttributes(MBeanServer proxy, ObjectName objectName, Attri } private boolean canBypassRBAC(ObjectName objectName) { - return jmxAccessControlList.isInAllowList(objectName); + return bypassRBACCache.computeIfAbsent(objectName, name -> jmxAccessControlList.isInAllowList(name)); } @Override @@ -162,6 +166,7 @@ public boolean canInvoke(String object, String operationName) { } Set currentUserRoles = getCurrentUserRoles(); + boolean authorized = authorizeUserForMethod(objectName, operationName, currentUserRoles); if (authorized) { From a10dbbfac97272a51034be6b6cfd1dc5b1667746 Mon Sep 17 00:00:00 2001 From: gchuf Date: Mon, 27 Apr 2026 15:12:58 +0200 Subject: [PATCH 4/9] exit if current user roles are empty --- .../core/server/management/ArtemisMBeanServerGuard.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/ArtemisMBeanServerGuard.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/ArtemisMBeanServerGuard.java index dc38a50dadf..0d67e336e50 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/ArtemisMBeanServerGuard.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/ArtemisMBeanServerGuard.java @@ -166,6 +166,9 @@ public boolean canInvoke(String object, String operationName) { } Set currentUserRoles = getCurrentUserRoles(); + if (currentUserRoles.isEmpty()) { + return false; + } boolean authorized = authorizeUserForMethod(objectName, operationName, currentUserRoles); From 7e7c4f16ef977582c73ea869a4955d5a699fff42 Mon Sep 17 00:00:00 2001 From: gchuf Date: Mon, 27 Apr 2026 15:17:39 +0200 Subject: [PATCH 5/9] compare based on prefixes, and use equals before comparing with regexp --- .../server/management/JMXAccessControlList.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/JMXAccessControlList.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/JMXAccessControlList.java index 908e3fb7e35..53d5d755828 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/JMXAccessControlList.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/JMXAccessControlList.java @@ -90,12 +90,18 @@ public boolean authorizeUserForMethod(ObjectName objectName, String methodName, if (domainMap != null) { Map keyPropertyList = objectName.getKeyPropertyList(); for (Map.Entry keyEntry : keyPropertyList.entrySet()) { + String prefixFilter = keyEntry.getKey() + "="; String key = normalizeKey(keyEntry.getKey() + "=" + keyEntry.getValue()); for (Access accessEntry : domainMap.values()) { - boolean matches = accessEntry.getKeyPattern().matcher(key).matches(); - if (matches) { - boolean authorized = accessEntry.authorizeUserForMethod(methodName, userRoles); - return authorized; + String rawPattern = accessEntry.getKeyPattern().pattern(); + if (rawPattern.startsWith(prefixFilter)) { + if (key.equals(rawPattern)) { + return accessEntry.authorizeUserForMethod(methodName, userRoles); + } + // regexp check if previous did not return true + if (accessEntry.getKeyPattern().matcher(key).matches()) { + return accessEntry.authorizeUserForMethod(methodName, userRoles); + } } } } From 8f9510ce448c439787de091e06e47ade20400634 Mon Sep 17 00:00:00 2001 From: gchuf Date: Mon, 27 Apr 2026 15:21:22 +0200 Subject: [PATCH 6/9] add keyPropertyList cache --- .../server/management/JMXAccessControlList.java | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/JMXAccessControlList.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/JMXAccessControlList.java index 53d5d755828..984ae6fd262 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/JMXAccessControlList.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/JMXAccessControlList.java @@ -50,6 +50,14 @@ public class JMXAccessControlList { return key2.length() - key1.length(); }; + private final Map> keyPropertyCache = + Collections.synchronizedMap(new LinkedHashMap>(128, 0.75f, true) { + @Override + protected boolean removeEldestEntry(Map.Entry> eldest) { + return size() > 5000; + } + }); + public void addToAllowList(String domain, String key) { TreeMap domainMap = new TreeMap<>(keyComparator); domainMap = allowList.putIfAbsent(domain, domainMap); @@ -88,7 +96,14 @@ public boolean authorizeUserForMethod(ObjectName objectName, String methodName, TreeMap domainMap = domainAccess.get(objectName.getDomain()); if (domainMap != null) { - Map keyPropertyList = objectName.getKeyPropertyList(); + + String cacheKey = objectName.getCanonicalName(); + Map keyPropertyList = keyPropertyCache.get(cacheKey); + if (keyPropertyList == null) { + keyPropertyList = objectName.getKeyPropertyList(); + keyPropertyCache.put(cacheKey, keyPropertyList); + } + for (Map.Entry keyEntry : keyPropertyList.entrySet()) { String prefixFilter = keyEntry.getKey() + "="; String key = normalizeKey(keyEntry.getKey() + "=" + keyEntry.getValue()); From 50be5eca74f8afff55b47a6b20647e0ffa284a3d Mon Sep 17 00:00:00 2001 From: gchuf Date: Mon, 27 Apr 2026 15:46:13 +0200 Subject: [PATCH 7/9] domain caches --- .../management/JMXAccessControlList.java | 76 +++++++++++++++---- 1 file changed, 62 insertions(+), 14 deletions(-) diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/JMXAccessControlList.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/JMXAccessControlList.java index 984ae6fd262..99e8f2a1c92 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/JMXAccessControlList.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/JMXAccessControlList.java @@ -33,6 +33,36 @@ public class JMXAccessControlList { private static final String WILDCARD = "*"; + private record AccessEntry(Access access, String rawPattern) {} + private record Bucket( + Map exactMatches, + List regexPatterns + ) {} + + private final Map> keyPropertyCache = + Collections.synchronizedMap(new LinkedHashMap>(128, 0.75f, true) { + @Override + protected boolean removeEldestEntry(Map.Entry> eldest) { + return size() > 5000; + } + }); + + private final Map> domainCache = + Collections.synchronizedMap(new LinkedHashMap>(128, 0.75f, true) { + @Override + protected boolean removeEldestEntry(Map.Entry> eldest) { + return size() > 5000; + } + }); + + private final Map> bucketedDomainCache = + Collections.synchronizedMap(new LinkedHashMap<>(128, 0.75f, true) { + @Override + protected boolean removeEldestEntry(Map.Entry> eldest) { + return size() > 1000; + } + }); + private Access defaultAccess = new Access(WILDCARD); private ConcurrentMap> domainAccess = new ConcurrentHashMap<>(); private ConcurrentMap> allowList = new ConcurrentHashMap<>(); @@ -50,13 +80,6 @@ public class JMXAccessControlList { return key2.length() - key1.length(); }; - private final Map> keyPropertyCache = - Collections.synchronizedMap(new LinkedHashMap>(128, 0.75f, true) { - @Override - protected boolean removeEldestEntry(Map.Entry> eldest) { - return size() > 5000; - } - }); public void addToAllowList(String domain, String key) { TreeMap domainMap = new TreeMap<>(keyComparator); @@ -93,9 +116,30 @@ public List getRolesForObject(ObjectName objectName, String methodName) public boolean authorizeUserForMethod(ObjectName objectName, String methodName, Set userRoles) { - TreeMap domainMap = domainAccess.get(objectName.getDomain()); - if (domainMap != null) { + String domainKey = objectName.getDomain(); + + TreeMap domainMap = domainCache.computeIfAbsent(objectName.getDomain(), key -> + domainAccess.get(key) + ); + + Map> bucketedMap = bucketedDomainCache.computeIfAbsent(domainKey, d -> { + TreeMap rawMap = domainAccess.get(d); + if (rawMap == null) return null; + + Map> grouped = new HashMap<>(); + for (Access access : rawMap.values()) { + String pattern = access.getKeyPattern().pattern(); + // Extract prefix (e.g., "address" from "address=QUEUE.A") + int eqIndex = pattern.indexOf('='); + String prefix = (eqIndex != -1) ? pattern.substring(0, eqIndex) : ""; + + grouped.computeIfAbsent(prefix, k -> new ArrayList<>()).add(access); + } + return grouped; + }); + + if (bucketedMap != null) { String cacheKey = objectName.getCanonicalName(); Map keyPropertyList = keyPropertyCache.get(cacheKey); @@ -106,10 +150,15 @@ public boolean authorizeUserForMethod(ObjectName objectName, String methodName, for (Map.Entry keyEntry : keyPropertyList.entrySet()) { String prefixFilter = keyEntry.getKey() + "="; - String key = normalizeKey(keyEntry.getKey() + "=" + keyEntry.getValue()); - for (Access accessEntry : domainMap.values()) { - String rawPattern = accessEntry.getKeyPattern().pattern(); - if (rawPattern.startsWith(prefixFilter)) { + + //filter out relevant access entries based on prefix + List relevantAccessEntries = bucketedMap.get(keyEntry.getKey()); + + if (relevantAccessEntries != null) { + String key = normalizeKey(prefixFilter + "=" + keyEntry.getValue()); + + for (Access accessEntry : relevantAccessEntries) { + String rawPattern = accessEntry.getKeyPattern().pattern(); if (key.equals(rawPattern)) { return accessEntry.authorizeUserForMethod(methodName, userRoles); } @@ -119,7 +168,6 @@ public boolean authorizeUserForMethod(ObjectName objectName, String methodName, } } } - } Access access = domainMap.get(""); if (access != null) { From 0b6e0dd1be660ad42b8e7450252b26326afd1a0c Mon Sep 17 00:00:00 2001 From: gchuf Date: Wed, 29 Apr 2026 20:48:08 +0200 Subject: [PATCH 8/9] bucketedmap --- .../management/JMXAccessControlList.java | 70 +++++++++++-------- 1 file changed, 42 insertions(+), 28 deletions(-) diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/JMXAccessControlList.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/JMXAccessControlList.java index 99e8f2a1c92..4b52889fd61 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/JMXAccessControlList.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/JMXAccessControlList.java @@ -33,17 +33,17 @@ public class JMXAccessControlList { private static final String WILDCARD = "*"; - private record AccessEntry(Access access, String rawPattern) {} + private record AccessEntry(Access access, String rawPattern) { } private record Bucket( - Map exactMatches, + Map exactMatches, List regexPatterns - ) {} + ) { } private final Map> keyPropertyCache = Collections.synchronizedMap(new LinkedHashMap>(128, 0.75f, true) { @Override protected boolean removeEldestEntry(Map.Entry> eldest) { - return size() > 5000; + return size() > 5000; } }); @@ -119,22 +119,35 @@ public boolean authorizeUserForMethod(ObjectName objectName, String methodName, String domainKey = objectName.getDomain(); - TreeMap domainMap = domainCache.computeIfAbsent(objectName.getDomain(), key -> + TreeMap domainMap = domainCache.computeIfAbsent(objectName.getDomain(), key -> domainAccess.get(key) ); - Map> bucketedMap = bucketedDomainCache.computeIfAbsent(domainKey, d -> { + Map bucketedMap = bucketedDomainCache.computeIfAbsent(domainKey, d -> { TreeMap rawMap = domainAccess.get(d); - if (rawMap == null) return null; + if (rawMap == null) { + return null; + } - Map> grouped = new HashMap<>(); + Map grouped = new HashMap<>(); for (Access access : rawMap.values()) { - String pattern = access.getKeyPattern().pattern(); - // Extract prefix (e.g., "address" from "address=QUEUE.A") - int eqIndex = pattern.indexOf('='); - String prefix = (eqIndex != -1) ? pattern.substring(0, eqIndex) : ""; - - grouped.computeIfAbsent(prefix, k -> new ArrayList<>()).add(access); + String rawPattern = access.getKeyPattern().pattern(); + int eqIndex = rawPattern.indexOf('='); + String prefix = (eqIndex != -1) ? rawPattern.substring(0, eqIndex) : ""; + + // Initialize the Bucket (Map + List) instead of just an ArrayList + Bucket bucket = grouped.computeIfAbsent(prefix, k -> + new Bucket(new HashMap<>(), new ArrayList<>()) + ); + + AccessEntry entry = new AccessEntry(access, rawPattern); + + // Sort into Exact or Regex + if (rawPattern.contains("*") || rawPattern.contains("?") || rawPattern.contains("[")) { + bucket.regexPatterns().add(entry); + } else { + bucket.exactMatches().put(rawPattern, entry); + } } return grouped; }); @@ -148,26 +161,27 @@ public boolean authorizeUserForMethod(ObjectName objectName, String methodName, keyPropertyCache.put(cacheKey, keyPropertyList); } - for (Map.Entry keyEntry : keyPropertyList.entrySet()) { - String prefixFilter = keyEntry.getKey() + "="; - //filter out relevant access entries based on prefix - List relevantAccessEntries = bucketedMap.get(keyEntry.getKey()); + for (Map.Entry entry : keyPropertyList.entrySet()) { + String propKey = entry.getKey(); + Bucket bucket = bucketedMap.get(propKey); - if (relevantAccessEntries != null) { - String key = normalizeKey(prefixFilter + "=" + keyEntry.getValue()); + if (bucket != null) { + String normalizedValue = normalizeKey(propKey + "=" + entry.getValue()); - for (Access accessEntry : relevantAccessEntries) { - String rawPattern = accessEntry.getKeyPattern().pattern(); - if (key.equals(rawPattern)) { - return accessEntry.authorizeUserForMethod(methodName, userRoles); - } - // regexp check if previous did not return true - if (accessEntry.getKeyPattern().matcher(key).matches()) { - return accessEntry.authorizeUserForMethod(methodName, userRoles); + // Priority 1: O(1) Exact Match Check + if (bucket.exactMatches().containsKey(normalizedValue)) { + return bucket.exactMatches().get(normalizedValue).access().authorizeUserForMethod(methodName, userRoles); + } + + // Priority 2: O(N) Regex Match (but only for actual regexes) + for (AccessEntry regexEntry : bucket.regexPatterns()) { + if (regexEntry.access().getKeyPattern().matcher(normalizedValue).matches()) { + return regexEntry.access().authorizeUserForMethod(methodName, userRoles); } } } + } Access access = domainMap.get(""); if (access != null) { From 76b82354cf0da098122da8df70cb1150faafbfea Mon Sep 17 00:00:00 2001 From: gchuf Date: Wed, 29 Apr 2026 21:15:05 +0200 Subject: [PATCH 9/9] Fix test name --- .../core/server/management/ArtemisMBeanServerGuardTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/artemis-server/src/test/java/org/apache/activemq/artemis/core/server/management/ArtemisMBeanServerGuardTest.java b/artemis-server/src/test/java/org/apache/activemq/artemis/core/server/management/ArtemisMBeanServerGuardTest.java index dba3dea0378..9a9b6d6bdc3 100644 --- a/artemis-server/src/test/java/org/apache/activemq/artemis/core/server/management/ArtemisMBeanServerGuardTest.java +++ b/artemis-server/src/test/java/org/apache/activemq/artemis/core/server/management/ArtemisMBeanServerGuardTest.java @@ -82,7 +82,7 @@ public void testCanInvokeMethodHasRole() throws Throwable { @Test - public void testCanInvokeMethodDoeNotHasRole() throws Throwable { + public void testCanInvokeMethodDoesNotHaveRole() throws Throwable { ArtemisMBeanServerGuard guard = new ArtemisMBeanServerGuard(); JMXAccessControlList controlList = new JMXAccessControlList(); guard.setJMXAccessControlList(controlList);