diff options
| author | Alex Rudyy <orudyy@apache.org> | 2013-03-29 17:30:54 +0000 |
|---|---|---|
| committer | Alex Rudyy <orudyy@apache.org> | 2013-03-29 17:30:54 +0000 |
| commit | 9dbb92b10991f7c0c75aebda6d4a2f33fd43f787 (patch) | |
| tree | 0431f53602889ed315c110f7de867747682c7dc8 /java/broker | |
| parent | 0257f4d2d1ccd3916cf22ba71773ceef6eb44473 (diff) | |
| download | qpid-python-9dbb92b10991f7c0c75aebda6d4a2f33fd43f787.tar.gz | |
QPID-4678: Add ACL checks to restrict the operations to change broker level configuration through the management interfaces
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk/qpid@1462551 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'java/broker')
11 files changed, 243 insertions, 9 deletions
diff --git a/java/broker/etc/broker_example.acl b/java/broker/etc/broker_example.acl index fc650801c8..bb85ef5e57 100644 --- a/java/broker/etc/broker_example.acl +++ b/java/broker/etc/broker_example.acl @@ -72,6 +72,9 @@ ACL ALLOW-LOG webadmins UPDATE USER ACL ALLOW-LOG webadmins UPDATE METHOD +# authorise operations changing broker model +ACL ALLOW-LOG webadmins CONFIGURE BROKER + # at the moment only the following UPDATE METHOD rules are supported by web management console #ACL ALLOW-LOG webadmins UPDATE METHOD component="VirtualHost.Queue" name="moveMessages" #ACL ALLOW-LOG webadmins UPDATE METHOD component="VirtualHost.Queue" name="copyMessages" diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractAdapter.java index ce8e06bf4f..8ff0b6d9e1 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractAdapter.java +++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractAdapter.java @@ -90,6 +90,7 @@ abstract class AbstractAdapter implements ConfiguredObject public final State setDesiredState(final State currentState, final State desiredState) throws IllegalStateTransitionException, AccessControlException { + authoriseSetDesiredState(currentState, desiredState); if (_taskExecutor.isTaskExecutorThread()) { if (setState(currentState, desiredState)) @@ -224,6 +225,7 @@ abstract class AbstractAdapter implements ConfiguredObject public Object setAttribute(final String name, final Object expected, final Object desired) throws IllegalStateException, AccessControlException, IllegalArgumentException { + authoriseSetAttribute(name, expected, desired); if (_taskExecutor.isTaskExecutorThread()) { if (changeAttribute(name, expected, desired)) @@ -302,6 +304,7 @@ abstract class AbstractAdapter implements ConfiguredObject @Override public <C extends ConfiguredObject> C createChild(Class<C> childClass, Map<String, Object> attributes, ConfiguredObject... otherParents) { + authoriseCreateChild(childClass, attributes, otherParents); if (_taskExecutor.isTaskExecutorThread()) { C child = addChild(childClass, attributes, otherParents); @@ -331,6 +334,7 @@ abstract class AbstractAdapter implements ConfiguredObject @Override public void setAttributes(final Map<String, Object> attributes) throws IllegalStateException, AccessControlException, IllegalArgumentException { + authoriseSetAttributes(attributes); if (getTaskExecutor().isTaskExecutorThread()) { changeAttributes(attributes); @@ -357,4 +361,24 @@ abstract class AbstractAdapter implements ConfiguredObject } } } + + protected void authoriseSetDesiredState(State currentState, State desiredState) throws AccessControlException + { + // allowed by default + } + + protected void authoriseSetAttribute(String name, Object expected, Object desired) throws AccessControlException + { + // allowed by default + } + + protected <C extends ConfiguredObject> void authoriseCreateChild(Class<C> childClass, Map<String, Object> attributes, ConfiguredObject... otherParents) throws AccessControlException + { + // allowed by default + } + + protected void authoriseSetAttributes(Map<String, Object> attributes) throws AccessControlException + { + // allowed by default + } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderAdapter.java index 0c17637e2f..594ef7520a 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderAdapter.java +++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderAdapter.java @@ -316,6 +316,36 @@ public abstract class AuthenticationProviderAdapter<T extends AuthenticationMana return manager; } + @Override + protected void authoriseSetDesiredState(State currentState, 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 authoriseSetAttribute(String name, Object expected, Object desired) throws AccessControlException + { + if (!_broker.getSecurityManager().authoriseConfiguringBroker(getName(), AuthenticationProvider.class, Operation.UPDATE)) + { + throw new AccessControlException("Setting of authentication provider attributes is denied"); + } + } + + @Override + protected void authoriseSetAttributes(Map<String, Object> attributes) throws AccessControlException + { + if (!_broker.getSecurityManager().authoriseConfiguringBroker(getName(), AuthenticationProvider.class, Operation.UPDATE)) + { + throw new AccessControlException("Setting of authentication provider attributes is denied"); + } + } + public static class SimpleAuthenticationProviderAdapter extends AuthenticationProviderAdapter<AuthenticationManager> { diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java index 54c28f81d0..97acac668b 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java +++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java @@ -59,8 +59,7 @@ import org.apache.qpid.server.model.TrustStore; import org.apache.qpid.server.model.UUIDGenerator; import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.configuration.updater.TaskExecutor; -import org.apache.qpid.server.security.auth.manager.Base64MD5PasswordFileAuthenticationManagerFactory; -import org.apache.qpid.server.security.auth.manager.PlainPasswordFileAuthenticationManagerFactory; +import org.apache.qpid.server.security.access.Operation; import org.apache.qpid.server.security.group.FileGroupManager; import org.apache.qpid.server.security.group.GroupManager; import org.apache.qpid.server.security.SecurityManager; @@ -390,7 +389,18 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat final VirtualHostAdapter virtualHostAdapter = new VirtualHostAdapter(UUID.randomUUID(), attributes, this, _statisticsGatherer, getTaskExecutor()); addVirtualHost(virtualHostAdapter); - virtualHostAdapter.setDesiredState(State.INITIALISING, State.ACTIVE); + + // permission has already been granted to create the virtual host + // disable further access check on other operations, e.g. create exchange + _securityManager.setAccessChecksDisabled(true); + try + { + virtualHostAdapter.setDesiredState(State.INITIALISING, State.ACTIVE); + } + finally + { + _securityManager.setAccessChecksDisabled(false); + } return virtualHostAdapter; } @@ -1031,7 +1041,6 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat @Override protected void changeAttributes(Map<String, Object> attributes) { - //TODO: Add ACL check //TODO: Add management mode check Map<String, Object> convertedAttributes = MapValueConverter.convert(attributes, ATTRIBUTE_TYPES); validateAttributes(convertedAttributes); @@ -1200,4 +1209,32 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat } } } + + @Override + protected void authoriseSetAttribute(String name, Object expected, Object desired) throws AccessControlException + { + if (!_securityManager.authoriseConfiguringBroker(getName(), Broker.class, Operation.UPDATE)) + { + throw new AccessControlException("Setting of broker attributes is denied"); + } + } + + @Override + protected <C extends ConfiguredObject> void authoriseCreateChild(Class<C> childClass, Map<String, Object> attributes, + ConfiguredObject... otherParents) throws AccessControlException + { + 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(Map<String, Object> attributes) throws AccessControlException + { + if (!_securityManager.authoriseConfiguringBroker(getName(), Broker.class, Operation.UPDATE)) + { + throw new AccessControlException("Setting of broker attributes is denied"); + } + } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java index 63063ff58c..a37c2dceb7 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java +++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java @@ -45,6 +45,7 @@ import org.apache.qpid.server.model.Statistics; import org.apache.qpid.server.model.Transport; import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.model.VirtualHostAlias; +import org.apache.qpid.server.security.access.Operation; import org.apache.qpid.server.util.MapValueConverter; import org.apache.qpid.server.util.ParameterizedTypeImpl; import org.apache.qpid.server.configuration.updater.TaskExecutor; @@ -356,4 +357,34 @@ public class PortAdapter extends AbstractAdapter implements Port } super.changeAttributes(MapValueConverter.convert(attributes, ATTRIBUTE_TYPES)); } + + @Override + protected void authoriseSetDesiredState(State currentState, 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 authoriseSetAttribute(String name, Object expected, Object desired) throws AccessControlException + { + if (!_broker.getSecurityManager().authoriseConfiguringBroker(getName(), Port.class, Operation.UPDATE)) + { + throw new AccessControlException("Setting of port attributes is denied"); + } + } + + @Override + protected void authoriseSetAttributes(Map<String, Object> attributes) throws AccessControlException + { + if (!_broker.getSecurityManager().authoriseConfiguringBroker(getName(), Port.class, Operation.UPDATE)) + { + throw new AccessControlException("Setting of port attributes is denied"); + } + } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java index 884e688b4b..09fc3a446f 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java +++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java @@ -71,6 +71,7 @@ import org.apache.qpid.server.queue.AMQQueueFactory; import org.apache.qpid.server.queue.QueueEntry; import org.apache.qpid.server.queue.QueueRegistry; import org.apache.qpid.server.security.SecurityManager; +import org.apache.qpid.server.security.access.Operation; import org.apache.qpid.server.security.auth.AuthenticatedPrincipal; import org.apache.qpid.server.stats.StatisticsGatherer; import org.apache.qpid.server.store.MessageStore; @@ -980,8 +981,6 @@ public final class VirtualHostAdapter extends AbstractAdapter implements Virtual } else if (desiredState == State.DELETED) { - //TODO: add ACL check to authorize the operation - String hostName = getName(); if (hostName.equals(_broker.getAttribute(Broker.DEFAULT_VIRTUAL_HOST))) @@ -1091,4 +1090,34 @@ public final class VirtualHostAdapter extends AbstractAdapter implements Virtual { throw new UnsupportedOperationException("Changing attributes on virtualhosts is not supported."); } + + @Override + protected void authoriseSetDesiredState(State currentState, State desiredState) throws AccessControlException + { + if(desiredState == State.DELETED) + { + if (!_broker.getSecurityManager().authoriseConfiguringBroker(getName(), VirtualHost.class, Operation.DELETE)) + { + throw new AccessControlException("Deletion of virtual host is denied"); + } + } + } + + @Override + protected void authoriseSetAttribute(String name, Object expected, Object desired) throws AccessControlException + { + if (!_broker.getSecurityManager().authoriseConfiguringBroker(getName(), VirtualHost.class, Operation.UPDATE)) + { + throw new AccessControlException("Setting of virtual host attributes is denied"); + } + } + + @Override + protected void authoriseSetAttributes(Map<String, Object> attributes) throws AccessControlException + { + if (!_broker.getSecurityManager().authoriseConfiguringBroker(getName(), VirtualHost.class, Operation.UPDATE)) + { + throw new AccessControlException("Setting of virtual host attributes is denied"); + } + } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/SecurityManager.java b/java/broker/src/main/java/org/apache/qpid/server/security/SecurityManager.java index 9ef1ae1a3a..3fb3f70f2e 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/security/SecurityManager.java +++ b/java/broker/src/main/java/org/apache/qpid/server/security/SecurityManager.java @@ -33,7 +33,9 @@ import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.security.access.ObjectProperties; import org.apache.qpid.server.security.access.ObjectType; import org.apache.qpid.server.security.access.Operation; +import org.apache.qpid.server.security.access.OperationLoggingDetails; +import 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; @@ -41,6 +43,7 @@ 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.Operation.BIND; +import static org.apache.qpid.server.security.access.Operation.CONFIGURE; import static org.apache.qpid.server.security.access.Operation.CONSUME; import static org.apache.qpid.server.security.access.Operation.CREATE; import static org.apache.qpid.server.security.access.Operation.DELETE; @@ -549,4 +552,20 @@ public class SecurityManager implements ConfigurationChangeListener } } + 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); + } + }); + } + } diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java b/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java index 8e38681e68..6c631fc360 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java +++ b/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java @@ -350,4 +350,9 @@ public class ObjectProperties { return _properties.toString(); } + + public boolean isEmpty() + { + return _properties.isEmpty(); + } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectType.java b/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectType.java index 8bc4b9d278..e93f487bdb 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectType.java +++ b/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectType.java @@ -20,6 +20,7 @@ package org.apache.qpid.server.security.access; import static org.apache.qpid.server.security.access.Operation.ACCESS; import static org.apache.qpid.server.security.access.Operation.BIND; +import static org.apache.qpid.server.security.access.Operation.CONFIGURE; import static org.apache.qpid.server.security.access.Operation.CONSUME; import static org.apache.qpid.server.security.access.Operation.CREATE; import static org.apache.qpid.server.security.access.Operation.DELETE; @@ -48,7 +49,8 @@ public enum ObjectType ROUTE, // Not allowed in the Java broker METHOD(Operation.ALL, ACCESS, UPDATE), USER(Operation.ALL, CREATE, DELETE, UPDATE), - GROUP(Operation.ALL, CREATE, DELETE, UPDATE); + GROUP(Operation.ALL, CREATE, DELETE, UPDATE), + BROKER(Operation.ALL, CONFIGURE); private EnumSet<Operation> _actions; diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/access/Operation.java b/java/broker/src/main/java/org/apache/qpid/server/security/access/Operation.java index 21ea042eed..df5289b7bf 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/security/access/Operation.java +++ b/java/broker/src/main/java/org/apache/qpid/server/security/access/Operation.java @@ -32,8 +32,9 @@ public enum Operation UNBIND, DELETE, PURGE, - UPDATE; - + UPDATE, + CONFIGURE; + public static Operation parse(String text) { for (Operation operation : values()) diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/access/OperationLoggingDetails.java b/java/broker/src/main/java/org/apache/qpid/server/security/access/OperationLoggingDetails.java new file mode 100644 index 0000000000..a683199abc --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/security/access/OperationLoggingDetails.java @@ -0,0 +1,53 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.security.access; + + +public class OperationLoggingDetails extends ObjectProperties +{ + private String _description; + + public OperationLoggingDetails(String description) + { + super(); + _description = description; + } + + @Override + public String toString() + { + StringBuilder sb = new StringBuilder("("); + if (!super.isEmpty()) + { + sb.append("properties=").append(super.toString()); + } + if (_description != null) + { + if (sb.length() > 1) + { + sb.append(", "); + } + sb.append(_description); + } + sb.append(")"); + return sb.toString(); + } +} |
