summaryrefslogtreecommitdiff
path: root/qpid/java/broker-core/src
diff options
context:
space:
mode:
authorKeith Wall <kwall@apache.org>2014-03-21 17:16:34 +0000
committerKeith Wall <kwall@apache.org>2014-03-21 17:16:34 +0000
commitd77447d7230dd29d7dc9ee0575caf1997ec3a7a6 (patch)
treea6e4dcfe2edf677b6c20bd361886edc6dfbf01d3 /qpid/java/broker-core/src
parent801e80d3b2361375c357b2f33feaeae77b3f8a14 (diff)
downloadqpid-python-d77447d7230dd29d7dc9ee0575caf1997ec3a7a6.tar.gz
QPID-5634: [Java Broker] Remove support for AccessPlugins at the level of the virtualhost. Introduce supports for ACLs rules that include virtualhost predicate.
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1579986 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'qpid/java/broker-core/src')
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java2
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHost.java7
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java7
-rwxr-xr-xqpid/java/broker-core/src/main/java/org/apache/qpid/server/security/SecurityManager.java366
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java64
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/access/OperationLoggingDetails.java36
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java2
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/security/SecurityManagerTest.java571
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/AbstractDurableConfigurationStoreTestCase.java1
9 files changed, 787 insertions, 269 deletions
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java
index a30806d810..25f20ba1ee 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java
@@ -612,7 +612,7 @@ public abstract class AbstractExchange<T extends AbstractExchange<T>>
}
// Check access
- _virtualHost.getSecurityManager().authoriseUnbind(this, bindingKey, queue);
+ _virtualHost.getSecurityManager().authoriseUnbind(binding);
BindingImpl b = _bindingsMap.remove(new BindingIdentifier(bindingKey,queue));
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHost.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHost.java
index 4aec9b38a0..ee10ecfc8b 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHost.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHost.java
@@ -22,7 +22,6 @@ package org.apache.qpid.server.model;
import org.apache.qpid.server.configuration.updater.TaskExecutor;
import org.apache.qpid.server.message.MessageInstance;
-import org.apache.qpid.server.security.SecurityManager;
import org.apache.qpid.server.store.MessageStore;
import java.security.AccessControlException;
@@ -179,12 +178,6 @@ public interface VirtualHost<X extends VirtualHost<X>> extends ConfiguredObject<
void executeTransaction(TransactionalOperation op);
- /**
- * A temporary hack to expose host security manager.
- * TODO We need to add and implement an authorization provider configured object instead
- */
- SecurityManager getSecurityManager();
-
// TODO - remove this
TaskExecutor getTaskExecutor();
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java
index 72b316c784..6dbc2eea85 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java
@@ -49,7 +49,6 @@ import org.apache.qpid.server.plugin.ExchangeType;
import org.apache.qpid.server.protocol.AMQConnectionModel;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.ConflationQueue;
-import org.apache.qpid.server.security.SecurityManager;
import org.apache.qpid.server.security.access.Operation;
import org.apache.qpid.server.stats.StatisticsGatherer;
import org.apache.qpid.server.store.MessageStore;
@@ -1126,12 +1125,6 @@ public final class VirtualHostAdapter extends AbstractConfiguredObject<VirtualHo
}
@Override
- public SecurityManager getSecurityManager()
- {
- return _virtualHost.getSecurityManager();
- }
-
- @Override
public MessageStore getMessageStore()
{
return _virtualHost.getMessageStore();
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/SecurityManager.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/SecurityManager.java
index 77886e9030..478499fe6c 100755
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/SecurityManager.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/SecurityManager.java
@@ -18,27 +18,6 @@
*/
package org.apache.qpid.server.security;
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.server.binding.BindingImpl;
-import org.apache.qpid.server.consumer.ConsumerImpl;
-import org.apache.qpid.server.exchange.ExchangeImpl;
-
-import org.apache.qpid.server.model.*;
-import org.apache.qpid.server.plugin.AccessControlFactory;
-import org.apache.qpid.server.plugin.QpidServiceLoader;
-import org.apache.qpid.server.protocol.AMQConnectionModel;
-import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.security.access.FileAccessControlProviderConstants;
-import org.apache.qpid.server.security.access.ObjectProperties;
-import org.apache.qpid.server.security.access.ObjectType;
-import org.apache.qpid.server.security.access.Operation;
-import org.apache.qpid.server.security.access.OperationLoggingDetails;
-import org.apache.qpid.server.security.auth.AuthenticatedPrincipal;
-import org.apache.qpid.server.security.auth.TaskPrincipal;
-
-import javax.security.auth.Subject;
-
import static org.apache.qpid.server.security.access.ObjectType.BROKER;
import static org.apache.qpid.server.security.access.ObjectType.EXCHANGE;
import static org.apache.qpid.server.security.access.ObjectType.GROUP;
@@ -62,54 +41,48 @@ import java.security.AccessController;
import java.security.Principal;
import java.util.Collection;
import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
+import javax.security.auth.Subject;
+
+import org.apache.qpid.server.binding.BindingImpl;
+import org.apache.qpid.server.consumer.ConsumerImpl;
+import org.apache.qpid.server.exchange.ExchangeImpl;
+import org.apache.qpid.server.model.AccessControlProvider;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.ConfigurationChangeListener;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.protocol.AMQConnectionModel;
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.security.access.ObjectProperties;
+import org.apache.qpid.server.security.access.ObjectProperties.Property;
+import org.apache.qpid.server.security.access.ObjectType;
+import org.apache.qpid.server.security.access.Operation;
+import org.apache.qpid.server.security.access.OperationLoggingDetails;
+import org.apache.qpid.server.security.auth.AuthenticatedPrincipal;
+import org.apache.qpid.server.security.auth.TaskPrincipal;
+
public class SecurityManager implements ConfigurationChangeListener
{
- private static final Logger _logger = Logger.getLogger(SecurityManager.class);
-
private static final Subject SYSTEM = new Subject(true,
Collections.singleton(new SystemPrincipal()),
Collections.emptySet(),
Collections.emptySet());
+ private final ConcurrentHashMap<String, AccessControl> _plugins = new ConcurrentHashMap<String, AccessControl>();
+ private final boolean _managementMode;
+ private final Broker<?> _broker;
- private ConcurrentHashMap<String, AccessControl> _globalPlugins = new ConcurrentHashMap<String, AccessControl>();
- private ConcurrentHashMap<String, AccessControl> _hostPlugins = new ConcurrentHashMap<String, AccessControl>();
-
- private boolean _managementMode;
-
- private Broker _broker;
+ private final ConcurrentHashMap<PublishAccessCheckCacheEntry, PublishAccessCheck> _publishAccessCheckCache = new ConcurrentHashMap<SecurityManager.PublishAccessCheckCacheEntry, SecurityManager.PublishAccessCheck>();
- /*
- * Used by the Broker.
- */
- public SecurityManager(Broker broker, boolean managementMode)
+ public SecurityManager(Broker<?> broker, boolean managementMode)
{
_managementMode = managementMode;
_broker = broker;
}
- /*
- * Used by the VirtualHost to allow deferring to the broker level security plugins if required.
- */
- public SecurityManager(SecurityManager parent, String aclFile, String vhostName)
- {
- _managementMode = parent._managementMode;
- _broker = parent._broker;
- if(!_managementMode)
- {
- configureVirtualHostAclPlugin(aclFile, vhostName);
-
- // our global plugins are the parent's host plugins
- _globalPlugins = parent._hostPlugins;
- }
- }
-
public static Subject getSubjectWithAddedSystemRights()
{
Subject subject = Subject.getSubject(AccessController.getContext());
@@ -135,50 +108,11 @@ public class SecurityManager implements ConfigurationChangeListener
return subject;
}
- private void configureVirtualHostAclPlugin(String aclFile, String vhostName)
- {
- if(aclFile != null)
- {
- Map<String, Object> attributes = new HashMap<String, Object>();
-
- attributes.put(AccessControlProvider.TYPE, FileAccessControlProviderConstants.ACL_FILE_PROVIDER_TYPE);
- attributes.put(FileAccessControlProviderConstants.PATH, aclFile);
-
- for (AccessControlFactory provider : (new QpidServiceLoader<AccessControlFactory>()).instancesOf(AccessControlFactory.class))
- {
- AccessControl accessControl = provider.createInstance(attributes, _broker);
- accessControl.open();
- if(accessControl != null)
- {
- String pluginTypeName = getPluginTypeName(accessControl);
- _hostPlugins.put(pluginTypeName, accessControl);
-
- if(_logger.isDebugEnabled())
- {
- _logger.debug("Added access control to host plugins with name: " + vhostName);
- }
-
- break;
- }
- }
- }
-
- if(_logger.isDebugEnabled())
- {
- _logger.debug("Configured " + _hostPlugins.size() + " access control plugins");
- }
- }
-
private String getPluginTypeName(AccessControl accessControl)
{
return accessControl.getClass().getName();
}
- public static Logger getLogger()
- {
- return _logger;
- }
-
public static boolean isSystemProcess()
{
Subject subject = Subject.getSubject(AccessController.getContext());
@@ -234,71 +168,14 @@ public class SecurityManager implements ConfigurationChangeListener
return true;
}
- Map<String, AccessControl> remainingPlugins = _globalPlugins.isEmpty()
- ? Collections.<String, AccessControl>emptyMap()
- : _hostPlugins.isEmpty() ? _globalPlugins : new HashMap<String, AccessControl>(_globalPlugins);
-
- if(!_hostPlugins.isEmpty())
- {
- for (Entry<String, AccessControl> hostEntry : _hostPlugins.entrySet())
- {
- // Create set of global only plugins
- AccessControl globalPlugin = remainingPlugins.get(hostEntry.getKey());
- if (globalPlugin != null)
- {
- remainingPlugins.remove(hostEntry.getKey());
- }
-
- Result host = checker.allowed(hostEntry.getValue());
-
- if (host == Result.DENIED)
- {
- // Something vetoed the access, we're done
- return false;
- }
-
- // host allow overrides global allow, so only check global on abstain or defer
- if (host != Result.ALLOWED)
- {
- if (globalPlugin == null)
- {
- if (host == Result.DEFER)
- {
- host = hostEntry.getValue().getDefault();
- }
- if (host == Result.DENIED)
- {
- return false;
- }
- }
- else
- {
- Result global = checker.allowed(globalPlugin);
- if (global == Result.DEFER)
- {
- global = globalPlugin.getDefault();
- }
- if (global == Result.ABSTAIN && host == Result.DEFER)
- {
- global = hostEntry.getValue().getDefault();
- }
- if (global == Result.DENIED)
- {
- return false;
- }
- }
- }
- }
- }
-
- for (AccessControl plugin : remainingPlugins.values())
+ for (AccessControl plugin : _plugins.values())
{
Result remaining = checker.allowed(plugin);
- if (remaining == Result.DEFER)
+ if (remaining == Result.DEFER)
{
remaining = plugin.getDefault();
}
- if (remaining == Result.DENIED)
+ if (remaining == Result.DENIED)
{
return false;
}
@@ -308,28 +185,23 @@ public class SecurityManager implements ConfigurationChangeListener
return true;
}
- public void authoriseCreateBinding(BindingImpl binding)
+ public void authoriseCreateBinding(final BindingImpl binding)
{
- final ExchangeImpl exch = binding.getExchange();
- final AMQQueue queue = binding.getAMQQueue();
- final String bindingKey = binding.getBindingKey();
-
- boolean allowed =
- checkAllPlugins(new AccessCheck()
+ boolean allowed = checkAllPlugins(new AccessCheck()
{
Result allowed(AccessControl plugin)
{
- return plugin.authorise(BIND, EXCHANGE, new ObjectProperties(exch, queue, bindingKey));
+ return plugin.authorise(BIND, EXCHANGE, new ObjectProperties(binding));
}
});
if(!allowed)
{
- throw new AccessControlException("Permission denied: binding " + bindingKey);
+ throw new AccessControlException("Permission denied: binding " + binding.getBindingKey());
}
}
- public void authoriseMethod(final Operation operation, final String componentName, final String methodName)
+ public void authoriseMethod(final Operation operation, final String componentName, final String methodName, final String virtualHostName)
{
boolean allowed = checkAllPlugins(new AccessCheck()
{
@@ -339,8 +211,11 @@ public class SecurityManager implements ConfigurationChangeListener
properties.setName(methodName);
if (componentName != null)
{
- // Only set the property if there is a component name
- properties.put(ObjectProperties.Property.COMPONENT, componentName);
+ properties.put(ObjectProperties.Property.COMPONENT, componentName);
+ }
+ if (virtualHostName != null)
+ {
+ properties.put(ObjectProperties.Property.VIRTUALHOST_NAME, virtualHostName);
}
return plugin.authorise(operation, METHOD, properties);
}
@@ -367,15 +242,19 @@ public class SecurityManager implements ConfigurationChangeListener
public void authoriseCreateConnection(final AMQConnectionModel connection)
{
+ final String virtualHostName = connection.getVirtualHostName();
if(!checkAllPlugins(new AccessCheck()
{
Result allowed(AccessControl plugin)
{
- return plugin.authorise(Operation.ACCESS, VIRTUALHOST, ObjectProperties.EMPTY);
+ // We put the name into the properties under both name and virtualhost_name so the user may express predicates using either.
+ ObjectProperties properties = new ObjectProperties(virtualHostName);
+ properties.put(Property.VIRTUALHOST_NAME, virtualHostName);
+ return plugin.authorise(Operation.ACCESS, VIRTUALHOST, properties);
}
}))
{
- throw new AccessControlException("Permission denied: " + connection.getVirtualHostName());
+ throw new AccessControlException("Permission denied: " + virtualHostName);
}
}
@@ -403,10 +282,7 @@ public class SecurityManager implements ConfigurationChangeListener
{
Result allowed(AccessControl plugin)
{
- return plugin.authorise(CREATE, EXCHANGE, new ObjectProperties(exchange.isAutoDelete(),
- exchange.isDurable(),
- exchangeName,
- exchange.getTypeName()));
+ return plugin.authorise(CREATE, EXCHANGE, new ObjectProperties(exchange));
}
}))
{
@@ -421,11 +297,7 @@ public class SecurityManager implements ConfigurationChangeListener
{
Result allowed(AccessControl plugin)
{
- return plugin.authorise(CREATE, QUEUE, new ObjectProperties(queue.getAttribute(Queue.LIFETIME_POLICY) != LifetimePolicy.PERMANENT,
- Boolean.TRUE.equals(queue.getAttribute(Queue.DURABLE)),
- queue.getAttribute(Queue.EXCLUSIVE) != ExclusivityPolicy.NONE,
- queueName,
- queue.getOwner()));
+ return plugin.authorise(CREATE, QUEUE, new ObjectProperties(queue));
}
}))
{
@@ -470,7 +342,7 @@ public class SecurityManager implements ConfigurationChangeListener
{
Result allowed(AccessControl plugin)
{
- return plugin.authorise(UPDATE, EXCHANGE, new ObjectProperties(exchange.getName()));
+ return plugin.authorise(UPDATE, EXCHANGE, new ObjectProperties(exchange));
}
}))
{
@@ -484,7 +356,7 @@ public class SecurityManager implements ConfigurationChangeListener
{
Result allowed(AccessControl plugin)
{
- return plugin.authorise(DELETE, EXCHANGE, new ObjectProperties(exchange.getName()));
+ return plugin.authorise(DELETE, EXCHANGE, new ObjectProperties(exchange));
}
}))
{
@@ -522,39 +394,15 @@ public class SecurityManager implements ConfigurationChangeListener
}
}
- private ConcurrentHashMap<String, ConcurrentHashMap<String, PublishAccessCheck>> _immediatePublishPropsCache
- = new ConcurrentHashMap<String, ConcurrentHashMap<String, PublishAccessCheck>>();
- private ConcurrentHashMap<String, ConcurrentHashMap<String, PublishAccessCheck>> _publishPropsCache
- = new ConcurrentHashMap<String, ConcurrentHashMap<String, PublishAccessCheck>>();
-
- public void authorisePublish(final boolean immediate, String routingKey, String exchangeName)
+ public void authorisePublish(final boolean immediate, String routingKey, String exchangeName, String virtualHostName)
{
- if(routingKey == null)
+ PublishAccessCheckCacheEntry key = new PublishAccessCheckCacheEntry(immediate, routingKey, exchangeName, virtualHostName);
+ PublishAccessCheck check = _publishAccessCheckCache.get(key);
+ if (check == null)
{
- routingKey = "";
+ check = new PublishAccessCheck(new ObjectProperties(virtualHostName, exchangeName, routingKey, immediate));
+ _publishAccessCheckCache.putIfAbsent(key, check);
}
- if(exchangeName == null)
- {
- exchangeName = "";
- }
- PublishAccessCheck check;
- ConcurrentHashMap<String, ConcurrentHashMap<String, PublishAccessCheck>> cache =
- immediate ? _immediatePublishPropsCache : _publishPropsCache;
-
- ConcurrentHashMap<String, PublishAccessCheck> exchangeMap = cache.get(exchangeName);
- if(exchangeMap == null)
- {
- cache.putIfAbsent(exchangeName, new ConcurrentHashMap<String, PublishAccessCheck>());
- exchangeMap = cache.get(exchangeName);
- }
-
- check = exchangeMap.get(routingKey);
- if(check == null)
- {
- check = new PublishAccessCheck(new ObjectProperties(exchangeName, routingKey, immediate));
- exchangeMap.put(routingKey, check);
- }
-
if(!checkAllPlugins(check))
{
throw new AccessControlException("Permission denied, publish to: exchange-name '" + exchangeName + "'");
@@ -575,17 +423,17 @@ public class SecurityManager implements ConfigurationChangeListener
}
}
- public void authoriseUnbind(final ExchangeImpl exch, final String routingKey, final AMQQueue queue)
+ public void authoriseUnbind(final BindingImpl binding)
{
if(! checkAllPlugins(new AccessCheck()
{
Result allowed(AccessControl plugin)
{
- return plugin.authorise(UNBIND, EXCHANGE, new ObjectProperties(exch, queue, routingKey));
+ return plugin.authorise(UNBIND, EXCHANGE, new ObjectProperties(binding));
}
}))
{
- throw new AccessControlException("Permission denied: unbinding " + routingKey);
+ throw new AccessControlException("Permission denied: unbinding " + binding.getBindingKey());
}
}
@@ -618,29 +466,29 @@ public class SecurityManager implements ConfigurationChangeListener
{
if(newState == State.ACTIVE)
{
- synchronized (_hostPlugins)
+ synchronized (_plugins)
{
AccessControl accessControl = ((AccessControlProvider)object).getAccessControl();
String pluginTypeName = getPluginTypeName(accessControl);
- _hostPlugins.put(pluginTypeName, accessControl);
+ _plugins.put(pluginTypeName, accessControl);
}
}
else if(newState == State.DELETED)
{
- synchronized (_hostPlugins)
+ synchronized (_plugins)
{
AccessControl control = ((AccessControlProvider)object).getAccessControl();
String pluginTypeName = getPluginTypeName(control);
// Remove the type->control mapping for this type key only if the
// given control is actually referred to.
- if(_hostPlugins.containsValue(control))
+ if(_plugins.containsValue(control))
{
// If we are removing this control, check if another of the same
// type already exists on the broker and use it in instead.
AccessControl other = null;
- Collection<AccessControlProvider> providers = _broker.getAccessControlProviders();
+ Collection<AccessControlProvider<?>> providers = _broker.getAccessControlProviders();
for(AccessControlProvider p : providers)
{
if(p == object || p.getState() != State.ACTIVE)
@@ -660,12 +508,12 @@ public class SecurityManager implements ConfigurationChangeListener
if(other != null)
{
//Another control of this type was found, use it instead
- _hostPlugins.replace(pluginTypeName, control, other);
+ _plugins.replace(pluginTypeName, control, other);
}
else
{
//No other was found, remove the type entirely
- _hostPlugins.remove(pluginTypeName);
+ _plugins.remove(pluginTypeName);
}
}
}
@@ -718,4 +566,90 @@ public class SecurityManager implements ConfigurationChangeListener
});
}
+ public static class PublishAccessCheckCacheEntry
+ {
+ private final boolean _immediate;
+ private final String _routingKey;
+ private final String _exchangeName;
+ private final String _virtualHostName;
+
+ public PublishAccessCheckCacheEntry(boolean immediate, String routingKey, String exchangeName, String virtualHostName)
+ {
+ super();
+ _immediate = immediate;
+ _routingKey = routingKey;
+ _exchangeName = exchangeName;
+ _virtualHostName = virtualHostName;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((_exchangeName == null) ? 0 : _exchangeName.hashCode());
+ result = prime * result + (_immediate ? 1231 : 1237);
+ result = prime * result + ((_routingKey == null) ? 0 : _routingKey.hashCode());
+ result = prime * result + ((_virtualHostName == null) ? 0 : _virtualHostName.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if (obj == null)
+ {
+ return false;
+ }
+ if (getClass() != obj.getClass())
+ {
+ return false;
+ }
+ PublishAccessCheckCacheEntry other = (PublishAccessCheckCacheEntry) obj;
+ if (_exchangeName == null)
+ {
+ if (other._exchangeName != null)
+ {
+ return false;
+ }
+ }
+ else if (!_exchangeName.equals(other._exchangeName))
+ {
+ return false;
+ }
+ if (_immediate != other._immediate)
+ {
+ return false;
+ }
+ if (_routingKey == null)
+ {
+ if (other._routingKey != null)
+ {
+ return false;
+ }
+ }
+ else if (!_routingKey.equals(other._routingKey))
+ {
+ return false;
+ }
+ if (_virtualHostName == null)
+ {
+ if (other._virtualHostName != null)
+ {
+ return false;
+ }
+ }
+ else if (!_virtualHostName.equals(other._virtualHostName))
+ {
+ return false;
+ }
+ return true;
+ }
+
+
+ }
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java
index ae0241314f..6122cef5c1 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java
@@ -26,8 +26,10 @@ import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.qpid.server.binding.BindingImpl;
import org.apache.qpid.server.exchange.ExchangeImpl;
import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.VirtualHost;
import org.apache.qpid.server.queue.AMQQueue;
/**
@@ -39,7 +41,7 @@ import org.apache.qpid.server.queue.AMQQueue;
*/
public class ObjectProperties
{
- public static final String STAR= "*";
+ public static final String WILD_CARD = "*";
public static final ObjectProperties EMPTY = new ObjectProperties();
@@ -65,7 +67,8 @@ public class ObjectProperties
PACKAGE,
CLASS,
FROM_NETWORK,
- FROM_HOSTNAME;
+ FROM_HOSTNAME,
+ VIRTUALHOST_NAME;
private static final Map<String, Property> _canonicalNameToPropertyMap = new HashMap<String, ObjectProperties.Property>();
@@ -152,60 +155,49 @@ public class ObjectProperties
{
put(Property.OWNER, queue.getOwner());
}
-
+ put(Property.VIRTUALHOST_NAME, queue.getParent(VirtualHost.class).getName());
}
- public ObjectProperties(ExchangeImpl exch, AMQQueue queue, String routingKey)
+ public ObjectProperties(BindingImpl binding)
{
- this(queue);
+ ExchangeImpl<?> exch = binding.getExchange();
+ AMQQueue<?> queue = binding.getAMQQueue();
+ String routingKey = binding.getBindingKey();
setName(exch.getName());
- put(Property.QUEUE_NAME, queue.getName());
+ put(Property.QUEUE_NAME, queue.getName());
put(Property.ROUTING_KEY, routingKey);
- }
-
- public ObjectProperties(String exchangeName, String routingKey, Boolean immediate)
- {
- this(exchangeName, routingKey);
+ put(Property.VIRTUALHOST_NAME, queue.getParent(VirtualHost.class).getName());
- put(Property.IMMEDIATE, immediate);
+ // The temporary attribute (inherited from the binding's queue) seems to exist to allow the user to
+ // express rules about the binding of temporary queues (whose names cannot be predicted).
+ put(Property.TEMPORARY, queue.getLifetimePolicy() != LifetimePolicy.PERMANENT);
+ put(Property.DURABLE, queue.isDurable());
}
- public ObjectProperties(String exchangeName, String routingKey)
+ public ObjectProperties(String virtualHostName, String exchangeName, String routingKey, Boolean immediate)
{
super();
setName(exchangeName);
put(Property.ROUTING_KEY, routingKey);
+ put(Property.IMMEDIATE, immediate);
+ put(Property.VIRTUALHOST_NAME, virtualHostName);
}
- public ObjectProperties(Boolean autoDelete, Boolean durable, String exchangeName,
- String exchangeType)
- {
- super();
-
- setName(exchangeName);
-
- put(Property.AUTO_DELETE, autoDelete);
- put(Property.TEMPORARY, autoDelete);
- put(Property.DURABLE, durable);
- put(Property.TYPE, exchangeType);
- }
-
- public ObjectProperties(Boolean autoDelete, Boolean durable, Boolean exclusive,
- String queueName, String owner)
+ public ObjectProperties(ExchangeImpl<?> exchange)
{
super();
- setName(queueName);
+ setName(exchange.getName());
- put(Property.AUTO_DELETE, autoDelete);
- put(Property.TEMPORARY, autoDelete);
- put(Property.DURABLE, durable);
- put(Property.EXCLUSIVE, exclusive);
- put(Property.OWNER, owner);
+ put(Property.AUTO_DELETE, exchange.isAutoDelete());
+ put(Property.TEMPORARY, exchange.getLifetimePolicy() != LifetimePolicy.PERMANENT);
+ put(Property.DURABLE, exchange.isDurable());
+ put(Property.TYPE, exchange.getTypeName());
+ put(Property.VIRTUALHOST_NAME, exchange.getParent(VirtualHost.class).getName());
}
public ObjectProperties(Boolean exclusive, Boolean noAck, Boolean noLocal, Boolean nowait, AMQQueue queue)
@@ -283,8 +275,8 @@ public class ObjectProperties
{
return (StringUtils.isEmpty(ruleValue)
|| StringUtils.equals(thisValue, ruleValue))
- || ruleValue.equals(STAR)
- || (ruleValue.endsWith(STAR)
+ || ruleValue.equals(WILD_CARD)
+ || (ruleValue.endsWith(WILD_CARD)
&& thisValue != null
&& thisValue.length() >= ruleValue.length() - 1
&& thisValue.startsWith(ruleValue.substring(0, ruleValue.length() - 1)));
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/access/OperationLoggingDetails.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/access/OperationLoggingDetails.java
index a683199abc..f36695cb86 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/access/OperationLoggingDetails.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/access/OperationLoggingDetails.java
@@ -32,6 +32,42 @@ public class OperationLoggingDetails extends ObjectProperties
}
@Override
+ public int hashCode()
+ {
+ return super.hashCode() + ((_description == null) ? 0 : _description.hashCode());
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if (!super.equals(obj))
+ {
+ return false;
+ }
+ if (getClass() != obj.getClass())
+ {
+ return false;
+ }
+ OperationLoggingDetails other = (OperationLoggingDetails) obj;
+ if (_description == null)
+ {
+ if (other._description != null)
+ {
+ return false;
+ }
+ }
+ else if (!_description.equals(other._description))
+ {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
public String toString()
{
StringBuilder sb = new StringBuilder("(");
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java
index a4719f6058..2f1939be39 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java
@@ -156,7 +156,7 @@ public abstract class AbstractVirtualHost implements VirtualHost, IConnectionReg
_eventLogger.message(VirtualHostMessages.CREATED(_name));
- _securityManager = new SecurityManager(parentSecurityManager, _vhostConfig.getConfig().getString("security.acl"), _name);
+ _securityManager = parentSecurityManager;
_connectionRegistry = new ConnectionRegistry();
_connectionRegistry.addRegistryChangeListener(this);
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/security/SecurityManagerTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/security/SecurityManagerTest.java
new file mode 100644
index 0000000000..e27981d22c
--- /dev/null
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/security/SecurityManagerTest.java
@@ -0,0 +1,571 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.security;
+
+import static org.apache.qpid.server.security.access.ObjectType.BROKER;
+import static org.apache.qpid.server.security.access.ObjectType.EXCHANGE;
+import static org.apache.qpid.server.security.access.Operation.ACCESS_LOGS;
+import static org.apache.qpid.server.security.access.Operation.PUBLISH;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.security.AccessControlException;
+
+import org.apache.qpid.server.binding.BindingImpl;
+import org.apache.qpid.server.consumer.ConsumerImpl;
+import org.apache.qpid.server.exchange.ExchangeImpl;
+import org.apache.qpid.server.model.AccessControlProvider;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.protocol.AMQConnectionModel;
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.security.access.ObjectProperties;
+import org.apache.qpid.server.security.access.ObjectProperties.Property;
+import org.apache.qpid.server.security.access.ObjectType;
+import org.apache.qpid.server.security.access.Operation;
+import org.apache.qpid.server.security.access.OperationLoggingDetails;
+import org.apache.qpid.test.utils.QpidTestCase;
+
+public class SecurityManagerTest extends QpidTestCase
+{
+ private static final String TEST_EXCHANGE_TYPE = "testExchangeType";
+ private static final String TEST_VIRTUAL_HOST = "testVirtualHost";
+ private static final String TEST_EXCHANGE = "testExchange";
+ private static final String TEST_QUEUE = "testQueue";
+
+ private AccessControl _accessControl;
+ private SecurityManager _securityManager;
+ private VirtualHost<?> _virtualHost;
+
+ @Override
+ public void setUp() throws Exception
+ {
+ super.setUp();
+ _accessControl = mock(AccessControl.class);
+ _virtualHost = mock(VirtualHost.class);
+
+ AccessControlProvider<?> aclProvider = mock(AccessControlProvider.class);
+ when(aclProvider.getAccessControl()).thenReturn(_accessControl);
+
+ when(_virtualHost.getName()).thenReturn(TEST_VIRTUAL_HOST);
+
+ _securityManager = new SecurityManager(mock(Broker.class), false);
+ _securityManager.stateChanged(aclProvider, State.INITIALISING, State.ACTIVE);
+ }
+
+ public void testAuthoriseCreateBinding()
+ {
+ ExchangeImpl<?> exchange = mock(ExchangeImpl.class);
+ when(exchange.getParent(VirtualHost.class)).thenReturn(_virtualHost);
+ when(exchange.getName()).thenReturn(TEST_EXCHANGE);
+
+ AMQQueue<?> queue = mock(AMQQueue.class);
+ when(queue.getParent(VirtualHost.class)).thenReturn(_virtualHost);
+ when(queue.getName()).thenReturn(TEST_QUEUE);
+ when(queue.isDurable()).thenReturn(true);
+ when(queue.getLifetimePolicy()).thenReturn(LifetimePolicy.PERMANENT);
+
+ BindingImpl binding = mock(BindingImpl.class);
+ when(binding.getExchange()).thenReturn(exchange);
+ when(binding.getAMQQueue()).thenReturn(queue);
+ when(binding.getBindingKey()).thenReturn("bindingKey");
+
+ ObjectProperties properties = new ObjectProperties();
+ properties.put(Property.NAME, TEST_EXCHANGE);
+ properties.put(Property.VIRTUALHOST_NAME, TEST_VIRTUAL_HOST);
+ properties.put(Property.QUEUE_NAME, TEST_QUEUE);
+ properties.put(Property.ROUTING_KEY, "bindingKey");
+ properties.put(Property.TEMPORARY, false);
+ properties.put(Property.DURABLE, true);
+
+
+ configureAccessPlugin(Result.ALLOWED);
+ _securityManager.authoriseCreateBinding(binding);
+ verify(_accessControl).authorise(eq(Operation.BIND), eq(ObjectType.EXCHANGE), eq(properties));
+
+ configureAccessPlugin(Result.DENIED);
+ try
+ {
+ _securityManager.authoriseCreateBinding(binding);
+ fail("AccessControlException is expected");
+ }
+ catch(AccessControlException e)
+ {
+ // pass
+ }
+ verify(_accessControl, times(2)).authorise(eq(Operation.BIND), eq(ObjectType.EXCHANGE), eq(properties));
+ }
+
+
+ public void testAuthoriseMethod()
+ {
+ ObjectProperties properties = new ObjectProperties("testMethod");
+ properties.put(ObjectProperties.Property.COMPONENT, "testComponent");
+ properties.put(ObjectProperties.Property.VIRTUALHOST_NAME, TEST_VIRTUAL_HOST);
+
+ configureAccessPlugin(Result.ALLOWED);
+ _securityManager.authoriseMethod(Operation.UPDATE, "testComponent", "testMethod", TEST_VIRTUAL_HOST);
+ verify(_accessControl).authorise(eq(Operation.UPDATE), eq(ObjectType.METHOD), eq(properties));
+
+ configureAccessPlugin(Result.DENIED);
+ try
+ {
+ _securityManager.authoriseMethod(Operation.UPDATE, "testComponent", "testMethod", TEST_VIRTUAL_HOST);
+ fail("AccessControlException is expected");
+ }
+ catch(AccessControlException e)
+ {
+ // pass
+ }
+ verify(_accessControl, times(2)).authorise(eq(Operation.UPDATE), eq(ObjectType.METHOD), eq(properties));
+ }
+
+ public void testAccessManagement()
+ {
+ configureAccessPlugin(Result.ALLOWED);
+ _securityManager.accessManagement();
+ verify(_accessControl).authorise(Operation.ACCESS, ObjectType.MANAGEMENT, ObjectProperties.EMPTY);
+
+ configureAccessPlugin(Result.DENIED);
+ try
+ {
+ _securityManager.accessManagement();
+ fail("AccessControlException is expected");
+ }
+ catch(AccessControlException e)
+ {
+ // pass
+ }
+ verify(_accessControl, times(2)).authorise(Operation.ACCESS, ObjectType.MANAGEMENT, ObjectProperties.EMPTY);
+ }
+
+ public void testAuthoriseCreateConnection()
+ {
+ AMQConnectionModel<?,?> connection = mock(AMQConnectionModel.class);
+ when(connection.getVirtualHostName()).thenReturn(TEST_VIRTUAL_HOST);
+
+ ObjectProperties properties = new ObjectProperties();
+ properties.put(Property.NAME, TEST_VIRTUAL_HOST);
+ properties.put(Property.VIRTUALHOST_NAME, TEST_VIRTUAL_HOST);
+
+ configureAccessPlugin(Result.ALLOWED);
+ _securityManager.authoriseCreateConnection(connection);
+ verify(_accessControl).authorise(eq(Operation.ACCESS), eq(ObjectType.VIRTUALHOST), eq(properties));
+
+ configureAccessPlugin(Result.DENIED);
+ try
+ {
+ _securityManager.authoriseCreateConnection(connection);
+ fail("AccessControlException is expected");
+ }
+ catch(AccessControlException e)
+ {
+ // pass
+ }
+ verify(_accessControl, times(2)).authorise(eq(Operation.ACCESS), eq(ObjectType.VIRTUALHOST), eq(properties));
+ }
+
+ public void testAuthoriseCreateConsumer()
+ {
+ AMQQueue<?> queue = mock(AMQQueue.class);
+ when(queue.getParent(VirtualHost.class)).thenReturn(_virtualHost);
+ when(queue.getName()).thenReturn(TEST_QUEUE);
+ when(queue.isDurable()).thenReturn(true);
+ when(queue.getLifetimePolicy()).thenReturn(LifetimePolicy.PERMANENT);
+
+ ConsumerImpl consumer = mock(ConsumerImpl.class);
+ when(consumer.getMessageSource()).thenReturn(queue);
+
+ ObjectProperties properties = new ObjectProperties();
+ properties.put(Property.NAME, TEST_QUEUE);
+ properties.put(Property.VIRTUALHOST_NAME, TEST_VIRTUAL_HOST);
+ properties.put(Property.AUTO_DELETE, false);
+ properties.put(Property.TEMPORARY, false);
+ properties.put(Property.DURABLE, true);
+ properties.put(Property.EXCLUSIVE, false);
+
+ configureAccessPlugin(Result.ALLOWED);
+ _securityManager.authoriseCreateConsumer(consumer);
+ verify(_accessControl).authorise(eq(Operation.CONSUME), eq(ObjectType.QUEUE), eq(properties));
+
+ configureAccessPlugin(Result.DENIED);
+ try
+ {
+ _securityManager.authoriseCreateConsumer(consumer);
+ fail("AccessControlException is expected");
+ }
+ catch(AccessControlException e)
+ {
+ // pass
+ }
+ verify(_accessControl, times(2)).authorise(eq(Operation.CONSUME), eq(ObjectType.QUEUE), eq(properties));
+ }
+
+ public void testAuthoriseCreateExchange()
+ {
+ ExchangeImpl<?> exchange = mock(ExchangeImpl.class);
+ when(exchange.getParent(VirtualHost.class)).thenReturn(_virtualHost);
+ when(exchange.getName()).thenReturn(TEST_EXCHANGE);
+ when(exchange.getTypeName()).thenReturn(TEST_EXCHANGE_TYPE);
+
+ ObjectProperties properties = createExpectedExchangeObjectProperties();
+
+ configureAccessPlugin(Result.ALLOWED);
+ _securityManager.authoriseCreateExchange(exchange);
+ verify(_accessControl).authorise(eq(Operation.CREATE), eq(ObjectType.EXCHANGE), eq(properties));
+
+ configureAccessPlugin(Result.DENIED);
+ try
+ {
+ _securityManager.authoriseCreateExchange(exchange);
+ fail("AccessControlException is expected");
+ }
+ catch(AccessControlException e)
+ {
+ // pass
+ }
+ verify(_accessControl, times(2)).authorise(eq(Operation.CREATE), eq(ObjectType.EXCHANGE), eq(properties));
+ }
+
+ public void testAuthoriseCreateQueue()
+ {
+ AMQQueue<?> queue = mock(AMQQueue.class);
+ when(queue.getParent(VirtualHost.class)).thenReturn(_virtualHost);
+ when(queue.getName()).thenReturn(TEST_QUEUE);
+
+ ObjectProperties properties = createExpectedQueueObjectProperties();
+
+ configureAccessPlugin(Result.ALLOWED);
+ _securityManager.authoriseCreateQueue(queue);
+ verify(_accessControl).authorise(eq(Operation.CREATE), eq(ObjectType.QUEUE), eq(properties));
+
+ configureAccessPlugin(Result.DENIED);
+ try
+ {
+ _securityManager.authoriseCreateQueue(queue);
+ fail("AccessControlException is expected");
+ }
+ catch(AccessControlException e)
+ {
+ // pass
+ }
+ verify(_accessControl, times(2)).authorise(eq(Operation.CREATE), eq(ObjectType.QUEUE), eq(properties));
+ }
+
+ public void testAuthoriseDeleteQueue()
+ {
+ AMQQueue<?> queue = mock(AMQQueue.class);
+ when(queue.getParent(VirtualHost.class)).thenReturn(_virtualHost);
+ when(queue.getName()).thenReturn(TEST_QUEUE);
+
+ ObjectProperties properties = createExpectedQueueObjectProperties();
+
+ configureAccessPlugin(Result.ALLOWED);
+ _securityManager.authoriseDelete(queue);
+ verify(_accessControl).authorise(eq(Operation.DELETE), eq(ObjectType.QUEUE), eq(properties));
+
+ configureAccessPlugin(Result.DENIED);
+ try
+ {
+ _securityManager.authoriseDelete(queue);
+ fail("AccessControlException is expected");
+ }
+ catch(AccessControlException e)
+ {
+ // pass
+ }
+ verify(_accessControl, times(2)).authorise(eq(Operation.DELETE), eq(ObjectType.QUEUE), eq(properties));
+ }
+
+ public void testAuthoriseUpdateQueue()
+ {
+ AMQQueue<?> queue = mock(AMQQueue.class);
+ when(queue.getParent(VirtualHost.class)).thenReturn(_virtualHost);
+ when(queue.getName()).thenReturn(TEST_QUEUE);
+
+ ObjectProperties properties = createExpectedQueueObjectProperties();
+
+ configureAccessPlugin(Result.ALLOWED);
+ _securityManager.authoriseUpdate(queue);
+ verify(_accessControl).authorise(eq(Operation.UPDATE), eq(ObjectType.QUEUE), eq(properties));
+
+ configureAccessPlugin(Result.DENIED);
+ try
+ {
+ _securityManager.authoriseUpdate(queue);
+ fail("AccessControlException is expected");
+ }
+ catch(AccessControlException e)
+ {
+ // pass
+ }
+ verify(_accessControl, times(2)).authorise(eq(Operation.UPDATE), eq(ObjectType.QUEUE), eq(properties));
+ }
+
+ public void testAuthoriseUpdateExchange()
+ {
+ ExchangeImpl<?> exchange = mock(ExchangeImpl.class);
+ when(exchange.getParent(VirtualHost.class)).thenReturn(_virtualHost);
+ when(exchange.getName()).thenReturn(TEST_EXCHANGE);
+ when(exchange.getTypeName()).thenReturn(TEST_EXCHANGE_TYPE);
+
+ ObjectProperties properties = createExpectedExchangeObjectProperties();
+
+ configureAccessPlugin(Result.ALLOWED);
+ _securityManager.authoriseUpdate(exchange);
+ verify(_accessControl).authorise(eq(Operation.UPDATE), eq(ObjectType.EXCHANGE), eq(properties));
+
+ configureAccessPlugin(Result.DENIED);
+ try
+ {
+ _securityManager.authoriseUpdate(exchange);
+ fail("AccessControlException is expected");
+ }
+ catch(AccessControlException e)
+ {
+ // pass
+ }
+ verify(_accessControl, times(2)).authorise(eq(Operation.UPDATE), eq(ObjectType.EXCHANGE), eq(properties));
+ }
+
+ public void testAuthoriseDeleteExchange()
+ {
+ ExchangeImpl<?> exchange = mock(ExchangeImpl.class);
+ when(exchange.getParent(VirtualHost.class)).thenReturn(_virtualHost);
+ when(exchange.getName()).thenReturn(TEST_EXCHANGE);
+ when(exchange.getTypeName()).thenReturn(TEST_EXCHANGE_TYPE);
+
+ ObjectProperties properties = createExpectedExchangeObjectProperties();
+
+ configureAccessPlugin(Result.ALLOWED);
+ _securityManager.authoriseDelete(exchange);
+ verify(_accessControl).authorise(eq(Operation.DELETE), eq(ObjectType.EXCHANGE), eq(properties));
+
+ configureAccessPlugin(Result.DENIED);
+ try
+ {
+ _securityManager.authoriseDelete(exchange);
+ fail("AccessControlException is expected");
+ }
+ catch(AccessControlException e)
+ {
+ // pass
+ }
+ verify(_accessControl, times(2)).authorise(eq(Operation.DELETE), eq(ObjectType.EXCHANGE), eq(properties));
+ }
+
+ public void testAuthoriseGroupOperation()
+ {
+ ObjectProperties properties = new ObjectProperties("testGroup");
+
+ configureAccessPlugin(Result.ALLOWED);
+ _securityManager.authoriseGroupOperation(Operation.CREATE, "testGroup");
+ verify(_accessControl).authorise(eq(Operation.CREATE), eq(ObjectType.GROUP), eq(properties));
+
+ configureAccessPlugin(Result.DENIED);
+ try
+ {
+ _securityManager.authoriseGroupOperation(Operation.CREATE, "testGroup");
+ fail("AccessControlException is expected");
+ }
+ catch(AccessControlException e)
+ {
+ // pass
+ }
+ verify(_accessControl, times(2)).authorise(eq(Operation.CREATE), eq(ObjectType.GROUP), eq(properties));
+ }
+
+ public void testAuthoriseUserOperation()
+ {
+ ObjectProperties properties = new ObjectProperties("testUser");
+
+ configureAccessPlugin(Result.ALLOWED);
+ _securityManager.authoriseUserOperation(Operation.CREATE, "testUser");
+ verify(_accessControl).authorise(eq(Operation.CREATE), eq(ObjectType.USER), eq(properties));
+
+ configureAccessPlugin(Result.DENIED);
+ try
+ {
+ _securityManager.authoriseUserOperation(Operation.CREATE, "testUser");
+ fail("AccessControlException is expected");
+ }
+ catch(AccessControlException e)
+ {
+ // pass
+ }
+ verify(_accessControl, times(2)).authorise(eq(Operation.CREATE), eq(ObjectType.USER), eq(properties));
+ }
+
+ public void testAuthorisePublish()
+ {
+ String routingKey = "routingKey";
+ String exchangeName = "exchangeName";
+ boolean immediate = true;
+ ObjectProperties properties = new ObjectProperties(TEST_VIRTUAL_HOST, exchangeName, routingKey, immediate);
+
+ configureAccessPlugin(Result.ALLOWED);
+ _securityManager.authorisePublish(immediate, routingKey, exchangeName, TEST_VIRTUAL_HOST);
+ verify(_accessControl).authorise(eq(Operation.PUBLISH), eq(ObjectType.EXCHANGE), eq(properties));
+
+ configureAccessPlugin(Result.DENIED);
+ try
+ {
+ _securityManager.authorisePublish(immediate, routingKey, exchangeName, TEST_VIRTUAL_HOST);
+ fail("AccessControlException is expected");
+ }
+ catch(AccessControlException e)
+ {
+ // pass
+ }
+ verify(_accessControl, times(2)).authorise(eq(Operation.PUBLISH), eq(ObjectType.EXCHANGE), eq(properties));
+ }
+
+ public void testAuthorisePurge()
+ {
+ AMQQueue<?> queue = mock(AMQQueue.class);
+ when(queue.getParent(VirtualHost.class)).thenReturn(_virtualHost);
+ when(queue.getName()).thenReturn(TEST_QUEUE);
+
+ ObjectProperties properties = createExpectedQueueObjectProperties();
+
+ configureAccessPlugin(Result.ALLOWED);
+ _securityManager.authorisePurge(queue);
+ verify(_accessControl).authorise(eq(Operation.PURGE), eq(ObjectType.QUEUE), eq(properties));
+
+ configureAccessPlugin(Result.DENIED);
+ try
+ {
+ _securityManager.authorisePurge(queue);
+ fail("AccessControlException is expected");
+ }
+ catch(AccessControlException e)
+ {
+ // pass
+ }
+ verify(_accessControl, times(2)).authorise(eq(Operation.PURGE), eq(ObjectType.QUEUE), eq(properties));
+ }
+
+
+ public void testAuthoriseUnbind()
+ {
+ ExchangeImpl<?> exchange = mock(ExchangeImpl.class);
+ when(exchange.getParent(VirtualHost.class)).thenReturn(_virtualHost);
+ when(exchange.getName()).thenReturn(TEST_EXCHANGE);
+
+ AMQQueue<?> queue = mock(AMQQueue.class);
+ when(queue.getParent(VirtualHost.class)).thenReturn(_virtualHost);
+ when(queue.getName()).thenReturn(TEST_QUEUE);
+ when(queue.isDurable()).thenReturn(true);
+ when(queue.getLifetimePolicy()).thenReturn(LifetimePolicy.PERMANENT);
+
+ BindingImpl binding = mock(BindingImpl.class);
+ when(binding.getExchange()).thenReturn(exchange);
+ when(binding.getAMQQueue()).thenReturn(queue);
+ when(binding.getBindingKey()).thenReturn("bindingKey");
+
+ ObjectProperties properties = new ObjectProperties();
+ properties.put(Property.NAME, TEST_EXCHANGE);
+ properties.put(Property.VIRTUALHOST_NAME, TEST_VIRTUAL_HOST);
+ properties.put(Property.QUEUE_NAME, TEST_QUEUE);
+ properties.put(Property.ROUTING_KEY, "bindingKey");
+ properties.put(Property.TEMPORARY, false);
+ properties.put(Property.DURABLE, true);
+
+
+ configureAccessPlugin(Result.ALLOWED);
+ _securityManager.authoriseUnbind(binding);
+ verify(_accessControl).authorise(eq(Operation.UNBIND), eq(ObjectType.EXCHANGE), eq(properties));
+
+ configureAccessPlugin(Result.DENIED);
+ try
+ {
+ _securityManager.authoriseUnbind(binding);
+ fail("AccessControlException is expected");
+ }
+ catch(AccessControlException e)
+ {
+ // pass
+ }
+ verify(_accessControl, times(2)).authorise(eq(Operation.UNBIND), eq(ObjectType.EXCHANGE), eq(properties));
+ }
+
+ public void testAuthoriseConfiguringBroker()
+ {
+ OperationLoggingDetails properties = new OperationLoggingDetails("create virtualhost 'test'");
+
+ configureAccessPlugin(Result.ALLOWED);
+ assertTrue(_securityManager.authoriseConfiguringBroker("test", VirtualHost.class, Operation.CREATE));
+ verify(_accessControl).authorise(eq(Operation.CONFIGURE), eq(ObjectType.BROKER), eq(properties));
+
+ configureAccessPlugin(Result.DENIED);
+ assertFalse(_securityManager.authoriseConfiguringBroker("test", VirtualHost.class, Operation.CREATE));
+ verify(_accessControl, times(2)).authorise(eq(Operation.CONFIGURE), eq(ObjectType.BROKER), eq(properties));
+ }
+
+ public void testAuthoriseLogsAccess()
+ {
+ configureAccessPlugin(Result.ALLOWED);
+ assertTrue(_securityManager.authoriseLogsAccess());
+ verify(_accessControl).authorise(ACCESS_LOGS, BROKER, ObjectProperties.EMPTY);
+
+ configureAccessPlugin(Result.DENIED);
+ assertFalse(_securityManager.authoriseLogsAccess());
+ verify(_accessControl, times(2)).authorise(ACCESS_LOGS, BROKER, ObjectProperties.EMPTY);
+ }
+
+ private void configureAccessPlugin(Result result)
+ {
+ when(_accessControl.authorise(any(Operation.class), any(ObjectType.class), any(ObjectProperties.class))).thenReturn(result);
+ }
+
+ private ObjectProperties createExpectedExchangeObjectProperties()
+ {
+ ObjectProperties properties = new ObjectProperties();
+ properties.put(Property.NAME, TEST_EXCHANGE);
+ properties.put(Property.VIRTUALHOST_NAME, TEST_VIRTUAL_HOST);
+ properties.put(Property.AUTO_DELETE, false);
+ properties.put(Property.TEMPORARY, true);
+ properties.put(Property.DURABLE, false);
+ properties.put(Property.TYPE, TEST_EXCHANGE_TYPE);
+ return properties;
+ }
+
+ private ObjectProperties createExpectedQueueObjectProperties()
+ {
+ ObjectProperties properties = new ObjectProperties();
+ properties.put(Property.NAME, TEST_QUEUE);
+ properties.put(Property.VIRTUALHOST_NAME, TEST_VIRTUAL_HOST);
+ properties.put(Property.AUTO_DELETE, true);
+ properties.put(Property.TEMPORARY, true);
+ properties.put(Property.DURABLE, false);
+ properties.put(Property.EXCLUSIVE, false);
+ return properties;
+ }
+
+
+
+}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/AbstractDurableConfigurationStoreTestCase.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/AbstractDurableConfigurationStoreTestCase.java
index 650b22ff51..04c2f974c9 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/AbstractDurableConfigurationStoreTestCase.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/AbstractDurableConfigurationStoreTestCase.java
@@ -108,7 +108,6 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest
_queueEntryRecoveryHandler = mock(TransactionLogRecoveryHandler.QueueEntryRecoveryHandler.class);
_dtxRecordRecoveryHandler = mock(TransactionLogRecoveryHandler.DtxRecordRecoveryHandler.class);
_virtualHost = mock(VirtualHost.class);
- when(_virtualHost.getSecurityManager()).thenReturn(mock(org.apache.qpid.server.security.SecurityManager.class));
when(_messageStoreRecoveryHandler.begin()).thenReturn(_storedMessageRecoveryHandler);
when(_logRecoveryHandler.begin(any(MessageStore.class))).thenReturn(_queueEntryRecoveryHandler);