diff options
author | Keith Wall <kwall@apache.org> | 2015-03-12 14:13:28 +0000 |
---|---|---|
committer | Keith Wall <kwall@apache.org> | 2015-03-12 14:13:28 +0000 |
commit | e8e05131324cf3137a3c65a95cad833cd3275c78 (patch) | |
tree | e4ad0110b5696cef4282b29eb02cc4257f03f2d2 | |
parent | 657ad54bf98f740fb37405daeaa95a95754841f5 (diff) | |
download | qpid-python-e8e05131324cf3137a3c65a95cad833cd3275c78.tar.gz |
Merge from trunk
git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/QPID-6262-JavaBrokerNIO@1666200 13f79535-47bb-0310-9956-ffa450edef68
81 files changed, 1766 insertions, 1435 deletions
diff --git a/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ConnectionEndpoint.java b/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ConnectionEndpoint.java index e5a82eb2a3..f9b3bc3c7b 100644 --- a/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ConnectionEndpoint.java +++ b/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ConnectionEndpoint.java @@ -33,6 +33,7 @@ import java.security.Principal; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; @@ -148,6 +149,7 @@ public class ConnectionEndpoint implements DescribedTypeConstructorRegistry.Sour private String _localHostname; private boolean _secure; private Principal _externalPrincipal; + private List<Runnable> _postLockActions = new ArrayList<>(); public ConnectionEndpoint(Container container, SaslServerProvider cbs) { @@ -792,22 +794,37 @@ public class ConnectionEndpoint implements DescribedTypeConstructorRegistry.Sour _logger = logger; } - public synchronized void receive(final short channel, final Object frame) + public void receive(final short channel, final Object frame) { - if (_logger.isEnabled()) + List<Runnable> postLockActions; + synchronized(this) { - _logger.received(_remoteAddress, channel, frame); - } - if (frame instanceof FrameBody) - { - ((FrameBody) frame).invoke(channel, this); + if (_logger.isEnabled()) + { + _logger.received(_remoteAddress, channel, frame); + } + if (frame instanceof FrameBody) + { + ((FrameBody) frame).invoke(channel, this); + } + else if (frame instanceof SaslFrameBody) + { + ((SaslFrameBody) frame).invoke(this); + } + postLockActions = _postLockActions; + _postLockActions = new ArrayList<>(); } - else if (frame instanceof SaslFrameBody) + for(Runnable action : postLockActions) { - ((SaslFrameBody) frame).invoke(this); + action.run(); } } + synchronized void addPostLockAction(Runnable action) + { + _postLockActions.add(action); + } + public AMQPDescribedTypeRegistry getDescribedTypeRegistry() { return _describedTypeRegistry; diff --git a/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/SendingLinkEndpoint.java b/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/SendingLinkEndpoint.java index fb525f0666..b52e37a18d 100644 --- a/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/SendingLinkEndpoint.java +++ b/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/SendingLinkEndpoint.java @@ -21,15 +21,19 @@ package org.apache.qpid.amqp_1_0.transport; -import org.apache.qpid.amqp_1_0.type.*; +import java.util.HashMap; +import java.util.Map; + +import org.apache.qpid.amqp_1_0.type.Binary; +import org.apache.qpid.amqp_1_0.type.DeliveryState; +import org.apache.qpid.amqp_1_0.type.Outcome; +import org.apache.qpid.amqp_1_0.type.Symbol; +import org.apache.qpid.amqp_1_0.type.UnsignedInteger; import org.apache.qpid.amqp_1_0.type.transport.Attach; import org.apache.qpid.amqp_1_0.type.transport.Flow; import org.apache.qpid.amqp_1_0.type.transport.Role; import org.apache.qpid.amqp_1_0.type.transport.Transfer; -import java.util.HashMap; -import java.util.Map; - public class SendingLinkEndpoint extends LinkEndpoint<SendingLinkListener> { @@ -162,8 +166,14 @@ public class SendingLinkEndpoint extends LinkEndpoint<SendingLinkListener> setLinkCredit(limit.subtract(getDeliveryCount())); } } - getLinkEventListener().flowStateChanged(); - + getSession().getConnection().addPostLockAction(new Runnable() + { + @Override + public void run() + { + flowStateChanged(); + } + }); } @Override diff --git a/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/SessionEndpoint.java b/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/SessionEndpoint.java index 5a28ddcb60..af263d0f45 100644 --- a/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/SessionEndpoint.java +++ b/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/SessionEndpoint.java @@ -456,32 +456,42 @@ public class SessionEndpoint public void receiveFlow(final Flow flow) { - - synchronized(getLock()) + synchronized (getLock()) { UnsignedInteger handle = flow.getHandle(); - LinkEndpoint endpoint = handle == null ? null : _remoteLinkEndpoints.get(handle); + final LinkEndpoint endpoint = handle == null ? null : _remoteLinkEndpoints.get(handle); - final UnsignedInteger nextOutgoingId = flow.getNextIncomingId() == null ? _initialOutgoingId : flow.getNextIncomingId(); + final UnsignedInteger nextOutgoingId = + flow.getNextIncomingId() == null ? _initialOutgoingId : flow.getNextIncomingId(); int limit = (nextOutgoingId.intValue() + flow.getIncomingWindow().intValue()); _outgoingSessionCredit = UnsignedInteger.valueOf(limit - _nextOutgoingTransferId.intValue()); - if(endpoint != null) + if (endpoint != null) { - endpoint.receiveFlow( flow ); + endpoint.receiveFlow(flow); } else { - for(LinkEndpoint le : _remoteLinkEndpoints.values()) + final Collection<LinkEndpoint> allLinkEndpoints = _remoteLinkEndpoints.values(); + getConnection().addPostLockAction(new Runnable() { - le.flowStateChanged(); - } + @Override + public void run() + { + + for(LinkEndpoint le : allLinkEndpoints) + { + le.flowStateChanged(); + } + } + }); } getLock().notifyAll(); } + } public void receiveDisposition(final Disposition disposition) diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHARemoteReplicationNodeImpl.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHARemoteReplicationNodeImpl.java index 926e9a956f..002e012cac 100644 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHARemoteReplicationNodeImpl.java +++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHARemoteReplicationNodeImpl.java @@ -21,7 +21,6 @@ package org.apache.qpid.server.virtualhostnode.berkeleydb; -import java.security.AccessControlException; import java.util.Map; import java.util.Set; @@ -44,7 +43,6 @@ import org.apache.qpid.server.model.State; import org.apache.qpid.server.model.StateTransition; import org.apache.qpid.server.model.SystemConfig; import org.apache.qpid.server.model.VirtualHostNode; -import org.apache.qpid.server.security.access.Operation; import org.apache.qpid.server.store.berkeleydb.replication.ReplicatedEnvironmentFacade; public class BDBHARemoteReplicationNodeImpl extends AbstractConfiguredObject<BDBHARemoteReplicationNodeImpl> implements BDBHARemoteReplicationNode<BDBHARemoteReplicationNodeImpl> @@ -122,27 +120,6 @@ public class BDBHARemoteReplicationNodeImpl extends AbstractConfiguredObject<BDB super.deleted(); } - - @Override - protected void authoriseSetAttributes(final ConfiguredObject<?> proxyForValidation, - final Set<String> modifiedAttributes) - { - _broker.getSecurityManager().authoriseVirtualHostNode(getName(), Operation.UPDATE); - } - - @Override - protected void authoriseSetDesiredState(State desiredState) throws AccessControlException - { - if(desiredState == State.DELETED) - { - _broker.getSecurityManager().authoriseVirtualHostNode(getName(), Operation.DELETE); - } - else - { - _broker.getSecurityManager().authoriseVirtualHostNode(getName(), Operation.UPDATE); - } - } - @Override public String toString() { diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHARemoteReplicationNodeTest.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHARemoteReplicationNodeTest.java index 8522a39918..cb9d02c767 100644 --- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHARemoteReplicationNodeTest.java +++ b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHARemoteReplicationNodeTest.java @@ -36,7 +36,6 @@ import org.apache.qpid.server.model.ConfiguredObjectFactory; import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.model.VirtualHostNode; import org.apache.qpid.server.security.SecurityManager; -import org.apache.qpid.server.security.access.Operation; import org.apache.qpid.server.store.DurableConfigurationStore; import org.apache.qpid.server.store.berkeleydb.replication.ReplicatedEnvironmentFacade; import org.apache.qpid.server.util.BrokerTestHelper; @@ -106,9 +105,7 @@ public class BDBHARemoteReplicationNodeTest extends QpidTestCase String remoteReplicationName = getName(); BDBHARemoteReplicationNode remoteReplicationNode = createRemoteReplicationNode(remoteReplicationName); - doThrow(new AccessControlException("mocked ACL exception")).when(_mockSecurityManager).authoriseVirtualHostNode( - remoteReplicationName, - Operation.UPDATE); + doThrow(new AccessControlException("mocked ACL exception")).when(_mockSecurityManager).authoriseUpdate(remoteReplicationNode); assertNull(remoteReplicationNode.getDescription()); @@ -130,9 +127,7 @@ public class BDBHARemoteReplicationNodeTest extends QpidTestCase String remoteReplicationName = getName(); BDBHARemoteReplicationNode remoteReplicationNode = createRemoteReplicationNode(remoteReplicationName); - doThrow(new AccessControlException("mocked ACL exception")).when(_mockSecurityManager).authoriseVirtualHostNode( - remoteReplicationName, - Operation.DELETE); + doThrow(new AccessControlException("mocked ACL exception")).when(_mockSecurityManager).authoriseDelete(remoteReplicationNode); assertNull(remoteReplicationNode.getDescription()); diff --git a/qpid/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/BDBHAVirtualHostNodeRestTest.java b/qpid/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/BDBHAVirtualHostNodeRestTest.java index 45cf9a483c..6d3bacc286 100644 --- a/qpid/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/BDBHAVirtualHostNodeRestTest.java +++ b/qpid/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/BDBHAVirtualHostNodeRestTest.java @@ -398,9 +398,9 @@ public class BDBHAVirtualHostNodeRestTest extends QpidRestTestCase assertNotNull("Node " + name + " has unexpected lastKnownReplicationId", lastKnownTransactionId); assertTrue("Node " + name + " has unexpected lastKnownReplicationId " + lastKnownTransactionId, lastKnownTransactionId > 0); - Long joinTime = (Long) nodeData.get(BDBHAVirtualHostNode.JOIN_TIME); + Number joinTime = (Number) nodeData.get(BDBHAVirtualHostNode.JOIN_TIME); assertNotNull("Node " + name + " has unexpected joinTime", joinTime); - assertTrue("Node " + name + " has unexpected joinTime " + joinTime, joinTime > 0); + assertTrue("Node " + name + " has unexpected joinTime " + joinTime, joinTime.longValue() > 0); } private void assertActualAndDesiredStates(final String restUrl, diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/binding/BindingImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/binding/BindingImpl.java index 0463bb64a3..06ce48ffa2 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/binding/BindingImpl.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/binding/BindingImpl.java @@ -48,6 +48,7 @@ import org.apache.qpid.server.model.Queue; import org.apache.qpid.server.model.State; import org.apache.qpid.server.model.StateTransition; import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.security.SecurityManager; import org.apache.qpid.server.util.StateChangeListener; public class BindingImpl @@ -254,7 +255,7 @@ public class BindingImpl @Override public void validateOnCreate() { - _queue.getVirtualHost().getSecurityManager().authoriseCreateBinding(this); + authoriseCreate(this); AMQQueue queue = getAMQQueue(); Map<String, Object> arguments = getArguments(); @@ -271,4 +272,10 @@ public class BindingImpl } } + @Override + protected SecurityManager getSecurityManager() + { + return _queue.getVirtualHost().getSecurityManager(); + } + } diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/store/StoreConfigurationChangeListener.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/store/StoreConfigurationChangeListener.java index d5bbe16446..23d24c4423 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/store/StoreConfigurationChangeListener.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/store/StoreConfigurationChangeListener.java @@ -29,7 +29,7 @@ import org.apache.qpid.server.store.DurableConfigurationStore; public class StoreConfigurationChangeListener implements ConfigurationChangeListener { - private DurableConfigurationStore _store; + private final DurableConfigurationStore _store; public StoreConfigurationChangeListener(DurableConfigurationStore store) { 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 4f8b472058..61bbe6f732 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 @@ -20,7 +20,6 @@ */ package org.apache.qpid.server.exchange; -import java.security.AccessControlException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -141,12 +140,6 @@ public abstract class AbstractExchange<T extends AbstractExchange<T>> } @Override - public void validateOnCreate() - { - _virtualHost.getSecurityManager().authoriseCreateExchange(this); - } - - @Override public void onValidate() { super.onValidate(); @@ -195,8 +188,6 @@ public abstract class AbstractExchange<T extends AbstractExchange<T>> @Override public void deleteWithChecks() { - _virtualHost.getSecurityManager().authoriseDelete(this); - if(hasReferrers()) { throw new ExchangeIsAlternateException(getName()); @@ -656,7 +647,7 @@ public abstract class AbstractExchange<T extends AbstractExchange<T>> } // Check access - _virtualHost.getSecurityManager().authoriseUnbind(binding); + authoriseDelete(binding); BindingImpl b = _bindingsMap.remove(new BindingIdentifier(bindingKey,queue)); @@ -810,7 +801,7 @@ public abstract class AbstractExchange<T extends AbstractExchange<T>> preSetAlternateExchange(); setState(State.DELETED); } - catch (ExchangeIsAlternateException | RequiredExchangeException e) + catch (ExchangeIsAlternateException e) { } @@ -925,16 +916,5 @@ public abstract class AbstractExchange<T extends AbstractExchange<T>> return binding; } - @Override - protected void authoriseSetAttributes(ConfiguredObject<?> modified, Set<String> attributes) throws AccessControlException - { - _virtualHost.getSecurityManager().authoriseUpdate(this); - } - - @Override - protected void changeAttributes(final Map<String, Object> attributes) - { - super.changeAttributes(attributes); - } } diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java index 28329f099b..529aa230d4 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java @@ -1288,17 +1288,18 @@ public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> im } } - }); - - } else { - authoriseSetDesiredState(desiredState); - validateChange(createProxyForValidation(Collections.<String, Object>singletonMap( - ConfiguredObject.DESIRED_STATE, - desiredState)), Collections.singleton(ConfiguredObject.DESIRED_STATE)); + ConfiguredObject<?> proxyForValidation = + createProxyForValidation(Collections.<String, Object>singletonMap( + ConfiguredObject.DESIRED_STATE, + desiredState)); + Set<String> desiredStateOnlySet = Collections.unmodifiableSet( + Collections.singleton(ConfiguredObject.DESIRED_STATE)); + authoriseSetAttributes(proxyForValidation, desiredStateOnlySet); + validateChange(proxyForValidation, desiredStateOnlySet); if (changeAttribute(ConfiguredObject.DESIRED_STATE, currentDesiredState, desiredState)) { @@ -2014,12 +2015,6 @@ public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> im } } - protected void authoriseSetAttributes(final ConfiguredObject<?> proxyForValidation, - final Set<String> modifiedAttributes) - { - - } - protected void changeAttributes(final Map<String, Object> attributes) { Collection<String> names = getAttributeNames(); @@ -2077,17 +2072,61 @@ public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> im { return (ConfiguredObject<?>) Proxy.newProxyInstance(getClass().getClassLoader(), new Class<?>[]{_bestFitInterface}, - new AttributeGettingHandler(attributes)); + new AttributeGettingHandler(attributes, _attributeTypes, this)); } - protected void authoriseSetDesiredState(State desiredState) throws AccessControlException + private ConfiguredObject<?> createProxyForAuthorisation(final Class<? extends ConfiguredObject> category, + final Map<String, Object> attributes, + final ConfiguredObject<?> parent, + final ConfiguredObject<?>... otherParents) { - // allowed by default + return (ConfiguredObject<?>) Proxy.newProxyInstance(getClass().getClassLoader(), + new Class<?>[]{category}, + new AuthorisationProxyInvocationHandler(attributes, + getModel().getTypeRegistry().getAttributeTypes(category), + category, parent, otherParents)); } - protected <C extends ConfiguredObject> void authoriseCreateChild(Class<C> childClass, Map<String, Object> attributes, ConfiguredObject... otherParents) throws AccessControlException + protected final <C extends ConfiguredObject<?>> void authoriseCreateChild(Class<C> childClass, Map<String, Object> attributes, ConfiguredObject... otherParents) throws AccessControlException { - // allowed by default + ConfiguredObject<?> configuredObject = createProxyForAuthorisation(childClass, attributes, this, otherParents); + getSecurityManager().authoriseCreate(configuredObject); + } + + protected final void authoriseCreate(ConfiguredObject<?> object) throws AccessControlException + { + getSecurityManager().authoriseCreate(object); + } + + protected final void authoriseSetAttributes(final ConfiguredObject<?> proxyForValidation, + final Set<String> modifiedAttributes) + { + if (modifiedAttributes.contains(DESIRED_STATE) && State.DELETED.equals(proxyForValidation.getDesiredState())) + { + authoriseDelete(this); + if (modifiedAttributes.size() == 1) + { + // nothing left to authorize + return; + } + } + getSecurityManager().authoriseUpdate(this); + } + + protected final void authoriseDelete(ConfiguredObject<?> object) + { + getSecurityManager().authoriseDelete(object); + } + + protected SecurityManager getSecurityManager() + { + Broker broker = getModel().getAncestor(Broker.class, getCategoryClass(), this); + if (broker != null ) + { + return broker.getSecurityManager(); + } + LOGGER.warn("Broker parent is not found for " + getName() + " of type " + getClass()); + return null; } @Override @@ -2440,15 +2479,23 @@ public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> im } - private class AttributeGettingHandler implements InvocationHandler + private static class AttributeGettingHandler implements InvocationHandler { - private Map<String,Object> _attributes; + private final Map<String,Object> _attributes; + private final Map<String, ConfiguredObjectAttribute<?,?>> _attributeTypes; + private final ConfiguredObject<?> _configuredObject; - AttributeGettingHandler(final Map<String, Object> modifiedAttributes) + AttributeGettingHandler(final Map<String, Object> modifiedAttributes, Map<String, ConfiguredObjectAttribute<?,?>> attributeTypes, ConfiguredObject<?> configuredObject) { - Map<String,Object> combinedAttributes = new HashMap<String, Object>(getActualAttributes()); + Map<String,Object> combinedAttributes = new HashMap<>(); + if (configuredObject != null) + { + combinedAttributes.putAll(configuredObject.getActualAttributes()); + } combinedAttributes.putAll(modifiedAttributes); _attributes = combinedAttributes; + _attributeTypes = attributeTypes; + _configuredObject = configuredObject; } @Override @@ -2477,16 +2524,26 @@ public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> im protected Object getValue(final ConfiguredObjectAttribute attribute) { + Object value; if(attribute.isAutomated()) { - ConfiguredAutomatedAttribute autoAttr = (ConfiguredAutomatedAttribute)attribute; - Object value = _attributes.get(attribute.getName()); - return attribute.convert(value == null && !"".equals(autoAttr.defaultValue()) ? autoAttr.defaultValue() : value , AbstractConfiguredObject.this); + ConfiguredAutomatedAttribute autoAttr = (ConfiguredAutomatedAttribute) attribute; + value = _attributes.get(attribute.getName()); + if (value == null && !"".equals(autoAttr.defaultValue())) + { + value = autoAttr.defaultValue(); + } } else { - return _attributes.get(attribute.getName()); + value = _attributes.get(attribute.getName()); } + return convert(attribute, value); + } + + protected Object convert(ConfiguredObjectAttribute attribute, Object value) + { + return attribute.convert(value, _configuredObject); } private ConfiguredObjectAttribute getAttributeFromMethod(final Method method) @@ -2503,6 +2560,54 @@ public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> im } } + private static class AuthorisationProxyInvocationHandler extends AttributeGettingHandler + { + private final Class<? extends ConfiguredObject> _category; + private final Map<Class<? extends ConfiguredObject>, ConfiguredObject<?>> _parents; + private final ConfiguredObject<?> _parent ; + + AuthorisationProxyInvocationHandler(Map<String, Object> attributes, + Map<String, ConfiguredObjectAttribute<?, ?>> attributeTypes, + Class<? extends ConfiguredObject> categoryClass, + ConfiguredObject<?> parent, + ConfiguredObject<?>... parents) + { + super(attributes, attributeTypes, null); + _parent = parent; + _category = categoryClass; + _parents = new HashMap<>(); + if (parents != null) + { + for (ConfiguredObject<?> parentObject : parents) + { + _parents.put(parentObject.getCategoryClass(), parentObject); + } + } + _parents.put(parent.getCategoryClass(), parent); + } + + @Override + public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable + { + if(method.getName().equals("getParent") && args != null && args.length == 1 && args[0] instanceof Class) + { + Class<ConfiguredObject> parentClass = (Class<ConfiguredObject> )args[0]; + return _parents.get(parentClass); + } + else if(method.getName().equals("getCategoryClass")) + { + return _category; + } + return super.invoke(proxy, method, args); + } + + @Override + protected Object convert(ConfiguredObjectAttribute attribute, Object value) + { + return attribute.convert(value, _parent); + } + } + protected final static class DuplicateIdException extends IllegalArgumentException { public DuplicateIdException(final ConfiguredObject<?> child) diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/AbstractPluginAdapter.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/AbstractPluginAdapter.java index 3e662fac32..9008705de1 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/AbstractPluginAdapter.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/AbstractPluginAdapter.java @@ -20,7 +20,6 @@ */ package org.apache.qpid.server.model.adapter; -import java.security.AccessControlException; import java.util.Collection; import java.util.Collections; import java.util.Map; @@ -30,8 +29,6 @@ import org.apache.qpid.server.model.AbstractConfiguredObject; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.ConfiguredObject; import org.apache.qpid.server.model.Plugin; -import org.apache.qpid.server.model.State; -import org.apache.qpid.server.security.access.Operation; public abstract class AbstractPluginAdapter<X extends Plugin<X>> extends AbstractConfiguredObject<X> implements Plugin<X> { @@ -70,27 +67,6 @@ public abstract class AbstractPluginAdapter<X extends Plugin<X>> extends Abstrac return Collections.emptyList(); } - @Override - protected void authoriseSetDesiredState(State desiredState) throws AccessControlException - { - if(desiredState == State.DELETED) - { - if (!_broker.getSecurityManager().authoriseConfiguringBroker(getName(), Plugin.class, Operation.DELETE)) - { - throw new AccessControlException("Deletion of plugin is denied"); - } - } - } - - @Override - protected void authoriseSetAttributes(ConfiguredObject<?> modified, Set<String> attributes) throws AccessControlException - { - if (!_broker.getSecurityManager().authoriseConfiguringBroker(getName(), Plugin.class, Operation.UPDATE)) - { - throw new AccessControlException("Setting of plugin attributes is denied"); - } - } - protected Broker<?> getBroker() { return _broker; diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java index dfbe8b12ef..036c4d7716 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java @@ -54,7 +54,6 @@ import org.apache.qpid.server.plugin.ConfigurationSecretEncrypterFactory; import org.apache.qpid.server.plugin.PluggableFactoryLoader; import org.apache.qpid.server.security.SecurityManager; import org.apache.qpid.server.security.SubjectCreator; -import org.apache.qpid.server.security.access.Operation; import org.apache.qpid.server.security.auth.manager.SimpleAuthenticationManager; import org.apache.qpid.server.stats.StatisticsCounter; import org.apache.qpid.server.stats.StatisticsGatherer; @@ -908,35 +907,6 @@ public class BrokerAdapter extends AbstractConfiguredObject<BrokerAdapter> imple } @Override - protected <C extends ConfiguredObject> void authoriseCreateChild(Class<C> childClass, Map<String, Object> attributes, - ConfiguredObject... otherParents) throws AccessControlException - { - if (childClass == VirtualHostNode.class) - { - _securityManager.authoriseVirtualHostNode(String.valueOf(attributes.get(NAME)), Operation.CREATE); - - } - else - { - if (!_securityManager.authoriseConfiguringBroker(String.valueOf(attributes.get(NAME)), - childClass, - Operation.CREATE)) - { - throw new AccessControlException("Creation of new broker level entity is denied"); - } - } - } - - @Override - protected void authoriseSetAttributes(ConfiguredObject<?> modified, Set<String> attributes) throws AccessControlException - { - if (!_securityManager.authoriseConfiguringBroker(getName(), Broker.class, Operation.UPDATE)) - { - throw new AccessControlException("Setting of broker attributes is denied"); - } - } - - @Override public boolean isManagementMode() { return _parent.isManagementMode(); diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileBasedGroupProviderImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileBasedGroupProviderImpl.java index 67533f8244..1a119be32d 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileBasedGroupProviderImpl.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileBasedGroupProviderImpl.java @@ -21,7 +21,6 @@ package org.apache.qpid.server.model.adapter; import java.io.File; import java.io.IOException; -import java.security.AccessControlException; import java.security.Principal; import java.util.ArrayList; import java.util.Collection; @@ -50,7 +49,6 @@ import org.apache.qpid.server.model.ManagedObjectFactoryConstructor; import org.apache.qpid.server.model.State; import org.apache.qpid.server.model.StateTransition; import org.apache.qpid.server.security.SecurityManager; -import org.apache.qpid.server.security.access.Operation; import org.apache.qpid.server.security.auth.UsernamePrincipal; import org.apache.qpid.server.security.group.FileGroupDatabase; import org.apache.qpid.server.security.group.GroupPrincipal; @@ -219,8 +217,6 @@ public class FileBasedGroupProviderImpl { String groupName = (String) attributes.get(Group.NAME); - getSecurityManager().authoriseGroupOperation(Operation.CREATE, groupName); - if (getState() != State.ACTIVE) { throw new IllegalConfigurationException(String.format("Group provider '%s' is not activated. Cannot create a group.", getName())); @@ -262,8 +258,8 @@ public class FileBasedGroupProviderImpl } } - - private SecurityManager getSecurityManager() + @Override + protected SecurityManager getSecurityManager() { return _broker.getSecurityManager(); } @@ -360,27 +356,6 @@ public class FileBasedGroupProviderImpl // no-op, as per above, groups are not in the store } - @Override - protected void authoriseSetDesiredState(State desiredState) throws AccessControlException - { - if(desiredState == State.DELETED) - { - if (!_broker.getSecurityManager().authoriseConfiguringBroker(getName(), GroupProvider.class, Operation.DELETE)) - { - throw new AccessControlException("Deletion of groups provider is denied"); - } - } - } - - @Override - protected void authoriseSetAttributes(ConfiguredObject<?> modified, Set<String> attributes) throws AccessControlException - { - if (!_broker.getSecurityManager().authoriseConfiguringBroker(getName(), GroupProvider.class, Operation.UPDATE)) - { - throw new AccessControlException("Setting of group provider attributes is denied"); - } - } - private class GroupAdapter extends AbstractConfiguredObject<GroupAdapter> implements Group<GroupAdapter> { private GroupPrincipal _groupPrincipal; @@ -465,8 +440,6 @@ public class FileBasedGroupProviderImpl { String memberName = (String) attributes.get(GroupMember.NAME); - getSecurityManager().authoriseGroupOperation(Operation.UPDATE, getName()); - _groupDatabase.addUserToGroup(memberName, getName()); UUID id = UUID.randomUUID(); Map<String,Object> attrMap = new HashMap<String, Object>(); @@ -486,7 +459,6 @@ public class FileBasedGroupProviderImpl @StateTransition( currentState = State.ACTIVE, desiredState = State.DELETED ) private ListenableFuture<Void> doDelete() { - getSecurityManager().authoriseGroupOperation(Operation.DELETE, getName()); _groupDatabase.removeGroup(getName()); deleted(); setState(State.DELETED); @@ -557,8 +529,6 @@ public class FileBasedGroupProviderImpl @StateTransition(currentState = State.ACTIVE, desiredState = State.DELETED) private ListenableFuture<Void> doDelete() { - getSecurityManager().authoriseGroupOperation(Operation.UPDATE, GroupAdapter.this.getName()); - _groupDatabase.removeUserFromGroup(getName(), GroupAdapter.this.getName()); deleted(); setState(State.DELETED); diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderImpl.java index c95b3ab804..500df8cb87 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderImpl.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderImpl.java @@ -235,6 +235,7 @@ public class FileSystemPreferencesProviderImpl @Override public Map<String, Object> getPreferences(String userId) { + getSecurityManager().authoriseUserUpdate(userId); return _store == null? Collections.<String, Object>emptyMap() : _store.getPreferences(userId); } @@ -257,6 +258,10 @@ public class FileSystemPreferencesProviderImpl throw new IllegalStateException("Cannot delete preferences with preferences provider " + getName() + " in state " + getState() ); } + for (String userId: userIDs) + { + getSecurityManager().authoriseUserUpdate(userId); + } return _store.deletePreferences(userIDs); } diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java index 5c53eed509..0e6f18a70a 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java @@ -21,7 +21,6 @@ package org.apache.qpid.server.model.port; -import java.security.AccessControlException; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; @@ -46,7 +45,6 @@ import org.apache.qpid.server.model.State; import org.apache.qpid.server.model.StateTransition; import org.apache.qpid.server.model.Transport; import org.apache.qpid.server.model.TrustStore; -import org.apache.qpid.server.security.access.Operation; abstract public class AbstractPort<X extends AbstractPort<X>> extends AbstractConfiguredObject<X> implements Port<X> { @@ -276,28 +274,6 @@ abstract public class AbstractPort<X extends AbstractPort<X>> extends AbstractCo return State.ACTIVE; } - - @Override - protected void authoriseSetDesiredState(State desiredState) throws AccessControlException - { - if(desiredState == State.DELETED) - { - if (!_broker.getSecurityManager().authoriseConfiguringBroker(getName(), Port.class, Operation.DELETE)) - { - throw new AccessControlException("Deletion of port is denied"); - } - } - } - - @Override - protected void authoriseSetAttributes(ConfiguredObject<?> modified, Set<String> attributes) throws AccessControlException - { - if (!_broker.getSecurityManager().authoriseConfiguringBroker(getName(), Port.class, Operation.UPDATE)) - { - throw new AccessControlException("Setting of port attributes is denied"); - } - } - @Override public Collection<String> getEnabledCipherSuites() { diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java index 664c544de4..2a51657f60 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java @@ -273,12 +273,6 @@ public abstract class AbstractQueue<X extends AbstractQueue<X>> } @Override - protected void validateOnCreate() - { - _virtualHost.getSecurityManager().authoriseCreateQueue(this); - } - - @Override protected void onCreate() { super.onCreate(); @@ -3049,12 +3043,6 @@ public abstract class AbstractQueue<X extends AbstractQueue<X>> } } - @Override - protected void authoriseSetAttributes(ConfiguredObject<?> modified, Set<String> attributes) throws AccessControlException - { - _virtualHost.getSecurityManager().authoriseUpdate(this); - } - int getMaxAsyncDeliveries() { return _maxAsyncDeliveries; diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueConsumerImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueConsumerImpl.java index a5225f3aa4..b409b638b3 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueConsumerImpl.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueConsumerImpl.java @@ -51,6 +51,7 @@ import org.apache.qpid.server.model.ManagedAttributeField; import org.apache.qpid.server.model.State; import org.apache.qpid.server.protocol.AMQSessionModel; import org.apache.qpid.server.protocol.MessageConverterRegistry; +import org.apache.qpid.server.security.SecurityManager; import org.apache.qpid.server.util.StateChangeListener; class QueueConsumerImpl @@ -126,7 +127,7 @@ class QueueConsumerImpl _queue = queue; // Access control - _queue.getVirtualHost().getSecurityManager().authoriseCreateConsumer(this); + authoriseCreate(this); open(); @@ -145,6 +146,12 @@ class QueueConsumerImpl _target.addStateListener(_listener); } + @Override + protected SecurityManager getSecurityManager() + { + return _queue.getVirtualHost().getSecurityManager(); + } + private static Map<String, Object> createAttributeMap(String name, FilterManager filters, EnumSet<Option> optionSet) { Map<String,Object> attributes = new HashMap<String, Object>(); diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/FileKeyStoreImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/FileKeyStoreImpl.java index 5f585f3d88..aedfb3670a 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/FileKeyStoreImpl.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/FileKeyStoreImpl.java @@ -24,7 +24,6 @@ import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; -import java.security.AccessControlException; import java.security.GeneralSecurityException; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; @@ -53,7 +52,6 @@ import org.apache.qpid.server.model.ManagedObjectFactoryConstructor; import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.State; import org.apache.qpid.server.model.StateTransition; -import org.apache.qpid.server.security.access.Operation; import org.apache.qpid.server.util.ServerScopedRuntimeException; import org.apache.qpid.server.util.urlstreamhandler.data.Handler; import org.apache.qpid.transport.network.security.ssl.QpidClientX509KeyManager; @@ -127,27 +125,6 @@ public class FileKeyStoreImpl extends AbstractConfiguredObject<FileKeyStoreImpl> } @Override - protected void authoriseSetDesiredState(State desiredState) throws AccessControlException - { - if(desiredState == State.DELETED) - { - if (!_broker.getSecurityManager().authoriseConfiguringBroker(getName(), KeyStore.class, Operation.DELETE)) - { - throw new AccessControlException("Deletion of key store is denied"); - } - } - } - - @Override - protected void authoriseSetAttributes(ConfiguredObject<?> modified, Set<String> attributes) throws AccessControlException - { - if (!_broker.getSecurityManager().authoriseConfiguringBroker(getName(), KeyStore.class, Operation.UPDATE)) - { - throw new AccessControlException("Setting key store attributes is denied"); - } - } - - @Override protected void validateChange(final ConfiguredObject<?> proxyForValidation, final Set<String> changedAttributes) { super.validateChange(proxyForValidation, changedAttributes); diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/FileTrustStoreImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/FileTrustStoreImpl.java index df1cbd0493..ce5a394591 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/FileTrustStoreImpl.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/FileTrustStoreImpl.java @@ -24,7 +24,6 @@ import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; -import java.security.AccessControlException; import java.security.GeneralSecurityException; import java.security.KeyStore; import java.security.NoSuchAlgorithmException; @@ -53,7 +52,6 @@ import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.State; import org.apache.qpid.server.model.StateTransition; import org.apache.qpid.server.model.TrustStore; -import org.apache.qpid.server.security.access.Operation; import org.apache.qpid.server.security.auth.manager.SimpleLDAPAuthenticationManager; import org.apache.qpid.server.util.urlstreamhandler.data.Handler; import org.apache.qpid.transport.network.security.ssl.QpidMultipleTrustManager; @@ -153,27 +151,6 @@ public class FileTrustStoreImpl extends AbstractConfiguredObject<FileTrustStoreI } @Override - protected void authoriseSetDesiredState(State desiredState) throws AccessControlException - { - if(desiredState == State.DELETED) - { - if (!_broker.getSecurityManager().authoriseConfiguringBroker(getName(), TrustStore.class, Operation.DELETE)) - { - throw new AccessControlException("Deletion of key store is denied"); - } - } - } - - @Override - protected void authoriseSetAttributes(ConfiguredObject<?> modified, Set<String> attributes) throws AccessControlException - { - if (!_broker.getSecurityManager().authoriseConfiguringBroker(getName(), TrustStore.class, Operation.UPDATE)) - { - throw new AccessControlException("Setting key store attributes is denied"); - } - } - - @Override protected void validateChange(final ConfiguredObject<?> proxyForValidation, final Set<String> changedAttributes) { super.validateChange(proxyForValidation, changedAttributes); diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/NonJavaKeyStoreImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/NonJavaKeyStoreImpl.java index c2779415d1..ea6a0394f0 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/NonJavaKeyStoreImpl.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/NonJavaKeyStoreImpl.java @@ -32,7 +32,6 @@ import java.net.URL; import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; -import java.security.AccessControlException; import java.security.GeneralSecurityException; import java.security.KeyFactory; import java.security.PrivateKey; @@ -66,14 +65,12 @@ import org.apache.qpid.server.model.AbstractConfiguredObject; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.ConfiguredObject; import org.apache.qpid.server.model.IntegrityViolationException; -import org.apache.qpid.server.model.KeyStore; import org.apache.qpid.server.model.ManagedAttributeField; import org.apache.qpid.server.model.ManagedObject; import org.apache.qpid.server.model.ManagedObjectFactoryConstructor; import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.State; import org.apache.qpid.server.model.StateTransition; -import org.apache.qpid.server.security.access.Operation; import org.apache.qpid.server.util.urlstreamhandler.data.Handler; @ManagedObject( category = false ) @@ -215,28 +212,6 @@ public class NonJavaKeyStoreImpl extends AbstractConfiguredObject<NonJavaKeyStor } @Override - protected void authoriseSetDesiredState(State desiredState) throws AccessControlException - { - if (desiredState == State.DELETED) - { - if (!_broker.getSecurityManager().authoriseConfiguringBroker(getName(), KeyStore.class, Operation.DELETE)) - { - throw new AccessControlException("Deletion of key store is denied"); - } - } - } - - @Override - protected void authoriseSetAttributes(ConfiguredObject<?> modified, Set<String> attributes) - throws AccessControlException - { - if (!_broker.getSecurityManager().authoriseConfiguringBroker(getName(), KeyStore.class, Operation.UPDATE)) - { - throw new AccessControlException("Setting key store attributes is denied"); - } - } - - @Override protected void validateChange(final ConfiguredObject<?> proxyForValidation, final Set<String> changedAttributes) { super.validateChange(proxyForValidation, changedAttributes); diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/NonJavaTrustStoreImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/NonJavaTrustStoreImpl.java index 397e226699..c18189785d 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/NonJavaTrustStoreImpl.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/NonJavaTrustStoreImpl.java @@ -25,7 +25,6 @@ import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; -import java.security.AccessControlException; import java.security.GeneralSecurityException; import java.security.cert.Certificate; import java.security.cert.CertificateException; @@ -55,7 +54,6 @@ import org.apache.qpid.server.model.AuthenticationProvider; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.ConfiguredObject; import org.apache.qpid.server.model.IntegrityViolationException; -import org.apache.qpid.server.model.KeyStore; import org.apache.qpid.server.model.ManagedAttributeField; import org.apache.qpid.server.model.ManagedObject; import org.apache.qpid.server.model.ManagedObjectFactoryConstructor; @@ -63,7 +61,6 @@ import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.State; import org.apache.qpid.server.model.StateTransition; import org.apache.qpid.server.model.TrustStore; -import org.apache.qpid.server.security.access.Operation; import org.apache.qpid.server.security.auth.manager.SimpleLDAPAuthenticationManager; import org.apache.qpid.server.util.urlstreamhandler.data.Handler; @@ -228,28 +225,6 @@ public class NonJavaTrustStoreImpl } @Override - protected void authoriseSetDesiredState(State desiredState) throws AccessControlException - { - if (desiredState == State.DELETED) - { - if (!_broker.getSecurityManager().authoriseConfiguringBroker(getName(), KeyStore.class, Operation.DELETE)) - { - throw new AccessControlException("Deletion of key store is denied"); - } - } - } - - @Override - protected void authoriseSetAttributes(ConfiguredObject<?> modified, Set<String> attributes) - throws AccessControlException - { - if (!_broker.getSecurityManager().authoriseConfiguringBroker(getName(), KeyStore.class, Operation.UPDATE)) - { - throw new AccessControlException("Setting key store attributes is denied"); - } - } - - @Override protected void validateChange(final ConfiguredObject<?> proxyForValidation, final Set<String> changedAttributes) { super.validateChange(proxyForValidation, changedAttributes); 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 71878dcf72..c475824c2d 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 @@ -20,34 +20,54 @@ 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.ObjectType.GROUP; import static org.apache.qpid.server.security.access.ObjectType.METHOD; import static org.apache.qpid.server.security.access.ObjectType.QUEUE; import static org.apache.qpid.server.security.access.ObjectType.USER; -import static org.apache.qpid.server.security.access.ObjectType.VIRTUALHOST; -import static org.apache.qpid.server.security.access.ObjectType.VIRTUALHOSTNODE; -import static org.apache.qpid.server.security.access.Operation.*; +import static org.apache.qpid.server.security.access.Operation.ACCESS_LOGS; +import static org.apache.qpid.server.security.access.Operation.PUBLISH; +import static org.apache.qpid.server.security.access.Operation.PURGE; import java.security.AccessControlException; import java.security.AccessController; import java.security.Principal; import java.util.Collection; import java.util.Collections; +import java.util.EnumSet; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; 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.log4j.Logger; import org.apache.qpid.server.model.AccessControlProvider; +import org.apache.qpid.server.model.AuthenticationProvider; +import org.apache.qpid.server.model.Binding; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.Connection; +import org.apache.qpid.server.model.Consumer; +import org.apache.qpid.server.model.Exchange; +import org.apache.qpid.server.model.ExclusivityPolicy; +import org.apache.qpid.server.model.Group; +import org.apache.qpid.server.model.GroupMember; +import org.apache.qpid.server.model.GroupProvider; +import org.apache.qpid.server.model.KeyStore; +import org.apache.qpid.server.model.LifetimePolicy; +import org.apache.qpid.server.model.Model; +import org.apache.qpid.server.model.Plugin; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Queue; +import org.apache.qpid.server.model.RemoteReplicationNode; +import org.apache.qpid.server.model.Session; import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.TrustStore; +import org.apache.qpid.server.model.User; +import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.model.VirtualHostAlias; +import org.apache.qpid.server.model.VirtualHostNode; import org.apache.qpid.server.protocol.AMQConnectionModel; -import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.queue.QueueConsumer; 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; @@ -58,20 +78,22 @@ import org.apache.qpid.server.security.auth.TaskPrincipal; public class SecurityManager { + 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 boolean _managementMode; - private final Broker<?> _broker; + private final ConfiguredObject<?> _aclProvidersParent; - private final ConcurrentMap<PublishAccessCheckCacheEntry, PublishAccessCheck> _publishAccessCheckCache = new ConcurrentHashMap<PublishAccessCheckCacheEntry, SecurityManager.PublishAccessCheck>(); + private final ConcurrentMap<PublishAccessCheckCacheEntry, PublishAccessCheck> _publishAccessCheckCache = new ConcurrentHashMap<>(); - public SecurityManager(Broker<?> broker, boolean managementMode) + public SecurityManager(ConfiguredObject<?> aclProvidersParent, boolean managementMode) { _managementMode = managementMode; - _broker = broker; + _aclProvidersParent = aclProvidersParent; } public static Subject getSubjectWithAddedSystemRights() @@ -99,11 +121,6 @@ public class SecurityManager return subject; } - private String getPluginTypeName(AccessControl accessControl) - { - return accessControl.getClass().getName(); - } - public static boolean isSystemProcess() { Subject subject = Subject.getSubject(AccessController.getContext()); @@ -161,7 +178,7 @@ public class SecurityManager } - Collection<AccessControlProvider<?>> accessControlProviders = _broker.getAccessControlProviders(); + Collection<AccessControlProvider> accessControlProviders = _aclProvidersParent.getChildren(AccessControlProvider.class); if(accessControlProviders != null && !accessControlProviders.isEmpty()) { AccessControlProvider<?> accessControlProvider = accessControlProviders.iterator().next(); @@ -184,22 +201,6 @@ public class SecurityManager return true; } - public void authoriseCreateBinding(final BindingImpl binding) - { - boolean allowed = checkAllPlugins(new AccessCheck() - { - Result allowed(AccessControl plugin) - { - return plugin.authorise(BIND, EXCHANGE, new ObjectProperties(binding)); - } - }); - - if(!allowed) - { - throw new AccessControlException("Permission denied: binding " + binding.getBindingKey()); - } - } - public void authoriseMethod(final Operation operation, final String componentName, final String methodName, final String virtualHostName) { boolean allowed = checkAllPlugins(new AccessCheck() @@ -239,176 +240,326 @@ public class SecurityManager } } - public void authoriseVirtualHostNode(final String virtualHostNodeName, final Operation operation) + public void authoriseCreateConnection(final AMQConnectionModel connection) { - if(!checkAllPlugins(new AccessCheck() - { - Result allowed(AccessControl plugin) - { - ObjectProperties properties = new ObjectProperties(virtualHostNodeName); - return plugin.authorise(operation, VIRTUALHOSTNODE, properties); - } - })) + String virtualHostName = connection.getVirtualHostName(); + ObjectProperties properties = new ObjectProperties(virtualHostName); + properties.put(Property.VIRTUALHOST_NAME, virtualHostName); + if (!checkAllPlugins(ObjectType.VIRTUALHOST, properties, Operation.ACCESS)) { - throw new AccessControlException(operation + " permission denied for " + VIRTUALHOSTNODE - + " : " + virtualHostNodeName); + throw new AccessControlException("Permission denied: " + virtualHostName); } } - public void authoriseVirtualHost(final String virtualHostName, final Operation operation) + public void authoriseCreate(ConfiguredObject<?> object) { - if(!checkAllPlugins(new AccessCheck() - { - Result allowed(AccessControl plugin) - { - // 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, VIRTUALHOST, properties); - } - })) - { - throw new AccessControlException(operation + " permission denied for " + VIRTUALHOST - + " : " + virtualHostName); - } + authorise(Operation.CREATE, object); } - public void authoriseCreateConnection(final AMQConnectionModel connection) + public void authoriseUpdate(ConfiguredObject<?> configuredObject) { - String virtualHostName = connection.getVirtualHostName(); - try + authorise(Operation.UPDATE, configuredObject); + } + + public void authoriseDelete(ConfiguredObject<?> configuredObject) + { + authorise(Operation.DELETE, configuredObject); + } + + public void authorise(Operation operation, ConfiguredObject<?> configuredObject) + { + // If we are running as SYSTEM then no ACL checking + if(isSystemProcess() || _managementMode) { - authoriseVirtualHost(virtualHostName, Operation.ACCESS); + return; } - catch (AccessControlException ace) + + if (Operation.CREATE == operation && configuredObject instanceof RemoteReplicationNode) { - throw new AccessControlException("Permission denied: " + virtualHostName); + // creation of remote replication node is out of control for user of this broker + return; } - } - - public void authoriseCreateConsumer(final ConsumerImpl consumer) - { - // TODO - remove cast to AMQQueue and allow testing of consumption from any MessageSource - final AMQQueue queue = (AMQQueue) consumer.getMessageSource(); - if(!checkAllPlugins(new AccessCheck() + if ((Operation.CREATE == operation) && configuredObject instanceof RemoteReplicationNode) { - Result allowed(AccessControl plugin) - { - return plugin.authorise(CONSUME, QUEUE, new ObjectProperties(queue)); - } - })) + // creation of remote replication node is out of control for user of this broker + return; + } + + if ((EnumSet.of(Operation.CREATE, Operation.UPDATE, Operation.DELETE).contains(operation)) && configuredObject instanceof Session) { - throw new AccessControlException("Permission denied: consume from queue '" + queue.getName() + "'."); + return; } - } - public void authoriseCreateExchange(final ExchangeImpl exchange) - { - final String exchangeName = exchange.getName(); - if(!checkAllPlugins(new AccessCheck() + if ((EnumSet.of(Operation.UPDATE, Operation.DELETE).contains(operation)) && (configuredObject instanceof Consumer || configuredObject instanceof Connection)) { - Result allowed(AccessControl plugin) - { - return plugin.authorise(CREATE, EXCHANGE, new ObjectProperties(exchange)); - } - })) + return; + } + + + Class<? extends ConfiguredObject> categoryClass = configuredObject.getCategoryClass(); + LOGGER.debug("getCategoryClass " + categoryClass); + ObjectType objectType = getACLObjectTypeManagingConfiguredObjectOfCategory(categoryClass); + LOGGER.debug("objectType " + objectType); + if (objectType == null) { - throw new AccessControlException("Permission denied: exchange-name '" + exchangeName + "'"); + LOGGER.warn("Cannot determine object type for " + configuredObject.getName() + " of category " + + categoryClass + ". Skipping ACL check..."); + return; } - } - public void authoriseCreateQueue(final AMQQueue queue) - { - final String queueName = queue.getName(); - if(! checkAllPlugins(new AccessCheck() + ObjectProperties properties = getACLObjectProperties(configuredObject, operation); + Operation authoriseOperation = validateAuthoriseOperation(operation, categoryClass); + if(!checkAllPlugins(objectType, properties, authoriseOperation)) { - Result allowed(AccessControl plugin) + String objectName = (String)configuredObject.getAttribute(ConfiguredObject.NAME); + StringBuilder exceptionMessage = new StringBuilder(String.format("Permission %s %s is denied for : %s %s '%s'", + authoriseOperation.name(), objectType.name(), operation.name(), categoryClass.getSimpleName(), objectName )); + Model model = getModel(); + + Collection<Class<? extends ConfiguredObject>> parentClasses = model.getParentTypes(categoryClass); + if (parentClasses != null) { - return plugin.authorise(CREATE, QUEUE, new ObjectProperties(queue)); + exceptionMessage.append(" on"); + for (Class<? extends ConfiguredObject> parentClass: parentClasses) + { + String objectCategory = parentClass.getSimpleName(); + ConfiguredObject<?> parent = configuredObject.getParent(parentClass); + exceptionMessage.append(" ").append(objectCategory); + if (parent != null) + { + exceptionMessage.append(" '").append(parent.getAttribute(ConfiguredObject.NAME)).append("'"); + } + } } - })) - { - throw new AccessControlException("Permission denied: queue-name '" + queueName + "'"); + throw new AccessControlException(exceptionMessage.toString()); } } + private Model getModel() + { + return _aclProvidersParent.getModel(); + } - public void authoriseDelete(final AMQQueue queue) + private boolean checkAllPlugins(final ObjectType objectType, final ObjectProperties properties, final Operation authoriseOperation) { - if(!checkAllPlugins(new AccessCheck() + return checkAllPlugins(new AccessCheck() { Result allowed(AccessControl plugin) { - return plugin.authorise(DELETE, QUEUE, new ObjectProperties(queue)); + return plugin.authorise(authoriseOperation, objectType, properties); } - })) - { - throw new AccessControlException("Permission denied, delete queue: " + queue.getName()); - } + }); } - - public void authoriseUpdate(final AMQQueue queue) + private Operation validateAuthoriseOperation(Operation operation, Class<? extends ConfiguredObject> category) { - if(!checkAllPlugins(new AccessCheck() + if (operation == Operation.CREATE || operation == Operation.UPDATE) { - Result allowed(AccessControl plugin) + if (Binding.class.isAssignableFrom(category)) { - return plugin.authorise(UPDATE, QUEUE, new ObjectProperties(queue)); + // CREATE BINDING is transformed into BIND EXCHANGE rule + return Operation.BIND; } - })) + else if (Consumer.class.isAssignableFrom(category)) + { + // CREATE CONSUMER is transformed into CONSUME QUEUE rule + return Operation.CONSUME; + } + else if (GroupMember.class.isAssignableFrom(category)) + { + // CREATE GROUP MEMBER is transformed into UPDATE GROUP rule + return Operation.UPDATE; + } + else if (isBrokerOrBrokerChild(category)) + { + // CREATE/UPDATE broker child is transformed into CONFIGURE BROKER rule + return Operation.CONFIGURE; + } + } + else if (operation == Operation.DELETE) { - throw new AccessControlException("Permission denied: update queue: " + queue.getName()); + if (Binding.class.isAssignableFrom(category)) + { + // DELETE BINDING is transformed into UNBIND EXCHANGE rule + return Operation.UNBIND; + } + else if (isBrokerOrBrokerChild(category)) + { + // DELETE broker child is transformed into CONFIGURE BROKER rule + return Operation.CONFIGURE; + } + else if (GroupMember.class.isAssignableFrom(category)) + { + // DELETE GROUP MEMBER is transformed into UPDATE GROUP rule + return Operation.UPDATE; + } } + return operation; } + private boolean isBrokerOrBrokerChild(Class<? extends ConfiguredObject> category) + { + return Broker.class.isAssignableFrom(category) + || Port.class.isAssignableFrom(category) + || AuthenticationProvider.class.isAssignableFrom(category) + || AccessControlProvider.class.isAssignableFrom(category) + || GroupProvider.class.isAssignableFrom(category) + || KeyStore.class.isAssignableFrom(category) + || TrustStore.class.isAssignableFrom(category) + || Plugin.class.isAssignableFrom(category); + } - public void authoriseUpdate(final ExchangeImpl exchange) + private ObjectProperties getACLObjectProperties(ConfiguredObject<?> configuredObject, Operation configuredObjectOperation) { - if(!checkAllPlugins(new AccessCheck() + String objectName = (String)configuredObject.getAttribute(ConfiguredObject.NAME); + Class<? extends ConfiguredObject> configuredObjectType = configuredObject.getCategoryClass(); + ObjectProperties properties = new ObjectProperties(objectName); + if (configuredObject instanceof Binding) { - Result allowed(AccessControl plugin) - { - return plugin.authorise(UPDATE, EXCHANGE, new ObjectProperties(exchange)); - } - })) + Exchange<?> exchange = (Exchange<?>)configuredObject.getParent(Exchange.class); + Queue<?> queue = (Queue<?>)configuredObject.getParent(Queue.class); + properties.setName((String)exchange.getAttribute(Exchange.NAME)); + properties.put(Property.QUEUE_NAME, (String)queue.getAttribute(Queue.NAME)); + properties.put(Property.ROUTING_KEY, (String)configuredObject.getAttribute(Binding.NAME)); + properties.put(Property.VIRTUALHOST_NAME, (String)queue.getParent(VirtualHost.class).getAttribute(VirtualHost.NAME)); + + // 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). + properties.put(Property.TEMPORARY, queue.getAttribute(Queue.LIFETIME_POLICY) != LifetimePolicy.PERMANENT); + properties.put(Property.DURABLE, (Boolean)queue.getAttribute(Queue.DURABLE)); + } + else if (configuredObject instanceof Queue) { - throw new AccessControlException("Permission denied: update exchange: " + exchange.getName()); + setQueueProperties(configuredObject, properties); } - } - - public void authoriseDelete(final ExchangeImpl exchange) - { - if(! checkAllPlugins(new AccessCheck() + else if (configuredObject instanceof Exchange) { - Result allowed(AccessControl plugin) - { - return plugin.authorise(DELETE, EXCHANGE, new ObjectProperties(exchange)); - } - })) + Object lifeTimePolicy = configuredObject.getAttribute(ConfiguredObject.LIFETIME_POLICY); + properties.put(Property.AUTO_DELETE, lifeTimePolicy != LifetimePolicy.PERMANENT); + properties.put(Property.TEMPORARY, lifeTimePolicy != LifetimePolicy.PERMANENT); + properties.put(Property.DURABLE, (Boolean) configuredObject.getAttribute(ConfiguredObject.DURABLE)); + properties.put(Property.TYPE, (String) configuredObject.getAttribute(Exchange.TYPE)); + VirtualHost virtualHost = configuredObject.getParent(VirtualHost.class); + properties.put(Property.VIRTUALHOST_NAME, (String)virtualHost.getAttribute(virtualHost.NAME)); + } + else if (configuredObject instanceof QueueConsumer) { - throw new AccessControlException("Permission denied, delete exchange: '" + exchange.getName() + "'"); + Queue<?> queue = (Queue<?>)configuredObject.getParent(Queue.class); + setQueueProperties(queue, properties); } + else if (isBrokerOrBrokerChild(configuredObjectType)) + { + String description = String.format("%s %s '%s'", + configuredObjectOperation == null? null : configuredObjectOperation.name().toLowerCase(), + configuredObjectType == null ? null : configuredObjectType.getSimpleName().toLowerCase(), + objectName); + properties = new OperationLoggingDetails(description); + } + return properties; } - public void authoriseGroupOperation(final Operation operation, final String groupName) + private void setQueueProperties(ConfiguredObject<?> queue, ObjectProperties properties) { - if(!checkAllPlugins(new AccessCheck() + properties.setName((String)queue.getAttribute(Exchange.NAME)); + Object lifeTimePolicy = queue.getAttribute(ConfiguredObject.LIFETIME_POLICY); + properties.put(Property.AUTO_DELETE, lifeTimePolicy!= LifetimePolicy.PERMANENT); + properties.put(Property.TEMPORARY, lifeTimePolicy != LifetimePolicy.PERMANENT); + properties.put(Property.DURABLE, (Boolean)queue.getAttribute(ConfiguredObject.DURABLE)); + properties.put(Property.EXCLUSIVE, queue.getAttribute(Queue.EXCLUSIVE) != ExclusivityPolicy.NONE); + Object alternateExchange = queue.getAttribute(Queue.ALTERNATE_EXCHANGE); + if (alternateExchange != null) + { + String name = alternateExchange instanceof ConfiguredObject ? + (String)((ConfiguredObject)alternateExchange).getAttribute(ConfiguredObject.NAME) : + String.valueOf(alternateExchange); + properties.put(Property.ALTERNATE,name); + } + String owner = (String)queue.getAttribute(Queue.OWNER); + if (owner != null) + { + properties.put(Property.OWNER, owner); + } + VirtualHost virtualHost = queue.getParent(VirtualHost.class); + properties.put(Property.VIRTUALHOST_NAME, (String)virtualHost.getAttribute(virtualHost.NAME)); + } + + private ObjectType getACLObjectTypeManagingConfiguredObjectOfCategory(Class<? extends ConfiguredObject> category) + { + if (Binding.class.isAssignableFrom(category)) { - Result allowed(AccessControl plugin) - { - return plugin.authorise(operation, GROUP, new ObjectProperties(groupName)); - } - })) + return ObjectType.EXCHANGE; + } + else if (VirtualHostNode.class.isAssignableFrom(category)) { - throw new AccessControlException("Do not have permission" + - " to perform the " + operation + " on the group " + groupName); + return ObjectType.VIRTUALHOSTNODE; + } + else if (isBrokerOrBrokerChild(category)) + { + return ObjectType.BROKER; + } + else if (Group.class.isAssignableFrom(category)) + { + return ObjectType.GROUP; } + else if (GroupMember.class.isAssignableFrom(category)) + { + // UPDATE GROUP + return ObjectType.GROUP; + } + else if (User.class.isAssignableFrom(category)) + { + return ObjectType.USER; + } + else if (VirtualHost.class.isAssignableFrom(category)) + { + return ObjectType.VIRTUALHOST; + } + else if (VirtualHostAlias.class.isAssignableFrom(category)) + { + return ObjectType.VIRTUALHOST; + } + else if (Queue.class.isAssignableFrom(category)) + { + return ObjectType.QUEUE; + } + else if (Exchange.class.isAssignableFrom(category)) + { + return ObjectType.EXCHANGE; + } + else if (Connection.class.isAssignableFrom(category)) + { + // ACCESS VIRTUALHOST + return ObjectType.VIRTUALHOST; + } + else if (Session.class.isAssignableFrom(category)) + { + // PUBLISH EXCHANGE + return ObjectType.EXCHANGE; + } + else if (Consumer.class.isAssignableFrom(category)) + { + // CONSUME QUEUE + return ObjectType.QUEUE; + } + else if (RemoteReplicationNode.class.isAssignableFrom(category)) + { + // VHN permissions apply to remote nodes + return ObjectType.VIRTUALHOSTNODE; + } + return null; } - public void authoriseUserOperation(final Operation operation, final String userName) + public void authoriseUserUpdate(final String userName) { + AuthenticatedPrincipal principal = getCurrentUser(); + if (principal != null && principal.getName().equals(userName)) + { + // allow user to update its own data + return; + } + + final Operation operation = Operation.UPDATE; if(! checkAllPlugins(new AccessCheck() { Result allowed(AccessControl plugin) @@ -437,13 +588,15 @@ public class SecurityManager } } - public void authorisePurge(final AMQQueue queue) + public void authorisePurge(final Queue queue) { + final ObjectProperties properties = new ObjectProperties(); + setQueueProperties(queue, properties); if(!checkAllPlugins(new AccessCheck() { Result allowed(AccessControl plugin) { - return plugin.authorise(PURGE, QUEUE, new ObjectProperties(queue)); + return plugin.authorise(PURGE, QUEUE, properties); } })) { @@ -451,21 +604,6 @@ public class SecurityManager } } - public void authoriseUnbind(final BindingImpl binding) - { - if(! checkAllPlugins(new AccessCheck() - { - Result allowed(AccessControl plugin) - { - return plugin.authorise(UNBIND, EXCHANGE, new ObjectProperties(binding)); - } - })) - { - throw new AccessControlException("Permission denied: unbinding " + binding.getBindingKey()); - } - } - - private class PublishAccessCheck extends AccessCheck { private final ObjectProperties _props; @@ -481,22 +619,6 @@ public class SecurityManager } } - public boolean authoriseConfiguringBroker(String configuredObjectName, Class<? extends ConfiguredObject> configuredObjectType, Operation configuredObjectOperation) - { - String description = String.format("%s %s '%s'", - configuredObjectOperation == null? null : configuredObjectOperation.name().toLowerCase(), - configuredObjectType == null ? null : configuredObjectType.getSimpleName().toLowerCase(), - configuredObjectName); - final OperationLoggingDetails properties = new OperationLoggingDetails(description); - return checkAllPlugins(new AccessCheck() - { - Result allowed(AccessControl plugin) - { - return plugin.authorise(CONFIGURE, BROKER, properties); - } - }); - } - public boolean authoriseLogsAccess() { return checkAllPlugins(new AccessCheck() 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 05b3f0d9d1..6d3fbb1cea 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,11 +26,6 @@ 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; /** * An set of properties for an access control v2 rule {@link ObjectType}. @@ -139,42 +134,6 @@ public class ObjectProperties setName(name); } - public ObjectProperties(AMQQueue queue) - { - setName(queue.getName()); - - put(Property.AUTO_DELETE, queue.getLifetimePolicy() != LifetimePolicy.PERMANENT); - put(Property.TEMPORARY, queue.getLifetimePolicy() != LifetimePolicy.PERMANENT); - put(Property.DURABLE, queue.isDurable()); - put(Property.EXCLUSIVE, queue.isExclusive()); - if (queue.getAlternateExchange() != null) - { - put(Property.ALTERNATE, queue.getAlternateExchange().getName()); - } - if (queue.getOwner() != null) - { - put(Property.OWNER, queue.getOwner()); - } - put(Property.VIRTUALHOST_NAME, queue.getParent(VirtualHost.class).getName()); - } - - public ObjectProperties(BindingImpl binding) - { - ExchangeImpl<?> exch = binding.getExchange(); - AMQQueue<?> queue = binding.getAMQQueue(); - String routingKey = binding.getBindingKey(); - - setName(exch.getName()); - - put(Property.QUEUE_NAME, queue.getName()); - put(Property.ROUTING_KEY, routingKey); - put(Property.VIRTUALHOST_NAME, queue.getParent(VirtualHost.class).getName()); - - // 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 virtualHostName, String exchangeName, String routingKey, Boolean immediate) { @@ -187,29 +146,6 @@ public class ObjectProperties put(Property.VIRTUALHOST_NAME, virtualHostName); } - public ObjectProperties(ExchangeImpl<?> exchange) - { - super(); - - setName(exchange.getName()); - - put(Property.AUTO_DELETE, exchange.isAutoDelete()); - put(Property.TEMPORARY, exchange.getLifetimePolicy() != LifetimePolicy.PERMANENT); - put(Property.DURABLE, exchange.isDurable()); - put(Property.TYPE, exchange.getType()); - put(Property.VIRTUALHOST_NAME, exchange.getParent(VirtualHost.class).getName()); - } - - public ObjectProperties(Boolean exclusive, Boolean noAck, Boolean noLocal, Boolean nowait, AMQQueue queue) - { - this(queue); - - put(Property.NO_LOCAL, noLocal); - put(Property.NO_ACK, noAck); - put(Property.EXCLUSIVE, exclusive); - put(Property.NO_WAIT, nowait); - } - public Boolean isSet(Property key) { return _properties.containsKey(key) && Boolean.valueOf(_properties.get(key)); diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractAuthenticationManager.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractAuthenticationManager.java index 9befcebe5b..255457a846 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractAuthenticationManager.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractAuthenticationManager.java @@ -20,7 +20,6 @@ */ package org.apache.qpid.server.security.auth.manager; -import java.security.AccessControlException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -48,7 +47,6 @@ import org.apache.qpid.server.model.User; import org.apache.qpid.server.model.VirtualHostAlias; import org.apache.qpid.server.model.port.AbstractPortWithAuthProvider; import org.apache.qpid.server.security.SubjectCreator; -import org.apache.qpid.server.security.access.Operation; public abstract class AbstractAuthenticationManager<T extends AbstractAuthenticationManager<T>> extends AbstractConfiguredObject<T> @@ -155,28 +153,6 @@ public abstract class AbstractAuthenticationManager<T extends AbstractAuthentica throw new IllegalArgumentException("Cannot create child of class " + childClass.getSimpleName()); } - - @Override - protected void authoriseSetDesiredState(State desiredState) throws AccessControlException - { - if(desiredState == State.DELETED) - { - if (!_broker.getSecurityManager().authoriseConfiguringBroker(getName(), AuthenticationProvider.class, Operation.DELETE)) - { - throw new AccessControlException("Deletion of authentication provider is denied"); - } - } - } - - @Override - protected void authoriseSetAttributes(ConfiguredObject<?> modified, Set<String> attributes) throws AccessControlException - { - if (!_broker.getSecurityManager().authoriseConfiguringBroker(getName(), AuthenticationProvider.class, Operation.UPDATE)) - { - throw new AccessControlException("Setting of authentication provider attributes is denied"); - } - } - @StateTransition( currentState = State.UNINITIALIZED, desiredState = State.QUIESCED ) protected ListenableFuture<Void> startQuiesced() { diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ConfigModelPasswordManagingAuthenticationProvider.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ConfigModelPasswordManagingAuthenticationProvider.java index 7046fc4885..50a2a36130 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ConfigModelPasswordManagingAuthenticationProvider.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ConfigModelPasswordManagingAuthenticationProvider.java @@ -70,27 +70,21 @@ public abstract class ConfigModelPasswordManagingAuthenticationProvider<X extend @Override public Boolean execute() { - getSecurityManager().authoriseUserOperation(Operation.CREATE, username); - if (_users.containsKey(username)) - { - throw new IllegalArgumentException("User '" + username + "' already exists"); - } Map<String, Object> userAttrs = new HashMap<>(); userAttrs.put(User.ID, UUID.randomUUID()); userAttrs.put(User.NAME, username); - userAttrs.put(User.PASSWORD, createStoredPassword(password)); + userAttrs.put(User.PASSWORD, password); userAttrs.put(User.TYPE, ManagedUser.MANAGED_USER_TYPE); - ManagedUser user = new ManagedUser(userAttrs, ConfigModelPasswordManagingAuthenticationProvider.this); - user.create(); - - return true; + User user = createChild(User.class, userAttrs); + return user != null; } }); } - SecurityManager getSecurityManager() + @Override + protected SecurityManager getSecurityManager() { return getBroker().getSecurityManager(); } @@ -201,20 +195,15 @@ public abstract class ConfigModelPasswordManagingAuthenticationProvider<X extend { if(childClass == User.class) { - String username = (String) attributes.get("name"); - String password = (String) attributes.get("password"); - - if(createUser(username, password,null)) + String username = (String) attributes.get(User.NAME); + if (_users.containsKey(username)) { - @SuppressWarnings("unchecked") - C user = (C) getUser(username); - return user; - } - else - { - return null; - + throw new IllegalArgumentException("User '" + username + "' already exists"); } + attributes.put(User.PASSWORD, createStoredPassword((String) attributes.get(User.PASSWORD))); + ManagedUser user = new ManagedUser(attributes, ConfigModelPasswordManagingAuthenticationProvider.this); + user.create(); + return (C)getUser(username); } return super.addChild(childClass, attributes, otherParents); } diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ManagedUser.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ManagedUser.java index 6f36ec7d11..db69445c41 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ManagedUser.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ManagedUser.java @@ -40,7 +40,6 @@ import org.apache.qpid.server.model.PreferencesProvider; import org.apache.qpid.server.model.State; import org.apache.qpid.server.model.StateTransition; import org.apache.qpid.server.model.User; -import org.apache.qpid.server.security.access.Operation; @ManagedObject( category = false, type = ManagedUser.MANAGED_USER_TYPE) class ManagedUser extends AbstractConfiguredObject<ManagedUser> implements User<ManagedUser> @@ -88,16 +87,6 @@ class ManagedUser extends AbstractConfiguredObject<ManagedUser> implements User< } } - @Override - protected void authoriseSetDesiredState(final State desiredState) throws AccessControlException - { - if(desiredState == State.DELETED) - { - _authenticationManager.getSecurityManager().authoriseUserOperation(Operation.DELETE, getName()); - } - - } - @StateTransition(currentState = {State.ACTIVE}, desiredState = State.DELETED) private ListenableFuture<Void> doDelete() { @@ -106,31 +95,18 @@ class ManagedUser extends AbstractConfiguredObject<ManagedUser> implements User< return Futures.immediateFuture(null); } - @Override - public void setAttributes(final Map<String, Object> attributes) - throws IllegalStateException, AccessControlException, IllegalArgumentException + protected boolean changeAttribute(String name, Object expected, Object desired) { - runTask(new VoidTask() + if (User.PASSWORD.equals(name)) { - - @Override - public void execute() + String storedPassword = _authenticationManager.createStoredPassword((String)desired); + if (!storedPassword.equals(getActualAttributes().get(User.PASSWORD))) { - Map<String, Object> modifiedAttributes = new HashMap<String, Object>(attributes); - final String newPassword = (String) attributes.get(User.PASSWORD); - if (attributes.containsKey(User.PASSWORD) - && !newPassword.equals(getActualAttributes().get(User.PASSWORD))) - { - modifiedAttributes.put(User.PASSWORD, - _authenticationManager.createStoredPassword(newPassword)); - - } - ManagedUser.super.setAttributes(modifiedAttributes); + desired = storedPassword; } - }); - - + } + return super.changeAttribute(name, expected, desired); } @Override @@ -142,10 +118,7 @@ class ManagedUser extends AbstractConfiguredObject<ManagedUser> implements User< @Override public void setPassword(final String password) { - _authenticationManager.getSecurityManager().authoriseUserOperation(Operation.UPDATE, getName()); - - changeAttribute(User.PASSWORD, getAttribute(User.PASSWORD), - _authenticationManager.createStoredPassword(password)); + setAttributes(Collections.<String, Object>singletonMap(User.PASSWORD, password)); } diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java index a4dbcdc284..0fcab33f5d 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java @@ -57,11 +57,11 @@ import org.apache.qpid.server.model.PreferencesSupportingAuthenticationProvider; import org.apache.qpid.server.model.State; import org.apache.qpid.server.model.StateTransition; import org.apache.qpid.server.model.User; -import org.apache.qpid.server.security.access.Operation; import org.apache.qpid.server.security.auth.AuthenticationResult; import org.apache.qpid.server.security.auth.AuthenticationResult.AuthenticationStatus; import org.apache.qpid.server.security.auth.UsernamePrincipal; import org.apache.qpid.server.security.auth.database.PrincipalDatabase; +import org.apache.qpid.server.security.SecurityManager; import org.apache.qpid.server.util.FileHelper; public abstract class PrincipalDatabaseAuthenticationManager<T extends PrincipalDatabaseAuthenticationManager<T>> @@ -265,26 +265,18 @@ public abstract class PrincipalDatabaseAuthenticationManager<T extends Principal @Override public boolean createUser(String username, String password, Map<String, String> attributes) { - getSecurityManager().authoriseUserOperation(Operation.CREATE, username); - Principal principal = new UsernamePrincipal(username); - boolean created = - getPrincipalDatabase().createPrincipal(principal, password.toCharArray()); - if(created) - { - principal = getPrincipalDatabase().getUser(username); + Map<String, Object> userAttrs = new HashMap<>(); + userAttrs.put(User.NAME, username); + userAttrs.put(User.PASSWORD, password); - PrincipalAdapter principalAdapter = new PrincipalAdapter(principal); - principalAdapter.create(); - _userMap.put(principal, principalAdapter); - } - return created; + User user = createChild(User.class, userAttrs); + return user != null; } private void deleteUserFromDatabase(String username) throws AccountNotFoundException { - getSecurityManager().authoriseUserOperation(Operation.DELETE, username); UsernamePrincipal principal = new UsernamePrincipal(username); getPrincipalDatabase().deletePrincipal(principal); _userMap.remove(principal); @@ -301,11 +293,12 @@ public abstract class PrincipalDatabaseAuthenticationManager<T extends Principal } else { - deleteUserFromDatabase(username); + throw new AccountNotFoundException("No such user: '" + username + "'"); } } - private org.apache.qpid.server.security.SecurityManager getSecurityManager() + @Override + protected SecurityManager getSecurityManager() { return getBroker().getSecurityManager(); } @@ -313,10 +306,12 @@ public abstract class PrincipalDatabaseAuthenticationManager<T extends Principal @Override public void setPassword(String username, String password) throws AccountNotFoundException { - getSecurityManager().authoriseUserOperation(Operation.UPDATE, username); - - getPrincipalDatabase().updatePassword(new UsernamePrincipal(username), password.toCharArray()); - + Principal principal = new UsernamePrincipal(username); + User user = _userMap.get(principal); + if (user != null) + { + user.setPassword(password); + } } @Override @@ -346,8 +341,22 @@ public abstract class PrincipalDatabaseAuthenticationManager<T extends Principal String username = (String) attributes.get("name"); String password = (String) attributes.get("password"); Principal p = new UsernamePrincipal(username); + if (_userMap.containsKey(p)) + { + throw new IllegalArgumentException("User '" + username + "' already exists"); + } - if(createUser(username, password,null)) + boolean created = getPrincipalDatabase().createPrincipal(p, password.toCharArray()); + if(created) + { + p = getPrincipalDatabase().getUser(username); + + PrincipalAdapter principalAdapter = new PrincipalAdapter(p); + principalAdapter.create(); + _userMap.put(p, principalAdapter); + } + + if(created) { return (C) _userMap.get(p); } @@ -474,14 +483,7 @@ public abstract class PrincipalDatabaseAuthenticationManager<T extends Principal @Override public void setPassword(String password) { - try - { - PrincipalDatabaseAuthenticationManager.this.setPassword(_user.getName(), password); - } - catch (AccountNotFoundException e) - { - throw new IllegalStateException(e); - } + setAttributes(Collections.<String, Object>singletonMap(PASSWORD, password)); } @Override @@ -490,8 +492,20 @@ public abstract class PrincipalDatabaseAuthenticationManager<T extends Principal { if(name.equals(PASSWORD)) { - setPassword((String)desired); - return true; + try + { + String desiredPassword = (String) desired; + boolean changed = getPrincipalDatabase().updatePassword(_user, desiredPassword.toCharArray()); + if (changed) + { + return super.changeAttribute(name, expected, desired); + } + return false; + } + catch(AccountNotFoundException e) + { + throw new IllegalStateException(e); + } } return super.changeAttribute(name, expected, desired); } diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/BrokerStoreUpgraderAndRecoverer.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/BrokerStoreUpgraderAndRecoverer.java index 69d94a6710..70b8c6296b 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/BrokerStoreUpgraderAndRecoverer.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/BrokerStoreUpgraderAndRecoverer.java @@ -260,6 +260,11 @@ public class BrokerStoreUpgraderAndRecoverer private ConfiguredObjectRecord upgradeKeyStoreRecordIfTypeTheSame(ConfiguredObjectRecord record, String expectedType) { Map<String, Object> attributes = new HashMap<>(record.getAttributes()); + // Type may not be present, in which case the default type - which is the type affected - will be being used + if(!attributes.containsKey("type")) + { + attributes.put("type", expectedType); + } if (expectedType.equals(attributes.get("type"))) { Object path = attributes.remove("path"); diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/NonBlockingConnection.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/NonBlockingConnection.java index 9070d75e69..ae5816a0d1 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/NonBlockingConnection.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/NonBlockingConnection.java @@ -45,7 +45,6 @@ import org.slf4j.LoggerFactory; import org.apache.qpid.server.protocol.ServerProtocolEngine; import org.apache.qpid.server.util.Action; import org.apache.qpid.transport.ByteBufferSender; -import org.apache.qpid.transport.SenderClosedException; import org.apache.qpid.transport.SenderException; import org.apache.qpid.transport.network.NetworkConnection; import org.apache.qpid.transport.network.Ticker; @@ -627,10 +626,13 @@ public class NonBlockingConnection implements NetworkConnection, ByteBufferSende if (_closed.get()) { - throw new SenderClosedException("I/O for thread " + _remoteSocketAddress + " is already closed"); + LOGGER.warn("Send ignored as the connection is already closed"); + } + else + { + _buffers.add(msg); + _protocolEngine.notifyWork(); } - _buffers.add(msg); - _protocolEngine.notifyWork(); } @Override diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/SelectorThread.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/SelectorThread.java index d2351b5500..774888e934 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/SelectorThread.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/SelectorThread.java @@ -32,12 +32,16 @@ import java.util.List; import java.util.Queue; import java.util.Set; import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.Executors; import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import org.slf4j.LoggerFactory; +import org.apache.qpid.thread.LoggingUncaughtExceptionHandler; + public class SelectorThread extends Thread { 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 4a2d30ac9f..220beb20f8 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 @@ -21,7 +21,6 @@ package org.apache.qpid.server.virtualhost; import java.io.File; -import java.security.AccessControlException; import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Collection; @@ -80,7 +79,6 @@ import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.QueueConsumer; import org.apache.qpid.server.queue.QueueEntry; import org.apache.qpid.server.security.SecurityManager; -import org.apache.qpid.server.security.access.Operation; import org.apache.qpid.server.stats.StatisticsCounter; import org.apache.qpid.server.store.ConfiguredObjectRecord; import org.apache.qpid.server.store.DurableConfigurationStore; @@ -465,25 +463,6 @@ public abstract class AbstractVirtualHost<X extends AbstractVirtualHost<X>> exte return _connectionRegistry; } - @Override - protected void authoriseSetDesiredState(State desiredState) throws AccessControlException - { - if(desiredState == State.DELETED) - { - _broker.getSecurityManager().authoriseVirtualHost(getName(), Operation.DELETE); - } - else - { - _broker.getSecurityManager().authoriseVirtualHost(getName(), Operation.UPDATE); - } - } - - @Override - protected void authoriseSetAttributes(ConfiguredObject<?> modified, Set<String> attributes) throws AccessControlException - { - _broker.getSecurityManager().authoriseVirtualHost(getName(), Operation.UPDATE); - } - public Collection<Connection> getConnections() { return getChildren(Connection.class); @@ -709,11 +688,7 @@ public abstract class AbstractVirtualHost<X extends AbstractVirtualHost<X>> exte public AMQQueue<?> createQueue(Map<String, Object> attributes) throws QueueExistsException { - checkVHostStateIsActive(); - - AMQQueue<?> queue = addQueue(attributes); - childAdded(queue); - return queue; + return (AMQQueue<?> )createChild(Queue.class, attributes); } private AMQQueue<?> addQueue(Map<String, Object> attributes) throws QueueExistsException @@ -738,7 +713,7 @@ public abstract class AbstractVirtualHost<X extends AbstractVirtualHost<X>> exte } catch (DuplicateNameException e) { - throw new QueueExistsException(getQueue(e.getName())); + throw new QueueExistsException(String.format("Queue with name '%s' already exists", e.getName()), getQueue(e.getName())); } } @@ -797,10 +772,7 @@ public abstract class AbstractVirtualHost<X extends AbstractVirtualHost<X>> exte throws ExchangeExistsException, ReservedExchangeNameException, NoFactoryForTypeException { - checkVHostStateIsActive(); - ExchangeImpl child = addExchange(attributes); - childAdded(child); - return child; + return (ExchangeImpl)createChild(Exchange.class, attributes); } @@ -814,7 +786,7 @@ public abstract class AbstractVirtualHost<X extends AbstractVirtualHost<X>> exte } catch (DuplicateNameException e) { - throw new ExchangeExistsException(getExchange(e.getName())); + throw new ExchangeExistsException(String.format("Exchange with name '%s' already exists", e.getName()), getExchange(e.getName())); } } diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/ExchangeExistsException.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/ExchangeExistsException.java index 109bf85aef..fe988afe61 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/ExchangeExistsException.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/ExchangeExistsException.java @@ -27,7 +27,12 @@ public class ExchangeExistsException extends RuntimeException public ExchangeExistsException(ExchangeImpl existing) { - super(existing.getName()); + this(existing.getName(), existing); + } + + public ExchangeExistsException(String message, ExchangeImpl existing) + { + super(message); _existing = existing; } diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java index bccf284b34..8e08554358 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java @@ -26,7 +26,6 @@ import java.io.Reader; import java.io.StringReader; import java.net.MalformedURLException; import java.net.URL; -import java.security.AccessControlException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -64,7 +63,6 @@ import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.model.VirtualHostNode; import org.apache.qpid.server.plugin.ConfiguredObjectRegistration; import org.apache.qpid.server.plugin.QpidServiceLoader; -import org.apache.qpid.server.security.access.Operation; import org.apache.qpid.server.security.auth.AuthenticatedPrincipal; import org.apache.qpid.server.store.ConfiguredObjectRecord; import org.apache.qpid.server.store.ConfiguredObjectRecordConverter; @@ -312,43 +310,6 @@ public abstract class AbstractVirtualHostNode<X extends AbstractVirtualHostNode< closeConfigurationStore(); } - @Override - protected void authoriseSetDesiredState(State desiredState) throws AccessControlException - { - if(desiredState == State.DELETED) - { - _broker.getSecurityManager().authoriseVirtualHostNode(getName(), Operation.DELETE); - } - else - { - _broker.getSecurityManager().authoriseVirtualHostNode(getName(), Operation.UPDATE); - } - } - - @Override - protected <C extends ConfiguredObject> void authoriseCreateChild(final Class<C> childClass, - final Map<String, Object> attributes, - final ConfiguredObject... otherParents) - throws AccessControlException - { - if (childClass == VirtualHost.class) - { - _broker.getSecurityManager().authoriseVirtualHost(String.valueOf(attributes.get(VirtualHost.NAME)), - Operation.CREATE); - - } - else - { - super.authoriseCreateChild(childClass, attributes, otherParents); - } - } - - @Override - protected void authoriseSetAttributes(ConfiguredObject<?> modified, Set<String> attributes) throws AccessControlException - { - _broker.getSecurityManager().authoriseVirtualHostNode(getName(), Operation.UPDATE); - } - private void closeConfigurationStore() { DurableConfigurationStore configurationStore = getConfigurationStore(); diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/exchange/FanoutExchangeTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/exchange/FanoutExchangeTest.java index cb5034b3f3..3e0ba31b08 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/exchange/FanoutExchangeTest.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/exchange/FanoutExchangeTest.java @@ -32,6 +32,9 @@ import java.util.Set; import java.util.UUID; import junit.framework.TestCase; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.model.VirtualHostNode; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; @@ -63,14 +66,27 @@ public class FanoutExchangeTest extends TestCase attributes.put(Exchange.NAME, "test"); attributes.put(Exchange.DURABLE, false); + Broker broker = mock(Broker.class); + SecurityManager securityManager = new SecurityManager(broker, false); + when(broker.getCategoryClass()).thenReturn(Broker.class); + when(broker.getModel()).thenReturn(BrokerModel.getInstance()); + when(broker.getSecurityManager()).thenReturn(securityManager); + + VirtualHostNode virtualHostNode = mock(VirtualHostNode.class); + when(virtualHostNode.getCategoryClass()).thenReturn(VirtualHostNode.class); + when(virtualHostNode.getParent(Broker.class)).thenReturn(broker); + when(virtualHostNode.getModel()).thenReturn(BrokerModel.getInstance()); + _taskExecutor = new CurrentThreadTaskExecutor(); _taskExecutor.start(); _virtualHost = mock(VirtualHostImpl.class); - SecurityManager securityManager = mock(SecurityManager.class); + when(_virtualHost.getSecurityManager()).thenReturn(securityManager); when(_virtualHost.getEventLogger()).thenReturn(new EventLogger()); when(_virtualHost.getTaskExecutor()).thenReturn(_taskExecutor); when(_virtualHost.getModel()).thenReturn(BrokerModel.getInstance()); + when(_virtualHost.getParent(VirtualHostNode.class)).thenReturn(virtualHostNode); + when(_virtualHost.getCategoryClass()).thenReturn(VirtualHost.class); _exchange = new FanoutExchange(attributes, _virtualHost); _exchange.open(); } @@ -134,6 +150,7 @@ public class FanoutExchangeTest extends TestCase when(queue.getCategoryClass()).thenReturn(Queue.class); when(queue.getModel()).thenReturn(BrokerModel.getInstance()); when(queue.getTaskExecutor()).thenReturn(CurrentThreadTaskExecutor.newStartedInstance()); + when(queue.getParent(VirtualHost.class)).thenReturn(_virtualHost); return queue; } diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/exchange/HeadersExchangeTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/exchange/HeadersExchangeTest.java index 6d9277006f..c5ad190477 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/exchange/HeadersExchangeTest.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/exchange/HeadersExchangeTest.java @@ -35,6 +35,9 @@ import java.util.Set; import java.util.UUID; import junit.framework.TestCase; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.VirtualHostNode; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; @@ -70,7 +73,18 @@ public class HeadersExchangeTest extends TestCase _taskExecutor = new CurrentThreadTaskExecutor(); _taskExecutor.start(); _virtualHost = mock(VirtualHostImpl.class); - SecurityManager securityManager = mock(SecurityManager.class); + + Broker broker = mock(Broker.class); + SecurityManager securityManager = new SecurityManager(broker, false); + when(broker.getCategoryClass()).thenReturn(Broker.class); + when(broker.getModel()).thenReturn(BrokerModel.getInstance()); + when(broker.getSecurityManager()).thenReturn(securityManager); + + VirtualHostNode virtualHostNode = mock(VirtualHostNode.class); + when(virtualHostNode.getCategoryClass()).thenReturn(VirtualHostNode.class); + when(virtualHostNode.getParent(Broker.class)).thenReturn(broker); + when(virtualHostNode.getModel()).thenReturn(BrokerModel.getInstance()); + when(_virtualHost.getSecurityManager()).thenReturn(securityManager); when(_virtualHost.getEventLogger()).thenReturn(new EventLogger()); when(_virtualHost.getCategoryClass()).thenReturn(VirtualHost.class); @@ -78,6 +92,7 @@ public class HeadersExchangeTest extends TestCase _factory = new ConfiguredObjectFactoryImpl(BrokerModel.getInstance()); when(_virtualHost.getObjectFactory()).thenReturn(_factory); when(_virtualHost.getModel()).thenReturn(_factory.getModel()); + when(_virtualHost.getParent(VirtualHostNode.class)).thenReturn(virtualHostNode); Map<String,Object> attributes = new HashMap<String, Object>(); attributes.put(Exchange.ID, UUID.randomUUID()); attributes.put(Exchange.NAME, "test"); @@ -149,6 +164,7 @@ public class HeadersExchangeTest extends TestCase AMQQueue q = mock(AMQQueue.class); when(q.toString()).thenReturn(name); when(q.getVirtualHost()).thenReturn(_virtualHost); + when(q.getParent(VirtualHost.class)).thenReturn(_virtualHost); when(q.getCategoryClass()).thenReturn(Queue.class); when(q.getObjectFactory()).thenReturn(_factory); when(q.getModel()).thenReturn(_factory.getModel()); diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/VirtualHostTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/VirtualHostTest.java index 26db573e41..4acc925392 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/VirtualHostTest.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/VirtualHostTest.java @@ -69,7 +69,7 @@ public class VirtualHostTest extends QpidTestCase private final SecurityManager _mockSecurityManager = mock(SecurityManager.class); private Broker _broker; private TaskExecutor _taskExecutor; - private VirtualHostNode<?> _virtualHostNode; + private VirtualHostNode _virtualHostNode; private DurableConfigurationStore _configStore; private VirtualHost<?, ?, ?> _virtualHost; private StoreConfigurationChangeListener _storeConfigurationChangeListener; @@ -86,6 +86,8 @@ public class VirtualHostTest extends QpidTestCase when(_broker.getTaskExecutor()).thenReturn(_taskExecutor); _virtualHostNode = mock(VirtualHostNode.class); + when(_virtualHostNode.getParent(Broker.class)).thenReturn(_broker); + when(_virtualHostNode.getCategoryClass()).thenReturn(VirtualHostNode.class); when(_virtualHostNode.isDurable()).thenReturn(true); _configStore = mock(DurableConfigurationStore.class); _storeConfigurationChangeListener = new StoreConfigurationChangeListener(_configStore); @@ -333,9 +335,7 @@ public class VirtualHostTest extends QpidTestCase String virtualHostName = getName(); VirtualHost<?,?,?> virtualHost = createVirtualHost(virtualHostName); - doThrow(new AccessControlException("mocked ACL exception")).when(_mockSecurityManager).authoriseVirtualHost( - virtualHostName, - Operation.UPDATE); + doThrow(new AccessControlException("mocked ACL exception")).when(_mockSecurityManager).authoriseUpdate(virtualHost); assertNull(virtualHost.getDescription()); @@ -359,9 +359,7 @@ public class VirtualHostTest extends QpidTestCase String virtualHostName = getName(); VirtualHost<?,?,?> virtualHost = createVirtualHost(virtualHostName); - doThrow(new AccessControlException("mocked ACL exception")).when(_mockSecurityManager).authoriseVirtualHost( - virtualHostName, - Operation.UPDATE); + doThrow(new AccessControlException("mocked ACL exception")).when(_mockSecurityManager).authoriseUpdate(virtualHost); try { @@ -383,9 +381,7 @@ public class VirtualHostTest extends QpidTestCase String virtualHostName = getName(); VirtualHost<?,?,?> virtualHost = createVirtualHost(virtualHostName); - doThrow(new AccessControlException("mocked ACL exception")).when(_mockSecurityManager).authoriseVirtualHost( - virtualHostName, - Operation.DELETE); + doThrow(new AccessControlException("mocked ACL exception")).when(_mockSecurityManager).authoriseDelete(virtualHost); try { diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestKitCarImpl.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestKitCarImpl.java index 5785071e15..43dcecd6c8 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestKitCarImpl.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestKitCarImpl.java @@ -25,6 +25,7 @@ import org.apache.qpid.server.model.AbstractConfiguredObject; import org.apache.qpid.server.model.ConfiguredObject; import org.apache.qpid.server.model.ManagedObject; import org.apache.qpid.server.model.ManagedObjectFactoryConstructor; +import org.apache.qpid.server.security.SecurityManager; @ManagedObject( category = false, type = TestKitCarImpl.TEST_KITCAR_TYPE) @@ -32,11 +33,13 @@ public class TestKitCarImpl extends AbstractConfiguredObject<TestKitCarImpl> implements TestKitCar<TestKitCarImpl> { public static final String TEST_KITCAR_TYPE = "testkitcar"; + private final SecurityManager _securityManager; @ManagedObjectFactoryConstructor public TestKitCarImpl(final Map<String, Object> attributes) { super(parentsMap(), attributes, newTaskExecutor(), TestModel.getInstance()); + _securityManager = new SecurityManager(this, false); } @Override @@ -53,4 +56,10 @@ public class TestKitCarImpl extends AbstractConfiguredObject<TestKitCarImpl> currentThreadTaskExecutor.start(); return currentThreadTaskExecutor; } + + @Override + protected SecurityManager getSecurityManager() + { + return _securityManager; + } } diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestStandardCarImpl.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestStandardCarImpl.java index 83dfd73b8b..7582de2952 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestStandardCarImpl.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestStandardCarImpl.java @@ -29,6 +29,7 @@ import org.apache.qpid.server.configuration.updater.CurrentThreadTaskExecutor; import org.apache.qpid.server.model.AbstractConfiguredObject; import org.apache.qpid.server.model.ManagedObject; import org.apache.qpid.server.model.ManagedObjectFactoryConstructor; +import org.apache.qpid.server.security.SecurityManager; @ManagedObject( category = false, type = TestStandardCarImpl.TEST_STANDARD_CAR_TYPE, @@ -37,11 +38,13 @@ public class TestStandardCarImpl extends AbstractConfiguredObject<TestStandardCa implements TestStandardCar<TestStandardCarImpl> { public static final String TEST_STANDARD_CAR_TYPE = "testpertrolcar"; + private final SecurityManager _securityManager; @ManagedObjectFactoryConstructor public TestStandardCarImpl(final Map<String, Object> attributes) { super(parentsMap(), attributes, newTaskExecutor(), TestModel.getInstance()); + _securityManager = new SecurityManager(this, false); } private static CurrentThreadTaskExecutor newTaskExecutor() @@ -57,4 +60,10 @@ public class TestStandardCarImpl extends AbstractConfiguredObject<TestStandardCa Collection<String> types = Arrays.asList(TestPetrolEngineImpl.TEST_PETROL_ENGINE_TYPE, TestHybridEngineImpl.TEST_HYBRID_ENGINE_TYPE); return Collections.singletonMap(TestEngine.class.getSimpleName(), types); } + + @Override + protected SecurityManager getSecurityManager() + { + return _securityManager; + } } diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/lifecycle/TestConfiguredObject.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/lifecycle/TestConfiguredObject.java index 5c91052956..d4223a2b38 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/lifecycle/TestConfiguredObject.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/lifecycle/TestConfiguredObject.java @@ -42,10 +42,12 @@ import org.apache.qpid.server.model.Model; import org.apache.qpid.server.model.State; import org.apache.qpid.server.model.StateTransition; import org.apache.qpid.server.plugin.ConfiguredObjectRegistration; +import org.apache.qpid.server.security.SecurityManager; @ManagedObject public class TestConfiguredObject extends AbstractConfiguredObject { + private final SecurityManager _securityManager; private boolean _opened; private boolean _validated; private boolean _resolved; @@ -79,6 +81,13 @@ public class TestConfiguredObject extends AbstractConfiguredObject { super(parents, attributes, taskExecutor, model); _opened = false; + _securityManager = new SecurityManager(this, false); + } + + @Override + protected SecurityManager getSecurityManager() + { + return _securityManager; } @Override diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/singleton/TestSingletonImpl.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/singleton/TestSingletonImpl.java index c4dc0fa39d..5de40042cc 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/singleton/TestSingletonImpl.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/singleton/TestSingletonImpl.java @@ -27,6 +27,7 @@ import org.apache.qpid.server.model.AbstractConfiguredObject; import org.apache.qpid.server.model.ManagedAttributeField; import org.apache.qpid.server.model.ManagedObject; import org.apache.qpid.server.model.ManagedObjectFactoryConstructor; +import org.apache.qpid.server.security.SecurityManager; @ManagedObject( category = false, type = TestSingletonImpl.TEST_SINGLETON_TYPE) public class TestSingletonImpl extends AbstractConfiguredObject<TestSingletonImpl> @@ -35,6 +36,7 @@ public class TestSingletonImpl extends AbstractConfiguredObject<TestSingletonImp public static final String TEST_SINGLETON_TYPE = "testsingleton"; public static final int DERIVED_VALUE = -100; + private final SecurityManager _securityManager; @ManagedAttributeField private String _automatedPersistedValue; @@ -71,6 +73,7 @@ public class TestSingletonImpl extends AbstractConfiguredObject<TestSingletonImp public TestSingletonImpl(final Map<String, Object> attributes) { super(parentsMap(), attributes, newTaskExecutor(), TestModel.getInstance()); + _securityManager = new SecurityManager(this, false); } private static CurrentThreadTaskExecutor newTaskExecutor() @@ -84,6 +87,7 @@ public class TestSingletonImpl extends AbstractConfiguredObject<TestSingletonImp final TaskExecutor taskExecutor) { super(parentsMap(), attributes, taskExecutor); + _securityManager = new SecurityManager(this, false); } @@ -152,4 +156,10 @@ public class TestSingletonImpl extends AbstractConfiguredObject<TestSingletonImp { return _secureValue; } + + @Override + protected SecurityManager getSecurityManager() + { + return _securityManager; + } } diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/security/FileKeyStoreTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/security/FileKeyStoreTest.java index 0a2e122d16..c691c21ce2 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/security/FileKeyStoreTest.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/security/FileKeyStoreTest.java @@ -49,7 +49,7 @@ import org.apache.qpid.util.FileUtils; public class FileKeyStoreTest extends QpidTestCase { - private final Broker<?> _broker = mock(Broker.class); + private final Broker _broker = mock(Broker.class); private final TaskExecutor _taskExecutor = CurrentThreadTaskExecutor.newStartedInstance(); private final SecurityManager _securityManager = mock(SecurityManager.class); private final Model _model = BrokerModel.getInstance(); @@ -63,6 +63,7 @@ public class FileKeyStoreTest extends QpidTestCase when(_broker.getTaskExecutor()).thenReturn(_taskExecutor); when(_broker.getModel()).thenReturn(_model); when(_broker.getSecurityManager()).thenReturn(_securityManager); + when(_broker.getCategoryClass()).thenReturn(Broker.class); } public void testCreateKeyStoreFromFile_Success() throws Exception @@ -237,9 +238,6 @@ public class FileKeyStoreTest extends QpidTestCase public void testUpdateKeyStore_Success() throws Exception { - - when(_securityManager.authoriseConfiguringBroker(any(String.class), (Class<? extends ConfiguredObject>)any(), any(Operation.class))).thenReturn(true); - Map<String,Object> attributes = new HashMap<>(); attributes.put(FileKeyStore.NAME, "myFileKeyStore"); attributes.put(FileKeyStore.STORE_URL, TestSSLConstants.BROKER_KEYSTORE); @@ -278,9 +276,6 @@ public class FileKeyStoreTest extends QpidTestCase public void testDeleteKeyStore_Success() throws Exception { - - when(_securityManager.authoriseConfiguringBroker(any(String.class), (Class<? extends ConfiguredObject>)any(), any(Operation.class))).thenReturn(true); - Map<String,Object> attributes = new HashMap<>(); attributes.put(FileKeyStore.NAME, "myFileKeyStore"); attributes.put(FileKeyStore.STORE_URL, TestSSLConstants.BROKER_KEYSTORE); @@ -293,10 +288,6 @@ public class FileKeyStoreTest extends QpidTestCase public void testDeleteKeyStore_KeyManagerInUseByPort() throws Exception { - when(_securityManager.authoriseConfiguringBroker(any(String.class), - any(Class.class), - any(Operation.class))).thenReturn(true); - Map<String,Object> attributes = new HashMap<>(); attributes.put(FileKeyStore.NAME, "myFileKeyStore"); attributes.put(FileKeyStore.STORE_URL, TestSSLConstants.BROKER_KEYSTORE); diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/security/FileTrustStoreTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/security/FileTrustStoreTest.java index 72c8926f85..8e7f004923 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/security/FileTrustStoreTest.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/security/FileTrustStoreTest.java @@ -53,7 +53,7 @@ import org.apache.qpid.util.FileUtils; public class FileTrustStoreTest extends QpidTestCase { - private final Broker<?> _broker = mock(Broker.class); + private final Broker _broker = mock(Broker.class); private final TaskExecutor _taskExecutor = CurrentThreadTaskExecutor.newStartedInstance(); private final SecurityManager _securityManager = mock(SecurityManager.class); private final Model _model = BrokerModel.getInstance(); @@ -66,7 +66,7 @@ public class FileTrustStoreTest extends QpidTestCase when(_broker.getTaskExecutor()).thenReturn(_taskExecutor); when(_broker.getModel()).thenReturn(_model); when(_broker.getSecurityManager()).thenReturn(_securityManager); - + when(_broker.getCategoryClass()).thenReturn(Broker.class); } public void testCreateTrustStoreFromFile_Success() throws Exception @@ -186,9 +186,6 @@ public class FileTrustStoreTest extends QpidTestCase public void testUpdateTrustStore_Success() throws Exception { - - when(_securityManager.authoriseConfiguringBroker(any(String.class), (Class<? extends ConfiguredObject>)any(), any(Operation.class))).thenReturn(true); - Map<String,Object> attributes = new HashMap<>(); attributes.put(FileTrustStore.NAME, "myFileTrustStore"); attributes.put(FileTrustStore.STORE_URL, TestSSLConstants.TRUSTSTORE); @@ -228,9 +225,6 @@ public class FileTrustStoreTest extends QpidTestCase public void testDeleteTrustStore_Success() throws Exception { - - when(_securityManager.authoriseConfiguringBroker(any(String.class), (Class<? extends ConfiguredObject>)any(), any(Operation.class))).thenReturn(true); - Map<String,Object> attributes = new HashMap<>(); attributes.put(FileTrustStore.NAME, "myFileTrustStore"); attributes.put(FileTrustStore.STORE_URL, TestSSLConstants.TRUSTSTORE); @@ -244,10 +238,6 @@ public class FileTrustStoreTest extends QpidTestCase public void testDeleteTrustStore_TrustManagerInUseByAuthProvider() throws Exception { - when(_securityManager.authoriseConfiguringBroker(any(String.class), - any(Class.class), - any(Operation.class))).thenReturn(true); - Map<String,Object> attributes = new HashMap<>(); attributes.put(FileTrustStore.NAME, "myFileTrustStore"); attributes.put(FileTrustStore.STORE_URL, TestSSLConstants.TRUSTSTORE); @@ -275,10 +265,6 @@ public class FileTrustStoreTest extends QpidTestCase public void testDeleteTrustStore_TrustManagerInUseByPort() throws Exception { - when(_securityManager.authoriseConfiguringBroker(any(String.class), - any(Class.class), - any(Operation.class))).thenReturn(true); - Map<String,Object> attributes = new HashMap<>(); attributes.put(FileTrustStore.NAME, "myFileTrustStore"); attributes.put(FileTrustStore.STORE_URL, TestSSLConstants.TRUSTSTORE); 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 index 54bd69120b..4b63577376 100644 --- 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 @@ -32,16 +32,31 @@ import static org.mockito.Mockito.when; import java.security.AccessControlException; import java.util.Collections; -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.AuthenticationProvider; +import org.apache.qpid.server.model.Binding; import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.BrokerModel; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.Consumer; +import org.apache.qpid.server.model.Exchange; +import org.apache.qpid.server.model.ExclusivityPolicy; +import org.apache.qpid.server.model.Group; +import org.apache.qpid.server.model.GroupMember; +import org.apache.qpid.server.model.GroupProvider; +import org.apache.qpid.server.model.KeyStore; import org.apache.qpid.server.model.LifetimePolicy; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Queue; +import org.apache.qpid.server.model.Session; import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.TrustStore; +import org.apache.qpid.server.model.User; import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.model.VirtualHostNode; import org.apache.qpid.server.protocol.AMQConnectionModel; import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.queue.QueueConsumer; 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; @@ -59,6 +74,8 @@ public class SecurityManagerTest extends QpidTestCase private AccessControl _accessControl; private SecurityManager _securityManager; private VirtualHost<?,?,?> _virtualHost; + private Broker _broker; + private VirtualHostNode<?> _virtualHostNode; @Override public void setUp() throws Exception @@ -72,28 +89,38 @@ public class SecurityManagerTest extends QpidTestCase when(aclProvider.getState()).thenReturn(State.ACTIVE); when(_virtualHost.getName()).thenReturn(TEST_VIRTUAL_HOST); - - Broker broker = mock(Broker.class); - when(broker.getAccessControlProviders()).thenReturn(Collections.singleton(aclProvider)); - _securityManager = new SecurityManager(broker, false); + when(_virtualHost.getAttribute(VirtualHost.NAME)).thenReturn(TEST_VIRTUAL_HOST); + + _broker = mock(Broker.class); + when(_broker.getAccessControlProviders()).thenReturn(Collections.singleton(aclProvider)); + when(_broker.getChildren(AccessControlProvider.class)).thenReturn(Collections.singleton(aclProvider)); + when(_broker.getCategoryClass()).thenReturn(Broker.class); + when(_broker.getName()).thenReturn("My Broker"); + when(_broker.getAttribute(Broker.NAME)).thenReturn("My Broker"); + when(_broker.getModel()).thenReturn(BrokerModel.getInstance()); + + _virtualHostNode = getMockVirtualHostNode(); + _securityManager = new SecurityManager(_broker, false); } public void testAuthoriseCreateBinding() { - ExchangeImpl exchange = mock(ExchangeImpl.class); + VirtualHost vh = getMockVirtualHost(); + + Exchange exchange = mock(Exchange.class); when(exchange.getParent(VirtualHost.class)).thenReturn(_virtualHost); - when(exchange.getName()).thenReturn(TEST_EXCHANGE); + when(exchange.getAttribute(Exchange.NAME)).thenReturn(TEST_EXCHANGE); + when(exchange.getCategoryClass()).thenReturn(Exchange.class); + when(exchange.getParent(VirtualHost.class)).thenReturn(vh); + when(exchange.getModel()).thenReturn(BrokerModel.getInstance()); - AMQQueue<?> queue = mock(AMQQueue.class); + Queue queue = mock(Queue.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"); + when(queue.getAttribute(Queue.NAME)).thenReturn(TEST_QUEUE); + when(queue.getAttribute(Queue.DURABLE)).thenReturn(true); + when(queue.getAttribute(Queue.LIFETIME_POLICY)).thenReturn(LifetimePolicy.PERMANENT); + when(queue.getCategoryClass()).thenReturn(Queue.class); + when(queue.getParent(VirtualHost.class)).thenReturn(vh); ObjectProperties properties = new ObjectProperties(); properties.put(Property.NAME, TEST_EXCHANGE); @@ -103,22 +130,13 @@ public class SecurityManagerTest extends QpidTestCase properties.put(Property.TEMPORARY, false); properties.put(Property.DURABLE, true); + Binding binding = mock(Binding.class); + when(binding.getParent(Exchange.class)).thenReturn(exchange); + when(binding.getParent(Queue.class)).thenReturn(queue); + when(binding.getAttribute(Binding.NAME)).thenReturn("bindingKey"); + when(binding.getCategoryClass()).thenReturn(Binding.class); - 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)); + assertCreateAuthorization(binding, Operation.BIND, ObjectType.EXCHANGE, properties, exchange, queue); } @@ -192,14 +210,23 @@ public class SecurityManagerTest extends QpidTestCase public void testAuthoriseCreateConsumer() { - AMQQueue<?> queue = mock(AMQQueue.class); + Queue queue = mock(Queue.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); + when(queue.getAttribute(Queue.NAME)).thenReturn(TEST_QUEUE); + when(queue.getAttribute(Queue.DURABLE)).thenReturn(true); + when(queue.getAttribute(Queue.LIFETIME_POLICY)).thenReturn(LifetimePolicy.PERMANENT); + when(queue.getAttribute(Queue.EXCLUSIVE)).thenReturn(ExclusivityPolicy.NONE); + when(queue.getCategoryClass()).thenReturn(Queue.class); + + Session session = mock(Session.class); + when(session.getCategoryClass()).thenReturn(Session.class); + when(session.getAttribute(Session.NAME)).thenReturn("1"); + + QueueConsumer consumer = mock(QueueConsumer.class); + when(consumer.getAttribute(QueueConsumer.NAME)).thenReturn("1"); + when(consumer.getParent(Queue.class)).thenReturn(queue); + when(consumer.getParent(Session.class)).thenReturn(session); + when(consumer.getCategoryClass()).thenReturn(Consumer.class); ObjectProperties properties = new ObjectProperties(); properties.put(Property.NAME, TEST_QUEUE); @@ -209,284 +236,573 @@ public class SecurityManagerTest extends QpidTestCase properties.put(Property.DURABLE, true); properties.put(Property.EXCLUSIVE, false); + assertAuthorization(Operation.CREATE, consumer, Operation.CONSUME, ObjectType.QUEUE, properties, queue, session); + } + + public void testAuthoriseUserOperation() + { + ObjectProperties properties = new ObjectProperties("testUser"); + configureAccessPlugin(Result.ALLOWED); - _securityManager.authoriseCreateConsumer(consumer); - verify(_accessControl).authorise(eq(Operation.CONSUME), eq(ObjectType.QUEUE), eq(properties)); + _securityManager.authoriseUserUpdate("testUser"); + verify(_accessControl).authorise(eq(Operation.UPDATE), eq(ObjectType.USER), 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)); + configureAccessPlugin(Result.DENIED); + try + { + _securityManager.authoriseUserUpdate("testUser"); + fail("AccessControlException is expected"); + } + catch(AccessControlException e) + { + // pass + } + verify(_accessControl, times(2)).authorise(eq(Operation.UPDATE), eq(ObjectType.USER), 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.getType()).thenReturn(TEST_EXCHANGE_TYPE); + VirtualHost vh = getMockVirtualHost(); + ObjectProperties expectedProperties = createExpectedExchangeObjectProperties(); + + Exchange exchange = mock(Exchange.class); + when(exchange.getAttribute(ConfiguredObject.NAME)).thenReturn(TEST_EXCHANGE); + when(exchange.getAttribute(ConfiguredObject.LIFETIME_POLICY)).thenReturn(LifetimePolicy.DELETE_ON_CONNECTION_CLOSE); + when(exchange.getAttribute(Exchange.DURABLE)).thenReturn(false); + when(exchange.getAttribute(Exchange.TYPE)).thenReturn(TEST_EXCHANGE_TYPE); + when(exchange.getCategoryClass()).thenReturn(Exchange.class); + when(exchange.getParent(VirtualHost.class)).thenReturn(vh); + + assertCreateAuthorization( exchange, Operation.CREATE, ObjectType.EXCHANGE, expectedProperties, vh); + } - ObjectProperties properties = createExpectedExchangeObjectProperties(); + public void testAuthoriseCreateQueue() + { + VirtualHost vh = getMockVirtualHost(); + ObjectProperties expectedProperties = createExpectedQueueObjectProperties(); + + Queue queue = mock(Queue.class); + when(queue.getAttribute(ConfiguredObject.NAME)).thenReturn(TEST_QUEUE); + when(queue.getAttribute(ConfiguredObject.LIFETIME_POLICY)).thenReturn(LifetimePolicy.DELETE_ON_CONNECTION_CLOSE); + when(queue.getAttribute(Queue.OWNER)).thenReturn(null); + when(queue.getAttribute(Queue.EXCLUSIVE)).thenReturn(ExclusivityPolicy.NONE); + when(queue.getAttribute(Queue.DURABLE)).thenReturn(false); + when(queue.getAttribute(Queue.ALTERNATE_EXCHANGE)).thenReturn(null); + when(queue.getCategoryClass()).thenReturn(Queue.class); + when(queue.getParent(VirtualHost.class)).thenReturn(vh); + + assertCreateAuthorization(queue, Operation.CREATE, ObjectType.QUEUE, expectedProperties, vh); + } - configureAccessPlugin(Result.ALLOWED); - _securityManager.authoriseCreateExchange(exchange); - verify(_accessControl).authorise(eq(Operation.CREATE), eq(ObjectType.EXCHANGE), eq(properties)); + public void testAuthoriseDeleteQueue() + { + VirtualHost vh = getMockVirtualHost(); + ObjectProperties expectedProperties = createExpectedQueueObjectProperties(); + + Queue queueObject = mock(Queue.class); + when(queueObject.getAttribute(Queue.NAME)).thenReturn(TEST_QUEUE); + when(queueObject.getAttribute(ConfiguredObject.LIFETIME_POLICY)).thenReturn(LifetimePolicy.DELETE_ON_CONNECTION_CLOSE); + when(queueObject.getAttribute(Queue.OWNER)).thenReturn(null); + when(queueObject.getAttribute(Queue.EXCLUSIVE)).thenReturn(ExclusivityPolicy.NONE); + when(queueObject.getAttribute(Queue.DURABLE)).thenReturn(false); + when(queueObject.getParent(VirtualHost.class)).thenReturn(vh); + when(queueObject.getCategoryClass()).thenReturn(Queue.class); + + assertDeleteAuthorization(queueObject, Operation.DELETE, ObjectType.QUEUE, expectedProperties, vh); + } - 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 testAuthoriseUpdateQueue() + { + VirtualHost vh = getMockVirtualHost(); + ObjectProperties expectedProperties = createExpectedQueueObjectProperties(); + + Queue queueObject = mock(Queue.class); + when(queueObject.getAttribute(Queue.NAME)).thenReturn(TEST_QUEUE); + when(queueObject.getAttribute(ConfiguredObject.LIFETIME_POLICY)).thenReturn(LifetimePolicy.DELETE_ON_CONNECTION_CLOSE); + when(queueObject.getAttribute(Queue.OWNER)).thenReturn(null); + when(queueObject.getAttribute(Queue.EXCLUSIVE)).thenReturn(ExclusivityPolicy.NONE); + when(queueObject.getAttribute(Queue.DURABLE)).thenReturn(false); + when(queueObject.getParent(VirtualHost.class)).thenReturn(vh); + when(queueObject.getCategoryClass()).thenReturn(Queue.class); + + assertUpdateAuthorization(queueObject, Operation.UPDATE, ObjectType.QUEUE, expectedProperties, vh); } - public void testAuthoriseCreateQueue() + public void testAuthoriseUpdateExchange() { - AMQQueue<?> queue = mock(AMQQueue.class); - when(queue.getParent(VirtualHost.class)).thenReturn(_virtualHost); - when(queue.getName()).thenReturn(TEST_QUEUE); + VirtualHost vh = getMockVirtualHost(); + ObjectProperties expectedProperties = createExpectedExchangeObjectProperties(); + + Exchange exchange = mock(Exchange.class); + when(exchange.getAttribute(Exchange.NAME)).thenReturn(TEST_EXCHANGE); + when(exchange.getAttribute(Exchange.LIFETIME_POLICY)).thenReturn(LifetimePolicy.DELETE_ON_CONNECTION_CLOSE); + when(exchange.getAttribute(Exchange.DURABLE)).thenReturn(false); + when(exchange.getAttribute(Exchange.TYPE)).thenReturn(TEST_EXCHANGE_TYPE); + when(exchange.getParent(VirtualHost.class)).thenReturn(vh); + when(exchange.getCategoryClass()).thenReturn(Exchange.class); + + assertUpdateAuthorization(exchange, Operation.UPDATE, ObjectType.EXCHANGE, expectedProperties, vh); + } - ObjectProperties properties = createExpectedQueueObjectProperties(); + public void testAuthoriseDeleteExchange() + { + VirtualHost vh = getMockVirtualHost(); + ObjectProperties expectedProperties = createExpectedExchangeObjectProperties(); + + Exchange exchange = mock(Exchange.class); + when(exchange.getAttribute(Exchange.NAME)).thenReturn(TEST_EXCHANGE); + when(exchange.getAttribute(Exchange.LIFETIME_POLICY)).thenReturn(LifetimePolicy.DELETE_ON_CONNECTION_CLOSE); + when(exchange.getAttribute(Exchange.DURABLE)).thenReturn(false); + when(exchange.getAttribute(Exchange.TYPE)).thenReturn(TEST_EXCHANGE_TYPE); + when(exchange.getParent(VirtualHost.class)).thenReturn(vh); + when(exchange.getCategoryClass()).thenReturn(Exchange.class); + + assertDeleteAuthorization(exchange, Operation.DELETE, ObjectType.EXCHANGE, expectedProperties, vh); + } + + 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.authoriseCreateQueue(queue); - verify(_accessControl).authorise(eq(Operation.CREATE), eq(ObjectType.QUEUE), eq(properties)); + _securityManager.authorisePublish(immediate, routingKey, exchangeName, TEST_VIRTUAL_HOST); + verify(_accessControl).authorise(eq(Operation.PUBLISH), eq(ObjectType.EXCHANGE), eq(properties)); configureAccessPlugin(Result.DENIED); try { - _securityManager.authoriseCreateQueue(queue); + _securityManager.authorisePublish(immediate, routingKey, exchangeName, TEST_VIRTUAL_HOST); fail("AccessControlException is expected"); } catch(AccessControlException e) { // pass } - verify(_accessControl, times(2)).authorise(eq(Operation.CREATE), eq(ObjectType.QUEUE), eq(properties)); + verify(_accessControl, times(2)).authorise(eq(Operation.PUBLISH), eq(ObjectType.EXCHANGE), eq(properties)); } - public void testAuthoriseDeleteQueue() + public void testAuthorisePurge() { - AMQQueue<?> queue = mock(AMQQueue.class); + Queue queue = mock(Queue.class); when(queue.getParent(VirtualHost.class)).thenReturn(_virtualHost); - when(queue.getName()).thenReturn(TEST_QUEUE); + when(queue.getAttribute(Queue.NAME)).thenReturn(TEST_QUEUE); + when(queue.getCategoryClass()).thenReturn(Queue.class); + when(queue.getAttribute(Queue.DURABLE)).thenReturn(false); + when(queue.getAttribute(Queue.EXCLUSIVE)).thenReturn(ExclusivityPolicy.NONE); + when(queue.getAttribute(Queue.LIFETIME_POLICY)).thenReturn(LifetimePolicy.DELETE_ON_CONNECTION_CLOSE); ObjectProperties properties = createExpectedQueueObjectProperties(); configureAccessPlugin(Result.ALLOWED); - _securityManager.authoriseDelete(queue); - verify(_accessControl).authorise(eq(Operation.DELETE), eq(ObjectType.QUEUE), eq(properties)); + _securityManager.authorisePurge(queue); + verify(_accessControl).authorise(eq(Operation.PURGE), eq(ObjectType.QUEUE), eq(properties)); configureAccessPlugin(Result.DENIED); try { - _securityManager.authoriseDelete(queue); + _securityManager.authorisePurge(queue); fail("AccessControlException is expected"); } catch(AccessControlException e) { // pass } - verify(_accessControl, times(2)).authorise(eq(Operation.DELETE), eq(ObjectType.QUEUE), eq(properties)); + verify(_accessControl, times(2)).authorise(eq(Operation.PURGE), eq(ObjectType.QUEUE), eq(properties)); } - public void testAuthoriseUpdateQueue() + public void testAuthoriseUnbind() { - AMQQueue<?> queue = mock(AMQQueue.class); + Exchange exchange = mock(Exchange.class); + when(exchange.getParent(VirtualHost.class)).thenReturn(_virtualHost); + when(exchange.getAttribute(Exchange.NAME)).thenReturn(TEST_EXCHANGE); + when(exchange.getCategoryClass()).thenReturn(Exchange.class); + + Queue queue = mock(Queue.class); when(queue.getParent(VirtualHost.class)).thenReturn(_virtualHost); - when(queue.getName()).thenReturn(TEST_QUEUE); + when(queue.getAttribute(Queue.NAME)).thenReturn(TEST_QUEUE); + when(queue.getAttribute(Queue.DURABLE)).thenReturn(true); + when(queue.getAttribute(Queue.LIFETIME_POLICY)).thenReturn(LifetimePolicy.PERMANENT); + when(queue.getCategoryClass()).thenReturn(Queue.class); - ObjectProperties properties = createExpectedQueueObjectProperties(); + Binding binding = mock(Binding.class); + when(binding.getParent(Exchange.class)).thenReturn(exchange); + when(binding.getParent(Queue.class)).thenReturn(queue); + when(binding.getAttribute(Binding.NAME)).thenReturn("bindingKey"); + when(binding.getCategoryClass()).thenReturn(Binding.class); - configureAccessPlugin(Result.ALLOWED); - _securityManager.authoriseUpdate(queue); - verify(_accessControl).authorise(eq(Operation.UPDATE), eq(ObjectType.QUEUE), eq(properties)); + 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.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)); + assertDeleteAuthorization(binding, Operation.UNBIND, ObjectType.EXCHANGE, properties, exchange, queue); } - public void testAuthoriseUpdateExchange() + public void testAuthoriseCreateVirtualHostNode() { - ExchangeImpl<?> exchange = mock(ExchangeImpl.class); - when(exchange.getParent(VirtualHost.class)).thenReturn(_virtualHost); - when(exchange.getName()).thenReturn(TEST_EXCHANGE); - when(exchange.getType()).thenReturn(TEST_EXCHANGE_TYPE); + VirtualHostNode vhn = getMockVirtualHostNode(); + assertCreateAuthorization(vhn, Operation.CREATE, ObjectType.VIRTUALHOSTNODE, new ObjectProperties("testVHN"), _broker); + } - ObjectProperties properties = createExpectedExchangeObjectProperties(); + public void testAuthoriseCreatePort() + { + Port port = mock(Port.class); + when(port.getParent(Broker.class)).thenReturn(_broker); + when(port.getAttribute(ConfiguredObject.NAME)).thenReturn("TEST"); + when(port.getCategoryClass()).thenReturn(Port.class); - configureAccessPlugin(Result.ALLOWED); - _securityManager.authoriseUpdate(exchange); - verify(_accessControl).authorise(eq(Operation.UPDATE), eq(ObjectType.EXCHANGE), eq(properties)); + assertBrokerChildCreateAuthorization(port); + } - 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 testAuthoriseCreateAuthenticationProvider() + { + AuthenticationProvider authenticationProvider = mock(AuthenticationProvider.class); + when(authenticationProvider.getParent(Broker.class)).thenReturn(_broker); + when(authenticationProvider.getAttribute(ConfiguredObject.NAME)).thenReturn("TEST"); + when(authenticationProvider.getCategoryClass()).thenReturn(AuthenticationProvider.class); + + assertBrokerChildCreateAuthorization(authenticationProvider); } - public void testAuthoriseDeleteExchange() + public void testAuthoriseCreateGroupProvider() { - ExchangeImpl<?> exchange = mock(ExchangeImpl.class); - when(exchange.getParent(VirtualHost.class)).thenReturn(_virtualHost); - when(exchange.getName()).thenReturn(TEST_EXCHANGE); - when(exchange.getType()).thenReturn(TEST_EXCHANGE_TYPE); + GroupProvider groupProvider = mock(GroupProvider.class); + when(groupProvider.getParent(Broker.class)).thenReturn(_broker); + when(groupProvider.getAttribute(ConfiguredObject.NAME)).thenReturn("TEST"); + when(groupProvider.getCategoryClass()).thenReturn(GroupProvider.class); - ObjectProperties properties = createExpectedExchangeObjectProperties(); + assertBrokerChildCreateAuthorization(groupProvider); + } - configureAccessPlugin(Result.ALLOWED); - _securityManager.authoriseDelete(exchange); - verify(_accessControl).authorise(eq(Operation.DELETE), eq(ObjectType.EXCHANGE), eq(properties)); + public void testAuthoriseCreateAccessControlProvider() + { + AccessControlProvider accessControlProvider = mock(AccessControlProvider.class); + when(accessControlProvider.getParent(Broker.class)).thenReturn(_broker); + when(accessControlProvider.getAttribute(ConfiguredObject.NAME)).thenReturn("TEST"); + when(accessControlProvider.getCategoryClass()).thenReturn(AccessControlProvider.class); - 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)); + assertBrokerChildCreateAuthorization(accessControlProvider); } - public void testAuthoriseGroupOperation() + public void testAuthoriseCreateKeyStore() { - ObjectProperties properties = new ObjectProperties("testGroup"); + KeyStore keyStore = mock(KeyStore.class); + when(keyStore.getParent(Broker.class)).thenReturn(_broker); + when(keyStore.getAttribute(ConfiguredObject.NAME)).thenReturn("TEST"); + when(keyStore.getCategoryClass()).thenReturn(KeyStore.class); - configureAccessPlugin(Result.ALLOWED); - _securityManager.authoriseGroupOperation(Operation.CREATE, "testGroup"); - verify(_accessControl).authorise(eq(Operation.CREATE), eq(ObjectType.GROUP), eq(properties)); + assertBrokerChildCreateAuthorization(keyStore); + } - 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 testAuthoriseCreateTrustStore() + { + TrustStore trustStore = mock(TrustStore.class); + when(trustStore.getParent(Broker.class)).thenReturn(_broker); + when(trustStore.getAttribute(ConfiguredObject.NAME)).thenReturn("TEST"); + when(trustStore.getCategoryClass()).thenReturn(TrustStore.class); + + assertBrokerChildCreateAuthorization(trustStore); } - public void testAuthoriseUserOperation() + public void testAuthoriseCreateGroup() { - ObjectProperties properties = new ObjectProperties("testUser"); + GroupProvider groupProvider = mock(GroupProvider.class); + when(groupProvider.getCategoryClass()).thenReturn(GroupProvider.class); + when(groupProvider.getAttribute(GroupProvider.NAME)).thenReturn("testGroupProvider"); + when(groupProvider.getModel()).thenReturn(BrokerModel.getInstance()); - configureAccessPlugin(Result.ALLOWED); - _securityManager.authoriseUserOperation(Operation.CREATE, "testUser"); - verify(_accessControl).authorise(eq(Operation.CREATE), eq(ObjectType.USER), eq(properties)); + Group group = mock(Group.class); + when(group.getCategoryClass()).thenReturn(Group.class); + when(group.getParent(GroupProvider.class)).thenReturn(groupProvider); + when(group.getAttribute(Group.NAME)).thenReturn("test"); - 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)); + assertCreateAuthorization(group, Operation.CREATE, ObjectType.GROUP, new ObjectProperties("test"), groupProvider); } - public void testAuthorisePublish() + public void testAuthoriseCreateGroupMember() { - String routingKey = "routingKey"; - String exchangeName = "exchangeName"; - boolean immediate = true; - ObjectProperties properties = new ObjectProperties(TEST_VIRTUAL_HOST, exchangeName, routingKey, immediate); + Group group = mock(Group.class); + when(group.getCategoryClass()).thenReturn(Group.class); + when(group.getAttribute(Group.NAME)).thenReturn("testGroup"); + when(group.getModel()).thenReturn(BrokerModel.getInstance()); - configureAccessPlugin(Result.ALLOWED); - _securityManager.authorisePublish(immediate, routingKey, exchangeName, TEST_VIRTUAL_HOST); - verify(_accessControl).authorise(eq(Operation.PUBLISH), eq(ObjectType.EXCHANGE), eq(properties)); + GroupMember groupMember = mock(GroupMember.class); + when(groupMember.getCategoryClass()).thenReturn(GroupMember.class); + when(groupMember.getParent(Group.class)).thenReturn(group); + when(groupMember.getAttribute(Group.NAME)).thenReturn("test"); - 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)); + assertCreateAuthorization(groupMember, Operation.UPDATE, ObjectType.GROUP, new ObjectProperties("test"), group); } - public void testAuthorisePurge() + public void testAuthoriseCreateUser() { - AMQQueue<?> queue = mock(AMQQueue.class); - when(queue.getParent(VirtualHost.class)).thenReturn(_virtualHost); - when(queue.getName()).thenReturn(TEST_QUEUE); + AuthenticationProvider authenticationProvider = mock(AuthenticationProvider.class); + when(authenticationProvider.getCategoryClass()).thenReturn(AuthenticationProvider.class); + when(authenticationProvider.getAttribute(AuthenticationProvider.NAME)).thenReturn("testAuthenticationProvider"); + when(authenticationProvider.getModel()).thenReturn(BrokerModel.getInstance()); + + User user = mock(User.class); + when(user.getCategoryClass()).thenReturn(User.class); + when(user.getAttribute(User.NAME)).thenReturn("test"); + when(user.getParent(AuthenticationProvider.class)).thenReturn(authenticationProvider); + when(user.getModel()).thenReturn(BrokerModel.getInstance()); + + assertCreateAuthorization(user, Operation.CREATE, ObjectType.USER, new ObjectProperties("test"), authenticationProvider); + } - ObjectProperties properties = createExpectedQueueObjectProperties(); + public void testAuthoriseCreateVirtualHost() + { + VirtualHost vh = getMockVirtualHost(); + assertCreateAuthorization(vh, Operation.CREATE, ObjectType.VIRTUALHOST, new ObjectProperties(TEST_VIRTUAL_HOST), _virtualHostNode); + } - configureAccessPlugin(Result.ALLOWED); - _securityManager.authorisePurge(queue); - verify(_accessControl).authorise(eq(Operation.PURGE), eq(ObjectType.QUEUE), eq(properties)); + public void testAuthoriseUpdateVirtualHostNode() + { + VirtualHostNode vhn = getMockVirtualHostNode(); + assertUpdateAuthorization(vhn, Operation.UPDATE, ObjectType.VIRTUALHOSTNODE, new ObjectProperties(vhn.getName()), vhn); + } - 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 testAuthoriseUpdatePort() + { + Port mock = mock(Port.class); + when(mock.getAttribute(ConfiguredObject.NAME)).thenReturn("test"); + when(mock.getCategoryClass()).thenReturn(Port.class); + when(mock.getParent(Broker.class)).thenReturn(_broker); + assertBrokerChildUpdateAuthorization(mock); } + public void testAuthoriseUpdateAuthenticationProvider() + { + AuthenticationProvider mock = mock(AuthenticationProvider.class); + when(mock.getAttribute(ConfiguredObject.NAME)).thenReturn("test"); + when(mock.getCategoryClass()).thenReturn(AuthenticationProvider.class); + when(mock.getParent(Broker.class)).thenReturn(_broker); + assertBrokerChildUpdateAuthorization(mock); + } - public void testAuthoriseUnbind() + public void testAuthoriseUpdateGroupProvider() + { + GroupProvider mock = mock(GroupProvider.class); + when(mock.getAttribute(ConfiguredObject.NAME)).thenReturn("test"); + when(mock.getCategoryClass()).thenReturn(GroupProvider.class); + when(mock.getParent(Broker.class)).thenReturn(_broker); + assertBrokerChildUpdateAuthorization(mock); + } + + public void testAuthoriseUpdateAccessControlProvider() + { + AccessControlProvider mock = mock(AccessControlProvider.class); + when(mock.getAttribute(ConfiguredObject.NAME)).thenReturn("test"); + when(mock.getCategoryClass()).thenReturn(AccessControlProvider.class); + when(mock.getParent(Broker.class)).thenReturn(_broker); + assertBrokerChildUpdateAuthorization(mock); + } + + public void testAuthoriseUpdateKeyStore() + { + KeyStore mock = mock(KeyStore.class); + when(mock.getAttribute(ConfiguredObject.NAME)).thenReturn("test"); + when(mock.getCategoryClass()).thenReturn(KeyStore.class); + when(mock.getParent(Broker.class)).thenReturn(_broker); + assertBrokerChildUpdateAuthorization(mock); + } + + public void testAuthoriseUpdateTrustStore() { - ExchangeImpl exchange = mock(ExchangeImpl.class); + TrustStore mock = mock(TrustStore.class); + when(mock.getAttribute(ConfiguredObject.NAME)).thenReturn("test"); + when(mock.getCategoryClass()).thenReturn(TrustStore.class); + when(mock.getParent(Broker.class)).thenReturn(_broker); + assertBrokerChildUpdateAuthorization(mock); + } + + public void testAuthoriseUpdateGroup() + { + GroupProvider groupProvider = mock(GroupProvider.class); + when(groupProvider.getCategoryClass()).thenReturn(GroupProvider.class); + when(groupProvider.getName()).thenReturn("testGroupProvider"); + Group mock = mock(Group.class); + when(mock.getAttribute(ConfiguredObject.NAME)).thenReturn("test"); + when(mock.getCategoryClass()).thenReturn(Group.class); + when(mock.getParent(GroupProvider.class)).thenReturn(groupProvider); + ObjectProperties properties = new ObjectProperties((String)mock.getAttribute(ConfiguredObject.NAME)); + assertUpdateAuthorization(mock, Operation.UPDATE, ObjectType.GROUP, properties, groupProvider); + } + + public void testAuthoriseUpdateGroupMember() + { + Group group = mock(Group.class); + when(group.getCategoryClass()).thenReturn(Group.class); + when(group.getName()).thenReturn("testGroup"); + GroupMember mock = mock(GroupMember.class); + when(mock.getAttribute(ConfiguredObject.NAME)).thenReturn("test"); + when(mock.getCategoryClass()).thenReturn(GroupMember.class); + when(mock.getParent(Group.class)).thenReturn(group); + ObjectProperties properties = new ObjectProperties((String)mock.getAttribute(ConfiguredObject.NAME)); + assertUpdateAuthorization(mock, Operation.UPDATE, ObjectType.GROUP, properties, group); + } + + public void testAuthoriseUpdateUser() + { + AuthenticationProvider authenticationProvider = mock(AuthenticationProvider.class); + when(authenticationProvider.getCategoryClass()).thenReturn(AuthenticationProvider.class); + when(authenticationProvider.getName()).thenReturn("testAuthenticationProvider"); + User mock = mock(User.class); + when(mock.getAttribute(ConfiguredObject.NAME)).thenReturn("test"); + when(mock.getCategoryClass()).thenReturn(User.class); + when(mock.getParent(AuthenticationProvider.class)).thenReturn(authenticationProvider); + ObjectProperties properties = new ObjectProperties((String)mock.getAttribute(ConfiguredObject.NAME)); + assertUpdateAuthorization(mock, Operation.UPDATE, ObjectType.USER, properties, authenticationProvider); + } + + public void testAuthoriseUpdateVirtualHost() + { + VirtualHostNode vhn = getMockVirtualHostNode(); + + VirtualHost mock = mock(VirtualHost.class); + when(mock.getAttribute(ConfiguredObject.NAME)).thenReturn("test"); + when(mock.getCategoryClass()).thenReturn(VirtualHost.class); + when(mock.getParent(VirtualHostNode.class)).thenReturn(vhn); + ObjectProperties properties = new ObjectProperties((String)mock.getAttribute(ConfiguredObject.NAME)); + assertUpdateAuthorization(mock, Operation.UPDATE, ObjectType.VIRTUALHOST, properties, vhn); + } + + public void testAuthoriseDeleteVirtualHostNode() + { + VirtualHostNode vhn = getMockVirtualHostNode(); + assertDeleteAuthorization(vhn, Operation.DELETE, ObjectType.VIRTUALHOSTNODE, new ObjectProperties(vhn.getName()), vhn); + } + + public void testAuthoriseDeletePort() + { + Port mock = mock(Port.class); + when(mock.getAttribute(ConfiguredObject.NAME)).thenReturn("test"); + when(mock.getCategoryClass()).thenReturn(Port.class); + when(mock.getParent(Broker.class)).thenReturn(_broker); + assertBrokerChildDeleteAuthorization(mock); + } + + public void testAuthoriseDeleteAuthenticationProvider() + { + AuthenticationProvider mock = mock(AuthenticationProvider.class); + when(mock.getAttribute(ConfiguredObject.NAME)).thenReturn("test"); + when(mock.getCategoryClass()).thenReturn(AuthenticationProvider.class); + when(mock.getParent(Broker.class)).thenReturn(_broker); + assertBrokerChildDeleteAuthorization(mock); + } + + public void testAuthoriseDeleteGroupProvider() + { + GroupProvider mock = mock(GroupProvider.class); + when(mock.getAttribute(ConfiguredObject.NAME)).thenReturn("test"); + when(mock.getCategoryClass()).thenReturn(GroupProvider.class); + when(mock.getParent(Broker.class)).thenReturn(_broker); + assertBrokerChildDeleteAuthorization(mock); + } + + public void testAuthoriseDeleteAccessControlProvider() + { + AccessControlProvider mock = mock(AccessControlProvider.class); + when(mock.getAttribute(ConfiguredObject.NAME)).thenReturn("test"); + when(mock.getCategoryClass()).thenReturn(AccessControlProvider.class); + when(mock.getParent(Broker.class)).thenReturn(_broker); + assertBrokerChildDeleteAuthorization(mock); + } + + public void testAuthoriseDeleteKeyStore() + { + KeyStore mock = mock(KeyStore.class); + when(mock.getAttribute(ConfiguredObject.NAME)).thenReturn("test"); + when(mock.getCategoryClass()).thenReturn(KeyStore.class); + when(mock.getParent(Broker.class)).thenReturn(_broker); + assertBrokerChildDeleteAuthorization(mock); + } + + public void testAuthoriseDeleteTrustStore() + { + TrustStore mock = mock(TrustStore.class); + when(mock.getAttribute(ConfiguredObject.NAME)).thenReturn("test"); + when(mock.getCategoryClass()).thenReturn(TrustStore.class); + when(mock.getParent(Broker.class)).thenReturn(_broker); + assertBrokerChildDeleteAuthorization(mock); + } + + public void testAuthoriseDeleteGroup() + { + GroupProvider groupProvider = mock(GroupProvider.class); + when(groupProvider.getCategoryClass()).thenReturn(GroupProvider.class); + when(groupProvider.getName()).thenReturn("testGroupProvider"); + Group mock = mock(Group.class); + when(mock.getAttribute(ConfiguredObject.NAME)).thenReturn("test"); + when(mock.getCategoryClass()).thenReturn(Group.class); + when(mock.getParent(GroupProvider.class)).thenReturn(groupProvider); + ObjectProperties properties = new ObjectProperties((String)mock.getAttribute(ConfiguredObject.NAME)); + assertDeleteAuthorization(mock, Operation.DELETE, ObjectType.GROUP, properties, groupProvider); + } + + public void testAuthoriseDeleteGroupMember() + { + Group group = mock(Group.class); + when(group.getCategoryClass()).thenReturn(Group.class); + when(group.getName()).thenReturn("testGroup"); + GroupMember mock = mock(GroupMember.class); + when(mock.getAttribute(ConfiguredObject.NAME)).thenReturn("test"); + when(mock.getCategoryClass()).thenReturn(GroupMember.class); + when(mock.getParent(Group.class)).thenReturn(group); + ObjectProperties properties = new ObjectProperties((String)mock.getAttribute(ConfiguredObject.NAME)); + assertDeleteAuthorization(mock, Operation.UPDATE, ObjectType.GROUP, properties, group); + } + + public void testAuthoriseDeleteUser() + { + AuthenticationProvider authenticationProvider = mock(AuthenticationProvider.class); + when(authenticationProvider.getCategoryClass()).thenReturn(AuthenticationProvider.class); + when(authenticationProvider.getName()).thenReturn("testAuthenticationProvider"); + User mock = mock(User.class); + when(mock.getAttribute(ConfiguredObject.NAME)).thenReturn("test"); + when(mock.getCategoryClass()).thenReturn(User.class); + when(mock.getParent(AuthenticationProvider.class)).thenReturn(authenticationProvider); + ObjectProperties properties = new ObjectProperties((String)mock.getAttribute(ConfiguredObject.NAME)); + assertDeleteAuthorization(mock, Operation.DELETE, ObjectType.USER, properties, authenticationProvider); + } + + public void testAuthoriseDeleteVirtualHost() + { + VirtualHostNode vhn = getMockVirtualHostNode(); + + VirtualHost mock = mock(VirtualHost.class); + when(mock.getAttribute(ConfiguredObject.NAME)).thenReturn("test"); + when(mock.getCategoryClass()).thenReturn(VirtualHost.class); + when(mock.getParent(VirtualHostNode.class)).thenReturn(vhn); + ObjectProperties properties = new ObjectProperties((String)mock.getAttribute(ConfiguredObject.NAME)); + assertDeleteAuthorization(mock, Operation.DELETE, ObjectType.VIRTUALHOST, properties, vhn); + } + + public void testAuthoriseDeleteBinding() + { + Exchange exchange = mock(Exchange.class); when(exchange.getParent(VirtualHost.class)).thenReturn(_virtualHost); - when(exchange.getName()).thenReturn(TEST_EXCHANGE); + when(exchange.getAttribute(Exchange.NAME)).thenReturn(TEST_EXCHANGE); + when(exchange.getCategoryClass()).thenReturn(Exchange.class); - AMQQueue<?> queue = mock(AMQQueue.class); + Queue queue = mock(Queue.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); + when(queue.getAttribute(Queue.NAME)).thenReturn(TEST_QUEUE); + when(queue.getAttribute(Queue.DURABLE)).thenReturn(true); + when(queue.getAttribute(Queue.LIFETIME_POLICY)).thenReturn(LifetimePolicy.PERMANENT); + when(queue.getCategoryClass()).thenReturn(Queue.class); - BindingImpl binding = mock(BindingImpl.class); - when(binding.getExchange()).thenReturn(exchange); - when(binding.getAMQQueue()).thenReturn(queue); - when(binding.getBindingKey()).thenReturn("bindingKey"); + Binding binding = mock(Binding.class); + when(binding.getParent(Exchange.class)).thenReturn(exchange); + when(binding.getParent(Queue.class)).thenReturn(queue); + when(binding.getAttribute(Binding.NAME)).thenReturn("bindingKey"); + when(binding.getCategoryClass()).thenReturn(Binding.class); ObjectProperties properties = new ObjectProperties(); properties.put(Property.NAME, TEST_EXCHANGE); @@ -496,35 +812,141 @@ public class SecurityManagerTest extends QpidTestCase properties.put(Property.TEMPORARY, false); properties.put(Property.DURABLE, true); + assertDeleteAuthorization(binding, Operation.UNBIND, ObjectType.EXCHANGE, properties, exchange, queue); + } + + private VirtualHost getMockVirtualHost() + { + VirtualHost vh = mock(VirtualHost.class); + when(vh.getCategoryClass()).thenReturn(VirtualHost.class); + when(vh.getName()).thenReturn(TEST_VIRTUAL_HOST); + when(vh.getAttribute(VirtualHost.NAME)).thenReturn(TEST_VIRTUAL_HOST); + when(vh.getParent(VirtualHostNode.class)).thenReturn(_virtualHostNode); + when(vh.getModel()).thenReturn(BrokerModel.getInstance()); + return vh; + } + + private VirtualHostNode getMockVirtualHostNode() + { + VirtualHostNode vhn = mock(VirtualHostNode.class); + when(vhn.getCategoryClass()).thenReturn(VirtualHostNode.class); + when(vhn.getName()).thenReturn("testVHN"); + when(vhn.getAttribute(ConfiguredObject.NAME)).thenReturn("testVHN"); + when(vhn.getParent(Broker.class)).thenReturn(_broker); + when(vhn.getModel()).thenReturn(BrokerModel.getInstance()); + return vhn; + } + + private void assertBrokerChildCreateAuthorization(ConfiguredObject object) + { + String description = String.format("%s %s '%s'", + Operation.CREATE.name().toLowerCase(), + object.getCategoryClass().getSimpleName().toLowerCase(), + "TEST"); + ObjectProperties properties = new OperationLoggingDetails(description); + assertCreateAuthorization(object, Operation.CONFIGURE, ObjectType.BROKER, properties, _broker ); + } + + private void assertBrokerChildUpdateAuthorization(ConfiguredObject configuredObject) + { + String description = String.format("%s %s '%s'", + Operation.UPDATE.name().toLowerCase(), + configuredObject.getCategoryClass().getSimpleName().toLowerCase(), + configuredObject.getAttribute(ConfiguredObject.NAME)); + ObjectProperties properties = new OperationLoggingDetails(description); + + assertUpdateAuthorization(configuredObject, Operation.CONFIGURE, ObjectType.BROKER, + properties, _broker ); + } + + private void assertBrokerChildDeleteAuthorization(ConfiguredObject configuredObject) + { + String description = String.format("%s %s '%s'", + Operation.DELETE.name().toLowerCase(), + configuredObject.getCategoryClass().getSimpleName().toLowerCase(), + configuredObject.getAttribute(ConfiguredObject.NAME)); + ObjectProperties properties = new OperationLoggingDetails(description); + + assertDeleteAuthorization(configuredObject, Operation.CONFIGURE, ObjectType.BROKER, + properties, _broker ); + } + private void assertAuthorization(Operation operation, ConfiguredObject<?> configuredObject, Operation aclOperation, ObjectType aclObjectType, ObjectProperties expectedProperties, ConfiguredObject... objects) + { configureAccessPlugin(Result.ALLOWED); - _securityManager.authoriseUnbind(binding); - verify(_accessControl).authorise(eq(Operation.UNBIND), eq(ObjectType.EXCHANGE), eq(properties)); + _securityManager.authorise(operation, configuredObject); + verify(_accessControl).authorise(eq(aclOperation), eq(aclObjectType), eq(expectedProperties)); configureAccessPlugin(Result.DENIED); try { - _securityManager.authoriseUnbind(binding); + _securityManager.authorise(operation, configuredObject); fail("AccessControlException is expected"); } catch(AccessControlException e) { - // pass + String expectedMessage = "Permission " + aclOperation.name() + " " + + aclObjectType.name() +" is denied for : " + operation.name() + " " + + configuredObject.getCategoryClass().getSimpleName() + " '" + + configuredObject.getAttribute(ConfiguredObject.NAME) + "' on"; + + assertTrue("Unexpected exception message: " + e.getMessage() + " vs " + expectedMessage, + e.getMessage().startsWith(expectedMessage)); + for (ConfiguredObject object: objects) + { + String parentInfo = object.getCategoryClass().getSimpleName() + " '" + + object.getAttribute(ConfiguredObject.NAME) + "'"; + assertTrue("Exception message does not contain information about parent object " + + object.getCategoryClass() + " " + object.getAttribute(ConfiguredObject.NAME) + ":" + + e.getMessage(), + e.getMessage().contains(parentInfo)); + } } - verify(_accessControl, times(2)).authorise(eq(Operation.UNBIND), eq(ObjectType.EXCHANGE), eq(properties)); + + verify(_accessControl, times(2)).authorise(eq(aclOperation), eq(aclObjectType), eq(expectedProperties)); } - public void testAuthoriseConfiguringBroker() + private void assertDeleteAuthorization(ConfiguredObject<?> configuredObject, Operation aclOperation, ObjectType aclObjectType, ObjectProperties expectedProperties, ConfiguredObject... objects) { - OperationLoggingDetails properties = new OperationLoggingDetails("create virtualhost 'test'"); + assertAuthorization(Operation.DELETE, configuredObject, aclOperation, aclObjectType, expectedProperties, objects); + } + private void assertUpdateAuthorization(ConfiguredObject<?> configuredObject, Operation aclOperation, ObjectType aclObjectType, ObjectProperties expectedProperties, ConfiguredObject... objects) + { + assertAuthorization(Operation.UPDATE, configuredObject, aclOperation, aclObjectType, expectedProperties, objects); + } + + private void assertCreateAuthorization(ConfiguredObject<?> configuredObject, Operation aclOperation, ObjectType aclObjectType, ObjectProperties expectedProperties, ConfiguredObject<?>... parents) + { configureAccessPlugin(Result.ALLOWED); - assertTrue(_securityManager.authoriseConfiguringBroker("test", VirtualHost.class, Operation.CREATE)); - verify(_accessControl).authorise(eq(Operation.CONFIGURE), eq(ObjectType.BROKER), eq(properties)); + _securityManager.authorise(Operation.CREATE, configuredObject); + verify(_accessControl).authorise(eq(aclOperation), eq(aclObjectType), eq(expectedProperties)); configureAccessPlugin(Result.DENIED); - assertFalse(_securityManager.authoriseConfiguringBroker("test", VirtualHost.class, Operation.CREATE)); - verify(_accessControl, times(2)).authorise(eq(Operation.CONFIGURE), eq(ObjectType.BROKER), eq(properties)); + try + { + _securityManager.authorise(Operation.CREATE, configuredObject); + fail("AccessControlException is expected"); + } + catch(AccessControlException e) + { + String expectedMessage = "Permission " + aclOperation.name() + " " + + aclObjectType.name() +" is denied for : CREATE " + configuredObject.getCategoryClass().getSimpleName() + " '" + + configuredObject.getAttribute(ConfiguredObject.NAME) + "' on"; + + assertTrue("Unexpected exception message", e.getMessage().startsWith(expectedMessage)); + for (ConfiguredObject object: parents) + { + String parentInfo = object.getCategoryClass().getSimpleName() + " '" + + object.getAttribute(ConfiguredObject.NAME) + "'"; + assertTrue("Exception message does not contain information about parent configuredObject " + + parentInfo + ": " + + e.getMessage(), + e.getMessage().contains(parentInfo)); + } + } + + verify(_accessControl, times(2)).authorise(eq(aclOperation), eq(aclObjectType), eq(expectedProperties)); } public void testAuthoriseLogsAccess() @@ -548,7 +970,7 @@ public class SecurityManagerTest extends QpidTestCase 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.AUTO_DELETE, true); properties.put(Property.TEMPORARY, true); properties.put(Property.DURABLE, false); properties.put(Property.TYPE, TEST_EXCHANGE_TYPE); diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java index 2f44218cf1..0f256d0999 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java @@ -196,7 +196,10 @@ public class BrokerTestHelper public static ExchangeImpl<?> createExchange(String hostName, final boolean durable, final EventLogger eventLogger) throws Exception { - SecurityManager securityManager = new SecurityManager(mock(Broker.class), false); + Broker broker = mock(Broker.class); + when(broker.getModel()).thenReturn(BrokerModel.getInstance()); + when(broker.getCategoryClass()).thenReturn(Broker.class); + SecurityManager securityManager = new SecurityManager(broker, false); final VirtualHostImpl<?,?,?> virtualHost = mock(VirtualHostImpl.class); when(virtualHost.getName()).thenReturn(hostName); when(virtualHost.getSecurityManager()).thenReturn(securityManager); diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/AbstractVirtualHostTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/AbstractVirtualHostTest.java index 74fe371b2f..8b53042f6f 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/AbstractVirtualHostTest.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/AbstractVirtualHostTest.java @@ -50,7 +50,7 @@ import org.apache.qpid.test.utils.QpidTestCase; public class AbstractVirtualHostTest extends QpidTestCase { private TaskExecutor _taskExecutor; - private VirtualHostNode<?> _node; + private VirtualHostNode _node; private MessageStore _failingStore; @Override @@ -73,6 +73,7 @@ public class AbstractVirtualHostTest extends QpidTestCase when(_node.getModel()).thenReturn(BrokerModel.getInstance()); when(_node.getTaskExecutor()).thenReturn(_taskExecutor); when(_node.getConfigurationStore()).thenReturn(mock(DurableConfigurationStore.class)); + when(_node.getCategoryClass()).thenReturn(VirtualHostNode.class); _failingStore = mock(MessageStore.class); doThrow(new RuntimeException("Cannot open store")).when(_failingStore).openMessageStore(any(ConfiguredObject.class)); diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/VirtualHostQueueCreationTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/VirtualHostQueueCreationTest.java index 78793726a8..fd6748f500 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/VirtualHostQueueCreationTest.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/VirtualHostQueueCreationTest.java @@ -68,7 +68,6 @@ public class VirtualHostQueueCreationTest extends QpidTestCase EventLogger eventLogger = mock(EventLogger.class); SecurityManager securityManager = mock(SecurityManager.class); - when(securityManager.authoriseConfiguringBroker(anyString(),any(Class.class),any(Operation.class))).thenReturn(true); ConfiguredObjectFactory objectFactory = new ConfiguredObjectFactoryImpl(BrokerModel.getInstance()); _taskExecutor = new CurrentThreadTaskExecutor(); diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNodeTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNodeTest.java index 4f8fe097ab..deb93d6527 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNodeTest.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNodeTest.java @@ -52,7 +52,6 @@ import org.apache.qpid.server.model.SystemConfig; import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.model.VirtualHostNode; import org.apache.qpid.server.security.SecurityManager; -import org.apache.qpid.server.security.access.Operation; import org.apache.qpid.server.store.ConfiguredObjectRecord; import org.apache.qpid.server.store.DurableConfigurationStore; import org.apache.qpid.server.store.NullMessageStore; @@ -278,9 +277,7 @@ public class AbstractStandardVirtualHostNodeTest extends QpidTestCase node.open(); node.start(); - doThrow(new AccessControlException("mocked ACL exception")).when(_mockSecurityManager).authoriseVirtualHostNode( - TEST_VIRTUAL_HOST_NODE_NAME, - Operation.UPDATE); + doThrow(new AccessControlException("mocked ACL exception")).when(_mockSecurityManager).authoriseUpdate(node); assertNull(node.getDescription()); try @@ -310,9 +307,7 @@ public class AbstractStandardVirtualHostNodeTest extends QpidTestCase node.open(); node.start(); - doThrow(new AccessControlException("mocked ACL exception")).when(mockSecurityManager).authoriseVirtualHostNode( - TEST_VIRTUAL_HOST_NODE_NAME, - Operation.DELETE); + doThrow(new AccessControlException("mocked ACL exception")).when(mockSecurityManager).authoriseDelete(node); try { @@ -342,9 +337,7 @@ public class AbstractStandardVirtualHostNodeTest extends QpidTestCase node.open(); node.start(); - doThrow(new AccessControlException("mocked ACL exception")).when(mockSecurityManager).authoriseVirtualHostNode( - TEST_VIRTUAL_HOST_NODE_NAME, - Operation.UPDATE); + doThrow(new AccessControlException("mocked ACL exception")).when(mockSecurityManager).authoriseUpdate(node); try { diff --git a/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/ACLFileAccessControlProviderImpl.java b/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/ACLFileAccessControlProviderImpl.java index c1bd1b0bb8..99db75ac91 100644 --- a/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/ACLFileAccessControlProviderImpl.java +++ b/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/ACLFileAccessControlProviderImpl.java @@ -20,7 +20,6 @@ */ package org.apache.qpid.server.security.access.plugins; -import java.security.AccessControlException; import java.util.Collection; import java.util.Collections; import java.util.Map; @@ -33,7 +32,6 @@ import org.apache.log4j.Logger; import org.apache.qpid.server.configuration.IllegalConfigurationException; import org.apache.qpid.server.model.AbstractConfiguredObject; -import org.apache.qpid.server.model.AccessControlProvider; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.ConfiguredObject; import org.apache.qpid.server.model.ManagedAttributeField; @@ -41,7 +39,6 @@ import org.apache.qpid.server.model.ManagedObjectFactoryConstructor; import org.apache.qpid.server.model.State; import org.apache.qpid.server.model.StateTransition; import org.apache.qpid.server.security.AccessControl; -import org.apache.qpid.server.security.access.Operation; import org.apache.qpid.server.util.urlstreamhandler.data.Handler; public class ACLFileAccessControlProviderImpl @@ -229,27 +226,6 @@ public class ACLFileAccessControlProviderImpl return returnVal; } - @Override - protected void authoriseSetDesiredState(State desiredState) throws AccessControlException - { - if(desiredState == State.DELETED) - { - if (!_broker.getSecurityManager().authoriseConfiguringBroker(getName(), AccessControlProvider.class, Operation.DELETE)) - { - throw new AccessControlException("Deletion of AccessControlProvider is denied"); - } - } - } - - @Override - protected void authoriseSetAttributes(ConfiguredObject<?> modified, Set<String> attributes) throws AccessControlException - { - if (!_broker.getSecurityManager().authoriseConfiguringBroker(getName(), AccessControlProvider.class, Operation.UPDATE)) - { - throw new AccessControlException("Setting of AccessControlProvider attributes is denied"); - } - } - public AccessControl getAccessControl() { return _accessControl; diff --git a/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java b/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java index a37c0c7858..5301d2e49d 100644 --- a/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java +++ b/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java @@ -22,14 +22,10 @@ package org.apache.qpid.server.security.access.plugins; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; import javax.security.auth.Subject; -import org.apache.qpid.server.exchange.ExchangeImpl; import org.apache.qpid.server.logging.EventLoggerProvider; -import org.apache.qpid.server.model.VirtualHost; -import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.security.Result; import org.apache.qpid.server.security.access.ObjectProperties; import org.apache.qpid.server.security.access.ObjectType; @@ -65,8 +61,6 @@ public class RuleSetTest extends QpidTestCase private String _exchangeName = "amq.direct"; private String _exchangeType = "direct"; private Subject _testSubject = TestPrincipalUtils.createTestSubject(TEST_USER); - private AMQQueue<?> _queue; - private VirtualHost<?,?,?> _virtualHost; @Override public void setUp() throws Exception @@ -74,11 +68,6 @@ public class RuleSetTest extends QpidTestCase super.setUp(); _ruleSet = new RuleSet(mock(EventLoggerProvider.class)); - - _virtualHost = mock(VirtualHost.class); - _queue = mock(AMQQueue.class); - when(_queue.getName()).thenReturn(_queueName); - when(_queue.getParent(VirtualHost.class)).thenReturn(_virtualHost); } @Override @@ -178,11 +167,13 @@ public class RuleSetTest extends QpidTestCase { _ruleSet.grant(0, TEST_USER, Permission.ALLOW, Operation.CREATE, ObjectType.QUEUE, new ObjectProperties(Property.VIRTUALHOST_NAME, ALLOWED_VH)); - when(_virtualHost.getName()).thenReturn(ALLOWED_VH); - assertEquals(Result.ALLOWED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, new ObjectProperties(_queue))); + ObjectProperties allowedQueueObjectProperties = new ObjectProperties(_queueName); + allowedQueueObjectProperties.put(Property.VIRTUALHOST_NAME, ALLOWED_VH); + assertEquals(Result.ALLOWED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, new ObjectProperties(allowedQueueObjectProperties))); - when(_virtualHost.getName()).thenReturn(DENIED_VH); - assertEquals(Result.DEFER, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, new ObjectProperties(_queue))); + ObjectProperties deniedQueueObjectProperties = new ObjectProperties(_queueName); + deniedQueueObjectProperties.put(Property.VIRTUALHOST_NAME, DENIED_VH); + assertEquals(Result.DEFER, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, deniedQueueObjectProperties)); } public void testQueueCreateNamedNullRoutingKey() @@ -197,15 +188,16 @@ public class RuleSetTest extends QpidTestCase { _ruleSet.grant(0, TEST_USER, Permission.ALLOW, Operation.CREATE, ObjectType.EXCHANGE, new ObjectProperties(Property.VIRTUALHOST_NAME, ALLOWED_VH)); - ExchangeImpl<?> exchange = mock(ExchangeImpl.class); - when(exchange.getParent(VirtualHost.class)).thenReturn(_virtualHost); - when(exchange.getType()).thenReturn(_exchangeType); - when(_virtualHost.getName()).thenReturn(ALLOWED_VH); + ObjectProperties allowedExchangeProperties = new ObjectProperties(_exchangeName); + allowedExchangeProperties.put(Property.TYPE, _exchangeType); + allowedExchangeProperties.put(Property.VIRTUALHOST_NAME, ALLOWED_VH); - assertEquals(Result.ALLOWED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.EXCHANGE, new ObjectProperties(exchange))); + assertEquals(Result.ALLOWED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.EXCHANGE, allowedExchangeProperties)); - when(_virtualHost.getName()).thenReturn(DENIED_VH); - assertEquals(Result.DEFER, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.EXCHANGE, new ObjectProperties(exchange))); + ObjectProperties deniedExchangeProperties = new ObjectProperties(_exchangeName); + deniedExchangeProperties.put(Property.TYPE, _exchangeType); + deniedExchangeProperties.put(Property.VIRTUALHOST_NAME, DENIED_VH); + assertEquals(Result.DEFER, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.EXCHANGE, deniedExchangeProperties)); } public void testExchangeCreate() diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ProtocolEngine_0_10.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ProtocolEngine_0_10.java index 10bf0e761e..e391bd6771 100755 --- a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ProtocolEngine_0_10.java +++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ProtocolEngine_0_10.java @@ -70,7 +70,7 @@ public class ProtocolEngine_0_10 extends InputHandler implements ServerProtocol public ProtocolEngine_0_10(ServerConnection conn, NetworkConnection network) { - super(new Assembler(conn)); + super(new ServerAssembler(conn)); _connection = conn; if(network != null) diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerAssembler.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerAssembler.java new file mode 100644 index 0000000000..456c9d36d9 --- /dev/null +++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerAssembler.java @@ -0,0 +1,57 @@ +/* + * + * 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.protocol.v0_10; + + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.apache.qpid.transport.network.Assembler; +import org.apache.qpid.transport.network.NetworkEvent; + +public class ServerAssembler extends Assembler +{ + private static final Logger LOGGER = LoggerFactory.getLogger(ServerAssembler.class); + + + private final ServerConnection _connection; + + public ServerAssembler(final ServerConnection connection) + { + super(connection); + _connection = connection; + } + + @Override + public void received(final NetworkEvent event) + { + if (!_connection.isIgnoreFutureInput()) + { + super.received(event); + } + else + { + LOGGER.debug("Ignored network event " + event + " as connection is ignoring further input "); + } + } + + +} diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerConnection.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerConnection.java index a6ed8c452a..2280377fca 100644 --- a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerConnection.java +++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerConnection.java @@ -97,6 +97,7 @@ public class ServerConnection extends Connection implements AMQConnectionModel<S private final int _maxMessageSize; private ServerProtocolEngine _serverProtocolEngine; + private boolean _ignoreFutureInput; public ServerConnection(final long connectionId, Broker<?> broker, @@ -734,4 +735,15 @@ public class ServerConnection extends Connection implements AMQConnectionModel<S } } + + public void closeAndIgnoreFutureInput() + { + _ignoreFutureInput = true; + getSender().close(); + } + + public boolean isIgnoreFutureInput() + { + return _ignoreFutureInput; + } } diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerConnectionDelegate.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerConnectionDelegate.java index 6e2a6cac7d..7f646b43b4 100644 --- a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerConnectionDelegate.java +++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerConnectionDelegate.java @@ -250,7 +250,7 @@ public class ServerConnectionDelegate extends ServerDelegate ") above the server's offered limit (" + getChannelMax() +")"); //Due to the error we must forcefully close the connection without negotiation - sconn.getSender().close(); + sconn.closeAndIgnoreFutureInput(); return; } @@ -261,7 +261,8 @@ public class ServerConnectionDelegate extends ServerDelegate ") above the server's offered limit (" + getFrameMax() +")"); //Due to the error we must forcefully close the connection without negotiation - sconn.getSender().close(); + sconn.closeAndIgnoreFutureInput(); + return; } else if(okMaxFrameSize > 0 && okMaxFrameSize < Constant.MIN_MAX_FRAME_SIZE) @@ -271,7 +272,7 @@ public class ServerConnectionDelegate extends ServerDelegate ") below the minimum permitted size (" + Constant.MIN_MAX_FRAME_SIZE +")"); //Due to the error we must forcefully close the connection without negotiation - sconn.getSender().close(); + sconn.closeAndIgnoreFutureInput(); return; } else if(okMaxFrameSize == 0) diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQProtocolEngine.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQProtocolEngine.java index d58ac36ff5..d7b5b00b26 100644 --- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQProtocolEngine.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQProtocolEngine.java @@ -920,15 +920,13 @@ public class AMQProtocolEngine implements ServerProtocolEngine, try { markChannelAwaitingCloseOk(channelId); - closeSession(false); // currently performs the delete actions. + closeSession(false); } finally { try { writeFrame(frame); - - // add an async job and not } finally { diff --git a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageMetaData_1_0.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageMetaData_1_0.java index fbc24ba454..6800b14d65 100755 --- a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageMetaData_1_0.java +++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageMetaData_1_0.java @@ -493,7 +493,13 @@ public class MessageMetaData_1_0 implements StorableMessageMetaData public String getType() { + String subject = getSubject(); + if(subject != null) + { + return subject; + } + // Use legacy annotation if present and there was no subject if(_messageAnnotations == null || _messageAnnotations.get(JMS_TYPE) == null) { return null; diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java index 19d498e240..93ff1adb63 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java @@ -406,6 +406,13 @@ public class RestServlet extends AbstractServlet @Override protected void doPutWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + performCreateOrUpdate(request, response); + } + + private void performCreateOrUpdate(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + { + boolean createOrUpdate = "PUT".equalsIgnoreCase(request.getMethod()); + response.setContentType("application/json"); List<String> names = new ArrayList<String>(); @@ -461,6 +468,13 @@ public class RestServlet extends AbstractServlet { if (_hierarchy.length == 0) { + if (!createOrUpdate) + { + sendErrorResponse(request, response, + "Only object creation is allowed with POST requests. Use PUT method to update broker attributes"); + return; + } + try { doUpdate(getBroker(), providedObject); @@ -484,7 +498,7 @@ public class RestServlet extends AbstractServlet Collection<ConfiguredObject>[] objects = new Collection[_hierarchy.length]; if (_hierarchy.length == 1) { - createOrUpdate(providedObject, _hierarchy[0], getBroker(), null, request, response); + createOrUpdate(providedObject, _hierarchy[0], getBroker(), null, request, response, createOrUpdate); } else { @@ -547,26 +561,29 @@ public class RestServlet extends AbstractServlet ConfiguredObject theParent = parents.remove(0); ConfiguredObject[] otherParents = parents.toArray(new ConfiguredObject[parents.size()]); - createOrUpdate(providedObject, objClass, theParent, otherParents, request, response); + createOrUpdate(providedObject, objClass, theParent, otherParents, request, response, createOrUpdate); } - } private void createOrUpdate(Map<String, Object> providedObject, Class<? extends ConfiguredObject> objClass, ConfiguredObject theParent, ConfiguredObject[] otherParents, HttpServletRequest request, - HttpServletResponse response) throws IOException + HttpServletResponse response, boolean createOrUpdate) throws IOException { try { Collection<? extends ConfiguredObject> existingChildren = theParent.getChildren(objClass); - for(ConfiguredObject obj: existingChildren) + + if (createOrUpdate) { - if((providedObject.containsKey("id") && String.valueOf(providedObject.get("id")).equals(obj.getId().toString())) - || (obj.getName().equals(providedObject.get("name")) && equalParents(obj, otherParents, objClass))) + for (ConfiguredObject obj : existingChildren) { - doUpdate(obj, providedObject); - response.setStatus(HttpServletResponse.SC_OK); - return; + if ((providedObject.containsKey("id") && String.valueOf(providedObject.get("id")).equals(obj.getId().toString())) + || (obj.getName().equals(providedObject.get("name")) && equalParents(obj, otherParents, objClass))) + { + doUpdate(obj, providedObject); + response.setStatus(HttpServletResponse.SC_OK); + return; + } } } @@ -626,11 +643,12 @@ public class RestServlet extends AbstractServlet } else { + String message = e.getMessage(); if (e instanceof IllegalConfigurationException || e instanceof IllegalArgumentException) { if (LOGGER.isDebugEnabled()) { - LOGGER.debug(e.getClass().getSimpleName() + " processing request : " + e.getMessage()); + LOGGER.debug(e.getClass().getSimpleName() + " processing request : " + message); } else if (LOGGER.isTraceEnabled()) { @@ -642,17 +660,22 @@ public class RestServlet extends AbstractServlet LOGGER.warn("Unexpected exception processing request ", e); } - response.setStatus(HttpServletResponse.SC_CONFLICT); + sendErrorResponse(request, response, message); - response.setContentType("application/json"); - response.setCharacterEncoding("UTF-8"); + } + } - Writer out = getOutputWriter(request, response); - ObjectMapper mapper = new ObjectMapper(); - mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true); - mapper.writeValue(out, Collections.singletonMap("errorMessage", e.getMessage())); + private void sendErrorResponse(HttpServletRequest request, HttpServletResponse response, String message) throws IOException + { + response.setStatus(HttpServletResponse.SC_CONFLICT); - } + response.setContentType("application/json"); + response.setCharacterEncoding("UTF-8"); + + Writer out = getOutputWriter(request, response); + ObjectMapper mapper = new ObjectMapper(); + mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true); + mapper.writeValue(out, Collections.singletonMap("errorMessage", message)); } @Override @@ -678,6 +701,12 @@ public class RestServlet extends AbstractServlet } } + @Override + protected void doPostWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + { + performCreateOrUpdate(request, response); + } + private void setCachingHeadersOnResponse(HttpServletResponse response) { response.setHeader("Cache-Control","no-cache"); diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/UserPreferencesServlet.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/UserPreferencesServlet.java index b782022986..11876f115e 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/UserPreferencesServlet.java +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/UserPreferencesServlet.java @@ -65,16 +65,6 @@ public class UserPreferencesServlet extends AbstractServlet private void getUserPreferences(String authenticationProviderName, String userId, HttpServletRequest request, HttpServletResponse response) throws IOException { - try - { - assertUserPreferencesOperationAuthorized(userId); - } - catch (SecurityException e) - { - response.sendError(HttpServletResponse.SC_FORBIDDEN, "Viewing of preferences is not allowed"); - return; - } - Map<String, Object> preferences = null; PreferencesProvider preferencesProvider = getPreferencesProvider(authenticationProviderName); if (preferencesProvider == null) @@ -82,9 +72,17 @@ public class UserPreferencesServlet extends AbstractServlet response.sendError(HttpServletResponse.SC_NOT_FOUND, "Preferences provider is not configured"); return; } - preferences = preferencesProvider.getPreferences(userId); + try + { + preferences = preferencesProvider.getPreferences(userId); - sendJsonResponse(preferences, request, response); + sendJsonResponse(preferences, request, response); + } + catch (SecurityException e) + { + response.sendError(HttpServletResponse.SC_FORBIDDEN, "Viewing of preferences is not allowed"); + return; + } } private void getUserList(String[] pathElements, HttpServletRequest request, HttpServletResponse response) throws IOException @@ -177,16 +175,6 @@ public class UserPreferencesServlet extends AbstractServlet String userId = elements[1]; - try - { - assertUserPreferencesOperationAuthorized(userId); - } - catch (SecurityException e) - { - response.sendError(HttpServletResponse.SC_FORBIDDEN, "Deletion of preferences is not allowed"); - return; - } - String providerName = elements[0]; Set<String> users = providerUsers.get(providerName); @@ -216,7 +204,15 @@ public class UserPreferencesServlet extends AbstractServlet if (preferencesProvider != null && !usersToDelete.isEmpty()) { String[] users = usersToDelete.toArray(new String[usersToDelete.size()]); - preferencesProvider.deletePreferences(users); + try + { + preferencesProvider.deletePreferences(users); + } + catch (SecurityException e) + { + response.sendError(HttpServletResponse.SC_FORBIDDEN, "Deletion of preferences is not allowed"); + return; + } } } } @@ -237,8 +233,4 @@ public class UserPreferencesServlet extends AbstractServlet return provider; } - private void assertUserPreferencesOperationAuthorized(String userId) - { - getBroker().getSecurityManager().authoriseUserOperation(Operation.UPDATE, userId); - } } diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/metadata.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/metadata.js index 1520cb8f7a..1a9ceb7419 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/metadata.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/metadata.js @@ -68,8 +68,12 @@ define(["dojo/_base/xhr", }, implementsManagedInterface: function (category, type, managedInterfaceName) { - var managedInterfaces = this.getMetaData(category, type).managedInterfaces; - return array.indexOf(managedInterfaces, managedInterfaceName) >= 0 ; + var md = this.getMetaData(category, type); + if (md && md.managedInterfaces) + { + return array.indexOf(md.managedInterfaces, managedInterfaceName) >= 0 ; + } + return false; }, validChildTypes: function (category, type, childCategory) { diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js index 746eb4bbbc..5bf5574347 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js @@ -791,5 +791,52 @@ define(["dojo/_base/xhr", on(window, "resize", resize); } + util.submit = function(method, resourceUrl, data, successAction, failureAction) + { + var result = {success: true, failureReason: null}; + var xhrArguments = { + url: resourceUrl, + sync: true, + handleAs: "json", + headers: { "Content-Type": "application/json"}, + load: function(x) { + result.success = true; + result.data = x; + if (successAction) + { + successAction(x); + } + }, + error: function(error) { + result.success = false; + result.failureReason = error; + if (failureAction) + { + failureAction(error); + } + else + { + util.xhrErrorHandler(error); + } + } + } + if (data && method != "del") + { + xhrArguments[method + "Data"] = json.stringify(data); + } + xhr[method](xhrArguments); + return result; + } + + util.post = function(resourceUrl, data, successAction, failureAction) + { + return util.submit("post", resourceUrl, data, successAction, failureAction) + } + + util.put = function(resourceUrl, data, successAction, failureAction) + { + return util.submit("put", resourceUrl, data, successAction, failureAction) + } + return util; }); diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/widgetconfigurer.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/widgetconfigurer.js index af8f1fc2fb..baafc6f71d 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/widgetconfigurer.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/widgetconfigurer.js @@ -119,12 +119,17 @@ define(["dojo/_base/xhr", if (widget instanceof dijit.form.FilteringSelect || widget instanceof dojox.form.CheckedMultiSelect) { - var widgetValue = dataValue ? dataValue : defaultValue; + var widgetValue = dataValue == null ? defaultValue : dataValue; if (widgetValue) { widget.set("value", widgetValue); } } + else if (widget instanceof dijit.form.CheckBox) + { + var widgetValue = dataValue == null ? (defaultValue == "true") : dataValue; + widget.set("checked", widgetValue ? true : false); + } else { if (dataValue) diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addAccessControlProvider.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addAccessControlProvider.js index 83bf23f669..a8b2b60a75 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addAccessControlProvider.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addAccessControlProvider.js @@ -99,30 +99,11 @@ define(["dojo/_base/lang", { if (this.accessControlProviderForm.validate()) { - var success = false,failureReason=null; - var accessControlProviderData = util.getFormWidgetValues(this.accessControlProviderForm, this.initialData); var encodedAccessControlProviderName = encodeURIComponent(this.accessControlProviderName.value); - - xhr.put( - { - url: "api/latest/accesscontrolprovider/" + encodedAccessControlProviderName, - sync: true, - handleAs: "json", - headers: { "Content-Type": "application/json"}, - putData: json.stringify(accessControlProviderData), - load: function(x) {success = true; }, - error: function(error) {success = false; failureReason = error;} - }); - - if (success == true) - { - this.dialog.hide(); - } - else - { - util.xhrErrorHandler(failureReason); - } + var that = this; + util.post("api/latest/accesscontrolprovider/" + encodedAccessControlProviderName, + accessControlProviderData, function(x){that.dialog.hide();}); } else { diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addAuthenticationProvider.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addAuthenticationProvider.js index ccae89d6c1..d367537731 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addAuthenticationProvider.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addAuthenticationProvider.js @@ -155,31 +155,21 @@ define(["dojo/_base/xhr", var authenticationProviderData = util.getFormWidgetValues(this.authenticationProviderForm, this.initialData); var encodedAuthenticationProviderName = encodeURIComponent(this.authenticationProviderName.value); - xhr.put({ - url: "api/latest/authenticationprovider/" + encodedAuthenticationProviderName, - sync: true, - handleAs: "json", - headers: { "Content-Type": "application/json"}, - putData: json.stringify(authenticationProviderData), - load: function(x) {success = true; }, - error: function(error) {success = false; failureReason = error;} - }); - - if(success === true) - { - var preferencesProviderResult = this.preferencesProviderForm.submit(encodedAuthenticationProviderName); - success = preferencesProviderResult.success; - failureReason = preferencesProviderResult.failureReason; - } + var that = this; - if (success == true) - { - this.dialog.hide(); - } - else - { - util.xhrErrorHandler(failureReason); - } + var methodName = this.initialData ? "put" : "post"; + util[methodName]("api/latest/authenticationprovider/" + encodedAuthenticationProviderName, authenticationProviderData, + function(x){ + var preferencesProviderResult = that.preferencesProviderForm.submit(encodedAuthenticationProviderName); + if (preferencesProviderResult.success == true) + { + that.dialog.hide(); + } + else + { + util.xhrErrorHandler(preferencesProviderResult.failureReason); + } + }); } else { diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addBinding.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addBinding.js index 56950c88b0..8257b7e54c 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addBinding.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addBinding.js @@ -308,30 +308,13 @@ define(["dojo/_base/connect", var newBinding = convertToBinding(theForm.getValues()); var that = this; - - xhr.put({url: "api/latest/binding/"+encodeURIComponent(addBinding.vhostnode) - +"/"+encodeURIComponent(addBinding.vhost) - +"/"+encodeURIComponent(newBinding.exchange) - +"/"+encodeURIComponent(newBinding.queue) - +"/"+encodeURIComponent(newBinding.name), - sync: true, handleAs: "json", - headers: { "Content-Type": "application/json"}, - putData: json.toJson(newBinding), - load: function(x) {that.success = true; }, - error: function(error) {that.success = false; that.failureReason = error;}}); - - if(this.success === true) - { - registry.byId("addBinding").hide(); - } - else - { - util.xhrErrorHandler(this.failureReason); - } - + var url = "api/latest/binding/"+encodeURIComponent(addBinding.vhostnode) + + "/"+encodeURIComponent(addBinding.vhost) + + "/"+encodeURIComponent(newBinding.exchange) + + "/"+encodeURIComponent(newBinding.queue) + + "/"+encodeURIComponent(newBinding.name); + util.post(url, newBinding, function(x){registry.byId("addBinding").hide();}); return false; - - }else{ alert('Form contains invalid data. Please correct first'); return false; diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addExchange.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addExchange.js index c7f281b8dc..ca43eca5d3 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addExchange.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addExchange.js @@ -110,23 +110,10 @@ define(["dojo/_base/xhr", var newExchange = convertToExchange(theForm.getValues()); var that = this; - xhr.put({url: "api/latest/exchange/"+encodeURIComponent(addExchange.vhostnode) + - "/"+encodeURIComponent(addExchange.vhost) + - "/"+encodeURIComponent(newExchange.name), sync: true, handleAs: "json", - headers: { "Content-Type": "application/json"}, - putData: json.toJson(newExchange), - load: function(x) {that.success = true; }, - error: function(error) {that.success = false; that.failureReason = error;}}); - - if(this.success === true) - { - registry.byId("addExchange").hide(); - } - else - { - util.xhrErrorHandler(this.failureReason); - } - + util.post("api/latest/exchange/" + encodeURIComponent(addExchange.vhostnode) + + "/" + encodeURIComponent(addExchange.vhost) + + "/" + encodeURIComponent(newExchange.name), + newExchange, function(x){ registry.byId("addExchange").hide(); }); return false; diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addGroupProvider.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addGroupProvider.js index 81ce40ebe9..f658a8ec3b 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addGroupProvider.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addGroupProvider.js @@ -124,33 +124,9 @@ define([ var groupProviderData = util.getFormWidgetValues(this.groupProviderForm, this.initialData); var encodedName = encodeURIComponent(this.groupProviderName.value); - var jsonString = json.stringify(groupProviderData); - - try { - xhr.put( - { - url: "api/latest/groupprovider/" + encodedName, - sync: true, - handleAs: "json", - headers: { "Content-Type": "application/json"}, - putData: jsonString, - load: function(x) {success = true; }, - error: function(error) {success = false; failureReason = error;} - }); - } - catch (e) - { - console.warn(e); - } - - if (success == true) - { - this.dialog.hide(); - } - else - { - util.xhrErrorHandler(failureReason); - } + var that = this; + var method = this.initialData ? "put" : "post"; + util[method]("api/latest/groupprovider/" + encodedName, groupProviderData, function(x){that.dialog.hide();}); } else { diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addPort.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addPort.js index befb5df9c1..1069e2300b 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addPort.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addPort.js @@ -267,33 +267,9 @@ define(["dojo/_base/xhr", alert("A trust store must be selected when requesting client certificates."); return false; } - var that = this; - - xhr.put({url: "api/latest/port/" + encodeURIComponent(newPort.name), sync: true, handleAs: "json", - headers: { "Content-Type": "application/json"}, - putData: json.toJson(newPort), - load: function (x) - { - that.success = true; - }, - error: function (error) - { - that.success = false; - that.failureReason = error; - }}); - - if (this.success === true) - { - registry.byId("addPort").hide(); - } - else - { - util.xhrErrorHandler(this.failureReason); - } - + var method = registry.byId("formAddPort.name").get("disabled") ? "put" : "post"; + util[method]("api/latest/port/" + encodeURIComponent(newPort.name), newPort, function(x){registry.byId("addPort").hide()}); return false; - - } else { alert('Form contains invalid data. Please correct first'); diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addQueue.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addQueue.js index 236efb2efa..da7879d671 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addQueue.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addQueue.js @@ -149,25 +149,9 @@ define(["dojo/_base/xhr", if(theForm.validate()){ var newQueue = convertToQueue(theForm.getValues()); - var that = this; - - xhr.put({url: "api/latest/queue/"+encodeURIComponent(addQueue.vhostnode) - +"/"+encodeURIComponent(addQueue.vhost) - +"/"+encodeURIComponent(newQueue.name), sync: true, handleAs: "json", - headers: { "Content-Type": "application/json"}, - putData: json.toJson(newQueue), - load: function(x) {that.success = true; }, - error: function(error) {that.success = false; that.failureReason = error;}}); - - if(this.success === true) - { - registry.byId("addQueue").hide(); - } - else - { - util.xhrErrorHandler(this.failureReason); - } - + util.post("api/latest/queue/" + encodeURIComponent(addQueue.vhostnode) + + "/"+encodeURIComponent(addQueue.vhost) + "/" + encodeURIComponent(newQueue.name), + newQueue, function(x){registry.byId("addQueue").hide();}); return false; diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addStore.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addStore.js index caf14d0cc8..ff672e92be 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addStore.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addStore.js @@ -19,7 +19,6 @@ * */ define(["dojo/_base/lang", - "dojo/_base/xhr", "dojo/dom", "dojo/dom-construct", "dijit/registry", @@ -45,7 +44,7 @@ define(["dojo/_base/lang", "dijit/layout/ContentPane", "dojox/layout/TableContainer", "dojo/domReady!"], - function (lang, xhr, dom, construct, registry, parser, memory, array, event, json, util, metadata, template) + function (lang, dom, construct, registry, parser, memory, array, event, json, util, metadata, template) { var addStore = { @@ -132,33 +131,9 @@ define(["dojo/_base/lang", var storeData = util.getFormWidgetValues(this.storeForm, this.initialData); var encodedStoreName = encodeURIComponent(this.storeName.value); var encodedCategory = encodeURIComponent(this.category.toLowerCase()); - var jsonString = json.stringify(storeData); - - try { - xhr.put( - { - url: "api/latest/" + encodedCategory + "/" + encodedStoreName, - sync: true, - handleAs: "json", - headers: { "Content-Type": "application/json"}, - putData: jsonString, - load: function(x) {success = true; }, - error: function(error) {success = false; failureReason = error;} - }); - } - catch (e) - { - console.warn(e); - } - - if (success == true) - { - this.dialog.hide(); - } - else - { - util.xhrErrorHandler(failureReason); - } + var that = this; + var method = this.effectiveData ? "put" : "post"; + util[method]("api/latest/" + encodedCategory + "/" + encodedStoreName, storeData, function(x){that.dialog.hide();}); } else { diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addVirtualHostNodeAndVirtualHost.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addVirtualHostNodeAndVirtualHost.js index 21927ea0e5..2cba022482 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addVirtualHostNodeAndVirtualHost.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addVirtualHostNodeAndVirtualHost.js @@ -18,7 +18,7 @@ * under the License. * */ -define(["dojo/_base/xhr", +define([ "dojo/_base/event", "dojo/_base/lang", "dojo/_base/array", @@ -48,7 +48,7 @@ define(["dojo/_base/xhr", "dojox/validate/us", "dojox/validate/web", "dojo/domReady!"], - function (xhr, event, lang, array, dom, domConstruct, json, parser, Memory, win, on, fobject, registry, Dialog, Button, FilteringSelect, properties, util, metadata, template) + function (event, lang, array, dom, domConstruct, json, parser, Memory, win, on, fobject, registry, Dialog, Button, FilteringSelect, properties, util, metadata, template) { var addVirtualHostNodeAndVirtualHost = @@ -339,27 +339,9 @@ define(["dojo/_base/xhr", return; } - var success = false,failureReason=null; - + var that = this; var encodedVirtualHostNodeName = encodeURIComponent(virtualHostNodeData.name); - xhr.put({ - url: "api/latest/virtualhostnode/" + encodedVirtualHostNodeName, - sync: true, - handleAs: "json", - headers: { "Content-Type": "application/json"}, - putData: json.stringify(virtualHostNodeData), - load: function(x) {success = true; }, - error: function(error) {success = false; failureReason = error;} - }); - - if (success == true) - { - this.dialog.hide(); - } - else - { - util.xhrErrorHandler(failureReason); - } + util.post("api/latest/virtualhostnode/" + encodedVirtualHostNodeName, virtualHostNodeData, function(x){that.dialog.hide();}); }, _getValues: function (form) { diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/authenticationprovider/PrincipalDatabaseAuthenticationManager.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/authenticationprovider/PrincipalDatabaseAuthenticationManager.js index e6f2249f65..87025adfae 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/authenticationprovider/PrincipalDatabaseAuthenticationManager.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/authenticationprovider/PrincipalDatabaseAuthenticationManager.js @@ -202,19 +202,7 @@ define(["dojo/_base/xhr", var url = "api/latest/user/"+encodeURIComponent(addUser.authProvider) + "/"+encodeURIComponent(newUser.name); - - xhr.put({url: url, sync: true, handleAs: "json", - headers: { "Content-Type": "application/json"}, - putData: json.toJson(newUser), - load: function(x) {that.success = true; }, - error: function(error) {that.success = false; that.failureReason = error;}}); - - if(that.success === true) { - registry.byId("addUser").hide(); - } else { - util.xhrErrorHandler(this.failureReason); - } - + util.post(url, newUser, function(x){registry.byId("addUser").hide();}); return false; @@ -260,18 +248,7 @@ define(["dojo/_base/xhr", var url = "api/latest/user/"+encodeURIComponent(setPassword.authProvider) + "/"+encodeURIComponent(newUser.name); - xhr.put({url: url, sync: true, handleAs: "json", - headers: { "Content-Type": "application/json"}, - putData: json.toJson(newUser), - load: function(x) {that.success = true; }, - error: function(error) {that.success = false; that.failureReason = error;}}); - - if(that.success === true) { - registry.byId("setPassword").hide(); - } else { - util.xhrErrorHandler(this.failureReason); - } - + util.put(url, newUser, function(x){registry.byId("setPassword").hide();}); return false; diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/group/addGroupMember.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/group/addGroupMember.js index 0a8e6a2e11..baa08d2309 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/group/addGroupMember.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/group/addGroupMember.js @@ -71,22 +71,11 @@ define(["dojo/_base/xhr", var newGroupMember = convertToGroupMember(theForm.getValues()); var that = this; - xhr.put({url: "api/latest/groupmember/"+encodeURIComponent(addGroupMember.groupProvider) + - "/" + encodeURIComponent(addGroupMember.group) + "/" + encodeURIComponent(newGroupMember.name), sync: true, handleAs: "json", - headers: { "Content-Type": "application/json"}, - putData: json.toJson(newGroupMember), - load: function(x) {that.success = true; }, - error: function(error) {that.success = false; that.failureReason = error;}}); - - if(this.success === true) - { - registry.byId("addGroupMember").hide(); - } - else - { - util.xhrErrorHandler(this.failureReason); - } + var url = "api/latest/groupmember/"+encodeURIComponent(addGroupMember.groupProvider) + + "/" + encodeURIComponent(addGroupMember.group) + + "/" + encodeURIComponent(newGroupMember.name); + util.post(url, newGroupMember, function(x){registry.byId("addGroupMember").hide();}); return false; diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/groupprovider/GroupManagingGroupProvider.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/groupprovider/GroupManagingGroupProvider.js index 5788fad8af..4182b580b7 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/groupprovider/GroupManagingGroupProvider.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/groupprovider/GroupManagingGroupProvider.js @@ -177,18 +177,7 @@ define(["dojo/_base/xhr", var url = "api/latest/group/"+encodeURIComponent(addGroup.groupProvider) + "/"+encodeURIComponent(newGroup.name); - xhr.put({url: url, sync: true, handleAs: "json", - headers: { "Content-Type": "application/json"}, - putData: json.toJson(newGroup), - load: function(x) {that.success = true; }, - error: function(error) {that.success = false; that.failureReason = error;}}); - - if(that.success === true) { - registry.byId("addGroup").hide(); - } else { - util.xhrErrorHandler(this.failureReason); - } - + util.post(url, newGroup, function(x){registry.byId("addGroup").hide();}); return false; diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/preferencesprovider/PreferencesProviderForm.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/preferencesprovider/PreferencesProviderForm.js index ef8273328b..099a75837b 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/preferencesprovider/PreferencesProviderForm.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/preferencesprovider/PreferencesProviderForm.js @@ -87,18 +87,26 @@ function (util, metadata, xhr, declare, array, domConstruct, win, query, json, _ { var preferencesProviderData = util.getFormWidgetValues(this.preferencesProviderForm, this.data) var encodedPreferencesProviderName = encodeURIComponent(this.preferencesProviderNameWidget.get("value")); - var success = false; - var failureReason = null; - xhr.put({ - url: "api/latest/preferencesprovider/" + encodedAuthenticationProviderName + "/" + encodedPreferencesProviderName, - sync: true, - handleAs: "json", - headers: { "Content-Type": "application/json"}, - putData: json.stringify(preferencesProviderData), - load: function (x) { success = true; }, - error: function (error) { success = false; failureReason = error; } - }); - return { success: success, failureReason: failureReason }; + var url = "api/latest/preferencesprovider/" + encodedAuthenticationProviderName + "/" + encodedPreferencesProviderName; + if (this.data) + { + var success = false; + var failureReason = null; + xhr.put({ + url: url, + sync: true, + handleAs: "json", + headers: { "Content-Type": "application/json"}, + putData: json.stringify(preferencesProviderData), + load: function (x) { success = true; }, + error: function (error) { success = false; failureReason = error; } + }); + return { success: success, failureReason: failureReason }; + } + else + { + return util.post(url, preferencesProviderData); + } } return { success: true, failureReason: null }; }, diff --git a/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBean.java b/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBean.java index 3b3d6b9cd2..bdf44e54da 100644 --- a/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBean.java +++ b/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBean.java @@ -216,7 +216,7 @@ public class VirtualHostManagerMBean extends AbstractStatisticsGatheringMBean<Vi try { - exchange.deleteWithChecks(); + exchange.delete(); } catch(RequiredExchangeException e) { diff --git a/qpid/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBeanTest.java b/qpid/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBeanTest.java index 5a804e7605..c8c27d386c 100644 --- a/qpid/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBeanTest.java +++ b/qpid/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBeanTest.java @@ -201,7 +201,7 @@ public class VirtualHostManagerMBeanTest extends TestCase _virtualHostManagerMBean.unregisterExchange(EXCHANGE_1_NAME); - verify(mockExchange).deleteWithChecks(); + verify(mockExchange).delete(); } public void testUnregisterExchangeWhenExchangeDoesNotExist() throws Exception diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/RestTestHelper.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/RestTestHelper.java index 67978a264e..2e3626eae6 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/RestTestHelper.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/RestTestHelper.java @@ -305,7 +305,7 @@ public class RestTestHelper { HttpURLConnection connection = openManagementConnection( "groupmember/" + encodeAsUTF(groupProviderName) + "/"+ encodeAsUTF(groupName) + "/" + encodeAsUTF(memberName), - "PUT"); + "POST"); Map<String, Object> groupMemberData = new HashMap<String, Object>(); // TODO add type @@ -358,7 +358,7 @@ public class RestTestHelper { HttpURLConnection connection = openManagementConnection( "group/" + encodeAsUTF(groupProviderName) + "/"+ encodeAsUTF(groupName), - "PUT"); + "POST"); Map<String, Object> groupData = new HashMap<String, Object>(); writeJsonRequest(connection, groupData); diff --git a/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/GroupRestTest.java b/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/GroupRestTest.java index eeb9511289..4fc5b1a184 100644 --- a/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/GroupRestTest.java +++ b/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/GroupRestTest.java @@ -20,8 +20,10 @@ */ package org.apache.qpid.systest.rest; +import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.FileOutputStream; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Properties; @@ -72,15 +74,31 @@ public class GroupRestTest extends QpidRestTestCase assertEquals(EXISTING_MEMBER, (String)member1.get(GroupMember.NAME)); } - public void testCreateNewMemberOfGroup() throws Exception + public void testCreateNewMemberByPut() throws Exception { Map<String, Object> group = getRestTestHelper().getJsonAsSingletonList("group/" + FILE_GROUP_MANAGER + "/myGroup"); getRestTestHelper().assertNumberOfGroupMembers(group, 1); - getRestTestHelper().createNewGroupMember(FILE_GROUP_MANAGER, GROUP_NAME, NEW_MEMBER); + String url = "groupmember/" + FILE_GROUP_MANAGER + "/"+ GROUP_NAME + "/" + NEW_MEMBER; + getRestTestHelper().submitRequest(url, "PUT", Collections.<String, Object>emptyMap(), HttpServletResponse.SC_CREATED); - group = getRestTestHelper().getJsonAsSingletonList("group/" + FILE_GROUP_MANAGER + "/myGroup"); - getRestTestHelper().assertNumberOfGroupMembers(group, 2); + Map<String, Object> member = getRestTestHelper().getJsonAsSingletonList(url); + assertEquals("Unexpected group name", NEW_MEMBER, member.get(GroupMember.NAME)); + } + + public void testCreateNewMemberByPost() throws Exception + { + Map<String, Object> group = getRestTestHelper().getJsonAsSingletonList("group/" + FILE_GROUP_MANAGER + "/myGroup"); + getRestTestHelper().assertNumberOfGroupMembers(group, 1); + + String url = "groupmember/" + FILE_GROUP_MANAGER + "/"+ GROUP_NAME + "/" + NEW_MEMBER; + getRestTestHelper().submitRequest(url, "POST", Collections.<String, Object>emptyMap(), HttpServletResponse.SC_CREATED); + + Map<String, Object> member = getRestTestHelper().getJsonAsSingletonList(url); + assertEquals("Unexpected group name", NEW_MEMBER, member.get(GroupMember.NAME)); + + // verify that second creation request by POST fails + getRestTestHelper().submitRequest(url, "POST", Collections.<String, Object>emptyMap(), HttpServletResponse.SC_CONFLICT); } public void testRemoveMemberFromGroup() throws Exception diff --git a/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/UserRestTest.java b/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/UserRestTest.java index 5df8a4ed9a..40eda50480 100644 --- a/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/UserRestTest.java +++ b/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/UserRestTest.java @@ -20,6 +20,8 @@ */ package org.apache.qpid.systest.rest; +import javax.servlet.http.HttpServletResponse; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -65,7 +67,7 @@ public class UserRestTest extends QpidRestTestCase } } - public void testPut() throws Exception + public void testCreateUserByPut() throws Exception { String userName = getTestName(); getRestTestHelper().createOrUpdateUser(userName, "newPassword"); @@ -76,6 +78,24 @@ public class UserRestTest extends QpidRestTestCase assertEquals("Unexpected user name", userName, userDetails.get(User.NAME)); } + public void testCreateUserByPost() throws Exception + { + String userName = getTestName(); + + Map<String,Object> userAttributes = new HashMap<>(); + userAttributes.put("password", "newPassword"); + + String url = "user/" + TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER + "/" + userName; + getRestTestHelper().submitRequest(url, "POST", userAttributes, HttpServletResponse.SC_CREATED); + + Map<String, Object> userDetails = getRestTestHelper().getJsonAsSingletonList(url); + assertUser(userDetails); + assertEquals("Unexpected user name", userName, userDetails.get(User.NAME)); + + // verify that second create request fails + getRestTestHelper().submitRequest(url, "POST", userAttributes, HttpServletResponse.SC_CONFLICT); + } + public void testDelete() throws Exception { String userName = getTestName(); diff --git a/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/VirtualHostNodeRestTest.java b/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/VirtualHostNodeRestTest.java index 9569b90251..a75d04e2a5 100644 --- a/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/VirtualHostNodeRestTest.java +++ b/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/VirtualHostNodeRestTest.java @@ -126,6 +126,23 @@ public class VirtualHostNodeRestTest extends QpidRestTestCase assertEquals(newDescription, virtualhostNode.get(VirtualHostNode.DESCRIPTION)); } + public void testCreateVirtualHostNodeByPost() throws Exception + { + String nodeName = getTestName(); + Map<String, Object> nodeData = new HashMap<>(); + nodeData.put(VirtualHostNode.NAME, nodeName); + nodeData.put(VirtualHostNode.TYPE, getTestProfileVirtualHostNodeType()); + + String url = "virtualhostnode/" + nodeName; + getRestTestHelper().submitRequest(url, "POST", nodeData, HttpServletResponse.SC_CREATED); + + Map<String, Object> virtualhostNode = getRestTestHelper().getJsonAsSingletonList(url); + Asserts.assertVirtualHostNode(nodeName, virtualhostNode); + + // verify that second create request fails + getRestTestHelper().submitRequest(url, "POST", nodeData, HttpServletResponse.SC_CONFLICT); + } + private void createAndDeleteVirtualHostNode(final String virtualhostNodeType, final String nodeName, final File storePathAsFile) throws Exception diff --git a/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/VirtualHostRestTest.java b/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/VirtualHostRestTest.java index 45cbee205d..7655601519 100644 --- a/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/VirtualHostRestTest.java +++ b/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/VirtualHostRestTest.java @@ -116,10 +116,10 @@ public class VirtualHostRestTest extends QpidRestTestCase Asserts.assertConnection(connections.get(0), _connection); } - public void testPutCreateProvidedVirtualHost() throws Exception + public void testCreateProvidedVirtualHost() throws Exception { String hostName = getTestName(); - createVirtualHost(hostName, ProvidedStoreVirtualHostImpl.VIRTUAL_HOST_TYPE); + createVirtualHost(hostName, ProvidedStoreVirtualHostImpl.VIRTUAL_HOST_TYPE, "PUT"); Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("virtualhost/" + EMPTY_VIRTUALHOSTNODE_NAME + "/" + hostName); Asserts.assertVirtualHost(hostName, hostDetails); @@ -127,7 +127,7 @@ public class VirtualHostRestTest extends QpidRestTestCase assertNewVirtualHost(hostDetails); } - public void testPutCreateVirtualHost() throws Exception + public void testCreateVirtualHostByPut() throws Exception { String hostName = getTestName(); String vhnType = getTestProfileVirtualHostNodeType(); @@ -135,13 +135,36 @@ public class VirtualHostRestTest extends QpidRestTestCase { vhnType = DerbyVirtualHostImpl.VIRTUAL_HOST_TYPE; } - createVirtualHost(hostName, vhnType); + createVirtualHost(hostName, vhnType, "PUT"); Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("virtualhost/" + EMPTY_VIRTUALHOSTNODE_NAME + "/" + hostName); Asserts.assertVirtualHost(hostName, hostDetails); assertNewVirtualHost(hostDetails); } + public void testCreateVirtualHostByPost() throws Exception + { + String hostName = getTestName(); + String type = getTestProfileVirtualHostNodeType(); + if (JsonVirtualHostNodeImpl.VIRTUAL_HOST_NODE_TYPE.equals(type)) + { + type = DerbyVirtualHostImpl.VIRTUAL_HOST_TYPE; + } + Map<String, Object> data = new HashMap<>(); + data.put(VirtualHost.NAME, hostName); + data.put(VirtualHost.TYPE, type); + + String url = "virtualhost/" + EMPTY_VIRTUALHOSTNODE_NAME + "/" + hostName; + getRestTestHelper().submitRequest(url, "POST", data, HttpServletResponse.SC_CREATED); + + Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList(url); + Asserts.assertVirtualHost(hostName, hostDetails); + assertNewVirtualHost(hostDetails); + + // verify second create request fails + getRestTestHelper().submitRequest(url, "POST", data, HttpServletResponse.SC_CONFLICT); + } + public void testDeleteHost() throws Exception { getRestTestHelper().submitRequest("virtualhost/" + TEST3_VIRTUALHOST + "/" + TEST3_VIRTUALHOST, @@ -576,14 +599,14 @@ public class VirtualHostRestTest extends QpidRestTestCase } private void createVirtualHost(final String virtualHostName, - final String virtualHostType) throws IOException + final String virtualHostType, String method) throws IOException { Map<String, Object> virtualhostData = new HashMap<>(); virtualhostData.put(VirtualHost.NAME, virtualHostName); virtualhostData.put(VirtualHost.TYPE, virtualHostType); getRestTestHelper().submitRequest("virtualhost/" + EMPTY_VIRTUALHOSTNODE_NAME + "/" + virtualHostName, - "PUT", + method, virtualhostData, HttpServletResponse.SC_CREATED); } diff --git a/qpid/java/tools/src/main/java/org/apache/qpid/tools/util/ArgumentsParser.java b/qpid/java/tools/src/main/java/org/apache/qpid/tools/util/ArgumentsParser.java index 56f3965ace..a71b466a0f 100644 --- a/qpid/java/tools/src/main/java/org/apache/qpid/tools/util/ArgumentsParser.java +++ b/qpid/java/tools/src/main/java/org/apache/qpid/tools/util/ArgumentsParser.java @@ -1,3 +1,23 @@ +/* + * + * 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.tools.util; |