https://issues.apache.org/jira/browse/AMQ-4709 - add support for <authorizationEntry .. read="*" ..> to match any group
Project: http://git-wip-us.apache.org/repos/asf/activemq/repo Commit: http://git-wip-us.apache.org/repos/asf/activemq/commit/05257721 Tree: http://git-wip-us.apache.org/repos/asf/activemq/tree/05257721 Diff: http://git-wip-us.apache.org/repos/asf/activemq/diff/05257721 Branch: refs/heads/trunk Commit: 0525772190019c6a012c007d1b39f1078b700a3b Parents: 9f26e0b Author: gtully <[email protected]> Authored: Tue Sep 3 00:37:33 2013 +0100 Committer: gtully <[email protected]> Committed: Tue Sep 3 00:37:33 2013 +0100 ---------------------------------------------------------------------- .../activemq/security/AuthorizationBroker.java | 2 +- .../security/DefaultAuthorizationMap.java | 78 ++++++++++++++++++-- .../activemq/security/AuthorizationMapTest.java | 56 +++++++++++++- .../SimpleSecurityBrokerSystemTest.java | 16 ++-- .../apache/activemq/security/jaas-broker.xml | 2 +- 5 files changed, 140 insertions(+), 14 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/activemq/blob/05257721/activemq-broker/src/main/java/org/apache/activemq/security/AuthorizationBroker.java ---------------------------------------------------------------------- diff --git a/activemq-broker/src/main/java/org/apache/activemq/security/AuthorizationBroker.java b/activemq-broker/src/main/java/org/apache/activemq/security/AuthorizationBroker.java index 6c1a09d..bce1a09 100644 --- a/activemq-broker/src/main/java/org/apache/activemq/security/AuthorizationBroker.java +++ b/activemq-broker/src/main/java/org/apache/activemq/security/AuthorizationBroker.java @@ -134,7 +134,7 @@ public class AuthorizationBroker extends BrokerFilter implements SecurityAdminMB allowedACLs = authorizationMap.getTempDestinationReadACLs(); } - if (!securityContext.isBrokerContext() && (allowedACLs == null || !securityContext.isInOneOf(allowedACLs))) { + if (!securityContext.isBrokerContext() && allowedACLs != null && !securityContext.isInOneOf(allowedACLs) ) { throw new SecurityException("User " + securityContext.getUserName() + " is not authorized to read from: " + info.getDestination()); } securityContext.getAuthorizedReadDests().put(info.getDestination(), info.getDestination()); http://git-wip-us.apache.org/repos/asf/activemq/blob/05257721/activemq-broker/src/main/java/org/apache/activemq/security/DefaultAuthorizationMap.java ---------------------------------------------------------------------- diff --git a/activemq-broker/src/main/java/org/apache/activemq/security/DefaultAuthorizationMap.java b/activemq-broker/src/main/java/org/apache/activemq/security/DefaultAuthorizationMap.java index 91bb4b2..2d8ae49 100644 --- a/activemq-broker/src/main/java/org/apache/activemq/security/DefaultAuthorizationMap.java +++ b/activemq-broker/src/main/java/org/apache/activemq/security/DefaultAuthorizationMap.java @@ -22,6 +22,8 @@ import org.apache.activemq.filter.DestinationMapEntry; import java.lang.reflect.Constructor; import java.lang.reflect.Method; +import java.security.Principal; +import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.List; @@ -64,7 +66,9 @@ public class DefaultAuthorizationMap extends DestinationMap implements Authoriza public Set<Object> getTempDestinationAdminACLs() { if (tempDestinationAuthorizationEntry != null) { - return tempDestinationAuthorizationEntry.getAdminACLs(); + Set<Object> answer = new WildcardAwareSet<Object>(); + answer.addAll(tempDestinationAuthorizationEntry.getAdminACLs()); + return answer; } else { return null; } @@ -72,7 +76,9 @@ public class DefaultAuthorizationMap extends DestinationMap implements Authoriza public Set<Object> getTempDestinationReadACLs() { if (tempDestinationAuthorizationEntry != null) { - return tempDestinationAuthorizationEntry.getReadACLs(); + Set<Object> answer = new WildcardAwareSet<Object>(); + answer.addAll(tempDestinationAuthorizationEntry.getReadACLs()); + return answer; } else { return null; } @@ -80,7 +86,9 @@ public class DefaultAuthorizationMap extends DestinationMap implements Authoriza public Set<Object> getTempDestinationWriteACLs() { if (tempDestinationAuthorizationEntry != null) { - return tempDestinationAuthorizationEntry.getWriteACLs(); + Set<Object> answer = new WildcardAwareSet<Object>(); + answer.addAll(tempDestinationAuthorizationEntry.getWriteACLs()); + return answer; } else { return null; } @@ -88,7 +96,8 @@ public class DefaultAuthorizationMap extends DestinationMap implements Authoriza public Set<Object> getAdminACLs(ActiveMQDestination destination) { Set<AuthorizationEntry> entries = getAllEntries(destination); - Set<Object> answer = new HashSet<Object>(); + Set<Object> answer = new WildcardAwareSet<Object>(); + // now lets go through each entry adding individual for (Iterator<AuthorizationEntry> iter = entries.iterator(); iter.hasNext();) { AuthorizationEntry entry = iter.next(); @@ -99,7 +108,7 @@ public class DefaultAuthorizationMap extends DestinationMap implements Authoriza public Set<Object> getReadACLs(ActiveMQDestination destination) { Set<AuthorizationEntry> entries = getAllEntries(destination); - Set<Object> answer = new HashSet<Object>(); + Set<Object> answer = new WildcardAwareSet<Object>(); // now lets go through each entry adding individual for (Iterator<AuthorizationEntry> iter = entries.iterator(); iter.hasNext();) { @@ -111,7 +120,7 @@ public class DefaultAuthorizationMap extends DestinationMap implements Authoriza public Set<Object> getWriteACLs(ActiveMQDestination destination) { Set<AuthorizationEntry> entries = getAllEntries(destination); - Set<Object> answer = new HashSet<Object>(); + Set<Object> answer = new WildcardAwareSet<Object>(); // now lets go through each entry adding individual for (Iterator<AuthorizationEntry> iter = entries.iterator(); iter.hasNext();) { @@ -197,7 +206,26 @@ public class DefaultAuthorizationMap extends DestinationMap implements Authoriza this.groupClass = groupClass; } + final static String WILDCARD = "*"; public static Object createGroupPrincipal(String name, String groupClass) throws Exception { + if (WILDCARD.equals(name)) { + // simple match all group principal - match any name and class + return new Principal() { + @Override + public String getName() { + return WILDCARD; + } + @Override + public boolean equals(Object other) { + return true; + } + + @Override + public int hashCode() { + return WILDCARD.hashCode(); + } + }; + } Object[] param = new Object[]{name}; Class<?> cls = Class.forName(groupClass); @@ -234,4 +262,42 @@ public class DefaultAuthorizationMap extends DestinationMap implements Authoriza return instance; } + class WildcardAwareSet<T> extends HashSet<T> { + boolean hasWildcard = false; + + @Override + public boolean contains(Object e) { + if (hasWildcard) { + return true; + } else { + return super.contains(e); + } + } + + @Override + public boolean addAll(Collection<? extends T> collection) { + boolean modified = false; + Iterator<? extends T> e = collection.iterator(); + while (e.hasNext()) { + final T item = e.next(); + if (isWildcard(item)) { + hasWildcard = true; + } + if (add(item)) { + modified = true; + } + } + return modified; + } + + private boolean isWildcard(T item) { + try { + if (item.getClass().getMethod("getName", new Class[]{}).invoke(item).equals("*")) { + return true; + } + } catch (Exception ignored) { + } + return false; + } + } } http://git-wip-us.apache.org/repos/asf/activemq/blob/05257721/activemq-unit-tests/src/test/java/org/apache/activemq/security/AuthorizationMapTest.java ---------------------------------------------------------------------- diff --git a/activemq-unit-tests/src/test/java/org/apache/activemq/security/AuthorizationMapTest.java b/activemq-unit-tests/src/test/java/org/apache/activemq/security/AuthorizationMapTest.java index f32279d..b6ace87 100644 --- a/activemq-unit-tests/src/test/java/org/apache/activemq/security/AuthorizationMapTest.java +++ b/activemq-unit-tests/src/test/java/org/apache/activemq/security/AuthorizationMapTest.java @@ -30,7 +30,6 @@ import org.apache.activemq.jaas.GroupPrincipal; * */ public class AuthorizationMapTest extends TestCase { - static final GroupPrincipal GUESTS = new GroupPrincipal("guests"); static final GroupPrincipal USERS = new GroupPrincipal("users"); static final GroupPrincipal ADMINS = new GroupPrincipal("admins"); static final GroupPrincipal TEMP_DESTINATION_ADMINS = new GroupPrincipal("tempDestAdmins"); @@ -67,6 +66,61 @@ public class AuthorizationMapTest extends TestCase { } + public void testWildcards() { + AuthorizationMap map = createWildcardAuthorizationMap(); + + Set<?> readACLs = map.getReadACLs(new ActiveMQQueue("USERS.FOO.BAR")); + assertEquals("set size: " + readACLs, 1, readACLs.size()); + assertTrue("Contains users group", readACLs.contains(ADMINS)); + assertTrue("Contains users group", readACLs.contains(USERS)); + + Set<?> writeAcls = map.getWriteACLs(new ActiveMQQueue("USERS.FOO.BAR")); + assertEquals("set size: " + writeAcls, 1, writeAcls.size()); + assertTrue("Contains users group", writeAcls.contains(ADMINS)); + assertTrue("Contains users group", writeAcls.contains(USERS)); + + Set<?> adminAcls = map.getAdminACLs(new ActiveMQQueue("USERS.FOO.BAR")); + assertEquals("set size: " + adminAcls, 1, adminAcls.size()); + assertTrue("Contains users group", adminAcls.contains(ADMINS)); + assertFalse("Contains users group", adminAcls.contains(USERS)); + + Set<?> tempAdminACLs = map.getTempDestinationAdminACLs(); + assertEquals("set size: " + tempAdminACLs, 1, tempAdminACLs.size()); + assertTrue("Contains users group", tempAdminACLs.contains(TEMP_DESTINATION_ADMINS)); + } + + protected AuthorizationMap createWildcardAuthorizationMap() { + DefaultAuthorizationMap answer = new DefaultAuthorizationMap(); + + List<DestinationMapEntry> entries = new ArrayList<DestinationMapEntry>(); + + AuthorizationEntry entry = new AuthorizationEntry(); + entry.setQueue(">"); + try { + entry.setRead("*"); + entry.setWrite("*"); + entry.setAdmin("admins"); + } catch (Exception e) { + fail(e.toString()); + } + + entries.add(entry); + + answer.setAuthorizationEntries(entries); + + TempDestinationAuthorizationEntry tEntry = new TempDestinationAuthorizationEntry(); + try { + tEntry.setAdmin("*"); + } catch (Exception e) { + fail(e.toString()); + } + + answer.setTempDestinationAuthorizationEntry(tEntry); + + return answer; + + } + @SuppressWarnings("rawtypes") protected AuthorizationMap createAuthorizationMap() { DefaultAuthorizationMap answer = new DefaultAuthorizationMap(); http://git-wip-us.apache.org/repos/asf/activemq/blob/05257721/activemq-unit-tests/src/test/java/org/apache/activemq/security/SimpleSecurityBrokerSystemTest.java ---------------------------------------------------------------------- diff --git a/activemq-unit-tests/src/test/java/org/apache/activemq/security/SimpleSecurityBrokerSystemTest.java b/activemq-unit-tests/src/test/java/org/apache/activemq/security/SimpleSecurityBrokerSystemTest.java index 395cc67..cc32b50 100644 --- a/activemq-unit-tests/src/test/java/org/apache/activemq/security/SimpleSecurityBrokerSystemTest.java +++ b/activemq-unit-tests/src/test/java/org/apache/activemq/security/SimpleSecurityBrokerSystemTest.java @@ -43,11 +43,19 @@ import org.slf4j.LoggerFactory; * */ public class SimpleSecurityBrokerSystemTest extends SecurityTestSupport { + private static final Logger LOG = LoggerFactory.getLogger(SimpleSecurityBrokerSystemTest.class); static final GroupPrincipal GUESTS = new GroupPrincipal("guests"); static final GroupPrincipal USERS = new GroupPrincipal("users"); static final GroupPrincipal ADMINS = new GroupPrincipal("admins"); - private static final Logger LOG = LoggerFactory.getLogger(SimpleSecurityBrokerSystemTest.class); + static Principal WILDCARD; + static { + try { + WILDCARD = (Principal) DefaultAuthorizationMap.createGroupPrincipal("*", GroupPrincipal.class.getName()); + } catch (Exception e) { + LOG.error("Failed to make wildcard principal", e); + } + } public BrokerPlugin authorizationPlugin; public BrokerPlugin authenticationPlugin; @@ -91,10 +99,8 @@ public class SimpleSecurityBrokerSystemTest extends SecurityTestSupport { writeAccess.put(new ActiveMQTopic("GUEST.>"), USERS); writeAccess.put(new ActiveMQTopic("GUEST.>"), GUESTS); - readAccess.put(new ActiveMQTopic("ActiveMQ.Advisory.>"), GUESTS); - readAccess.put(new ActiveMQTopic("ActiveMQ.Advisory.>"), USERS); - writeAccess.put(new ActiveMQTopic("ActiveMQ.Advisory.>"), GUESTS); - writeAccess.put(new ActiveMQTopic("ActiveMQ.Advisory.>"), USERS); + readAccess.put(new ActiveMQTopic("ActiveMQ.Advisory.>"), WILDCARD); + writeAccess.put(new ActiveMQTopic("ActiveMQ.Advisory.>"), WILDCARD); DestinationMap adminAccess = new DefaultAuthorizationMap(); adminAccess.put(new ActiveMQTopic(">"), ADMINS); http://git-wip-us.apache.org/repos/asf/activemq/blob/05257721/activemq-unit-tests/src/test/resources/org/apache/activemq/security/jaas-broker.xml ---------------------------------------------------------------------- diff --git a/activemq-unit-tests/src/test/resources/org/apache/activemq/security/jaas-broker.xml b/activemq-unit-tests/src/test/resources/org/apache/activemq/security/jaas-broker.xml index 55b3bbe..c36fec5 100644 --- a/activemq-unit-tests/src/test/resources/org/apache/activemq/security/jaas-broker.xml +++ b/activemq-unit-tests/src/test/resources/org/apache/activemq/security/jaas-broker.xml @@ -46,7 +46,7 @@ <authorizationEntry topic="USERS.>" read="users" write="users" admin="users" /> <authorizationEntry topic="GUEST.>" read="guests" write="guests,users" admin="guests,users" /> - <authorizationEntry topic="ActiveMQ.Advisory.>" read="guests,users" write="guests,users" admin="guests,users"/> + <authorizationEntry topic="ActiveMQ.Advisory.>" read="*" write="guests,users" admin="guests,users"/> </authorizationEntries> <!-- let's assign roles to temporary destinations. comment this entry if we don't want any roles assigned to temp destinations -->
