From 59c39b43a3d42498d065962aff6e3b5d58da6dbc Mon Sep 17 00:00:00 2001 From: Keith Wall Date: Thu, 24 Nov 2011 10:43:24 +0000 Subject: QPID-3641: ACLV2 Simplifications and Improvements for Java Broker Improvements and simplifications to ACL V2 for the Java Broker: 1) Removed 'EXECUTE' operation (we now just have ACCESS and UPDATE like C++ broker) 2) Enable users with management rights for a procedure to complete that procedure without matching AMQP rights (configurable) 3) Fix up system tests (make clearer, remove need for lots of support files) 4) Fix disparity in DENY_LOG and DENY-LOG values between brokers. 5) Get rid of transitive/expand permission rules Work from Robbie Gemmell and myself. git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk/qpid@1205782 13f79535-47bb-0310-9956-ffa450edef68 --- .../server/security/access/config/RuleSet.java | 111 +--- .../security/access/plugins/AccessControl.java | 1 + .../security/access/plugins/RuleSetTest.java | 1 - java/broker/etc/broker_example.acl | 63 +++ java/broker/etc/config.xml | 7 +- .../apache/qpid/server/binding/BindingFactory.java | 26 +- .../server/configuration/ServerConfiguration.java | 5 + .../management/MBeanInvocationHandlerImpl.java | 137 +++-- .../qpid/server/security/AbstractProxyPlugin.java | 7 - .../qpid/server/security/SecurityManager.java | 52 +- .../qpid/server/security/access/ObjectType.java | 10 +- .../qpid/server/security/access/Operation.java | 3 +- .../configuration/ServerConfigurationTest.java | 12 + .../etc/config-systests-aclv2-settings.xml | 30 - java/systests/etc/config-systests-aclv2.xml | 30 - java/systests/etc/global-default.txt | 31 - ...al-externaladminacl-changeloggerleveldenied.txt | 24 - ...l-externaladminacl-getallloggerlevelsdenied.txt | 25 - java/systests/etc/test-default.txt | 73 --- .../test-externalacljmx-deleteexchangefailure.txt | 26 - java/systests/etc/test-externalacljmx.txt | 35 -- java/systests/etc/test-logging.txt | 23 - java/systests/etc/test2-default.txt | 21 - .../etc/virtualhosts-systests-aclv2-settings.xml | 48 -- java/systests/etc/virtualhosts-systests-aclv2.xml | 29 - .../server/logging/AccessControlLoggingTest.java | 17 +- .../server/security/acl/AbstractACLTestCase.java | 88 +-- .../server/security/acl/ExhaustiveACLTest.java | 26 +- .../server/security/acl/ExternalACLFileTest.java | 19 +- .../server/security/acl/ExternalACLJMXTest.java | 342 ++++++----- .../qpid/server/security/acl/ExternalACLTest.java | 628 +++++++-------------- .../server/security/acl/ExternalAdminACLTest.java | 186 ------ .../apache/qpid/test/utils/QpidBrokerTestCase.java | 2 +- 33 files changed, 674 insertions(+), 1464 deletions(-) create mode 100644 java/broker/etc/broker_example.acl delete mode 100644 java/systests/etc/config-systests-aclv2-settings.xml delete mode 100644 java/systests/etc/config-systests-aclv2.xml delete mode 100644 java/systests/etc/global-default.txt delete mode 100644 java/systests/etc/global-externaladminacl-changeloggerleveldenied.txt delete mode 100644 java/systests/etc/global-externaladminacl-getallloggerlevelsdenied.txt delete mode 100644 java/systests/etc/test-default.txt delete mode 100644 java/systests/etc/test-externalacljmx-deleteexchangefailure.txt delete mode 100644 java/systests/etc/test-externalacljmx.txt delete mode 100644 java/systests/etc/test-logging.txt delete mode 100644 java/systests/etc/test2-default.txt delete mode 100644 java/systests/etc/virtualhosts-systests-aclv2-settings.xml delete mode 100644 java/systests/etc/virtualhosts-systests-aclv2.xml delete mode 100644 java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalAdminACLTest.java (limited to 'java') diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/RuleSet.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/RuleSet.java index 78355a7501..94f05ed265 100644 --- a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/RuleSet.java +++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/RuleSet.java @@ -36,7 +36,7 @@ import javax.security.auth.Subject; import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang.StringUtils; -import org.apache.qpid.exchange.ExchangeDefaults; +import org.apache.log4j.Logger; import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.security.Result; import org.apache.qpid.server.security.access.ObjectProperties; @@ -53,20 +53,15 @@ import org.apache.qpid.server.security.access.logging.AccessControlMessages; */ public class RuleSet { + public static final Logger _logger = Logger.getLogger(RuleSet.class); + private static final String AT = "@"; private static final String SLASH = "/"; public static final String DEFAULT_ALLOW = "defaultallow"; public static final String DEFAULT_DENY = "defaultdeny"; - public static final String TRANSITIVE = "transitive"; - public static final String EXPAND = "expand"; - public static final String AUTONUMBER = "autonumber"; - public static final String CONTROLLED = "controlled"; - public static final String VALIDATE = "validate"; - public static final List CONFIG_PROPERTIES = Arrays.asList( - DEFAULT_ALLOW, DEFAULT_DENY, TRANSITIVE, EXPAND, AUTONUMBER, CONTROLLED - ); + public static final List CONFIG_PROPERTIES = Arrays.asList(DEFAULT_ALLOW, DEFAULT_DENY); private static final Integer _increment = 10; @@ -80,7 +75,6 @@ public class RuleSet { // set some default configuration properties configure(DEFAULT_DENY, Boolean.TRUE); - configure(TRANSITIVE, Boolean.TRUE); } /** @@ -139,10 +133,20 @@ public class RuleSet // Save the rules we selected objects.put(objectType, filtered); + if(_logger.isDebugEnabled()) + { + _logger.debug("Cached " + objectType + " RulesList: " + filtered); + } } // Return the cached rules - return objects.get(objectType); + List rules = objects.get(objectType); + if(_logger.isDebugEnabled()) + { + _logger.debug("Returning RuleList: " + rules); + } + + return rules; } @@ -175,20 +179,6 @@ public class RuleSet return false; } - private Permission noLog(Permission permission) - { - switch (permission) - { - case ALLOW: - case ALLOW_LOG: - return Permission.ALLOW; - case DENY: - case DENY_LOG: - default: - return Permission.DENY; - } - } - // TODO make this work when group membership is not known at file parse time public void addRule(Integer number, String identity, Permission permission, Action action) { @@ -196,63 +186,13 @@ public class RuleSet if (!action.isAllowed()) { - throw new IllegalArgumentException("Action is not allowd: " + action); + throw new IllegalArgumentException("Action is not allowed: " + action); } if (ruleExists(identity, action)) { return; } - // expand actions - possibly multiply number by - if (isSet(EXPAND)) - { - if (action.getOperation() == Operation.CREATE && action.getObjectType() == ObjectType.TOPIC) - { - addRule(null, identity, noLog(permission), new Action(Operation.BIND, ObjectType.EXCHANGE, - new ObjectProperties("amq.topic", action.getProperties().get(ObjectProperties.Property.NAME)))); - ObjectProperties topicProperties = new ObjectProperties(); - topicProperties.put(ObjectProperties.Property.DURABLE, true); - addRule(null, identity, permission, new Action(Operation.CREATE, ObjectType.QUEUE, topicProperties)); - return; - } - if (action.getOperation() == Operation.DELETE && action.getObjectType() == ObjectType.TOPIC) - { - addRule(null, identity, noLog(permission), new Action(Operation.UNBIND, ObjectType.EXCHANGE, - new ObjectProperties("amq.topic", action.getProperties().get(ObjectProperties.Property.NAME)))); - ObjectProperties topicProperties = new ObjectProperties(); - topicProperties.put(ObjectProperties.Property.DURABLE, true); - addRule(null, identity, permission, new Action(Operation.DELETE, ObjectType.QUEUE, topicProperties)); - return; - } - } - - // transitive action dependencies - if (isSet(TRANSITIVE)) - { - if (action.getOperation() == Operation.CREATE && action.getObjectType() == ObjectType.QUEUE) - { - ObjectProperties exchProperties = new ObjectProperties(action.getProperties()); - exchProperties.setName(ExchangeDefaults.DEFAULT_EXCHANGE_NAME); - exchProperties.put(ObjectProperties.Property.ROUTING_KEY, action.getProperties().get(ObjectProperties.Property.NAME)); - addRule(null, identity, noLog(permission), new Action(Operation.BIND, ObjectType.EXCHANGE, exchProperties)); - if (action.getProperties().isSet(ObjectProperties.Property.AUTO_DELETE)) - { - addRule(null, identity, noLog(permission), new Action(Operation.DELETE, ObjectType.QUEUE, action.getProperties())); - } - } - else if (action.getOperation() == Operation.DELETE && action.getObjectType() == ObjectType.QUEUE) - { - ObjectProperties exchProperties = new ObjectProperties(action.getProperties()); - exchProperties.setName(ExchangeDefaults.DEFAULT_EXCHANGE_NAME); - exchProperties.put(ObjectProperties.Property.ROUTING_KEY, action.getProperties().get(ObjectProperties.Property.NAME)); - addRule(null, identity, noLog(permission), new Action(Operation.UNBIND, ObjectType.EXCHANGE, exchProperties)); - } - else if (action.getOperation() != Operation.ACCESS && action.getObjectType() != ObjectType.VIRTUALHOST) - { - addRule(null, identity, noLog(permission), new Action(Operation.ACCESS, ObjectType.VIRTUALHOST)); - } - } - // set rule number if needed Rule rule = new Rule(number, identity, action, permission); if (rule.getNumber() == null) @@ -392,24 +332,29 @@ public class RuleSet // Create the action to check Action action = new Action(operation, objectType, properties); + if(_logger.isDebugEnabled()) + { + _logger.debug("Checking action: " + action); + } + // get the list of rules relevant for this request List rules = getRules(subject, operation, objectType); if (rules == null) { - if (isSet(CONTROLLED)) + if(_logger.isDebugEnabled()) { - // Abstain if there are no rules for this operation - return Result.ABSTAIN; - } - else - { - return getDefault(); + _logger.debug("No rules found, returning default result"); } + return getDefault(); } // Iterate through a filtered set of rules dealing with this identity and operation for (Rule current : rules) { + if(_logger.isDebugEnabled()) + { + _logger.debug("Checking against rule: " + current); + } // Check if action matches if (action.matches(current.getAction())) { diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControl.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControl.java index a7b3059262..a97b66a287 100644 --- a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControl.java +++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControl.java @@ -101,6 +101,7 @@ public class AccessControl extends AbstractPlugin return Result.ABSTAIN; } + _logger.debug("Checking " + operation + " " + objectType); return _ruleSet.check(subject, operation, objectType, properties); } diff --git a/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java index bd9deac153..4d46a32f45 100644 --- a/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java +++ b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java @@ -69,7 +69,6 @@ public class RuleSetTest extends QpidTestCase super.setUp(); _ruleSet = new RuleSet(); - _ruleSet.configure(RuleSet.TRANSITIVE, Boolean.FALSE); } @Override diff --git a/java/broker/etc/broker_example.acl b/java/broker/etc/broker_example.acl new file mode 100644 index 0000000000..93955bb7f9 --- /dev/null +++ b/java/broker/etc/broker_example.acl @@ -0,0 +1,63 @@ +# +# 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. +# + +### EXAMPLE ACL V2 FILE + +### DEFINE GROUPS ### + +#Define a 'messaging-users' group with users 'client' and 'server' in it +GROUP messaging-users client server + +### MANAGEMENT #### + +#Allow 'guest' to perform read operations on the Serverinformation mbean and view logger levels +ACL ALLOW-LOG guest ACCESS METHOD component="ServerInformation" +ACL ALLOW-LOG guest ACCESS METHOD component="LoggingManagement" name="viewEffectiveRuntimeLoggerLevels" + +#Allow 'admin' all management operations +ACL ALLOW-LOG admin ALL METHOD + +### MESSAGING ### + +#Example permissions for request-response based messaging. + +#Allow 'messaging-users' group to connect to the virtualhost +ACL ALLOW-LOG messaging-users ACCESS VIRTUALHOST + +# Client side +# Allow the 'client' user to publish requests to the request queue and create, consume from, and delete temporary reply queues. +ACL ALLOW-LOG client CREATE QUEUE temporary="true" +ACL ALLOW-LOG client CONSUME QUEUE temporary="true" +ACL ALLOW-LOG client DELETE QUEUE temporary="true" +ACL ALLOW-LOG client BIND EXCHANGE name="amq.direct" temporary="true" +ACL ALLOW-LOG client UNBIND EXCHANGE name="amq.direct" temporary="true" +ACL ALLOW-LOG client PUBLISH EXCHANGE name="amq.direct" routingKey="example.RequestQueue" + +# Server side +# Allow the 'server' user to create and consume from the request queue and publish a response to the temporary response queue created by +# client. +ACL ALLOW-LOG server CREATE QUEUE name="example.RequestQueue" +ACL ALLOW-LOG server CONSUME QUEUE name="example.RequestQueue" +ACL ALLOW-LOG server BIND EXCHANGE +ACL ALLOW-LOG server PUBLISH EXCHANGE name="amq.direct" routingKey="TempQueue*" + +### DEFAULT ### + +#Deny all users from performing all operations +ACL DENY-LOG all all diff --git a/java/broker/etc/config.xml b/java/broker/etc/config.xml index d18e1392e6..389f380c31 100644 --- a/java/broker/etc/config.xml +++ b/java/broker/etc/config.xml @@ -80,7 +80,12 @@ - + + + false diff --git a/java/broker/src/main/java/org/apache/qpid/server/binding/BindingFactory.java b/java/broker/src/main/java/org/apache/qpid/server/binding/BindingFactory.java index 400ce50bc4..94ab43c851 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/binding/BindingFactory.java +++ b/java/broker/src/main/java/org/apache/qpid/server/binding/BindingFactory.java @@ -170,11 +170,17 @@ public class BindingFactory { arguments = Collections.emptyMap(); } - - //Perform ACLs - if (!getVirtualHost().getSecurityManager().authoriseBind(exchange, queue, new AMQShortString(bindingKey))) + + // The default exchange bindings must reflect the existence of queues, allow + // all operations on it to succeed. It is up to the broker to prevent illegal + // attempts at binding to this exchange, not the ACLs. + if(exchange != _defaultExchange) { - throw new AMQSecurityException("Permission denied: binding " + bindingKey); + //Perform ACLs + if (!getVirtualHost().getSecurityManager().authoriseBind(exchange, queue, new AMQShortString(bindingKey))) + { + throw new AMQSecurityException("Permission denied: binding " + bindingKey); + } } BindingImpl b = new BindingImpl(bindingKey,queue,exchange,arguments); @@ -238,10 +244,16 @@ public class BindingFactory arguments = Collections.emptyMap(); } - // Check access - if (!getVirtualHost().getSecurityManager().authoriseUnbind(exchange, new AMQShortString(bindingKey), queue)) + // The default exchange bindings must reflect the existence of queues, allow + // all operations on it to succeed. It is up to the broker to prevent illegal + // attempts at binding to this exchange, not the ACLs. + if(exchange != _defaultExchange) { - throw new AMQSecurityException("Permission denied: binding " + bindingKey); + // Check access + if (!getVirtualHost().getSecurityManager().authoriseUnbind(exchange, new AMQShortString(bindingKey), queue)) + { + throw new AMQSecurityException("Permission denied: unbinding " + bindingKey); + } } BindingImpl b = _bindings.remove(new BindingImpl(bindingKey,queue,exchange,arguments)); diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java index 0d347873c2..e13e2f4d8f 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java @@ -805,4 +805,9 @@ public class ServerConfiguration extends ConfigurationPlugin final List disabledFeatures = getListValue("disabledFeatures", Collections.emptyList()); return disabledFeatures; } + + public boolean getManagementRightsInferAllAccess() + { + return getBooleanValue("management.managementRightsInferAllAccess", true); + } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/management/MBeanInvocationHandlerImpl.java b/java/broker/src/main/java/org/apache/qpid/server/management/MBeanInvocationHandlerImpl.java index 169195304c..0dd8c95ef3 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/management/MBeanInvocationHandlerImpl.java +++ b/java/broker/src/main/java/org/apache/qpid/server/management/MBeanInvocationHandlerImpl.java @@ -33,6 +33,7 @@ import javax.management.JMException; import javax.management.MBeanInfo; import javax.management.MBeanOperationInfo; import javax.management.MBeanServer; +import javax.management.MalformedObjectNameException; import javax.management.Notification; import javax.management.NotificationListener; import javax.management.ObjectName; @@ -45,6 +46,7 @@ import org.apache.log4j.Logger; import org.apache.qpid.server.logging.actors.ManagementActor; import org.apache.qpid.server.logging.messages.ManagementConsoleMessages; import org.apache.qpid.server.registry.ApplicationRegistry; +import org.apache.qpid.server.registry.IApplicationRegistry; import org.apache.qpid.server.security.SecurityManager; import org.apache.qpid.server.security.access.Operation; @@ -56,22 +58,54 @@ public class MBeanInvocationHandlerImpl implements InvocationHandler, Notificati { private static final Logger _logger = Logger.getLogger(MBeanInvocationHandlerImpl.class); + private final IApplicationRegistry _appRegistry = ApplicationRegistry.getInstance(); private final static String DELEGATE = "JMImplementation:type=MBeanServerDelegate"; private MBeanServer _mbs; - private static ManagementActor _logActor; - + private final ManagementActor _logActor = new ManagementActor(_appRegistry.getRootMessageLogger()); + private final boolean _managementRightsInferAllAccess = + _appRegistry.getConfiguration().getManagementRightsInferAllAccess(); + public static MBeanServerForwarder newProxyInstance() { final InvocationHandler handler = new MBeanInvocationHandlerImpl(); final Class[] interfaces = new Class[] { MBeanServerForwarder.class }; - - _logActor = new ManagementActor(ApplicationRegistry.getInstance().getRootMessageLogger()); - Object proxy = Proxy.newProxyInstance(MBeanServerForwarder.class.getClassLoader(), interfaces, handler); return MBeanServerForwarder.class.cast(proxy); } + private boolean invokeDirectly(String methodName, Object[] args, Subject subject) + { + // Allow operations performed locally on behalf of the connector server itself + if (subject == null) + { + return true; + } + + if (args == null || DELEGATE.equals(args[0])) + { + return true; + } + + // Allow querying available object names + if (methodName.equals("queryNames")) + { + return true; + } + + if (args[0] instanceof ObjectName) + { + ObjectName mbean = (ObjectName) args[0]; + + if(!DefaultManagedObject.DOMAIN.equalsIgnoreCase(mbean.getDomain())) + { + return true; + } + } + + return false; + } + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { final String methodName = getMethodName(method, args); @@ -95,36 +129,24 @@ public class MBeanInvocationHandlerImpl implements InvocationHandler, Notificati return null; } + // Restrict access to "createMBean" and "unregisterMBean" to any user + if (methodName.equals("createMBean") || methodName.equals("unregisterMBean")) + { + _logger.debug("User trying to create or unregister an MBean"); + throw new SecurityException("Access denied: " + methodName); + } + // Retrieve Subject from current AccessControlContext AccessControlContext acc = AccessController.getContext(); Subject subject = Subject.getSubject(acc); try { - // Allow operations performed locally on behalf of the connector server itself - if (subject == null) + if(invokeDirectly(methodName, args, subject)) { return method.invoke(_mbs, args); } - - if (args == null || DELEGATE.equals(args[0])) - { - return method.invoke(_mbs, args); - } - - // Restrict access to "createMBean" and "unregisterMBean" to any user - if (methodName.equals("createMBean") || methodName.equals("unregisterMBean")) - { - _logger.debug("User trying to create or unregister an MBean"); - throw new SecurityException("Access denied: " + methodName); - } - - // Allow querying available object names - if (methodName.equals("queryNames")) - { - return method.invoke(_mbs, args); - } - + // Retrieve JMXPrincipal from Subject Set principals = subject.getPrincipals(JMXPrincipal.class); if (principals == null || principals.isEmpty()) @@ -134,23 +156,23 @@ public class MBeanInvocationHandlerImpl implements InvocationHandler, Notificati // Save the subject SecurityManager.setThreadSubject(subject); - + // Get the component, type and impact, which may be null String type = getType(method, args); String vhost = getVirtualHost(method, args); int impact = getImpact(method, args); - + // Get the security manager for the virtual host (if set) SecurityManager security; if (vhost == null) { - security = ApplicationRegistry.getInstance().getSecurityManager(); + security = _appRegistry.getSecurityManager(); } else { - security = ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHost(vhost).getSecurityManager(); + security = _appRegistry.getVirtualHostRegistry().getVirtualHost(vhost).getSecurityManager(); } - + if (isAccessMethod(methodName) || impact == MBeanOperationInfo.INFO) { // Check for read-only method invocation permission @@ -159,25 +181,33 @@ public class MBeanInvocationHandlerImpl implements InvocationHandler, Notificati throw new SecurityException("Permission denied: Access " + methodName); } } - else if (isUpdateMethod(methodName)) - { - // Check for setting properties permission - if (!security.authoriseMethod(Operation.UPDATE, type, methodName)) - { - throw new SecurityException("Permission denied: Update " + methodName); - } - } - else - { - // Check for invoking/executing method action/operation permission - if (!security.authoriseMethod(Operation.EXECUTE, type, methodName)) - { - throw new SecurityException("Permission denied: Execute " + methodName); - } - } - - // Actually invoke the method - return method.invoke(_mbs, args); + else + { + // Check for setting properties permission + if (!security.authoriseMethod(Operation.UPDATE, type, methodName)) + { + throw new SecurityException("Permission denied: Update " + methodName); + } + } + + boolean oldAccessChecksDisabled = false; + if(_managementRightsInferAllAccess) + { + oldAccessChecksDisabled = SecurityManager.setAccessChecksDisabled(true); + } + + try + { + // Actually invoke the method + return method.invoke(_mbs, args); + } + finally + { + if(_managementRightsInferAllAccess) + { + SecurityManager.setAccessChecksDisabled(oldAccessChecksDisabled); + } + } } catch (InvocationTargetException e) { @@ -290,13 +320,6 @@ public class MBeanInvocationHandlerImpl implements InvocationHandler, Notificati return (methodName.startsWith("query") || methodName.startsWith("get") || methodName.startsWith("is")); } - - private boolean isUpdateMethod(String methodName) - { - //handle standard set methods from MBeanServer - return methodName.startsWith("set"); - } - public void handleNotification(Notification notification, Object handback) { assert notification instanceof JMXConnectionNotification; diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/AbstractProxyPlugin.java b/java/broker/src/main/java/org/apache/qpid/server/security/AbstractProxyPlugin.java index 8b5ff6781d..ec11e2d39c 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/security/AbstractProxyPlugin.java +++ b/java/broker/src/main/java/org/apache/qpid/server/security/AbstractProxyPlugin.java @@ -73,11 +73,6 @@ public abstract class AbstractProxyPlugin extends AbstractPlugin return getDefault(); } - public Result authoriseExecute(ObjectType object, ObjectProperties properties) - { - return getDefault(); - } - public Result authoriseUpdate(ObjectType object, ObjectProperties properties) { return getDefault(); @@ -121,8 +116,6 @@ public abstract class AbstractProxyPlugin extends AbstractPlugin return authoriseDelete(objectType, properties); case PURGE: return authorisePurge(objectType, properties); - case EXECUTE: - return authoriseExecute(objectType, properties); case UPDATE: return authoriseUpdate(objectType, properties); } 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 f582fed6a0..abf9e3379d 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 @@ -20,10 +20,8 @@ package org.apache.qpid.server.security; import static org.apache.qpid.server.security.access.ObjectType.EXCHANGE; import static org.apache.qpid.server.security.access.ObjectType.METHOD; -import static org.apache.qpid.server.security.access.ObjectType.OBJECT; import static org.apache.qpid.server.security.access.ObjectType.QUEUE; import static org.apache.qpid.server.security.access.ObjectType.VIRTUALHOST; -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.CONSUME; import static org.apache.qpid.server.security.access.Operation.CREATE; @@ -67,7 +65,14 @@ public class SecurityManager /** Container for the {@link Principal} that is using to this thread. */ private static final ThreadLocal _subject = new ThreadLocal(); - + private static final ThreadLocal _accessChecksDisabled = new ThreadLocal() + { + protected Boolean initialValue() + { + return false; + } + }; + private PluginManager _pluginManager; private Map _pluginFactories = new HashMap(); private Map _globalPlugins = new HashMap(); @@ -194,6 +199,11 @@ public class SecurityManager private boolean checkAllPlugins(AccessCheck checker) { + if(_accessChecksDisabled.get()) + { + return true; + } + HashMap remainingPlugins = new HashMap(_globalPlugins); for (Entry hostEntry : _hostPlugins.entrySet()) @@ -273,21 +283,6 @@ public class SecurityManager } }); } - - // TODO not implemented yet, awaiting consensus - public boolean authoriseObject(final String packageName, final String className) - { - return checkAllPlugins(new AccessCheck() - { - Result allowed(SecurityPlugin plugin) - { - ObjectProperties properties = new ObjectProperties(); - properties.put(ObjectProperties.Property.PACKAGE, packageName); - properties.put(ObjectProperties.Property.CLASS, className); - return plugin.authorise(ACCESS, OBJECT, properties); - } - }); - } public boolean authoriseMethod(final Operation operation, final String componentName, final String methodName) { @@ -329,17 +324,6 @@ public class SecurityManager }); } - public boolean authoriseConsume(final boolean exclusive, final boolean noAck, final boolean noLocal, final boolean nowait, final AMQQueue queue) - { - return checkAllPlugins(new AccessCheck() - { - Result allowed(SecurityPlugin plugin) - { - return plugin.authorise(CONSUME, QUEUE, new ObjectProperties(exclusive, noAck, noLocal, nowait, queue)); - } - }); - } - public boolean authoriseCreateExchange(final Boolean autoDelete, final Boolean durable, final AMQShortString exchangeName, final Boolean internal, final Boolean nowait, final Boolean passive, final AMQShortString exchangeType) { @@ -419,4 +403,14 @@ public class SecurityManager } }); } + + public static boolean setAccessChecksDisabled(final boolean status) + { + //remember current value + boolean current = _accessChecksDisabled.get(); + + _accessChecksDisabled.set(status); + + return current; + } } 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 7103b30283..69c7ff185a 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 @@ -32,14 +32,12 @@ import java.util.Set; public enum ObjectType { ALL(Operation.ALL), - VIRTUALHOST(ACCESS), - QUEUE(CREATE, DELETE, PURGE, CONSUME), - TOPIC(CREATE, DELETE, PURGE, CONSUME), - EXCHANGE(ACCESS, CREATE, DELETE, BIND, UNBIND, PUBLISH), + VIRTUALHOST(Operation.ALL, ACCESS), + QUEUE(Operation.ALL, CREATE, DELETE, PURGE, CONSUME), + EXCHANGE(Operation.ALL, ACCESS, CREATE, DELETE, BIND, UNBIND, PUBLISH), LINK, // Not allowed in the Java broker ROUTE, // Not allowed in the Java broker - METHOD(Operation.ALL, ACCESS, UPDATE, EXECUTE), - OBJECT(ACCESS); + METHOD(Operation.ALL, ACCESS, UPDATE); private EnumSet _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 06d7f8fd0c..21ea042eed 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,7 @@ public enum Operation UNBIND, DELETE, PURGE, - UPDATE, - EXECUTE; + UPDATE; public static Operation parse(String text) { diff --git a/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java b/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java index 9afd2a45a9..9ee2ed3812 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java @@ -303,6 +303,18 @@ public class ServerConfigurationTest extends QpidTestCase assertEquals(false, _serverConfig.getManagementEnabled()); } + public void testGetManagementRightsInferAllAccess() throws Exception + { + _serverConfig.initialise(); + + //check default + assertTrue("default should be true", _serverConfig.getManagementRightsInferAllAccess()); + + //update it + _config.setProperty("management.managementRightsInferAllAccess", "false"); + assertFalse("New value should be false", _serverConfig.getManagementRightsInferAllAccess()); + } + public void testGetHeartBeatDelay() throws ConfigurationException { // Check default diff --git a/java/systests/etc/config-systests-aclv2-settings.xml b/java/systests/etc/config-systests-aclv2-settings.xml deleted file mode 100644 index fbf218fdfa..0000000000 --- a/java/systests/etc/config-systests-aclv2-settings.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - ${QPID_HOME}/etc/global-default.txt - - - ${QPID_HOME}/etc/virtualhosts-systests-aclv2.xml - - - diff --git a/java/systests/etc/config-systests-aclv2.xml b/java/systests/etc/config-systests-aclv2.xml deleted file mode 100644 index e8b971a2a0..0000000000 --- a/java/systests/etc/config-systests-aclv2.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - diff --git a/java/systests/etc/global-default.txt b/java/systests/etc/global-default.txt deleted file mode 100644 index 01b2c41809..0000000000 --- a/java/systests/etc/global-default.txt +++ /dev/null @@ -1,31 +0,0 @@ -# -# 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. -# - -CONFIG expand=true - -# This section grants the admin user access to all management methods -ACL ALLOW admin ALL METHOD - -# This section grants the client user access to all management methods except logging -ACL DENY client ALL METHOD component="LoggingManagement" -ACL ALLOW client ALL METHOD - -# This section grants the server user access to all management methods except configuration -ACL DENY server ALL METHOD component="ConfigurationManagement" -ACL ALLOW server ALL METHOD diff --git a/java/systests/etc/global-externaladminacl-changeloggerleveldenied.txt b/java/systests/etc/global-externaladminacl-changeloggerleveldenied.txt deleted file mode 100644 index a59b3176cb..0000000000 --- a/java/systests/etc/global-externaladminacl-changeloggerleveldenied.txt +++ /dev/null @@ -1,24 +0,0 @@ -# -# 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. -# - -# This section denies the admin user access to logging -ACL DENY admin UPDATE METHOD component="LoggingManagement" name="setRuntimeRootLoggerLevel" - -# This section grants the admin user access to management methods -ACL ALLOW admin ALL METHOD diff --git a/java/systests/etc/global-externaladminacl-getallloggerlevelsdenied.txt b/java/systests/etc/global-externaladminacl-getallloggerlevelsdenied.txt deleted file mode 100644 index ff024b5ee8..0000000000 --- a/java/systests/etc/global-externaladminacl-getallloggerlevelsdenied.txt +++ /dev/null @@ -1,25 +0,0 @@ -# -# 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. -# - -# This section denies the admin user access to logging methods -ACL DENY admin ACCESS METHOD component="LoggingManagement" name="getAvailableLoggerLevels" - -# This section grants the admin user access to all management methods -ACL ALLOW admin ALL METHOD - diff --git a/java/systests/etc/test-default.txt b/java/systests/etc/test-default.txt deleted file mode 100644 index 95e733d077..0000000000 --- a/java/systests/etc/test-default.txt +++ /dev/null @@ -1,73 +0,0 @@ -# -# 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. -# - -# This section grants virtualhost access rights -ACL ALLOW client ACCESS VIRTUALHOST -ACL ALLOW server ACCESS VIRTUALHOST - -# This section grants publish rights to an exchange + routing key pair - -# Allow clients to publish requests -ACL ALLOW client PUBLISH EXCHANGE name="amq.direct" routingKey="example.RequestQueue" - -# Allow the processor to respond to a client on their Temporary Topic -ACL ALLOW server PUBLISH EXCHANGE name="amq.direct" routingKey="tmp_*" -ACL ALLOW server PUBLISH EXCHANGE name="amq.direct" routingKey="TempQueue*" - -# This section grants users the ability to consume from the broker - -# Allow client to consume from temporary queues -ACL ALLOW client CONSUME QUEUE temporary=true - -# Only allow the server to consume from the Request Queue -ACL ALLOW server CONSUME QUEUE name="example.RequestQueue" - -# Allow client and server to consume from kipper queues -ACL ALLOW client CONSUME QUEUE name="clientid:kipper" -ACL ALLOW server CONSUME QUEUE name="clientid:kipper" - -# This section grants users the ability to create/delete queues and exchanges - -# Allow clients to create and delete temporary and kipper queue on this exchange -ACL ALLOW client CREATE QUEUE temporary=true -ACL ALLOW client DELETE QUEUE temporary=true -ACL ALLOW client CREATE QUEUE durable="true" -ACL ALLOW client DELETE QUEUE durable="true" - -# Allow the server to create the Request Queue and kipper queue -ACL ALLOW server CREATE QUEUE name="example.RequestQueue" -ACL ALLOW server CREATE QUEUE name="clientid:kipper" - -## Allow client and server exchange access for the relevant queues -ACL ALLOW client BIND EXCHANGE name="amq.direct" temporary=true -ACL ALLOW client UNBIND EXCHANGE name="amq.direct" temporary=true -ACL ALLOW client BIND EXCHANGE name="amq.direct" durable=true -ACL ALLOW client UNBIND EXCHANGE name="amq.direct" durable=true -ACL ALLOW server BIND EXCHANGE name="amq.direct" queueName="example.RequestQueue" - -## Allow client and server exchange access for the relevant topics -ACL ALLOW client BIND EXCHANGE name="amq.topic" durable=true routingKey=kipper -ACL ALLOW client UNBIND EXCHANGE name="amq.topic" durable=true routingKey=kipper -ACL ALLOW server BIND EXCHANGE name="amq.topic" durable=true routingKey=kipper - -# Action[operation=BIND,objectType=EXCHANGE,properties={OWNER=client, DURABLE=true, QUEUE_NAME=IllegalQueue, AUTO_DELETE=false, ROUTING_KEY=IllegalQueue, NAME=amq.direct, TEMPORARY=false, EXCLUSIVE=false}] - - -ACL ALLOW client CREATE EXCHANGE -ACL ALLOW server CREATE EXCHANGE diff --git a/java/systests/etc/test-externalacljmx-deleteexchangefailure.txt b/java/systests/etc/test-externalacljmx-deleteexchangefailure.txt deleted file mode 100644 index 197fe9dabe..0000000000 --- a/java/systests/etc/test-externalacljmx-deleteexchangefailure.txt +++ /dev/null @@ -1,26 +0,0 @@ -# -# 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. -# - -# This section grants virtualhost management rights -ACL ALLOW admin ALL METHOD - -# testDeleteExchangeFailure() -ACL ALLOW admin CREATE EXCHANGE name="amq.kipper.delete" -ACL DENY admin DELETE EXCHANGE name="amq.kipper.delete" - diff --git a/java/systests/etc/test-externalacljmx.txt b/java/systests/etc/test-externalacljmx.txt deleted file mode 100644 index f8a94bd44a..0000000000 --- a/java/systests/etc/test-externalacljmx.txt +++ /dev/null @@ -1,35 +0,0 @@ -# -# 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. -# - -# This section grants management access to the virtualhost -ACL ALLOW admin ALL METHOD -ACL ALLOW client ALL METHOD -ACL ALLOW server ALL METHOD - -# Allow create kipper queue -ACL ALLOW admin CREATE QUEUE name="kipper" owner = client # kipper -ACL ALLOW admin BIND EXCHANGE name="amq.direct" - -# testCreateExchangeSuccess(), testDeleteExchangeSuccess() -ACL ALLOW admin CREATE EXCHANGE name="amq.kipper.success" -ACL ALLOW admin DELETE EXCHANGE name="amq.kipper.success" - -# testCreateExchangeFailure() -ACL DENY admin CREATE EXCHANGE name="amq.kipper.failure" - diff --git a/java/systests/etc/test-logging.txt b/java/systests/etc/test-logging.txt deleted file mode 100644 index 76c6e442e0..0000000000 --- a/java/systests/etc/test-logging.txt +++ /dev/null @@ -1,23 +0,0 @@ -# -# 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. -# - -ACL ALLOW client CREATE QUEUE name="allow" -ACL ALLOW-LOG client CREATE QUEUE name="allow-log" -ACL DENY client CREATE QUEUE name="deny" -ACL DENY-LOG client CREATE QUEUE name="deny-log" diff --git a/java/systests/etc/test2-default.txt b/java/systests/etc/test2-default.txt deleted file mode 100644 index 0855e631d7..0000000000 --- a/java/systests/etc/test2-default.txt +++ /dev/null @@ -1,21 +0,0 @@ -# -# 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. -# - -# This section grants all access rights -ACL ALLOW guest ALL ALL \ No newline at end of file diff --git a/java/systests/etc/virtualhosts-systests-aclv2-settings.xml b/java/systests/etc/virtualhosts-systests-aclv2-settings.xml deleted file mode 100644 index db1ad33a39..0000000000 --- a/java/systests/etc/virtualhosts-systests-aclv2-settings.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - test - - - amq.direct - - 4235264 - - 2117632 - - 600000 - - - - ${QPID_HOME}/etc/test-default.txt - - - - - - test2 - - - - - diff --git a/java/systests/etc/virtualhosts-systests-aclv2.xml b/java/systests/etc/virtualhosts-systests-aclv2.xml deleted file mode 100644 index db396d7ab1..0000000000 --- a/java/systests/etc/virtualhosts-systests-aclv2.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - diff --git a/java/systests/src/main/java/org/apache/qpid/server/logging/AccessControlLoggingTest.java b/java/systests/src/main/java/org/apache/qpid/server/logging/AccessControlLoggingTest.java index 2629e82831..e7da4472f5 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/logging/AccessControlLoggingTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/logging/AccessControlLoggingTest.java @@ -18,7 +18,6 @@ */ package org.apache.qpid.server.logging; -import java.io.File; import java.util.List; import javax.jms.Connection; @@ -29,6 +28,7 @@ import org.apache.qpid.AMQException; import org.apache.qpid.client.AMQSession; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.protocol.AMQConstant; +import org.apache.qpid.server.security.acl.AbstractACLTestCase; /** * ACL version 2/3 file testing to verify that ACL actor logging works correctly. @@ -49,13 +49,18 @@ public class AccessControlLoggingTest extends AbstractTestLogging public void setUp() throws Exception { - setConfigurationProperty("virtualhosts.virtualhost.test.security.aclv2", - QpidHome + File.separator + "etc" + File.separator + "test-logging.txt"); - + // Write out ACL for this test + AbstractACLTestCase.writeACLFileUtil(this, "test", + "ACL ALLOW client ACCESS VIRTUALHOST", + "ACL ALLOW client CREATE QUEUE name='allow'", + "ACL ALLOW-LOG client CREATE QUEUE name='allow-log'", + "ACL DENY client CREATE QUEUE name='deny'", + "ACL DENY-LOG client CREATE QUEUE name='deny-log'"); + super.setUp(); + } - /** FIXME This comes from SimpleACLTest and makes me suspicious. */ @Override public void tearDown() throws Exception { @@ -69,7 +74,7 @@ public class AccessControlLoggingTest extends AbstractTestLogging //that we provoked with authentication failures, where the test passes - we can ignore on con close } } - + /** * Test that {@code allow} ACL entries do not log anything. */ diff --git a/java/systests/src/main/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java b/java/systests/src/main/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java index 32b0185f88..a4155d10e2 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java +++ b/java/systests/src/main/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java @@ -24,8 +24,6 @@ import java.io.IOException; import java.io.PrintWriter; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.util.Collections; -import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -55,29 +53,24 @@ import org.apache.qpid.url.URLSyntaxException; * @see ExternalACLTest * @see ExternalACLFileTest * @see ExternalACLJMXTest - * @see ExternalAdminACLTest * @see ExhaustiveACLTest */ public abstract class AbstractACLTestCase extends QpidBrokerTestCase implements ConnectionListener { /** Used to synchronise {@link #tearDown()} when exceptions are thrown */ - protected CountDownLatch _exceptionReceived; - - /** Override this to return the name of the configuration XML file. */ - public abstract String getConfig(); + protected CountDownLatch _exceptionReceived; - /** Override this to setup external ACL files for virtual hosts. */ - public List getHostList() + /** Override this to return the name of the configuration XML file. */ + public String getConfig() { - return Collections.emptyList(); + return "config-systests.xml"; } - + /** * This setup method checks {@link #getConfig()} and {@link #getHostList()} to initialise the broker with specific * ACL configurations and then runs an optional per-test setup method, which is simply a method with the same name * as the test, but starting with {@code setUp} rather than {@code test}. * - * @see #setUpACLFile(String) * @see org.apache.qpid.test.utils.QpidBrokerTestCase#setUp() */ @Override @@ -85,12 +78,7 @@ public abstract class AbstractACLTestCase extends QpidBrokerTestCase implements { // Initialise ACLs. _configFile = new File("build" + File.separator + "etc" + File.separator + getConfig()); - // Initialise ACL files - for (String virtualHost : getHostList()) - { - setUpACLFile(virtualHost); - } - + // run test specific setup String testSetup = StringUtils.replace(getName(), "test", "setUp"); try @@ -124,73 +112,27 @@ public abstract class AbstractACLTestCase extends QpidBrokerTestCase implements } } - /** - * Configures specific ACL files for a virtual host. - * - * This method checks for ACL files that exist on the filesystem. If dynamically generatyed ACL files are required in a test, - * then it is easier to use the {@code setUp} prefix on a method to generate the ACL file. In order, this method looks - * for three files: - *
    - *
  1. virtualhost-class-test.txt - *
  2. virtualhost-class.txt - *
  3. virtualhost-default.txt - *
- * The class and test parts are the test class and method names respectively, with the word {@code test} - * removed and the rest of the text converted to lowercase. For example, the test class and method named - * {@code org.apache.qpid.test.AccessExampleTest#testExampleMethod} on the {@code testhost} virtualhost would use - * one of the following files: - *
    - *
  1. testhost-accessexample-examplemethod.txt - *
  2. testhost-accessexample.txt - *
  3. testhost-default.txt - *
- * These files should be copied to the ${QPID_HOME}/etc directory when the test is run. - * - * @see #writeACLFile(String, String...) - */ - public void setUpACLFile(String virtualHost) throws IOException, ConfigurationException + public void writeACLFile(final String vhost, final String...rules) throws ConfigurationException, IOException { - String path = "build" + File.separator + "etc"; - String className = StringUtils.substringBeforeLast(getClass().getSimpleName().toLowerCase(), "test"); - String testName = StringUtils.substringAfter(getName(), "test").toLowerCase(); - - File aclFile = new File(path, virtualHost + "-" + className + "-" + testName + ".txt"); - if (!aclFile.exists()) - { - aclFile = new File(path, virtualHost + "-" + className + ".txt"); - if (!aclFile.exists()) - { - aclFile = new File(path, virtualHost + "-" + "default.txt"); - } - } - - // Set the ACL file configuration property - if (virtualHost.equals("global")) - { - setConfigurationProperty("security.aclv2", aclFile.getAbsolutePath()); - } - else - { - setConfigurationProperty("virtualhosts.virtualhost." + virtualHost + ".security.aclv2", aclFile.getAbsolutePath()); - } + writeACLFileUtil(this, vhost, rules); } - public void writeACLFile(String vhost, String...rules) throws ConfigurationException, IOException + public static void writeACLFileUtil(QpidBrokerTestCase testcase, String vhost, String...rules) throws ConfigurationException, IOException { - File aclFile = File.createTempFile(getClass().getSimpleName(), getName()); + File aclFile = File.createTempFile(testcase.getClass().getSimpleName(), testcase.getName()); aclFile.deleteOnExit(); - if ("global".equals(vhost)) + if (vhost == null) { - setConfigurationProperty("security.aclv2", aclFile.getAbsolutePath()); + testcase.setConfigurationProperty("security.aclv2", aclFile.getAbsolutePath()); } else { - setConfigurationProperty("virtualhosts.virtualhost." + vhost + ".security.aclv2", aclFile.getAbsolutePath()); + testcase.setConfigurationProperty("virtualhosts.virtualhost." + vhost + ".security.aclv2", aclFile.getAbsolutePath()); } PrintWriter out = new PrintWriter(new FileWriter(aclFile)); - out.println(String.format("# %s", getTestName())); + out.println(String.format("# %s", testcase.getName())); for (String line : rules) { out.println(line); @@ -265,7 +207,7 @@ public abstract class AbstractACLTestCase extends QpidBrokerTestCase implements public void check403Exception(Throwable t) throws Exception { assertNotNull("There was no linked exception", t); - assertTrue("Wrong linked exception type", t instanceof AMQException); + assertTrue("Wrong linked exception type : " + t.getClass(), t instanceof AMQException); assertEquals("Incorrect error code received", 403, ((AMQException) t).getErrorCode().getCode()); //use the latch to ensure the control thread waits long enough for the exception thread diff --git a/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExhaustiveACLTest.java b/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExhaustiveACLTest.java index 1b2c98d30a..4f2464e186 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExhaustiveACLTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExhaustiveACLTest.java @@ -18,9 +18,6 @@ */ package org.apache.qpid.server.security.acl; -import java.util.Arrays; -import java.util.List; - import javax.jms.Connection; import javax.jms.Session; @@ -31,7 +28,7 @@ import org.apache.qpid.protocol.AMQConstant; /** * ACL version 2/3 file testing to verify that ACL entries control queue creation with specific properties. - * + * * Tests have their own ACL files that setup specific permissions, and then try to create queues with every possible combination * of properties to show that rule matching works correctly. For example, a rule that specified {@code autodelete="true"} for * queues with {@link name="temp.true.*"} as well should not affect queues that have names that do not match, or queues that @@ -39,18 +36,7 @@ import org.apache.qpid.protocol.AMQConstant; */ public class ExhaustiveACLTest extends AbstractACLTestCase { - @Override - public String getConfig() - { - return "config-systests-aclv2.xml"; - } - @Override - public List getHostList() - { - return Arrays.asList("test", "test2"); - } - /** * Creates a queue. * @@ -130,11 +116,6 @@ public class ExhaustiveACLTest extends AbstractACLTestCase createQueueFailure("test", "client", "temp.false.07", true, false); createQueueFailure("test", "server", "temp.true.08", true, false); createQueueFailure("test", "client", "temp.other.09", false, false); - createQueueSuccess("test2", "guest", "temp.true.01", false, false); - createQueueSuccess("test2", "guest", "temp.false.02", true, false); - createQueueSuccess("test2", "guest", "temp.true.03", true, false); - createQueueSuccess("test2", "guest", "temp.false.04", false, false); - createQueueSuccess("test2", "guest", "temp.other.05", false, false); } public void setUpAuthoriseCreateQueue() throws Exception @@ -161,10 +142,6 @@ public class ExhaustiveACLTest extends AbstractACLTestCase createQueueFailure("test", "server", "create.05", true, false); createQueueFailure("test", "server", "create.06", false, true); createQueueFailure("test", "server", "create.07", true, false); - createQueueSuccess("test2", "guest", "create.00", true, true); - createQueueSuccess("test2", "guest", "create.01", true, false); - createQueueSuccess("test2", "guest", "create.02", false, true); - createQueueSuccess("test2", "guest", "create.03", true, false); } public void setUpAuthoriseCreateQueueBoth() throws Exception @@ -190,6 +167,5 @@ public class ExhaustiveACLTest extends AbstractACLTestCase createQueueSuccess("test", "client", "tmp.00", true, false); createQueueSuccess("test", "server", "tmp.01", true, false); createQueueSuccess("test", "guest", "tmp.02", true, false); - createQueueSuccess("test2", "guest", "create.02", false, false); } } diff --git a/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLFileTest.java b/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLFileTest.java index 1d08015669..5ab2fede83 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLFileTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLFileTest.java @@ -18,9 +18,6 @@ */ package org.apache.qpid.server.security.acl; -import java.util.Arrays; -import java.util.List; - import javax.jms.Connection; import javax.jms.Session; @@ -38,18 +35,6 @@ import org.apache.qpid.framing.AMQShortString; */ public class ExternalACLFileTest extends AbstractACLTestCase { - @Override - public String getConfig() - { - return "config-systests-aclv2.xml"; - } - - @Override - public List getHostList() - { - return Arrays.asList("test"); - } - private void createQueuePrefixList(String prefix, int count) { try @@ -99,6 +84,7 @@ public class ExternalACLFileTest extends AbstractACLTestCase { writeACLFile( "test", + "ACL ALLOW-LOG client ACCESS VIRTUALHOST", "acl allow client create queue name=mixed.000", "ACL ALLOW client CREATE QUEUE NAME=mixed.001", "Acl Allow client Create Queue Name=mixed.002", @@ -116,6 +102,7 @@ public class ExternalACLFileTest extends AbstractACLTestCase { writeACLFile( "test", + "ACL ALLOW-LOG client ACCESS VIRTUALHOST", "acl allow client create queue name=continuation.000", "acl allow client create queue \\", " name=continuation.001", @@ -143,6 +130,7 @@ public class ExternalACLFileTest extends AbstractACLTestCase { writeACLFile( "test", + "ACL ALLOW-LOG client ACCESS VIRTUALHOST", "acl allow client create queue name=whitespace.000", "acl\tallow\tclient\tcreate\tqueue\tname=whitespace.001", "acl allow client create queue name = whitespace.002", @@ -160,6 +148,7 @@ public class ExternalACLFileTest extends AbstractACLTestCase { writeACLFile( "test", + "ACL ALLOW-LOG client ACCESS VIRTUALHOST", "acl allow client create queue name='quoting.ABC.000'", "acl allow client create queue name='quoting.*.000'", "acl allow client create queue name='quoting.#.000'", diff --git a/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLJMXTest.java b/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLJMXTest.java index 4552cf7004..427d253ca5 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLJMXTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLJMXTest.java @@ -18,36 +18,26 @@ */ package org.apache.qpid.server.security.acl; -import java.util.Arrays; -import java.util.List; +import java.lang.management.ManagementFactory; +import java.lang.management.RuntimeMXBean; -import org.apache.qpid.AMQConnectionClosedException; -import org.apache.qpid.AMQException; -import org.apache.qpid.AMQSecurityException; -import org.apache.qpid.protocol.AMQConstant; +import org.apache.qpid.management.common.mbeans.ServerInformation; +import org.apache.qpid.server.management.ManagedObject; +import org.apache.qpid.server.security.access.ObjectType; import org.apache.qpid.test.utils.JMXTestUtils; /** - * Tests that ACL entries that apply to AMQP objects also apply when those objects are accessed via JMX. + * Tests that access to the JMX interface is governed only by {@link ObjectType#METHOD}/{@link ObjectType#ALL} + * rules and AMQP rights have no effect. + * + * Ensures that objects outside the Qpid domain ({@link ManagedObject#DOMAIN}) are not governed by the ACL model. */ public class ExternalACLJMXTest extends AbstractACLTestCase { private JMXTestUtils _jmx; - - private static final String QUEUE_NAME = "kipper"; - private static final String EXCHANGE_NAME = "amq.kipper"; - - @Override - public String getConfig() - { - return "config-systests-aclv2.xml"; - } - @Override - public List getHostList() - { - return Arrays.asList("test"); - } + private static final String TEST_QUEUE_OWNER = "admin"; + private static final String TEST_VHOST = "test"; @Override public void setUp() throws Exception @@ -65,180 +55,264 @@ public class ExternalACLJMXTest extends AbstractACLTestCase super.tearDown(); } - // test-externalacljmx.txt - // create queue owner=client # success - public void testCreateClientQueueSuccess() throws Exception - { - //Queue Parameters - String queueOwner = "client"; - - _jmx.createQueue("test", QUEUE_NAME, queueOwner, true); + /** + * Ensure an empty ACL defaults to DENY ALL. + */ + public void setUpDenyAllIsDefault() throws Exception + { + writeACLFile(null, "#Empty ACL file"); } - // test-externalacljmx.txt - // create queue owner=client # failure - public void testCreateServerQueueFailure() throws Exception - { - //Queue Parameters - String queueOwner = "server"; - + public void testDenyAllIsDefault() throws Exception + { + //try a broker-level method + ServerInformation info = _jmx.getServerInformation(); try { - _jmx.createQueue("test", QUEUE_NAME, queueOwner, true); - - fail("Queue create should fail"); + info.resetStatistics(); + fail("Exception not thrown"); } - catch (Exception e) + catch (SecurityException e) { - assertNotNull("Cause is not set", e.getCause()); - assertEquals("Cause message incorrect", - "org.apache.qpid.AMQSecurityException: Permission denied: queue-name 'kipper' [error code 403: access refused]", e.getCause().getMessage()); + assertEquals("Cause message incorrect", "Permission denied: Update resetStatistics", e.getMessage()); } - } - // no create queue acl in file # failure - public void testCreateQueueFailure() throws Exception - { - //Queue Parameters - String queueOwner = "guest"; - + //try a vhost-level method try { - _jmx.createQueue("test", QUEUE_NAME, queueOwner, true); - - fail("Queue create should fail"); + _jmx.createQueue(TEST_VHOST, getTestQueueName(), TEST_QUEUE_OWNER, true); + fail("Exception not thrown"); } catch (Exception e) { - assertNotNull("Cause is not set", e.getCause()); - assertEquals("Cause message incorrect", - "org.apache.qpid.AMQSecurityException: Permission denied: queue-name 'kipper' [error code 403: access refused]", e.getCause().getMessage()); + assertEquals("Cause message incorrect", "Permission denied: Update createNewQueue", e.getMessage()); } + + // Ensure that calls to MBeans outside the Qpid domain are not impeded. + final RuntimeMXBean runtimeBean = _jmx.getManagedObject(RuntimeMXBean.class, ManagementFactory.RUNTIME_MXBEAN_NAME); + runtimeBean.getName(); + // PASS } - // test-externalacljmx.txt - // allow create exchange name=amq.kipper.success - public void testCreateExchangeSuccess() throws Exception - { - _jmx.createExchange("test", EXCHANGE_NAME + ".success", "direct", true); + /** + * Ensure an ALLOW ALL ALL rule allows access to both getters/setters. + */ + public void setUpAllowAll() throws Exception + { + writeACLFile(null, "ACL ALLOW ALL ALL"); } - // test-externalacljmx.txt - // deny create exchange name=amq.kipper.failure - public void testCreateExchangeFailure() throws Exception - { - try - { - _jmx.createExchange("test", EXCHANGE_NAME + ".failure", "direct", true); - - fail("Exchange create should fail"); - } - catch (Exception e) - { - assertNotNull("Cause is not set", e.getCause()); - assertEquals("Cause message incorrect", - "org.apache.qpid.AMQSecurityException: Permission denied: exchange-name 'amq.kipper.failure' [error code 403: access refused]", e.getCause().getMessage()); - } + public void testAllowAll() throws Exception + { + ServerInformation info = _jmx.getServerInformation(); + info.getBuildVersion(); // getter - requires ACCESS + info.resetStatistics(); // setter - requires UPDATE + // PASS } - // test-externalacljmx.txt - // allow create exchange name=amq.kipper.success - // allow delete exchange name=amq.kipper.success - public void testDeleteExchangeSuccess() throws Exception - { - _jmx.createExchange("test", EXCHANGE_NAME + ".success", "direct", true); - _jmx.unregisterExchange("test", EXCHANGE_NAME + ".success"); + /** + * admin user is denied at broker level but allowed at vhost level. + */ + public void setUpVhostAllowOverridesGlobalDeny() throws Exception + { + writeACLFile(null, + "ACL DENY admin UPDATE METHOD component='VirtualHost.VirtualHostManager' name='createNewQueue'"); + writeACLFile(TEST_VHOST, + "ACL ALLOW admin UPDATE METHOD component='VirtualHost.VirtualHostManager' name='createNewQueue'"); } - // test-externalacljmx-deleteexchangefailure.txt - // allow create exchange name=amq.kipper.delete - // deny delete exchange name=amq.kipper.delete - public void testDeleteExchangeFailure() throws Exception - { - _jmx.createExchange("test", EXCHANGE_NAME + ".delete", "direct", true); + public void testVhostAllowOverridesGlobalDeny() throws Exception + { + //try a vhost-level method on the allowed vhost + _jmx.createQueue(TEST_VHOST, getTestQueueName(), TEST_QUEUE_OWNER, true); + + //try a vhost-level method on a different vhost try { - _jmx.unregisterExchange("test", EXCHANGE_NAME + ".delete"); - - fail("Exchange delete should fail"); + _jmx.createQueue("development", getTestQueueName(), TEST_QUEUE_OWNER, true); + fail("Exception not thrown"); } - catch (Exception e) + catch (SecurityException e) { - assertNotNull("Cause is not set", e.getCause()); - assertEquals("Cause message incorrect", - "org.apache.qpid.AMQSecurityException: Permission denied [error code 403: access refused]", e.getCause().getMessage()); + assertEquals("Cause message incorrect", "Permission denied: Update createNewQueue", e.getMessage()); } } - + + /** - * admin user has JMX right but not AMQP + * admin user is allowed all update methods on the component at broker level. */ - public void setUpCreateQueueJMXRights() throws Exception + public void setUpUpdateComponentOnlyAllow() throws Exception { - writeACLFile("test", - "ACL ALLOW admin EXECUTE METHOD component=\"VirtualHost.VirtualHostManager\" name=\"createNewQueue\"", - "ACL DENY admin CREATE QUEUE"); + writeACLFile(null, + "ACL ALLOW admin UPDATE METHOD component='VirtualHost.VirtualHostManager'"); } - - public void testCreateQueueJMXRights() throws Exception + + public void testUpdateComponentOnlyAllow() throws Exception + { + _jmx.createQueue(TEST_VHOST, getTestQueueName(), TEST_QUEUE_OWNER, true); + // PASS + _jmx.deleteQueue(TEST_VHOST, getTestQueueName()); + // PASS + } + + + /** + * admin user is allowed all update methods on all components at broker level. + */ + public void setUpUpdateMethodOnlyAllow() throws Exception + { + writeACLFile(null, + "ACL ALLOW admin UPDATE METHOD"); + } + + public void testUpdateMethodOnlyAllow() throws Exception + { + _jmx.createQueue(TEST_VHOST, getTestQueueName(), TEST_QUEUE_OWNER, true); + //PASS + _jmx.deleteQueue(TEST_VHOST, getTestQueueName()); + // PASS + } + + + /** + * admin user has JMX right, AMPQ right is irrelevant. + */ + public void setUpCreateQueueSuccess() throws Exception + { + writeACLFile(TEST_VHOST, + "ACL ALLOW admin UPDATE METHOD component='VirtualHost.VirtualHostManager' name='createNewQueue'"); + } + + public void testCreateQueueSuccess() throws Exception + { + _jmx.createQueue(TEST_VHOST, getTestQueueName(), TEST_QUEUE_OWNER, true); + } + + + /** + * admin user has JMX right, verifies lack of AMPQ rights is irrelevant. + */ + public void setUpCreateQueueSuccessNoAMQPRights() throws Exception + { + writeACLFile(TEST_VHOST, + "ACL ALLOW admin UPDATE METHOD component='VirtualHost.VirtualHostManager' name='createNewQueue'", + "ACL DENY admin CREATE QUEUE"); + } + + public void testCreateQueueSuccessNoAMQPRights() throws Exception + { + _jmx.createQueue(TEST_VHOST, getTestQueueName(), TEST_QUEUE_OWNER, true); + } + + + /** + * admin user does not have JMX right, AMPQ right is irrelevant. + */ + public void setUpCreateQueueDenied() throws Exception + { + writeACLFile(TEST_VHOST, + "ACL DENY admin UPDATE METHOD component='VirtualHost.VirtualHostManager' name='createNewQueue'"); + } + + public void testCreateQueueDenied() throws Exception { try { - _jmx.createQueue("test", QUEUE_NAME, "admin", true); - - fail("Queue create should fail"); + _jmx.createQueue(TEST_VHOST, getTestQueueName(), TEST_QUEUE_OWNER, true); + fail("Exception not thrown"); } - catch (Exception e) + catch (SecurityException e) { - assertNotNull("Cause is not set", e.getCause()); - assertEquals("Cause message incorrect", - "org.apache.qpid.AMQSecurityException: Permission denied: queue-name 'kipper' [error code 403: access refused]", e.getCause().getMessage()); + assertEquals("Cause message incorrect", "Permission denied: Update createNewQueue", e.getMessage()); } } + /** - * admin user has AMQP right but not JMX + * admin user does not have JMX right */ - public void setUpCreateQueueAMQPRights() throws Exception + public void setUpServerInformationUpdateDenied() throws Exception { - writeACLFile("test", - "ACL DENY admin EXECUTE METHOD component=\"VirtualHost.VirtualHostManager\" name=\"createNewQueue\"", - "ACL ALLOW admin CREATE QUEUE"); + writeACLFile(null, + "ACL DENY admin UPDATE METHOD component='ServerInformation' name='resetStatistics'"); } - - public void testCreateQueueAMQPRights() throws Exception + + public void testServerInformationUpdateDenied() throws Exception { + ServerInformation info = _jmx.getServerInformation(); try { - _jmx.createQueue("test", QUEUE_NAME, "admin", true); - - fail("Queue create should fail"); + info.resetStatistics(); + fail("Exception not thrown"); } - catch (Exception e) + catch (SecurityException e) { - assertEquals("Cause message incorrect", "Permission denied: Execute createNewQueue", e.getMessage()); + assertEquals("Cause message incorrect", "Permission denied: Update resetStatistics", e.getMessage()); } } + /** - * admin has both JMX and AMQP rights + * admin user has JMX right to check management API major version (but not minor version) */ - public void setUpCreateQueueJMXAMQPRights() throws Exception + public void setUpServerInformationAccessGranted() throws Exception { - writeACLFile("test", - "ACL ALLOW admin EXECUTE METHOD component=\"VirtualHost.VirtualHostManager\" name=\"createNewQueue\"", - "ACL ALLOW admin CREATE QUEUE"); + writeACLFile(null, + "ACL ALLOW-LOG admin ACCESS METHOD component='ServerInformation' name='getManagementApiMajorVersion'"); } - - public void testCreateQueueJMXAMQPRights() throws Exception + + public void testServerInformationAccessGranted() throws Exception { + ServerInformation info = _jmx.getServerInformation(); + info.getManagementApiMajorVersion(); + try { - _jmx.createQueue("test", QUEUE_NAME, "admin", true); + info.getManagementApiMinorVersion(); + fail("Exception not thrown"); } - catch (Exception e) + catch (SecurityException e) { - fail("Queue create should succeed: " + e.getCause().getMessage()); + assertEquals("Cause message incorrect", "Permission denied: Access getManagementApiMinorVersion", e.getMessage()); } } + + + /** + * admin user has JMX right to use the update method + */ + public void setUpServerInformationUpdateMethodPermission() throws Exception + { + writeACLFile(null, + "ACL ALLOW admin UPDATE METHOD component='ServerInformation' name='resetStatistics'"); + } + + public void testServerInformationUpdateMethodPermission() throws Exception + { + ServerInformation info = _jmx.getServerInformation(); + info.resetStatistics(); + // PASS + } + + + /** + * admin user has JMX right to use all types of method on ServerInformation + */ + public void setUpServerInformationAllMethodPermissions() throws Exception + { + writeACLFile(null, "ACL ALLOW admin ALL METHOD component='ServerInformation'"); + } + + public void testServerInformationAllMethodPermissions() throws Exception + { + //try an update method + ServerInformation info = _jmx.getServerInformation(); + info.resetStatistics(); + // PASS + //try an access method + info.getManagementApiMinorVersion(); + // PASS + } + } diff --git a/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLTest.java b/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLTest.java index 254e1fe6ac..e9b8a2efd5 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLTest.java @@ -18,13 +18,8 @@ */ package org.apache.qpid.server.security.acl; -import java.io.IOException; -import java.util.Arrays; -import java.util.List; - import javax.jms.Connection; -import javax.jms.DeliveryMode; -import javax.jms.IllegalStateException; +import javax.jms.Destination; import javax.jms.JMSException; import javax.jms.Message; import javax.jms.MessageConsumer; @@ -37,9 +32,6 @@ import javax.jms.TopicSubscriber; import javax.naming.NamingException; import org.apache.qpid.AMQException; -import org.apache.qpid.client.AMQConnection; -import org.apache.qpid.client.AMQSession; -import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.url.URLSyntaxException; @@ -49,7 +41,13 @@ import org.apache.qpid.url.URLSyntaxException; */ public class ExternalACLTest extends AbstractACLTestCase { - public void testAccessAuthorizedSuccess() throws AMQException, URLSyntaxException, Exception + + public void setUpAccessAuthorizedSuccess() throws Exception + { + writeACLFile("test", "ACL ALLOW-LOG client ACCESS VIRTUALHOST"); + } + + public void testAccessAuthorizedSuccess() throws Exception { try { @@ -68,43 +66,9 @@ public class ExternalACLTest extends AbstractACLTestCase } } - public void testAccessVhostAuthorisedGuestSuccess() throws IOException, Exception + public void setUpAccessNoRightsFailure() throws Exception { - //The 'guest' user has no access to the 'test' vhost, as tested below in testAccessNoRights(), and so - //is unable to perform actions such as connecting (and by extension, creating a queue, and consuming - //from a queue etc). In order to test the vhost-wide 'access' ACL right, the 'guest' user has been given - //this right in the 'test2' vhost. - - try - { - //get a connection to the 'test2' vhost using the guest user and perform various actions. - Connection conn = getConnection("test2", "guest", "guest"); - Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); - conn.start(); - - //create Queues and consumers for each - Queue namedQueue = sess.createQueue("vhostAccessCreatedQueue" + getTestQueueName()); - Queue tempQueue = sess.createTemporaryQueue(); - MessageConsumer consumer = sess.createConsumer(namedQueue); - MessageConsumer tempConsumer = sess.createConsumer(tempQueue); - - //send a message to each queue (also causing an exchange declare) - MessageProducer sender = ((AMQSession) sess).createProducer(null); - ((org.apache.qpid.jms.MessageProducer) sender).send(namedQueue, sess.createTextMessage("test"), - DeliveryMode.NON_PERSISTENT, 0, 0L, false, false); - ((org.apache.qpid.jms.MessageProducer) sender).send(tempQueue, sess.createTextMessage("test"), - DeliveryMode.NON_PERSISTENT, 0, 0L, false, false); - - //consume the messages from the queues - consumer.receive(2000); - tempConsumer.receive(2000); - - conn.close(); - } - catch (Exception e) - { - fail("Test failed due to:" + e.getMessage()); - } + writeACLFile("test", "ACL DENY-LOG client ACCESS VIRTUALHOST"); } public void testAccessNoRightsFailure() throws Exception @@ -131,228 +95,124 @@ public class ExternalACLTest extends AbstractACLTestCase } } - public void testClientDeleteQueueSuccess() throws Exception + public void setUpClientDeleteQueueSuccess() throws Exception { - try - { - Connection conn = getConnection("test", "client", "guest"); - Session sess = conn.createSession(true, Session.SESSION_TRANSACTED); - conn.start(); - - // create kipper - Topic kipper = sess.createTopic("kipper"); - TopicSubscriber subscriber = sess.createDurableSubscriber(kipper, "kipper"); - - subscriber.close(); - sess.unsubscribe("kipper"); - - //Do something to show connection is active. - sess.rollback(); - conn.close(); - } - catch (Exception e) - { - fail("Test failed due to:" + e.getMessage()); - } + writeACLFile("test", "ACL ALLOW-LOG client ACCESS VIRTUALHOST", + "ACL ALLOW-LOG client CREATE QUEUE durable=\"true\"" , + "ACL ALLOW-LOG client CONSUME QUEUE name=\"clientid:kipper\"", + "ACL ALLOW-LOG client BIND EXCHANGE name=\"amq.topic\" durable=true routingKey=kipper", + "ACL ALLOW-LOG client DELETE QUEUE durable=\"true\"", + "ACL ALLOW-LOG client UNBIND EXCHANGE name=\"amq.topic\" durable=true routingKey=kipper"); } - public void testServerDeleteQueueFailure() throws Exception + public void testClientDeleteQueueSuccess() throws Exception { - try - { - Connection conn = getConnection("test", "server", "guest"); - Session sess = conn.createSession(true, Session.SESSION_TRANSACTED); - conn.start(); + Connection conn = getConnection("test", "client", "guest"); + Session sess = conn.createSession(true, Session.SESSION_TRANSACTED); + conn.start(); - // create kipper - Topic kipper = sess.createTopic("kipper"); - TopicSubscriber subscriber = sess.createDurableSubscriber(kipper, "kipper"); + // create kipper + Topic kipper = sess.createTopic("kipper"); + TopicSubscriber subscriber = sess.createDurableSubscriber(kipper, "kipper"); - subscriber.close(); - sess.unsubscribe("kipper"); + subscriber.close(); + sess.unsubscribe("kipper"); - //Do something to show connection is active. - sess.rollback(); - conn.close(); - } - catch (JMSException e) - { - // JMSException -> linedException = AMQException.403 - check403Exception(e.getLinkedException()); - } + //Do something to show connection is active. + sess.rollback(); + conn.close(); } - public void testClientConsumeFromTempQueueSuccess() throws AMQException, URLSyntaxException, Exception - { - try - { - Connection conn = getConnection("test", "client", "guest"); - - Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); - - conn.start(); - - sess.createConsumer(sess.createTemporaryQueue()); - conn.close(); - } - catch (Exception e) - { - fail("Test failed due to:" + e.getMessage()); - } + public void setUpClientDeleteQueueFailure() throws Exception + { + writeACLFile("test", "ACL ALLOW-LOG client ACCESS VIRTUALHOST", + "ACL ALLOW-LOG client CREATE QUEUE durable=\"true\"" , + "ACL ALLOW-LOG client CONSUME QUEUE name=\"clientid:kipper\"", + "ACL ALLOW-LOG client BIND EXCHANGE name=\"amq.topic\" durable=true routingKey=kipper", + "ACL DENY-LOG client DELETE QUEUE durable=\"true\"", + "ACL DENY-LOG client UNBIND EXCHANGE name=\"amq.topic\" durable=true routingKey=kipper"); } - public void testClientConsumeFromNamedQueueFailure() throws NamingException, Exception + public void testClientDeleteQueueFailure() throws Exception { - try - { - Connection conn = getConnection("test", "client", "guest"); + Connection conn = getConnection("test", "client", "guest"); + Session sess = conn.createSession(true, Session.SESSION_TRANSACTED); + conn.start(); - Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + // create kipper + Topic kipper = sess.createTopic("kipper"); + TopicSubscriber subscriber = sess.createDurableSubscriber(kipper, "kipper"); - conn.start(); + subscriber.close(); + try + { + sess.unsubscribe("kipper"); - sess.createConsumer(sess.createQueue("IllegalQueue")); + //Do something to show connection is active. + sess.rollback(); - fail("Test failed as consumer was created."); + fail("Exception was not thrown"); } catch (JMSException e) { + // JMSException -> linedException = AMQException.403 check403Exception(e.getLinkedException()); } } - public void testClientCreateTemporaryQueueSuccess() throws JMSException, URLSyntaxException, Exception - { - try - { - Connection conn = getConnection("test", "client", "guest"); - - Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); - - conn.start(); - //Create Temporary Queue - can't use the createTempQueue as QueueName is null. - ((AMQSession) sess).createQueue(new AMQShortString("doesnt_matter_as_autodelete_means_tmp"), - true, false, false); - - conn.close(); - } - catch (Exception e) - { - fail("Test failed due to:" + e.getMessage()); - } - } - - public void testClientCreateNamedQueueFailure() throws NamingException, JMSException, AMQException, Exception + public void testClientConsumeFromTempQueueSuccess() throws Exception { - try - { - Connection conn = getConnection("test", "client", "guest"); + Connection conn = getConnection("test", "client", "guest"); - Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); - conn.start(); + conn.start(); - //Create a Named Queue - ((AMQSession) sess).createQueue(new AMQShortString("IllegalQueue"), false, false, false); - - fail("Test failed as Queue creation succeded."); - //conn will be automatically closed - } - catch (AMQException e) - { - check403Exception(e); - } + sess.createConsumer(sess.createTemporaryQueue()); } - public void testClientPublishUsingTransactionSuccess() throws AMQException, URLSyntaxException, Exception + public void setUpClientConsumeFromNamedQueueValid() throws Exception { - try - { - Connection conn = getConnection("test", "client", "guest"); + writeACLFile("test", "ACL ALLOW-LOG client ACCESS VIRTUALHOST", + "ACL ALLOW-LOG client CREATE QUEUE name=\"example.RequestQueue\"" , + "ACL ALLOW-LOG client CONSUME QUEUE name=\"example.RequestQueue\"", + "ACL ALLOW-LOG client BIND EXCHANGE name=\"amq.direct\" routingKey=\"example.RequestQueue\""); + } - Session sess = conn.createSession(true, Session.SESSION_TRANSACTED); - conn.start(); - - MessageProducer sender = sess.createProducer(sess.createQueue("example.RequestQueue")); + public void testClientConsumeFromNamedQueueValid() throws Exception + { + Connection conn = getConnection("test", "client", "guest"); - sender.send(sess.createTextMessage("test")); + Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); - //Send the message using a transaction as this will allow us to retrieve any errors that occur on the broker. - sess.commit(); + conn.start(); - conn.close(); - } - catch (Exception e) - { - fail("Test publish failed:" + e); - } + sess.createConsumer(sess.createQueue("example.RequestQueue")); } - public void testClientPublishValidQueueSuccess() throws AMQException, URLSyntaxException, Exception + public void setUpClientConsumeFromNamedQueueFailure() throws Exception { - try - { - Connection conn = getConnection("test", "client", "guest"); - - Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); - - conn.start(); - - MessageProducer sender = ((AMQSession) sess).createProducer(null); - - Queue queue = sess.createQueue("example.RequestQueue"); - - // Send a message that we will wait to be sent, this should give the broker time to process the msg - // before we finish this test. Message is set !immed !mand as the queue is invalid so want to test ACLs not - // queue existence. - ((org.apache.qpid.jms.MessageProducer) sender).send(queue, sess.createTextMessage("test"), - DeliveryMode.NON_PERSISTENT, 0, 0L, false, false); - - conn.close(); - } - catch (Exception e) - { - fail("Test publish failed:" + e); - } + writeACLFile("test", "ACL ALLOW-LOG client ACCESS VIRTUALHOST", + "ACL ALLOW-LOG client CREATE QUEUE" , + "ACL ALLOW-LOG client BIND EXCHANGE", + "ACL DENY-LOG client CONSUME QUEUE name=\"IllegalQueue\""); } - public void testClientPublishInvalidQueueSuccess() throws AMQException, URLSyntaxException, JMSException, NamingException, Exception + public void testClientConsumeFromNamedQueueFailure() throws NamingException, Exception { + Connection conn = getConnection("test", "client", "guest"); + Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + conn.start(); + Destination dest = sess.createQueue("IllegalQueue"); + try { - Connection conn = getConnection("test", "client", "guest"); - - Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); - - conn.start(); - - MessageProducer sender = ((AMQSession) session).createProducer(null); - - Queue queue = session.createQueue("Invalid"); - - // Send a message that we will wait to be sent, this should give the broker time to close the connection - // before we finish this test. Message is set !immed !mand as the queue is invalid so want to test ACLs not - // queue existence. - ((org.apache.qpid.jms.MessageProducer) sender).send(queue, session.createTextMessage("test"), - DeliveryMode.NON_PERSISTENT, 0, 0L, false, false); - - // Test the connection with a valid consumer - // This may fail as the session may be closed before the queue or the consumer created. - Queue temp = session.createTemporaryQueue(); + sess.createConsumer(dest); - session.createConsumer(temp).close(); - - //Connection should now be closed and will throw the exception caused by the above send - conn.close(); - - fail("Close is not expected to succeed."); - } - catch (IllegalStateException e) - { - _logger.info("QPID-2345: Session became closed and we got that error rather than the authentication error."); + fail("Test failed as consumer was created."); } catch (JMSException e) { @@ -360,39 +220,43 @@ public class ExternalACLTest extends AbstractACLTestCase } } - public void testServerConsumeFromNamedQueueValid() throws AMQException, URLSyntaxException, Exception + public void setUpClientCreateTemporaryQueueSuccess() throws Exception { - try - { - Connection conn = getConnection("test", "server", "guest"); - - Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + writeACLFile("test", "ACL ALLOW-LOG client ACCESS VIRTUALHOST", + "ACL ALLOW-LOG client CREATE QUEUE temporary=\"true\"" , + "ACL ALLOW-LOG client BIND EXCHANGE name=\"amq.direct\" temporary=true", + "ACL ALLOW-LOG client DELETE QUEUE temporary=\"true\"", + "ACL ALLOW-LOG client UNBIND EXCHANGE name=\"amq.direct\" temporary=true"); + } - conn.start(); + public void testClientCreateTemporaryQueueSuccess() throws JMSException, URLSyntaxException, Exception + { + Connection conn = getConnection("test", "client", "guest"); + Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + conn.start(); - sess.createConsumer(sess.createQueue("example.RequestQueue")); + sess.createTemporaryQueue(); + conn.close(); + } - conn.close(); - } - catch (Exception e) - { - fail("Test failed due to:" + e.getMessage()); - } + public void setUpClientCreateTemporaryQueueFailed() throws Exception + { + writeACLFile("test", "ACL ALLOW-LOG client ACCESS VIRTUALHOST", + "ACL DENY-LOG client CREATE QUEUE temporary=\"true\""); } - public void testServerConsumeFromNamedQueueInvalid() throws AMQException, URLSyntaxException, NamingException, Exception + public void testClientCreateTemporaryQueueFailed() throws NamingException, Exception { + Connection conn = getConnection("test", "client", "guest"); + Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + conn.start(); + try { - Connection conn = getConnection("test", "client", "guest"); - - Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); - conn.start(); - - sess.createConsumer(sess.createQueue("Invalid")); + session.createTemporaryQueue(); - fail("Test failed as consumer was created."); + fail("Test failed as creation succeded."); } catch (JMSException e) { @@ -400,247 +264,139 @@ public class ExternalACLTest extends AbstractACLTestCase } } - public void testServerConsumeFromTemporaryQueue() throws AMQException, URLSyntaxException, NamingException, Exception + public void setUpClientCreateNamedQueueFailure() throws Exception { - try - { - Connection conn = getConnection("test", "server", "guest"); - - Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); - - conn.start(); - - sess.createConsumer(sess.createTemporaryQueue()); - - fail("Test failed as consumer was created."); - } - catch (JMSException e) - { - check403Exception(e.getLinkedException()); - } + writeACLFile("test", "ACL ALLOW-LOG client ACCESS VIRTUALHOST", + "ACL ALLOW-LOG client CREATE QUEUE name=\"ValidQueue\"", + "ACL ALLOW-LOG client CONSUME QUEUE"); } - public void testServerCreateNamedQueueValid() throws JMSException, URLSyntaxException, Exception + public void testClientCreateNamedQueueFailure() throws NamingException, JMSException, AMQException, Exception { + Connection conn = getConnection("test", "client", "guest"); + Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + conn.start(); + Destination dest = sess.createQueue("IllegalQueue"); + try { - Connection conn = getConnection("test", "server", "guest"); - - Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); - - conn.start(); - - //Create Temporary Queue - ((AMQSession) sess).createQueue(new AMQShortString("example.RequestQueue"), false, false, false); - - conn.close(); + //Create a Named Queue as side effect + sess.createConsumer(dest); + fail("Test failed as Queue creation succeded."); } - catch (Exception e) + catch (JMSException e) { - fail("Test failed due to:" + e.getMessage()); + check403Exception(e.getLinkedException()); } } - public void testServerCreateNamedQueueInvalid() throws JMSException, URLSyntaxException, AMQException, NamingException, Exception + public void setUpClientPublishUsingTransactionSuccess() throws Exception { - try - { - Connection conn = getConnection("test", "server", "guest"); - - Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); - - conn.start(); - - //Create a Named Queue - ((AMQSession) sess).createQueue(new AMQShortString("IllegalQueue"), false, false, false); - - fail("Test failed as creation succeded."); - } - catch (Exception e) - { - check403Exception(e); - } + writeACLFile("test", "ACL ALLOW-LOG client ACCESS VIRTUALHOST", + "ACL ALLOW-LOG client CREATE QUEUE" , + "ACL ALLOW-LOG client BIND EXCHANGE", + "ACL ALLOW-LOG client PUBLISH EXCHANGE name=\"amq.direct\" routingKey=\"example.RequestQueue\""); } - public void testServerCreateTemporaryQueueInvalid() throws NamingException, Exception + public void testClientPublishUsingTransactionSuccess() throws Exception { - try - { - Connection conn = getConnection("test", "server", "guest"); - Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + Connection conn = getConnection("test", "client", "guest"); - conn.start(); + Session sess = conn.createSession(true, Session.SESSION_TRANSACTED); - session.createTemporaryQueue(); + conn.start(); - fail("Test failed as creation succeded."); - } - catch (JMSException e) - { - check403Exception(e.getLinkedException()); - } - } + MessageProducer sender = sess.createProducer(sess.createQueue("example.RequestQueue")); - public void testServerCreateAutoDeleteQueueInvalid() throws NamingException, JMSException, AMQException, Exception - { - try - { - Connection connection = getConnection("test", "server", "guest"); + sender.send(sess.createTextMessage("test")); - Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + //Send the message using a transaction as this will allow us to retrieve any errors that occur on the broker. + sess.commit(); - connection.start(); + conn.close(); + } - ((AMQSession) session).createQueue(new AMQShortString("again_ensure_auto_delete_queue_for_temporary"), - true, false, false); - fail("Test failed as creation succeded."); - } - catch (Exception e) - { - check403Exception(e); - } + public void setUpRequestResponseSuccess() throws Exception + { + writeACLFile("test", "GROUP messaging-users client server", + "ACL ALLOW-LOG messaging-users ACCESS VIRTUALHOST", + "# Server side", + "ACL ALLOW-LOG server CREATE QUEUE name=\"example.RequestQueue\"" , + "ACL ALLOW-LOG server BIND EXCHANGE", + "ACL ALLOW-LOG server PUBLISH EXCHANGE name=\"amq.direct\" routingKey=\"TempQueue*\"", + "ACL ALLOW-LOG server CONSUME QUEUE name=\"example.RequestQueue\"", + "# Client side", + "ACL ALLOW-LOG client PUBLISH EXCHANGE name=\"amq.direct\" routingKey=\"example.RequestQueue\"", + "ACL ALLOW-LOG client CONSUME QUEUE temporary=true", + "ACL ALLOW-LOG client BIND EXCHANGE name=\"amq.direct\" temporary=true", + "ACL ALLOW-LOG client UNBIND EXCHANGE name=\"amq.direct\" temporary=true", + "ACL ALLOW-LOG client CREATE QUEUE temporary=true", + "ACL ALLOW-LOG client DELETE QUEUE temporary=true"); } - /** - * This test uses both the cilent and sender to validate that the Server is able to publish to a temporary queue. - * The reason the client must be involved is that the Server is unable to create its own Temporary Queues. - * - * @throws AMQException - * @throws URLSyntaxException - * @throws JMSException - */ - public void testServerPublishUsingTransactionSuccess() throws AMQException, URLSyntaxException, JMSException, NamingException, Exception + + public void testRequestResponseSuccess() throws Exception { //Set up the Server Connection serverConnection = getConnection("test", "server", "guest"); - Session serverSession = serverConnection.createSession(true, Session.SESSION_TRANSACTED); - Queue requestQueue = serverSession.createQueue("example.RequestQueue"); - MessageConsumer server = serverSession.createConsumer(requestQueue); - serverConnection.start(); //Set up the consumer Connection clientConnection = getConnection("test", "client", "guest"); - - //Send a test mesage - Session clientSession = clientConnection.createSession(false, Session.AUTO_ACKNOWLEDGE); - + Session clientSession = clientConnection.createSession(true, Session.SESSION_TRANSACTED); Queue responseQueue = clientSession.createTemporaryQueue(); - MessageConsumer clientResponse = clientSession.createConsumer(responseQueue); - clientConnection.start(); + // Client Message request = clientSession.createTextMessage("Request"); - - assertNotNull("Response Queue is null", responseQueue); - request.setJMSReplyTo(responseQueue); clientSession.createProducer(requestQueue).send(request); - - try - { - Message msg = null; - - msg = server.receive(2000); - - while (msg != null && !((TextMessage) msg).getText().equals("Request")) - { - msg = server.receive(2000); - } - - assertNotNull("Message not received", msg); - - assertNotNull("Reply-To is Null", msg.getJMSReplyTo()); - - MessageProducer sender = serverSession.createProducer(msg.getJMSReplyTo()); - - sender.send(serverSession.createTextMessage("Response")); - - //Send the message using a transaction as this will allow us to retrieve any errors that occur on the broker. - serverSession.commit(); - - //Ensure Response is received. - Message clientResponseMsg = clientResponse.receive(2000); - assertNotNull("Client did not receive response message,", clientResponseMsg); - assertEquals("Incorrect message received", "Response", ((TextMessage) clientResponseMsg).getText()); - - } - catch (Exception e) - { - fail("Test publish failed:" + e); - } - finally - { - try - { - serverConnection.close(); - } - finally - { - clientConnection.close(); - } - } + clientSession.commit(); + + // Server + Message msg = server.receive(2000); + assertNotNull("Server should have received client's request", msg); + assertNotNull("Received msg should have Reply-To", msg.getJMSReplyTo()); + + MessageProducer sender = serverSession.createProducer(msg.getJMSReplyTo()); + sender.send(serverSession.createTextMessage("Response")); + serverSession.commit(); + + // Client + Message clientResponseMsg = clientResponse.receive(2000); + clientSession.commit(); + assertNotNull("Client did not receive response message,", clientResponseMsg); + assertEquals("Incorrect message received", "Response", ((TextMessage) clientResponseMsg).getText()); } - public void testServerPublishInvalidQueueSuccess() throws AMQException, URLSyntaxException, JMSException, NamingException, Exception + public void setUpClientDeleteQueueSuccessWithOnlyAllPermissions() throws Exception { - try - { - Connection conn = getConnection("test", "server", "guest"); - - ((AMQConnection) conn).setConnectionListener(this); - - Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); - - conn.start(); - - MessageProducer sender = ((AMQSession) session).createProducer(null); - - Queue queue = session.createQueue("Invalid"); - - // Send a message that we will wait to be sent, this should give the broker time to close the connection - // before we finish this test. Message is set !immed !mand as the queue is invalid so want to test ACLs not - // queue existence. - ((org.apache.qpid.jms.MessageProducer) sender).send(queue, session.createTextMessage("test"), - DeliveryMode.NON_PERSISTENT, 0, 0L, false, false); - - // Test the connection with a valid consumer - // This may not work as the session may be closed before the queue or consumer creation can occur. - // The correct JMSexception with linked error will only occur when the close method is recevied whilst in - // the failover safe block - session.createConsumer(session.createQueue("example.RequestQueue")).close(); - - //Connection should now be closed and will throw the exception caused by the above send - conn.close(); - - fail("Close is not expected to succeed."); - } - catch (IllegalStateException e) - { - _logger.info("QPID-2345: Session became closed and we got that error rather than the authentication error."); - } - catch (JMSException e) - { - check403Exception(e.getLinkedException()); - } + writeACLFile("test", "ACL ALLOW-LOG client ACCESS VIRTUALHOST", + "ACL ALLOW-LOG client ALL QUEUE", + "ACL ALLOW-LOG client ALL EXCHANGE"); } - - @Override - public String getConfig() + public void testClientDeleteQueueSuccessWithOnlyAllPermissions() throws Exception { - return "config-systests-aclv2.xml"; - } + Connection conn = getConnection("test", "client", "guest"); + Session sess = conn.createSession(true, Session.SESSION_TRANSACTED); + conn.start(); - @Override - public List getHostList() - { - return Arrays.asList("test", "test2"); + // create kipper + Topic kipper = sess.createTopic("kipper"); + TopicSubscriber subscriber = sess.createDurableSubscriber(kipper, "kipper"); + + subscriber.close(); + sess.unsubscribe("kipper"); + + //Do something to show connection is active. + sess.rollback(); + conn.close(); } } diff --git a/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalAdminACLTest.java b/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalAdminACLTest.java deleted file mode 100644 index b0bc4fd946..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalAdminACLTest.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * 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.acl; - -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.util.Arrays; -import java.util.List; - -import org.apache.qpid.server.logging.management.LoggingManagementMBean; -import org.apache.qpid.test.utils.JMXTestUtils; - -/** - * Tests that ACLs can be applied to mangement operations that do not correspond to a specific AMQP object. - * - * Theses tests use the logging component, exposed as the {@link LoggingManagementMBean}, to get and set properties. - */ -public class ExternalAdminACLTest extends AbstractACLTestCase -{ - private static final String CATEGORY_PRIORITY = "LogManMBeanTest.category.priority"; - private static final String CATEGORY_LEVEL = "LogManMBeanTest.category.level"; - private static final String LOGGER_LEVEL = "LogManMBeanTest.logger.level"; - - private static final String NEWLINE = System.getProperty("line.separator"); - - private JMXTestUtils _jmx; - private File _testConfigFile; - - @Override - public String getConfig() - { - return "config-systests-aclv2.xml"; - } - - @Override - public List getHostList() - { - return Arrays.asList("global"); - } - - @Override - public void setUp() throws Exception - { - _testConfigFile = createTempTestLog4JConfig(); - - _jmx = new JMXTestUtils(this); - _jmx.setUp(); - super.setUp(); - _jmx.open(); - } - - @Override - public void tearDown() throws Exception - { - _jmx.close(); - super.tearDown(); - } - - private File createTempTestLog4JConfig() - { - File tmpFile = null; - try - { - tmpFile = File.createTempFile("LogManMBeanTestLog4jConfig", ".tmp"); - tmpFile.deleteOnExit(); - - FileWriter fstream = new FileWriter(tmpFile); - BufferedWriter writer = new BufferedWriter(fstream); - - writer.write(""+NEWLINE); - writer.write(""+NEWLINE); - - writer.write(""+NEWLINE); - - writer.write(" "+NEWLINE); - writer.write(" "+NEWLINE); - writer.write(" "+NEWLINE); - writer.write(" "+NEWLINE); - writer.write(" "+NEWLINE); - - //Example of a 'category' with a 'priority' - writer.write(" "+NEWLINE); - writer.write(" "+NEWLINE); - writer.write(" "+NEWLINE); - writer.write(" "+NEWLINE); - - //Example of a 'category' with a 'level' - writer.write(" "+NEWLINE); - writer.write(" "+NEWLINE); - writer.write(" "+NEWLINE); - writer.write(" "+NEWLINE); - - //Example of a 'logger' with a 'level' - writer.write(" "+NEWLINE); - writer.write(" "+NEWLINE); - writer.write(" "+NEWLINE); - writer.write(" "+NEWLINE); - - //'root' logger - writer.write(" "+NEWLINE); - writer.write(" "+NEWLINE); - writer.write(" "+NEWLINE); - writer.write(" "+NEWLINE); - - writer.write(""+NEWLINE); - - writer.flush(); - writer.close(); - } - catch (IOException e) - { - fail("Unable to create temporary test log4j configuration"); - } - - return tmpFile; - } - - public void testGetAllLoggerLevels() throws Exception - { - String[] levels = _jmx.getAvailableLoggerLevels(); - for (int i = 0; i < levels.length; i++) - { - System.out.println(levels[i]); - } - assertEquals("Got incorrect number of log levels", 9, levels.length); - } - - public void testGetAllLoggerLevelsDenied() throws Exception - { - try - { - _jmx.getAvailableLoggerLevels(); - fail("Got list of log levels"); - } - catch (Exception e) - { - // Exception throws - e.printStackTrace(); - assertEquals("Permission denied: Access getAvailableLoggerLevels", e.getMessage()); - } - } - - public void testChangeLoggerLevel() throws Exception - { - String oldLevel = _jmx.getRuntimeRootLoggerLevel(); - System.out.println("old level = " + oldLevel); - _jmx.setRuntimeRootLoggerLevel("DEBUG"); - String newLevel = _jmx.getRuntimeRootLoggerLevel(); - System.out.println("new level = " + newLevel); - assertEquals("Logging level was not changed", "DEBUG", newLevel); - } - - public void testChangeLoggerLevelDenied() throws Exception - { - try - { - _jmx.setRuntimeRootLoggerLevel("DEBUG"); - fail("Logging level was changed"); - } - catch (Exception e) - { - assertEquals("Permission denied: Update setRuntimeRootLoggerLevel", e.getMessage()); - } - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java b/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java index 71fbf4cc81..14b9bacad4 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java +++ b/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java @@ -823,7 +823,7 @@ public class QpidBrokerTestCase extends QpidTestCase * @throws ConfigurationException when loading the current config file * @throws IOException when writing the new config file */ - protected void setConfigurationProperty(String property, String value) + public void setConfigurationProperty(String property, String value) throws ConfigurationException, IOException { // Choose which file to write the property to based on prefix. -- cgit v1.2.1