Skip to content

Commit ff397eb

Browse files
committed
ARTEMIS-6057 treat fqqn with wildcards as exact match
in security settings, fqqn are treated as an exact match, but when they contain a wildcard are being ignored for exact match semantics in error
1 parent 72489b2 commit ff397eb

2 files changed

Lines changed: 125 additions & 2 deletions

File tree

artemis-server/src/main/java/org/apache/activemq/artemis/core/settings/impl/HierarchicalObjectRepository.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import org.apache.activemq.artemis.core.settings.HierarchicalRepository;
3838
import org.apache.activemq.artemis.core.settings.HierarchicalRepositoryChangeListener;
3939
import org.apache.activemq.artemis.core.settings.Mergeable;
40+
import org.apache.activemq.artemis.utils.CompositeAddress;
4041
import org.apache.activemq.artemis.utils.collections.ConcurrentHashSet;
4142
import org.slf4j.Logger;
4243
import org.slf4j.LoggerFactory;
@@ -203,7 +204,7 @@ public void addMatch(final String match, final T value, final boolean immutableM
203204
lock.writeLock().lock();
204205
try {
205206
// an exact match (i.e. one without wildcards) won't impact any other matches so no need to clear the cache
206-
if (wildcardConfiguration.isWild(modifiedMatch)) {
207+
if (wildcardConfiguration.isWild(modifiedMatch) && !CompositeAddress.isFullyQualified(modifiedMatch)) {
207208
clearCache();
208209
} else if (modifiedMatch != null && cache.containsKey(modifiedMatch)) {
209210
cache.remove(modifiedMatch);
@@ -216,7 +217,7 @@ public void addMatch(final String match, final T value, final boolean immutableM
216217
Match<T> match1 = new Match<>(modifiedMatch, value, wildcardConfiguration, literal);
217218
if (literal) {
218219
literalMatches.put(modifiedMatch, match1);
219-
} else if (wildcardConfiguration.isWild(modifiedMatch)) {
220+
} else if (wildcardConfiguration.isWild(modifiedMatch) && !CompositeAddress.isFullyQualified(modifiedMatch)) {
220221
wildcardMatches.put(modifiedMatch, match1);
221222
} else {
222223
exactMatches.put(modifiedMatch, match1);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.activemq.artemis.tests.integration.jms.client;
18+
19+
import org.apache.activemq.artemis.api.core.QueueConfiguration;
20+
import org.apache.activemq.artemis.api.core.RoutingType;
21+
import org.apache.activemq.artemis.core.config.CoreAddressConfiguration;
22+
import org.apache.activemq.artemis.core.security.Role;
23+
import org.apache.activemq.artemis.core.server.ActiveMQServer;
24+
import org.apache.activemq.artemis.core.settings.HierarchicalRepository;
25+
import org.apache.activemq.artemis.spi.core.security.ActiveMQJAASSecurityManager;
26+
import org.apache.activemq.artemis.tests.util.JMSTestBase;
27+
import org.apache.activemq.artemis.utils.CompositeAddress;
28+
import org.junit.jupiter.api.Test;
29+
30+
import javax.jms.Connection;
31+
import javax.jms.DeliveryMode;
32+
import javax.jms.JMSSecurityException;
33+
import javax.jms.Message;
34+
import javax.jms.MessageConsumer;
35+
import javax.jms.MessageProducer;
36+
import javax.jms.ObjectMessage;
37+
import javax.jms.Session;
38+
import javax.jms.Topic;
39+
40+
import java.util.HashSet;
41+
import java.util.Set;
42+
43+
import static org.junit.jupiter.api.Assertions.assertNotNull;
44+
import static org.junit.jupiter.api.Assertions.assertThrows;
45+
46+
public class WildcardOnboardSecureTest extends JMSTestBase {
47+
48+
private final String publishTo = "test.topic.A";
49+
private final String subscribeToWildcard = "test.topic.*";
50+
private final String clientId = "id1";
51+
private final String subscriberName = "sub1";
52+
53+
@Test
54+
public void testConsumeFromExistingWildcardWithJustConsumePermissionViaLiteral() throws Exception {
55+
final String userPass = "joe";
56+
Session sendSession = createSession(null, userPass);
57+
MessageProducer producerA = createProducer(sendSession, publishTo);
58+
59+
ObjectMessage received;
60+
try (MessageConsumer consumerWC = createConsumer(subscribeToWildcard, userPass)) {
61+
Message message = sendSession.createObjectMessage(1);
62+
producerA.send(message);
63+
received = (ObjectMessage) consumerWC.receive(500);
64+
}
65+
assertNotNull(received);
66+
assertNotNull(received.getObject());
67+
}
68+
69+
@Test
70+
public void testConsumeFromExistingWildcardWithNoPermFails() {
71+
assertThrows(JMSSecurityException.class, () -> createConsumer(subscribeToWildcard, "deny"));
72+
}
73+
74+
@Override
75+
protected boolean useSecurity() {
76+
return true;
77+
}
78+
79+
@Override
80+
protected void extraServerConfig(ActiveMQServer server) {
81+
HierarchicalRepository<Set<Role>> securityRepository = server.getSecurityRepository();
82+
ActiveMQJAASSecurityManager securityManager = (ActiveMQJAASSecurityManager) server.getSecurityManager();
83+
securityManager.getConfiguration().addUser("deny", "deny");
84+
securityManager.getConfiguration().addUser("joe", "joe");
85+
securityManager.getConfiguration().addRole("joe", "joe");
86+
Role joe = new Role("joe", true, true, false, false, false, false, false, false, false, false, false, false);
87+
Set<Role> roles = new HashSet<>();
88+
// no auto create permissions
89+
roles.add(joe);
90+
91+
securityRepository.addMatch(publishTo, roles);
92+
securityRepository.addMatch(CompositeAddress.toFullyQualified(subscribeToWildcard, clientId + "." + subscriberName), roles);
93+
securityManager.getConfiguration().addRole("joe", "joe");
94+
// pre create address and consumer queue as only send/consume permissions exist
95+
server.getConfiguration().addAddressConfiguration(new CoreAddressConfiguration().setName(publishTo).addRoutingType(RoutingType.MULTICAST));
96+
server.getConfiguration().addQueueConfiguration(QueueConfiguration.of(clientId + "." + subscriberName).setAddress(subscribeToWildcard).setRoutingType(RoutingType.MULTICAST));
97+
}
98+
99+
private Session createSession(String clientId, String userPass) throws Exception {
100+
Connection connection = cf.createConnection(userPass, userPass);
101+
if (clientId != null) {
102+
connection.setClientID(clientId);
103+
}
104+
connection.start();
105+
addConnection(connection);
106+
107+
return connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
108+
}
109+
110+
private MessageProducer createProducer(Session session, String topicName) throws Exception {
111+
Topic topic = session.createTopic(topicName);
112+
MessageProducer producer = session.createProducer(topic);
113+
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
114+
return producer;
115+
}
116+
117+
private MessageConsumer createConsumer(String topicName, String userPass) throws Exception {
118+
Session session = createSession(clientId, userPass);
119+
Topic topic = session.createTopic(topicName);
120+
return session.createDurableConsumer(topic, subscriberName);
121+
}
122+
}

0 commit comments

Comments
 (0)