https://issues.apache.org/jira/browse/AMQ-4709 - add support for <authorizationEntry .. read="*" ..> to match any group

This commit is contained in:
gtully 2013-09-03 00:37:33 +01:00
parent 9f26e0b640
commit 0525772190
5 changed files with 140 additions and 14 deletions

View File

@ -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());

View File

@ -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;
}
}
}

View File

@ -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();

View File

@ -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);

View File

@ -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 -->