mirror of https://github.com/apache/activemq.git
https://issues.apache.org/jira/browse/AMQ-4709 - add support for <authorizationEntry .. read="*" ..> to match any group
This commit is contained in:
parent
9f26e0b640
commit
0525772190
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 -->
|
||||
|
|
Loading…
Reference in New Issue