From e8e05131324cf3137a3c65a95cad833cd3275c78 Mon Sep 17 00:00:00 2001 From: Keith Wall Date: Thu, 12 Mar 2015 14:13:28 +0000 Subject: Merge from trunk git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/QPID-6262-JavaBrokerNIO@1666200 13f79535-47bb-0310-9956-ffa450edef68 --- .../amqp_1_0/transport/ConnectionEndpoint.java | 35 +- .../amqp_1_0/transport/SendingLinkEndpoint.java | 22 +- .../qpid/amqp_1_0/transport/SessionEndpoint.java | 28 +- .../berkeleydb/BDBHARemoteReplicationNodeImpl.java | 23 - .../berkeleydb/BDBHARemoteReplicationNodeTest.java | 9 +- .../replication/BDBHAVirtualHostNodeRestTest.java | 4 +- .../apache/qpid/server/binding/BindingImpl.java | 9 +- .../store/StoreConfigurationChangeListener.java | 2 +- .../qpid/server/exchange/AbstractExchange.java | 24 +- .../server/model/AbstractConfiguredObject.java | 157 +++- .../model/adapter/AbstractPluginAdapter.java | 24 - .../qpid/server/model/adapter/BrokerAdapter.java | 30 - .../model/adapter/FileBasedGroupProviderImpl.java | 34 +- .../adapter/FileSystemPreferencesProviderImpl.java | 5 + .../qpid/server/model/port/AbstractPort.java | 24 - .../apache/qpid/server/queue/AbstractQueue.java | 12 - .../qpid/server/queue/QueueConsumerImpl.java | 9 +- .../qpid/server/security/FileKeyStoreImpl.java | 23 - .../qpid/server/security/FileTrustStoreImpl.java | 23 - .../qpid/server/security/NonJavaKeyStoreImpl.java | 25 - .../server/security/NonJavaTrustStoreImpl.java | 25 - .../qpid/server/security/SecurityManager.java | 474 +++++++---- .../server/security/access/ObjectProperties.java | 64 -- .../manager/AbstractAuthenticationManager.java | 24 - ...odelPasswordManagingAuthenticationProvider.java | 35 +- .../server/security/auth/manager/ManagedUser.java | 43 +- .../PrincipalDatabaseAuthenticationManager.java | 76 +- .../store/BrokerStoreUpgraderAndRecoverer.java | 5 + .../server/transport/NonBlockingConnection.java | 10 +- .../qpid/server/transport/SelectorThread.java | 4 + .../server/virtualhost/AbstractVirtualHost.java | 36 +- .../virtualhost/ExchangeExistsException.java | 7 +- .../virtualhostnode/AbstractVirtualHostNode.java | 39 - .../qpid/server/exchange/FanoutExchangeTest.java | 19 +- .../qpid/server/exchange/HeadersExchangeTest.java | 18 +- .../apache/qpid/server/model/VirtualHostTest.java | 16 +- .../model/testmodels/hierarchy/TestKitCarImpl.java | 9 + .../testmodels/hierarchy/TestStandardCarImpl.java | 9 + .../testmodels/lifecycle/TestConfiguredObject.java | 9 + .../testmodels/singleton/TestSingletonImpl.java | 10 + .../qpid/server/security/FileKeyStoreTest.java | 13 +- .../qpid/server/security/FileTrustStoreTest.java | 18 +- .../qpid/server/security/SecurityManagerTest.java | 900 +++++++++++++++------ .../apache/qpid/server/util/BrokerTestHelper.java | 5 +- .../virtualhost/AbstractVirtualHostTest.java | 3 +- .../virtualhost/VirtualHostQueueCreationTest.java | 1 - .../AbstractStandardVirtualHostNodeTest.java | 13 +- .../plugins/ACLFileAccessControlProviderImpl.java | 24 - .../security/access/plugins/RuleSetTest.java | 36 +- .../server/protocol/v0_10/ProtocolEngine_0_10.java | 2 +- .../server/protocol/v0_10/ServerAssembler.java | 57 ++ .../server/protocol/v0_10/ServerConnection.java | 12 + .../protocol/v0_10/ServerConnectionDelegate.java | 7 +- .../server/protocol/v0_8/AMQProtocolEngine.java | 4 +- .../server/protocol/v1_0/MessageMetaData_1_0.java | 6 + .../plugin/servlet/rest/RestServlet.java | 67 +- .../servlet/rest/UserPreferencesServlet.java | 46 +- .../main/java/resources/js/qpid/common/metadata.js | 8 +- .../src/main/java/resources/js/qpid/common/util.js | 47 ++ .../resources/js/qpid/common/widgetconfigurer.js | 7 +- .../js/qpid/management/addAccessControlProvider.js | 25 +- .../qpid/management/addAuthenticationProvider.js | 38 +- .../resources/js/qpid/management/addBinding.js | 29 +- .../resources/js/qpid/management/addExchange.js | 21 +- .../js/qpid/management/addGroupProvider.js | 30 +- .../java/resources/js/qpid/management/addPort.js | 28 +- .../java/resources/js/qpid/management/addQueue.js | 22 +- .../java/resources/js/qpid/management/addStore.js | 33 +- .../management/addVirtualHostNodeAndVirtualHost.js | 26 +- .../PrincipalDatabaseAuthenticationManager.js | 27 +- .../js/qpid/management/group/addGroupMember.js | 19 +- .../groupprovider/GroupManagingGroupProvider.js | 13 +- .../preferencesprovider/PreferencesProviderForm.js | 32 +- .../server/jmx/mbeans/VirtualHostManagerMBean.java | 2 +- .../jmx/mbeans/VirtualHostManagerMBeanTest.java | 2 +- .../apache/qpid/systest/rest/RestTestHelper.java | 4 +- .../apache/qpid/systest/rest/GroupRestTest.java | 26 +- .../org/apache/qpid/systest/rest/UserRestTest.java | 22 +- .../qpid/systest/rest/VirtualHostNodeRestTest.java | 17 + .../qpid/systest/rest/VirtualHostRestTest.java | 35 +- .../apache/qpid/tools/util/ArgumentsParser.java | 20 + 81 files changed, 1766 insertions(+), 1435 deletions(-) create mode 100644 qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerAssembler.java (limited to 'qpid/java') 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 _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 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 { @@ -162,8 +166,14 @@ public class SendingLinkEndpoint extends LinkEndpoint 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 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 implements BDBHARemoteReplicationNode @@ -122,27 +120,6 @@ public class BDBHARemoteReplicationNodeImpl extends AbstractConfiguredObject proxyForValidation, - final Set 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 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; @@ -140,12 +139,6 @@ public abstract class AbstractExchange> }; } - @Override - public void validateOnCreate() - { - _virtualHost.getSecurityManager().authoriseCreateExchange(this); - } - @Override public void onValidate() { @@ -195,8 +188,6 @@ public abstract class AbstractExchange> @Override public void deleteWithChecks() { - _virtualHost.getSecurityManager().authoriseDelete(this); - if(hasReferrers()) { throw new ExchangeIsAlternateException(getName()); @@ -656,7 +647,7 @@ public abstract class AbstractExchange> } // Check access - _virtualHost.getSecurityManager().authoriseUnbind(binding); + authoriseDelete(binding); BindingImpl b = _bindingsMap.remove(new BindingIdentifier(bindingKey,queue)); @@ -810,7 +801,7 @@ public abstract class AbstractExchange> preSetAlternateExchange(); setState(State.DELETED); } - catch (ExchangeIsAlternateException | RequiredExchangeException e) + catch (ExchangeIsAlternateException e) { } @@ -925,16 +916,5 @@ public abstract class AbstractExchange> return binding; } - @Override - protected void authoriseSetAttributes(ConfiguredObject modified, Set attributes) throws AccessControlException - { - _virtualHost.getSecurityManager().authoriseUpdate(this); - } - - @Override - protected void changeAttributes(final Map 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> im } } - }); - - } else { - authoriseSetDesiredState(desiredState); - validateChange(createProxyForValidation(Collections.singletonMap( - ConfiguredObject.DESIRED_STATE, - desiredState)), Collections.singleton(ConfiguredObject.DESIRED_STATE)); + ConfiguredObject proxyForValidation = + createProxyForValidation(Collections.singletonMap( + ConfiguredObject.DESIRED_STATE, + desiredState)); + Set 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> im } } - protected void authoriseSetAttributes(final ConfiguredObject proxyForValidation, - final Set modifiedAttributes) - { - - } - protected void changeAttributes(final Map attributes) { Collection names = getAttributeNames(); @@ -2077,17 +2072,61 @@ public abstract class AbstractConfiguredObject> 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 category, + final Map 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 void authoriseCreateChild(Class childClass, Map attributes, ConfiguredObject... otherParents) throws AccessControlException + protected final > void authoriseCreateChild(Class childClass, Map 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 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> im } - private class AttributeGettingHandler implements InvocationHandler + private static class AttributeGettingHandler implements InvocationHandler { - private Map _attributes; + private final Map _attributes; + private final Map> _attributeTypes; + private final ConfiguredObject _configuredObject; - AttributeGettingHandler(final Map modifiedAttributes) + AttributeGettingHandler(final Map modifiedAttributes, Map> attributeTypes, ConfiguredObject configuredObject) { - Map combinedAttributes = new HashMap(getActualAttributes()); + Map 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> 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> im } } + private static class AuthorisationProxyInvocationHandler extends AttributeGettingHandler + { + private final Class _category; + private final Map, ConfiguredObject> _parents; + private final ConfiguredObject _parent ; + + AuthorisationProxyInvocationHandler(Map attributes, + Map> attributeTypes, + Class 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 parentClass = (Class )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> extends AbstractConfiguredObject implements Plugin { @@ -70,27 +67,6 @@ public abstract class AbstractPluginAdapter> 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 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; @@ -907,35 +906,6 @@ public class BrokerAdapter extends AbstractConfiguredObject imple return children; } - @Override - protected void authoriseCreateChild(Class childClass, Map 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 attributes) throws AccessControlException - { - if (!_securityManager.authoriseConfiguringBroker(getName(), Broker.class, Operation.UPDATE)) - { - throw new AccessControlException("Setting of broker attributes is denied"); - } - } - @Override public boolean 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 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 implements Group { 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 attrMap = new HashMap(); @@ -486,7 +459,6 @@ public class FileBasedGroupProviderImpl @StateTransition( currentState = State.ACTIVE, desiredState = State.DELETED ) private ListenableFuture 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 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 getPreferences(String userId) { + getSecurityManager().authoriseUserUpdate(userId); return _store == null? Collections.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> extends AbstractConfiguredObject implements Port { @@ -276,28 +274,6 @@ abstract public class AbstractPort> 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 attributes) throws AccessControlException - { - if (!_broker.getSecurityManager().authoriseConfiguringBroker(getName(), Port.class, Operation.UPDATE)) - { - throw new AccessControlException("Setting of port attributes is denied"); - } - } - @Override public Collection 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 @@ -272,12 +272,6 @@ public abstract class AbstractQueue> } - @Override - protected void validateOnCreate() - { - _virtualHost.getSecurityManager().authoriseCreateQueue(this); - } - @Override protected void onCreate() { @@ -3049,12 +3043,6 @@ public abstract class AbstractQueue> } } - @Override - protected void authoriseSetAttributes(ConfiguredObject modified, Set 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 createAttributeMap(String name, FilterManager filters, EnumSet