diff options
| author | Keith Wall <kwall@apache.org> | 2014-03-21 17:16:34 +0000 |
|---|---|---|
| committer | Keith Wall <kwall@apache.org> | 2014-03-21 17:16:34 +0000 |
| commit | d77447d7230dd29d7dc9ee0575caf1997ec3a7a6 (patch) | |
| tree | a6e4dcfe2edf677b6c20bd361886edc6dfbf01d3 /qpid/java/broker-core/src | |
| parent | 801e80d3b2361375c357b2f33feaeae77b3f8a14 (diff) | |
| download | qpid-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')
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); |
