diff options
author | Robert Gemmell <robbie@apache.org> | 2011-06-26 13:53:49 +0000 |
---|---|---|
committer | Robert Gemmell <robbie@apache.org> | 2011-06-26 13:53:49 +0000 |
commit | 4edfb54cabefeba396f8e326fd22ce55854ac406 (patch) | |
tree | 81ae399400fa05f9aa6f0abe338f3be627c7595b | |
parent | a2f311080878ce6a9bd24dc456225baa9a3ffcef (diff) | |
download | qpid-python-4edfb54cabefeba396f8e326fd22ce55854ac406.tar.gz |
QPID-3301: remove support for ACL V1 (aka SimpleXML) from Java Broker.
Applied patch from Keith Wall <keith.wall@gmail.com>
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1139792 13f79535-47bb-0310-9956-ffa450edef68
14 files changed, 611 insertions, 2402 deletions
diff --git a/qpid/java/broker-plugins/simple-xml/MANIFEST.MF b/qpid/java/broker-plugins/simple-xml/MANIFEST.MF deleted file mode 100644 index 04fe7518df..0000000000 --- a/qpid/java/broker-plugins/simple-xml/MANIFEST.MF +++ /dev/null @@ -1,36 +0,0 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: Qpid Broker-Plugins Simple XML -Bundle-SymbolicName: broker-plugins-simple-xml -Bundle-Description: Simple XML ACL plugin for Qpid. -Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt -Bundle-DocURL: http://www.apache.org/ -Bundle-Version: 1.0.0 -Bundle-Activator: org.apache.qpid.server.security.access.plugins.SimpleXMLActivator -Bundle-RequiredExecutionEnvironment: JavaSE-1.5 -Bundle-ClassPath: . -Bundle-ActivationPolicy: lazy -Import-Package: org.apache.qpid, - org.apache.qpid.framing, - org.apache.qpid.junit.extensions.util, - org.apache.qpid.protocol, - org.apache.qpid.server.configuration, - org.apache.qpid.server.configuration.plugins, - org.apache.qpid.server.exchange, - org.apache.qpid.server.management, - org.apache.qpid.server.plugins, - org.apache.qpid.server.queue, - org.apache.qpid.server.security, - org.apache.qpid.server.security.access, - org.apache.qpid.server.virtualhost, - org.apache.qpid.util, - org.apache.commons.configuration;version=1.0.0, - org.apache.commons.lang;version=1.0.0, - org.apache.commons.lang.builder;version=1.0.0, - org.apache.log4j;version=1.0.0, - javax.management;version=1.0.0, - javax.management.openmbean;version=1.0.0, - org.osgi.util.tracker;version=1.0.0, - org.osgi.framework;version=1.3 -Private-Package: org.apache.qpid.server.security.access.config -Export-Package: org.apache.qpid.server.security.access.plugins diff --git a/qpid/java/broker-plugins/simple-xml/build.xml b/qpid/java/broker-plugins/simple-xml/build.xml deleted file mode 100644 index d3cd451648..0000000000 --- a/qpid/java/broker-plugins/simple-xml/build.xml +++ /dev/null @@ -1,29 +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. - --> -<project name="Qpid Broker-Plugins Simple XML" default="build"> - <property name="module.depends" value="common broker broker-plugins" /> - <property name="module.test.depends" value="test broker/test common/test management/common systests" /> - - <property name="module.manifest" value="MANIFEST.MF" /> - <property name="module.plugin" value="true" /> - - <import file="../../module.xml" /> - - <target name="bundle" depends="bundle-tasks" /> -</project> diff --git a/qpid/java/broker-plugins/simple-xml/src/main/java/org/apache/qpid/server/security/access/config/PrincipalPermissions.java b/qpid/java/broker-plugins/simple-xml/src/main/java/org/apache/qpid/server/security/access/config/PrincipalPermissions.java deleted file mode 100755 index d9fc292f03..0000000000 --- a/qpid/java/broker-plugins/simple-xml/src/main/java/org/apache/qpid/server/security/access/config/PrincipalPermissions.java +++ /dev/null @@ -1,687 +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.access.config; - -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import org.apache.commons.lang.StringUtils; -import org.apache.log4j.Logger; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.server.security.Result; - -@SuppressWarnings("unchecked") -public class PrincipalPermissions -{ - public enum Permission - { - CONSUME, - PUBLISH, - CREATEQUEUE, - CREATEEXCHANGE, - ACCESS, - BIND, - UNBIND, - DELETE, - PURGE - } - - private static final Logger _logger = Logger.getLogger(PrincipalPermissions.class); - - private static final Object CONSUME_QUEUES_KEY = new Object(); - private static final Object CONSUME_TEMPORARY_KEY = new Object(); - private static final Object CONSUME_OWN_QUEUES_ONLY_KEY = new Object(); - - private static final Object CREATE_QUEUES_KEY = new Object(); - private static final Object CREATE_EXCHANGES_KEY = new Object(); - - - private static final Object CREATE_QUEUE_TEMPORARY_KEY = new Object(); - private static final Object CREATE_QUEUE_QUEUES_KEY = new Object(); - private static final Object CREATE_QUEUE_EXCHANGES_KEY = new Object(); - - private static final Object CREATE_QUEUE_EXCHANGES_ROUTINGKEYS_KEY = new Object(); - - private static final int PUBLISH_EXCHANGES_KEY = 0; - - private Map _permissions; - private boolean _fullVHostAccess = false; - - private String _user; - - - public PrincipalPermissions(String user) - { - _user = user; - _permissions = new ConcurrentHashMap(); - } - - /** - * - * @param permission the type of permission to check - * - * @param parameters vararg depending on what permission was passed in - * ACCESS: none - * BIND: none - * CONSUME: AMQShortString queueName, Boolean temporary, Boolean ownQueueOnly - * CREATEQUEUE: Boolean temporary, AMQShortString queueName, AMQShortString exchangeName, AMQShortString routingKey - * CREATEEXCHANGE: AMQShortString exchangeName, AMQShortString Class - * DELETE: none - * PUBLISH: Exchange exchange, AMQShortString routingKey - * PURGE: none - * UNBIND: none - */ - public void grant(Permission permission, Object... parameters) - { - switch (permission) - { - case ACCESS:// Parameters : None - grantAccess(permission); - break; - case CONSUME: // Parameters : AMQShortString queueName, Boolean Temporary, Boolean ownQueueOnly - grantConsume(permission, parameters); - break; - case CREATEQUEUE: // Parameters : Boolean temporary, AMQShortString queueName - // , AMQShortString exchangeName , AMQShortString routingKey - grantCreateQueue(permission, parameters); - break; - case CREATEEXCHANGE: - // Parameters AMQShortString exchangeName , AMQShortString Class - grantCreateExchange(permission, parameters); - break; - case PUBLISH: // Parameters : Exchange exchange, AMQShortString routingKey - grantPublish(permission, parameters); - break; - /* The other cases just fall through to no-op */ - case DELETE: - case BIND: // All the details are currently included in the create setup. - case PURGE: - case UNBIND: - break; - } - - } - - private void grantAccess(Permission permission) - { - _fullVHostAccess = true; - } - - private void grantPublish(Permission permission, Object... parameters) { - Map publishRights = (Map) _permissions.get(permission); - - if (publishRights == null) - { - publishRights = new ConcurrentHashMap(); - _permissions.put(permission, publishRights); - } - - if (parameters == null || parameters.length == 0) - { - //If we have no parameters then allow publish to all destinations - // this is signified by having a null value for publish_exchanges - } - else - { - Map publish_exchanges = (Map) publishRights.get(PUBLISH_EXCHANGES_KEY); - - if (publish_exchanges == null) - { - publish_exchanges = new ConcurrentHashMap(); - publishRights.put(PUBLISH_EXCHANGES_KEY, publish_exchanges); - } - - - HashSet routingKeys = (HashSet) publish_exchanges.get(parameters[0]); - - // Check to see if we have a routing key - if (parameters.length == 2) - { - if (routingKeys == null) - { - routingKeys = new HashSet<AMQShortString>(); - } - //Add routing key to permitted publish destinations - routingKeys.add(parameters[1]); - } - - // Add the updated routingkey list or null if all values allowed - publish_exchanges.put(parameters[0], routingKeys); - } - } - - private void grantCreateExchange(Permission permission, Object... parameters) { - Map rights = (Map) _permissions.get(permission); - if (rights == null) - { - rights = new ConcurrentHashMap(); - _permissions.put(permission, rights); - } - - Map create_exchanges = (Map) rights.get(CREATE_EXCHANGES_KEY); - if (create_exchanges == null) - { - create_exchanges = new ConcurrentHashMap(); - rights.put(CREATE_EXCHANGES_KEY, create_exchanges); - } - - //Should perhaps error if parameters[0] is null; - AMQShortString name = parameters.length > 0 ? (AMQShortString) parameters[0] : null; - AMQShortString className = parameters.length > 1 ? (AMQShortString) parameters[1] : new AMQShortString("direct"); - - //Store the exchangeName / class mapping if the mapping is null - rights.put(name, className); - } - - private void grantCreateQueue(Permission permission, Object... parameters) - { - Map createRights = (Map) _permissions.get(permission); - - if (createRights == null) - { - createRights = new ConcurrentHashMap(); - _permissions.put(permission, createRights); - } - - //The existence of the empty map mean permission to all. - if (parameters.length == 0) - { - return; - } - - // Get the queues map - Map create_queues = (Map) createRights.get(CREATE_QUEUES_KEY); - - //Initialiase the queue permissions if not already done - if (create_queues == null) - { - create_queues = new ConcurrentHashMap(); - //initialise temp queue permission to false and overwrite below if true - create_queues.put(CREATE_QUEUE_TEMPORARY_KEY, false); - createRights.put(CREATE_QUEUES_KEY, create_queues); - } - - //Create empty list of queues - Map create_queues_queues = (Map) create_queues.get(CREATE_QUEUE_QUEUES_KEY); - - if (create_queues_queues == null) - { - create_queues_queues = new ConcurrentHashMap(); - create_queues.put(CREATE_QUEUE_QUEUES_KEY, create_queues_queues); - } - - // If we are initialising and granting CREATE rights to all temporary queues, then that's all we do - Boolean temporary = false; - if (parameters.length == 1) - { - temporary = (Boolean) parameters[0]; - create_queues.put(CREATE_QUEUE_TEMPORARY_KEY, temporary); - return; - } - - //From here we can be permissioning a variety of things, with varying parameters - AMQShortString queueName = parameters.length > 1 ? (AMQShortString) parameters[1] : null; - AMQShortString exchangeName = parameters.length > 2 ? (AMQShortString) parameters[2] : null; - //Set the routingkey to the specified value or the queueName if present - AMQShortString routingKey = (parameters.length > 3 && null != parameters[3]) ? (AMQShortString) parameters[3] : queueName; - // if we have a queueName then we need to store any associated exchange / rk bindings - if (queueName != null) - { - Map queue = (Map) create_queues_queues.get(queueName); - if (queue == null) - { - queue = new ConcurrentHashMap(); - create_queues_queues.put(queueName, queue); - } - - if (exchangeName != null) - { - queue.put(exchangeName, routingKey); - } - - //If no exchange is specified then the presence of the queueName in the map says any exchange is ok - } - - // Store the exchange that we are being granted rights to. This will be used as part of binding - - //Lookup the list of exchanges - Map create_queues_exchanges = (Map) create_queues.get(CREATE_QUEUE_EXCHANGES_KEY); - - if (create_queues_exchanges == null) - { - create_queues_exchanges = new ConcurrentHashMap(); - create_queues.put(CREATE_QUEUE_EXCHANGES_KEY, create_queues_exchanges); - } - - //if we have an exchange - if (exchangeName != null) - { - //Retrieve the list of permitted exchanges. - Map exchanges = (Map) create_queues_exchanges.get(exchangeName); - - if (exchanges == null) - { - exchanges = new ConcurrentHashMap(); - create_queues_exchanges.put(exchangeName, exchanges); - } - - //Store the binding details of queue/rk for this exchange. - if (queueName != null) - { - //Retrieve the list of permitted routingKeys. - Map rKeys = (Map) exchanges.get(exchangeName); - - if (rKeys == null) - { - rKeys = new ConcurrentHashMap(); - exchanges.put(CREATE_QUEUE_EXCHANGES_ROUTINGKEYS_KEY, rKeys); - } - - rKeys.put(queueName, routingKey); - } - } - } - - /** - * Grant consume permissions - */ - private void grantConsume(Permission permission, Object... parameters) - { - Map consumeRights = (Map) _permissions.get(permission); - - if (consumeRights == null) - { - consumeRights = new ConcurrentHashMap(); - _permissions.put(permission, consumeRights); - - //initialise own and temporary rights to false to be overwritten below if set - consumeRights.put(CONSUME_TEMPORARY_KEY, false); - consumeRights.put(CONSUME_OWN_QUEUES_ONLY_KEY, false); - } - - - //if we only have one param then we're permissioning temporary queues and topics - if (parameters.length == 1) - { - Boolean temporary = (Boolean) parameters[0]; - - if (temporary) - { - consumeRights.put(CONSUME_TEMPORARY_KEY, true); - } - } - - //if we have 2 parameters - should be a contract for this, but for now we'll handle it as is - if (parameters.length == 2) - { - AMQShortString queueName = (AMQShortString) parameters[0]; - Boolean ownQueueOnly = (Boolean) parameters[1]; - - if (ownQueueOnly) - { - consumeRights.put(CONSUME_OWN_QUEUES_ONLY_KEY, true); - } - - LinkedList queues = (LinkedList) consumeRights.get(CONSUME_QUEUES_KEY); - if (queues == null) - { - queues = new LinkedList(); - consumeRights.put(CONSUME_QUEUES_KEY, queues); - } - - if (queueName != null) - { - queues.add(queueName); - } - } - } - - /** - * - * @param permission the type of permission to check - * - * @param parameters vararg depending on what permission was passed in - * ACCESS: none - * BIND: QueueBindBody bindmethod, Exchange exchange, AMQQueue queue, AMQShortString routingKey - * CONSUME: AMQQueue queue - * CREATEQUEUE: Boolean autodelete, AMQShortString name - * CREATEEXCHANGE: AMQShortString exchangeName - * DELETE: none - * PUBLISH: Exchange exchange, AMQShortString routingKey - * PURGE: none - * UNBIND: none - */ - public Result authorise(Permission permission, String... parameters) - { - - switch (permission) - { - case ACCESS://No Parameters - return Result.ALLOWED; // The existence of this user-specific PP infers some level of access is authorised - case BIND: // Parameters : QueueBindMethod , exhangeName , queueName, routingKey - return authoriseBind(parameters); - case CREATEQUEUE:// Parameters : autoDelete, queueName - return authoriseCreateQueue(permission, parameters); - case CREATEEXCHANGE: //Parameters: exchangeName - return authoriseCreateExchange(permission, parameters); - case CONSUME: // Parameters : queueName, autoDelete, owner - return authoriseConsume(permission, parameters); - case PUBLISH: // Parameters : exchangeName, routingKey - return authorisePublish(permission, parameters); - /* Fall through */ - case DELETE: - case PURGE: - case UNBIND: - default: - if(_fullVHostAccess) - { - //user has been granted full access to the vhost - return Result.ALLOWED; - } - else - { - //SimpleXML ACL does not implement these permissions and should abstain - return Result.ABSTAIN; - } - } - - } - - private Result authoriseConsume(Permission permission, String... parameters) - { - if(_fullVHostAccess) - { - //user has been granted full access to the vhost - return Result.ALLOWED; - } - - if (parameters.length == 3) - { - AMQShortString queueName = new AMQShortString(parameters[0]); - Boolean autoDelete = Boolean.valueOf(parameters[1]); - AMQShortString owner = new AMQShortString(parameters[2]); - Map queuePermissions = (Map) _permissions.get(permission); - - _logger.error("auth consume on " + StringUtils.join(parameters, ", ")); - - if (queuePermissions == null) - { - //we have a problem - we've never granted this type of permission ..... - return Result.DENIED; - } - - List queues = (List) queuePermissions.get(CONSUME_QUEUES_KEY); - - Boolean temporaryQueues = (Boolean) queuePermissions.get(CONSUME_TEMPORARY_KEY); - Boolean ownQueuesOnly = (Boolean) queuePermissions.get(CONSUME_OWN_QUEUES_ONLY_KEY); - - - // If user is allowed to consume from temporary queues and this is a temp queue then allow it. - if (temporaryQueues && autoDelete) - { - // This will allow consumption from any temporary queue including ones not owned by this user. - // Of course the exclusivity will not be broken. - { - - // if not limited to ownQueuesOnly then ok else check queue Owner. - return (!ownQueuesOnly || owner.equals(_user)) ? Result.ALLOWED : Result.DENIED; - } - } - //if this is a temporary queue and the user does not have permissions for temporary queues then deny - else if (!temporaryQueues && autoDelete) - { - return Result.DENIED; - } - - // if queues are white listed then ensure it is ok - if (queues != null) - { - // if no queues are listed then ALL are ok othereise it must be specified. - if (ownQueuesOnly) - { - if (owner.equals(_user)) - { - return (queues.size() == 0 || queues.contains(queueName)) ? Result.ALLOWED : Result.DENIED; - } - else - { - return Result.DENIED; - } - } - - // If we are - return (queues.size() == 0 || queues.contains(queueName)) ? Result.ALLOWED : Result.DENIED; - } - } - - // Can't authenticate without the right parameters - return Result.DENIED; - } - - private Result authorisePublish(Permission permission, String... parameters) - { - if(_fullVHostAccess) - { - //user has been granted full access to the vhost - return Result.ALLOWED; - } - - Map publishRights = (Map) _permissions.get(permission); - - if (publishRights == null) - { - return Result.DENIED; - } - - Map exchanges = (Map) publishRights.get(PUBLISH_EXCHANGES_KEY); - - // Having no exchanges listed gives full publish rights to all exchanges - if (exchanges == null) - { - return Result.ALLOWED; - } - // Otherwise exchange must be listed in the white list - - // If the map doesn't have the exchange then it isn't allowed - AMQShortString exchangeName = new AMQShortString(parameters[0]); - if (!exchanges.containsKey(exchangeName)) - { - return Result.DENIED; - } - else - { - // Get valid routing keys - HashSet routingKeys = (HashSet) exchanges.get(exchangeName); - - // Having no routingKeys in the map then all are allowed. - if (routingKeys == null) - { - return Result.ALLOWED; - } - else - { - // We have routingKeys so a match must be found to allowed binding - Iterator keys = routingKeys.iterator(); - - AMQShortString publishRKey = new AMQShortString(parameters[1]); - - boolean matched = false; - while (keys.hasNext() && !matched) - { - AMQShortString rkey = (AMQShortString) keys.next(); - - if (rkey.endsWith("*")) - { - matched = publishRKey.startsWith(rkey.subSequence(0, rkey.length() - 1)); - } - else - { - matched = publishRKey.equals(rkey); - } - } - return (matched) ? Result.ALLOWED : Result.DENIED; - } - } - } - - private Result authoriseCreateExchange(Permission permission, String... parameters) - { - if(_fullVHostAccess) - { - //user has been granted full access to the vhost - return Result.ALLOWED; - } - - Map rights = (Map) _permissions.get(permission); - - AMQShortString exchangeName = new AMQShortString(parameters[0]); - - // If the exchange list is doesn't exist then all is allowed else - // check the valid exchanges - if (rights == null || rights.containsKey(exchangeName)) - { - return Result.ALLOWED; - } - else - { - return Result.DENIED; - } - } - - private Result authoriseCreateQueue(Permission permission, String... parameters) - { - if(_fullVHostAccess) - { - //user has been granted full access to the vhost - return Result.ALLOWED; - } - - Map createRights = (Map) _permissions.get(permission); - - // If there are no create rights then deny request - if (createRights == null) - { - return Result.DENIED; - } - - //Look up the Queue Creation Rights - Map create_queues = (Map) createRights.get(CREATE_QUEUES_KEY); - - //Lookup the list of queues allowed to be created - Map create_queues_queues = (Map) create_queues.get(CREATE_QUEUE_QUEUES_KEY); - - - Boolean autoDelete = Boolean.valueOf(parameters[0]); - AMQShortString queueName = new AMQShortString(parameters[1]); - - if (autoDelete)// we have a temporary queue - { - return ((Boolean) create_queues.get(CREATE_QUEUE_TEMPORARY_KEY)) ? Result.ALLOWED : Result.DENIED; - } - else - { - // If there is a white list then check - if (create_queues_queues == null || create_queues_queues.containsKey(queueName)) - { - return Result.ALLOWED; - } - else - { - return Result.DENIED; - } - - } - } - - private Result authoriseBind(String... parameters) - { - if(_fullVHostAccess) - { - //user has been granted full access to the vhost - return Result.ALLOWED; - } - - AMQShortString exchangeName = new AMQShortString(parameters[1]); - AMQShortString bind_queueName = new AMQShortString(parameters[2]); - AMQShortString routingKey = new AMQShortString(parameters[3]); - - //Get all Create Rights for this user - Map bindCreateRights = (Map) _permissions.get(Permission.CREATEQUEUE); - - //Lookup the list of queues - Map bind_create_queues_queues = (Map) bindCreateRights.get(CREATE_QUEUE_QUEUES_KEY); - - // Check and see if we have a queue white list to check - if (bind_create_queues_queues != null) - { - //There a white list for queues - Map exchangeDetails = (Map) bind_create_queues_queues.get(bind_queueName); - - if (exchangeDetails == null) //Then all queue can be bound to all exchanges. - { - return Result.ALLOWED; - } - - // Check to see if we have a white list of routingkeys to check - Map rkeys = (Map) exchangeDetails.get(exchangeName); - - // if keys is null then any rkey is allowed on this exchange - if (rkeys == null) - { - // There is no routingkey white list - return Result.ALLOWED; - } - else - { - // We have routingKeys so a match must be found to allowed binding - Iterator keys = rkeys.keySet().iterator(); - - boolean matched = false; - while (keys.hasNext() && !matched) - { - AMQShortString rkey = (AMQShortString) keys.next(); - if (rkey.endsWith("*")) - { - matched = routingKey.startsWith(rkey.subSequence(0, rkey.length() - 1).toString()); - } - else - { - matched = routingKey.equals(rkey); - } - } - - - return (matched) ? Result.ALLOWED : Result.DENIED; - } - - - } - else - { - //no white list so all allowed. - return Result.ALLOWED; - } - } -} diff --git a/qpid/java/broker-plugins/simple-xml/src/main/java/org/apache/qpid/server/security/access/plugins/SimpleXML.java b/qpid/java/broker-plugins/simple-xml/src/main/java/org/apache/qpid/server/security/access/plugins/SimpleXML.java deleted file mode 100644 index ab43653122..0000000000 --- a/qpid/java/broker-plugins/simple-xml/src/main/java/org/apache/qpid/server/security/access/plugins/SimpleXML.java +++ /dev/null @@ -1,427 +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.access.plugins; - -import static org.apache.qpid.server.security.access.ObjectProperties.Property.*; - -import java.security.Principal; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.log4j.Logger; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; -import org.apache.qpid.server.security.AbstractPlugin; -import org.apache.qpid.server.security.Result; -import org.apache.qpid.server.security.SecurityManager; -import org.apache.qpid.server.security.SecurityPluginFactory; -import org.apache.qpid.server.security.access.ObjectProperties; -import org.apache.qpid.server.security.access.ObjectType; -import org.apache.qpid.server.security.access.Operation; -import org.apache.qpid.server.security.access.config.PrincipalPermissions; -import org.apache.qpid.server.security.access.config.PrincipalPermissions.Permission; - -/** - * This uses the default - */ -public class SimpleXML extends AbstractPlugin -{ - public static final Logger _logger = Logger.getLogger(SimpleXML.class); - - private Map<String, PrincipalPermissions> _users; - - public static final SecurityPluginFactory<SimpleXML> FACTORY = new SecurityPluginFactory<SimpleXML>() - { - public SimpleXML newInstance(ConfigurationPlugin config) throws ConfigurationException - { - SimpleXMLConfiguration configuration = config.getConfiguration(SimpleXMLConfiguration.class.getName()); - - // If there is no configuration for this plugin then don't load it. - if (configuration == null) - { - return null; - } - - SimpleXML plugin = new SimpleXML(); - plugin.configure(configuration); - return plugin; - } - - public String getPluginName() - { - return SimpleXML.class.getName(); - } - - public Class<SimpleXML> getPluginClass() - { - return SimpleXML.class; - } - }; - - public void configure(ConfigurationPlugin config) - { - super.configure(config); - - SimpleXMLConfiguration configuration = (SimpleXMLConfiguration) _config; - - _users = new ConcurrentHashMap<String, PrincipalPermissions>(); - - processConfig(configuration.getConfiguration()); - } - - private void processConfig(Configuration config) - { - processPublish(config); - processConsume(config); - processCreate(config); - processAccess(config); - } - - /** - * @param config XML Configuration - */ - private void processAccess(Configuration config) - { - Configuration accessConfig = config.subset("access"); - - if (accessConfig.isEmpty()) - { - //there is no access configuration to process - return; - } - - // Process users that have full access permission - String[] users = accessConfig.getStringArray("users.user"); - - for (String user : users) - { - grant(Permission.ACCESS, user); - } - } - - /** - * Publish format takes Exchange + Routing Key Pairs - * - * @param config XML Configuration - */ - private void processPublish(Configuration config) - { - Configuration publishConfig = config.subset("publish"); - - // Process users that have full publish permission - String[] users = publishConfig.getStringArray("users.user"); - - for (String user : users) - { - grant(Permission.PUBLISH, user); - } - - // Process exchange limited users - int exchangeCount = 0; - Configuration exchangeConfig = publishConfig.subset("exchanges.exchange(" + exchangeCount + ")"); - - while (!exchangeConfig.isEmpty()) - { - // Get Exchange Name - AMQShortString exchangeName = new AMQShortString(exchangeConfig.getString("name")); - - // Get Routing Keys - int keyCount = 0; - Configuration routingkeyConfig = exchangeConfig.subset("routing_keys.routing_key(" + keyCount + ")"); - - while (!routingkeyConfig.isEmpty()) - { - // Get RoutingKey Value - AMQShortString routingKeyValue = new AMQShortString(routingkeyConfig.getString("value")); - - // Apply Exchange + RoutingKey permissions to Users - users = routingkeyConfig.getStringArray("users.user"); - for (String user : users) - { - grant(Permission.PUBLISH, user, exchangeName, routingKeyValue); - } - - // Apply permissions to Groups - - // Check for more configs - keyCount++; - routingkeyConfig = exchangeConfig.subset("routing_keys.routing_key(" + keyCount + ")"); - } - - // Apply Exchange wide permissions to Users - users = exchangeConfig.getStringArray("exchange(" + exchangeCount + ").users.user"); - - for (String user : users) - { - grant(Permission.PUBLISH, user, exchangeName); - } - - // Apply permissions to Groups - exchangeCount++; - exchangeConfig = publishConfig.subset("exchanges.exchange(" + exchangeCount + ")"); - } - } - - private void grant(Permission permission, String user, Object... parameters) - { - PrincipalPermissions permissions = _users.get(user); - - if (permissions == null) - { - permissions = new PrincipalPermissions(user); - } - - _users.put(user, permissions); - permissions.grant(permission, parameters); - } - - /** - * @param config XML Configuration - */ - private void processConsume(Configuration config) - { - boolean temporary = false; - Configuration tempConfig = null; - Configuration consumeConfig = config.subset("consume"); - - tempConfig = consumeConfig.subset("queues.temporary(0)"); - if (tempConfig != null) - { - temporary = true; - } - - //Permission all users who have rights to temp queues and topics - if (tempConfig != null && !tempConfig.isEmpty()) - { - String[] tempUsers = tempConfig.getStringArray("users.user"); - for (String user : tempUsers) - { - grant(Permission.CONSUME, user, temporary); - } - } - - // Process queue limited users - int queueCount = 0; - Configuration queueConfig = consumeConfig.subset("queues.queue(" + queueCount + ")"); - - while (!queueConfig.isEmpty()) - { - // Get queue Name - AMQShortString queueName = new AMQShortString(queueConfig.getString("name")); - // if there is no name then there may be a temporary element - - boolean ownQueues = queueConfig.containsKey("own_queues"); - - // Process permissions for this queue - String[] users = queueConfig.getStringArray("users.user"); - for (String user : users) - { - grant(Permission.CONSUME, user, queueName, ownQueues); - } - - // See if we have another config - queueCount++; - queueConfig = consumeConfig.subset("queues.queue(" + queueCount + ")"); - } - - // Process users that have full consume permission - String[] users = consumeConfig.getStringArray("users.user"); - - for (String user : users) - { - //NOTE: this call does not appear to do anything inside the grant section for consume - grant(Permission.CONSUME, user); - } - } - - /** - * @param config XML Configuration - */ - private void processCreate(Configuration config) - { - boolean temporary = false; - Configuration tempConfig = null; - - Configuration createConfig = config.subset("create"); - - tempConfig = createConfig.subset("queues.temporary(0)"); - if (tempConfig != null) - { - temporary = true; - } - - //Permission all users who have rights to temp queues and topics - if (tempConfig != null && !tempConfig.isEmpty()) - { - String[] tempUsers = tempConfig.getStringArray("users.user"); - for (String user : tempUsers) - { - grant(Permission.CREATEQUEUE, user, temporary); - } - } - // Process create permissions for queue creation - int queueCount = 0; - Configuration queueConfig = createConfig.subset("queues.queue(" + queueCount + ")"); - - while (!queueConfig.isEmpty()) - { - // Get queue Name - AMQShortString queueName = new AMQShortString(queueConfig.getString("name")); - - int exchangeCount = 0; - Configuration exchangeConfig = queueConfig.subset("exchanges.exchange(" + exchangeCount + ")"); - - while (!exchangeConfig.isEmpty()) - { - - AMQShortString exchange = new AMQShortString(exchangeConfig.getString("name")); - AMQShortString routingKey = new AMQShortString(exchangeConfig.getString("routing_key")); - - // Process permissions for this queue - String[] users = exchangeConfig.getStringArray("users.user"); - for (String user : users) - { - //This is broken as the user name is not stored - grant(Permission.CREATEEXCHANGE, user, exchange); - - //This call could be cleaned up as temporary is now being set earlier (above) - grant(Permission.CREATEQUEUE, user, temporary, (queueName.equals("") ? null : queueName), (exchange - .equals("") ? null : exchange), (routingKey.equals("") ? null : routingKey)); - } - - // See if we have another config - exchangeCount++; - exchangeConfig = queueConfig.subset("exchanges.exchange(" + exchangeCount + ")"); - } - - // Process users that are not bound to an exchange - String[] users = queueConfig.getStringArray("users.user"); - - for (String user : users) - { - grant(Permission.CREATEQUEUE, user, temporary, queueName); - } - - // See if we have another config - queueCount++; - queueConfig = createConfig.subset("queues.queue(" + queueCount + ")"); - } - - // Process create permissions for exchange creation - int exchangeCount = 0; - Configuration exchangeConfig = createConfig.subset("exchanges.exchange(" + exchangeCount + ")"); - - while (!exchangeConfig.isEmpty()) - { - AMQShortString exchange = new AMQShortString(exchangeConfig.getString("name")); - AMQShortString clazz = new AMQShortString(exchangeConfig.getString("class")); - - // Process permissions for this queue - String[] users = exchangeConfig.getStringArray("users.user"); - for (String user : users) - { - //And this is broken too - grant(Permission.CREATEEXCHANGE, user, exchange, clazz); - } - - // See if we have another config - exchangeCount++; - exchangeConfig = queueConfig.subset("exchanges.exchange(" + exchangeCount + ")"); - } - - // Process users that have full create permission - String[] users = createConfig.getStringArray("users.user"); - - for (String user : users) - { - grant(Permission.CREATEEXCHANGE, user); - grant(Permission.CREATEQUEUE, user); - } - } - - public Result access(ObjectType objectType, Object instance) - { - Principal principal = SecurityManager.getThreadPrincipal(); - if (principal == null) - { - return getDefault(); // Default if there is no user associated with the thread - } - PrincipalPermissions principalPermissions = _users.get(principal.getName()); - if (principalPermissions == null) - { - return Result.DENIED; - } - - // Authorise object access - if (objectType == ObjectType.VIRTUALHOST) - { - return principalPermissions.authorise(Permission.ACCESS); - } - - // Default - return getDefault(); - } - - public Result authorise(Operation operation, ObjectType objectType, ObjectProperties properties) - { - Principal principal = SecurityManager.getThreadPrincipal(); - if (principal == null) - { - return getDefault(); // Default if there is no user associated with the thread - } - PrincipalPermissions principalPermissions = _users.get(principal.getName()); - if (principalPermissions == null) - { - return Result.DENIED; - } - - // Authorise operation - switch (operation) - { - case CONSUME: - return principalPermissions.authorise(Permission.CONSUME, properties.get(NAME), properties.get(AUTO_DELETE), properties.get(OWNER)); - case PUBLISH: - return principalPermissions.authorise(Permission.PUBLISH, properties.get(NAME), properties.get(ROUTING_KEY)); - case CREATE: - if (objectType == ObjectType.EXCHANGE) - { - return principalPermissions.authorise(Permission.CREATEEXCHANGE, properties.get(NAME)); - } - else if (objectType == ObjectType.QUEUE) - { - return principalPermissions.authorise(Permission.CREATEQUEUE, properties.get(AUTO_DELETE), properties.get(NAME)); - } - case ACCESS: - return principalPermissions.authorise(Permission.ACCESS); - case BIND: - return principalPermissions.authorise(Permission.BIND, null, properties.get(NAME), properties.get(QUEUE_NAME), properties.get(ROUTING_KEY)); - case UNBIND: - return principalPermissions.authorise(Permission.UNBIND); - case DELETE: - return principalPermissions.authorise(Permission.DELETE); - case PURGE: - return principalPermissions.authorise(Permission.PURGE); - } - - // Default - return getDefault(); - } -} diff --git a/qpid/java/broker-plugins/simple-xml/src/main/java/org/apache/qpid/server/security/access/plugins/SimpleXMLActivator.java b/qpid/java/broker-plugins/simple-xml/src/main/java/org/apache/qpid/server/security/access/plugins/SimpleXMLActivator.java deleted file mode 100644 index c09a9da0d8..0000000000 --- a/qpid/java/broker-plugins/simple-xml/src/main/java/org/apache/qpid/server/security/access/plugins/SimpleXMLActivator.java +++ /dev/null @@ -1,42 +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.access.plugins; - -import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory; -import org.apache.qpid.server.security.SecurityPluginActivator; -import org.apache.qpid.server.security.SecurityPluginFactory; -import org.osgi.framework.BundleActivator; - -/** - * The OSGi {@link BundleActivator} for {@link SimpleXML}. - */ -public class SimpleXMLActivator extends SecurityPluginActivator -{ - public SecurityPluginFactory getFactory() - { - return SimpleXML.FACTORY; - } - - public ConfigurationPluginFactory getConfigurationFactory() - { - return SimpleXMLConfiguration.FACTORY; - } -} diff --git a/qpid/java/broker-plugins/simple-xml/src/main/java/org/apache/qpid/server/security/access/plugins/SimpleXMLConfiguration.java b/qpid/java/broker-plugins/simple-xml/src/main/java/org/apache/qpid/server/security/access/plugins/SimpleXMLConfiguration.java deleted file mode 100644 index e95c21b590..0000000000 --- a/qpid/java/broker-plugins/simple-xml/src/main/java/org/apache/qpid/server/security/access/plugins/SimpleXMLConfiguration.java +++ /dev/null @@ -1,57 +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.access.plugins; - -import java.util.Arrays; -import java.util.List; - -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; -import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory; - -public class SimpleXMLConfiguration extends ConfigurationPlugin -{ - public static final ConfigurationPluginFactory FACTORY = new ConfigurationPluginFactory() - { - public ConfigurationPlugin newInstance(String path, Configuration config) throws ConfigurationException - { - ConfigurationPlugin instance = new SimpleXMLConfiguration(); - instance.setConfiguration(path, config); - return instance; - } - - public List<String> getParentPaths() - { - return Arrays.asList("security.access_control_list", "virtualhosts.virtualhost.security.access_control_list"); - } - }; - - public String[] getElementsProcessed() - { - return new String[] { "" }; - } - - public Configuration getConfiguration() - { - return _configuration; - } -} diff --git a/qpid/java/broker-plugins/simple-xml/src/test/java/org/apache/qpid/server/security/access/PrincipalPermissionsTest.java b/qpid/java/broker-plugins/simple-xml/src/test/java/org/apache/qpid/server/security/access/PrincipalPermissionsTest.java deleted file mode 100644 index 65ab12a095..0000000000 --- a/qpid/java/broker-plugins/simple-xml/src/test/java/org/apache/qpid/server/security/access/PrincipalPermissionsTest.java +++ /dev/null @@ -1,209 +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.access; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.server.security.Result; -import org.apache.qpid.server.security.access.config.PrincipalPermissions; -import org.apache.qpid.server.security.access.config.PrincipalPermissions.Permission; -import org.apache.qpid.test.utils.QpidTestCase; - -public class PrincipalPermissionsTest extends QpidTestCase -{ - private String _user = "user"; - private PrincipalPermissions _perms; - - // Common things that are passed to frame constructors - private AMQShortString _queueName = new AMQShortString(this.getClass().getName() + "queue"); - private AMQShortString _tempQueueName = new AMQShortString(this.getClass().getName() + "tempqueue"); - private AMQShortString _exchangeName = new AMQShortString("amq.direct"); - private AMQShortString _routingKey = new AMQShortString(this.getClass().getName() + "route"); - private boolean _autoDelete = false; - private AMQShortString _exchangeType = new AMQShortString("direct"); - private Boolean _temporary = false; - private Boolean _ownQueue = false; - - @Override - public void setUp() throws Exception - { - super.setUp(); - - _perms = new PrincipalPermissions(_user); - } - - - public void testPrincipalPermissions() - { - assertNotNull(_perms); - assertEquals(Result.ALLOWED, _perms.authorise(Permission.ACCESS, (String[]) null)); - } - - // FIXME: test has been disabled since the permissions assume that the user has tried to create - // the queue first. QPID-1597 - public void disableTestBind() throws Exception - { - String[] args = new String[]{null, _exchangeName.asString(), _queueName.asString(), _routingKey.asString()}; - - assertEquals(Result.DENIED, _perms.authorise(Permission.BIND, args)); - _perms.grant(Permission.BIND, (Object[]) null); - assertEquals(Result.ALLOWED, _perms.authorise(Permission.BIND, args)); - } - - public void testQueueCreate() - { - Object[] grantArgs = new Object[]{_temporary , _queueName, _exchangeName, _routingKey}; - String[] authArgs = new String[]{Boolean.toString(_autoDelete), _queueName.asString()}; - - assertEquals(Result.DENIED, _perms.authorise(Permission.CREATEQUEUE, authArgs)); - _perms.grant(Permission.CREATEQUEUE, grantArgs); - assertEquals(Result.ALLOWED, _perms.authorise(Permission.CREATEQUEUE, authArgs)); - } - - public void testQueueCreateWithNullRoutingKey() - { - Object[] grantArgs = new Object[]{_temporary , _queueName, _exchangeName, null}; - String[] authArgs = new String[]{Boolean.toString(_autoDelete), _queueName.asString()}; - - assertEquals(Result.DENIED, _perms.authorise(Permission.CREATEQUEUE, authArgs)); - _perms.grant(Permission.CREATEQUEUE, grantArgs); - assertEquals(Result.ALLOWED, _perms.authorise(Permission.CREATEQUEUE, authArgs)); - } - - // FIXME disabled, this fails due to grant putting the grant into the wrong map QPID-1598 - public void disableTestExchangeCreate() - { - String[] authArgs = new String[]{_exchangeName.asString()}; - Object[] grantArgs = new Object[]{_exchangeName, _exchangeType}; - - assertEquals(Result.DENIED, _perms.authorise(Permission.CREATEEXCHANGE, authArgs)); - _perms.grant(Permission.CREATEEXCHANGE, grantArgs); - assertEquals(Result.ALLOWED, _perms.authorise(Permission.CREATEEXCHANGE, authArgs)); - } - - public void testConsume() - { - String[] authArgs = new String[]{_queueName.asString(), Boolean.toString(_autoDelete), _user}; - Object[] grantArgs = new Object[]{_queueName, _ownQueue}; - - // FIXME: This throws a null pointer exception QPID-1599 - // assertFalse(_perms.authorise(Permission.CONSUME, authArgs)); - _perms.grant(Permission.CONSUME, grantArgs); - assertEquals(Result.ALLOWED, _perms.authorise(Permission.CONSUME, authArgs)); - } - - public void testPublish() throws AMQException - { - String[] authArgs = new String[]{_exchangeName.asString(), _routingKey.asString()}; - Object[] grantArgs = new Object[]{_exchangeName, _routingKey}; - - assertEquals(Result.DENIED, _perms.authorise(Permission.PUBLISH, authArgs)); - _perms.grant(Permission.PUBLISH, grantArgs); - assertEquals(Result.ALLOWED, _perms.authorise(Permission.PUBLISH, authArgs)); - } - - public void testVhostAccess() - { - //Tests that granting a user Virtualhost level access allows all authorisation requests - //where previously they would be denied - - //QPID-2133 createExchange rights currently allow all exchange creation unless rights for creating some - //specific exchanges are granted. Grant a specific exchange creation to cause all others to be denied. - Object[] createArgsCreateExchange = new Object[]{new AMQShortString("madeup"), _exchangeType}; - String[] authArgsCreateExchange = new String[]{_exchangeName.asString()}; - assertEquals("Exchange creation was not allowed", Result.ALLOWED, _perms.authorise(Permission.CREATEEXCHANGE, authArgsCreateExchange)); - _perms.grant(Permission.CREATEEXCHANGE, createArgsCreateExchange); - - String[] authArgsPublish = new String[]{_exchangeName.asString(), _routingKey.asString()}; - String[] authArgsConsume = new String[]{_queueName.asString(), Boolean.toString(_autoDelete), _user}; - String[] authArgsCreateQueue = new String[]{Boolean.toString(_autoDelete), _queueName.asString()}; -// QueueBindBodyImpl bind = new QueueBindBodyImpl(_ticket, _queueName, _exchangeName, _routingKey, _nowait, _arguments); - String[] authArgsBind = new String[]{ null, _exchangeName.asString(), _queueName.asString(), _routingKey.asString()}; - - assertEquals("Exchange creation was not denied", Result.DENIED, _perms.authorise(Permission.CREATEEXCHANGE, authArgsCreateExchange)); - assertEquals("Publish was not denied", Result.DENIED, _perms.authorise(Permission.PUBLISH, authArgsPublish)); - assertEquals("Consume creation was not denied", Result.DENIED, _perms.authorise(Permission.CONSUME, authArgsConsume)); - assertEquals("Queue creation was not denied", Result.DENIED, _perms.authorise(Permission.CREATEQUEUE, authArgsCreateQueue)); - //BIND pre-grant authorise check disabled due to QPID-1597 - //assertEquals("Binding creation was not denied", Result.DENIED, _perms.authorise(Permission.BIND, authArgsBind)); - - _perms.grant(Permission.ACCESS); - - assertEquals("Exchange creation was not allowed", Result.ALLOWED, _perms.authorise(Permission.CREATEEXCHANGE, authArgsCreateExchange)); - assertEquals("Publish was not allowed", Result.ALLOWED, _perms.authorise(Permission.PUBLISH, authArgsPublish)); - assertEquals("Consume creation was not allowed", Result.ALLOWED, _perms.authorise(Permission.CONSUME, authArgsConsume)); - assertEquals("Queue creation was not allowed", Result.ALLOWED, _perms.authorise(Permission.CREATEQUEUE, authArgsCreateQueue)); - assertEquals("Binding creation was not allowed", Result.ALLOWED, _perms.authorise(Permission.BIND, authArgsBind)); - } - - /** - * If the consume permission for temporary queues is for an unnamed queue then is should - * be global for any temporary queue but not for any non-temporary queue - */ - public void testTemporaryUnnamedQueueConsume() - { - String[] authNonTempQArgs = new String[]{_queueName.asString(), Boolean.toString(_autoDelete), _user}; - String[] authTempQArgs = new String[]{_tempQueueName.asString(), Boolean.TRUE.toString(), _user}; - Object[] grantArgs = new Object[]{true}; - - _perms.grant(Permission.CONSUME, grantArgs); - - //Next line shows up bug - non temp queue should be denied - assertEquals(Result.DENIED, _perms.authorise(Permission.CONSUME, authNonTempQArgs)); - assertEquals(Result.ALLOWED, _perms.authorise(Permission.CONSUME, authTempQArgs)); - } - - /** - * Test that temporary queue permissions before queue perms in the ACL config work correctly - */ - public void testTemporaryQueueFirstConsume() - { - String[] authNonTempQArgs = new String[]{_queueName.asString(), Boolean.toString(_autoDelete), _user}; - String[] authTempQArgs = new String[]{_tempQueueName.asString(), Boolean.TRUE.toString(), _user}; - Object[] grantArgs = new Object[]{true}; - Object[] grantNonTempQArgs = new Object[]{_queueName, _ownQueue}; - - //should not matter if the temporary permission is processed first or last - _perms.grant(Permission.CONSUME, grantNonTempQArgs); - _perms.grant(Permission.CONSUME, grantArgs); - - assertEquals(Result.ALLOWED, _perms.authorise(Permission.CONSUME, authNonTempQArgs)); - assertEquals(Result.ALLOWED, _perms.authorise(Permission.CONSUME, authTempQArgs)); - } - - /** - * Test that temporary queue permissions after queue perms in the ACL config work correctly - */ - public void testTemporaryQueueLastConsume() - { - String[] authNonTempQArgs = new String[]{_queueName.asString(), Boolean.toString(_autoDelete), _user}; - String[] authTempQArgs = new String[]{_tempQueueName.asString(), Boolean.TRUE.toString(), _user}; - Object[] grantArgs = new Object[]{true}; - Object[] grantNonTempQArgs = new Object[]{_queueName, _ownQueue}; - - //should not matter if the temporary permission is processed first or last - _perms.grant(Permission.CONSUME, grantArgs); - _perms.grant(Permission.CONSUME, grantNonTempQArgs); - - assertEquals(Result.ALLOWED, _perms.authorise(Permission.CONSUME, authNonTempQArgs)); - assertEquals(Result.ALLOWED, _perms.authorise(Permission.CONSUME, authTempQArgs)); - } -} diff --git a/qpid/java/systests/etc/config-systests-acl-settings.xml b/qpid/java/systests/etc/config-systests-acl-settings.xml deleted file mode 100644 index eebc75f05f..0000000000 --- a/qpid/java/systests/etc/config-systests-acl-settings.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="ISO-8859-1"?> -<!-- - - - - 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. - - - --> -<broker> - <virtualhosts>${QPID_HOME}/etc/virtualhosts-systests-acl.xml</virtualhosts> -</broker> - - diff --git a/qpid/java/systests/etc/config-systests-acl.xml b/qpid/java/systests/etc/config-systests-acl.xml deleted file mode 100644 index 535108235e..0000000000 --- a/qpid/java/systests/etc/config-systests-acl.xml +++ /dev/null @@ -1,30 +0,0 @@ -<?xml version="1.0" encoding="ISO-8859-1"?> -<!-- - - - - 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. - - - --> -<configuration> - <system/> - <override> - <xml fileName="${test.config}" optional="true"/> - <xml fileName="${QPID_HOME}/etc/config-systests-acl-settings.xml"/> - <xml fileName="${QPID_HOME}/etc/config-systests-settings.xml"/> - <xml fileName="${QPID_HOME}/etc/config.xml"/> - </override> -</configuration> diff --git a/qpid/java/systests/etc/virtualhosts-systests-acl-settings.xml b/qpid/java/systests/etc/virtualhosts-systests-acl-settings.xml deleted file mode 100644 index ffbace569f..0000000000 --- a/qpid/java/systests/etc/virtualhosts-systests-acl-settings.xml +++ /dev/null @@ -1,180 +0,0 @@ -<?xml version="1.0" encoding="ISO-8859-1"?> -<!-- - - - - 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. - - - --> -<virtualhosts> - <virtualhost> - <name>test</name> - <test> - <queues> - <exchange>amq.direct</exchange> - <!-- 4Mb --> - <maximumQueueDepth>4235264</maximumQueueDepth> - <!-- 2Mb --> - <maximumMessageSize>2117632</maximumMessageSize> - <!-- 10 mins --> - <maximumMessageAge>600000</maximumMessageAge> - </queues> - - - <security> - <access_control_list> - <!-- This section grants pubish rights to an exchange + routing key pair --> - <publish> - <exchanges> - <exchange> - <name>amq.direct</name> - <routing_keys> - <!-- Allow clients to publish requests --> - <routing_key> - <value>example.RequestQueue</value> - <users> - <user>client</user> - </users> - </routing_key> - - <!-- Allow the processor to respond to a client on their Temporary Topic --> - <routing_key> - <value>tmp_*</value> - <users> - <user>server</user> - </users> - </routing_key> - <routing_key> - <value>TempQueue*</value> - <users> - <user>server</user> - </users> - </routing_key> - </routing_keys> - </exchange> - </exchanges> - </publish> - - <!-- This section grants users the ability to consume from the broker --> - <consume> - <queues> - <temporary> - <users> - <user>client</user> - </users> - </temporary> - - <!-- Only allow the server to consume from the Request Queue--> - <queue> - <name>example.RequestQueue</name> - <users> - <user>server</user> - </users> - </queue> - - <!-- Allow client and server to consume from the kipper Queue--> - <queue> - <name>clientid:kipper</name> - <users> - <user>client</user> - <user>server</user> - </users> - </queue> - </queues> - </consume> - - <!-- This section grants users the ability to create queues and exchanges --> - <create> - <queues> - <temporary> - <users> - <user>client</user> - </users> - </temporary> - - <!-- Allow clients to create queue on this exchange--> - <queue> - <exchanges> - <exchange> - <name>amq.direct</name> - <users> - <user>client</user> - <user>server</user> - </users> - </exchange> - <exchange> - <name>amq.topic</name> - <users> - <user>client</user> - <user>server</user> - </users> - </exchange> - </exchanges> - </queue> - - <!-- everyone can create the kipper queue --> - <queue> - <name>clientid:kipper</name> - <users> - <user>client</user> - <user>server</user> - </users> - </queue> - - <!-- Allow the server to create the Request Queue--> - <queue> - <name>example.RequestQueue</name> - <users> - <user>server</user> - </users> - </queue> - </queues> - </create> - - <delete> - <queues> - <!-- only client can delete the kipper queue --> - <queue> - <name>clientid:kipper</name> - <users> - <user>client</user> - </users> - </queue> - </queues> - </delete> - </access_control_list> - </security> - </test> - </virtualhost> - - <virtualhost> - <name>test2</name> - <test2> - <security> - <access_control_list> - <!-- This section grants specific users full permissions to all artifacts in this virtualhost --> - <access> - <users> - <user>guest</user> - </users> - </access> - </access_control_list> - </security> - </test2> - </virtualhost> -</virtualhosts> - - diff --git a/qpid/java/systests/etc/virtualhosts-systests-acl.xml b/qpid/java/systests/etc/virtualhosts-systests-acl.xml deleted file mode 100644 index 4a56c39de0..0000000000 --- a/qpid/java/systests/etc/virtualhosts-systests-acl.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="ISO-8859-1"?> -<!-- - - - - 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. - - - --> -<configuration> - <system/> - <override> - <xml fileName="${test.virtualhosts}" optional="true"/> - <xml fileName="${QPID_HOME}/etc/virtualhosts-systests-acl-settings.xml"/> - <xml fileName="${QPID_HOME}/etc/virtualhosts.xml"/> - </override> -</configuration> diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java index f845ff1214..7f8f71d965 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java @@ -52,7 +52,6 @@ import org.apache.qpid.url.URLSyntaxException; * * TODO move the pre broker-startup setup method invocation code to {@link QpidBrokerTestCase} * - * @see SimpleACLTest * @see ExternalACLTest * @see ExternalACLFileTest * @see ExternalACLJMXTest @@ -65,10 +64,7 @@ public abstract class AbstractACLTestCase extends QpidBrokerTestCase implements protected CountDownLatch _exceptionReceived; /** Override this to return the name of the configuration XML file. */ - public String getConfig() - { - return "config-systests-acl.xml"; - } + public abstract String getConfig(); /** Override this to setup external ACL files for virtual hosts. */ public List<String> getHostList() diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLTest.java index 4603cc1862..d1ba725721 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLTest.java @@ -18,11 +18,620 @@ */ package org.apache.qpid.server.security.acl; +import java.io.IOException; import java.util.Arrays; import java.util.List; -public class ExternalACLTest extends SimpleACLTest +import javax.jms.Connection; +import javax.jms.DeliveryMode; +import javax.jms.IllegalStateException; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Queue; +import javax.jms.Session; +import javax.jms.TextMessage; +import javax.jms.Topic; +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; + +/** + * Tests the V2 ACLs. The tests perform basic AMQP operations like creating queues or excahnges and publishing and consuming messages, using + * JMS to contact the broker. + */ +public class ExternalACLTest extends AbstractACLTestCase { + public void testAccessAuthorizedSuccess() throws AMQException, URLSyntaxException, Exception + { + try + { + Connection conn = getConnection("test", "client", "guest"); + Session sess = conn.createSession(true, Session.SESSION_TRANSACTED); + conn.start(); + + //Do something to show connection is active. + sess.rollback(); + + conn.close(); + } + catch (Exception e) + { + fail("Connection was not created due to:" + e); + } + } + + public void testAccessVhostAuthorisedGuestSuccess() throws IOException, 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, true); + ((org.apache.qpid.jms.MessageProducer) sender).send(tempQueue, sess.createTextMessage("test"), + DeliveryMode.NON_PERSISTENT, 0, 0L, false, false, true); + + //consume the messages from the queues + consumer.receive(2000); + tempConsumer.receive(2000); + + conn.close(); + } + catch (Exception e) + { + fail("Test failed due to:" + e.getMessage()); + } + } + + public void testAccessNoRightsFailure() throws Exception + { + try + { + Connection conn = getConnection("test", "guest", "guest"); + Session sess = conn.createSession(true, Session.SESSION_TRANSACTED); + conn.start(); + sess.rollback(); + + fail("Connection was created."); + } + catch (JMSException e) + { + // JMSException -> linkedException -> cause = AMQException (403 or 320) + Exception linkedException = e.getLinkedException(); + assertNotNull("There was no linked exception", linkedException); + Throwable cause = linkedException.getCause(); + assertNotNull("Cause was null", cause); + assertTrue("Wrong linked exception type", cause instanceof AMQException); + AMQConstant errorCode = isBroker010() ? AMQConstant.CONTEXT_IN_USE : AMQConstant.ACCESS_REFUSED; + assertEquals("Incorrect error code received", errorCode, ((AMQException) cause).getErrorCode()); + } + } + + public void testClientDeleteQueueSuccess() 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()); + } + } + + public void testServerDeleteQueueFailure() throws Exception + { + try + { + Connection conn = getConnection("test", "server", "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 (JMSException e) + { + // JMSException -> linedException = AMQException.403 + check403Exception(e.getLinkedException()); + } + } + + 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 testClientConsumeFromNamedQueueFailure() throws NamingException, Exception + { + try + { + Connection conn = getConnection("test", "client", "guest"); + + Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + + conn.start(); + + sess.createConsumer(sess.createQueue("IllegalQueue")); + + fail("Test failed as consumer was created."); + } + catch (JMSException e) + { + 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 + { + try + { + Connection conn = getConnection("test", "client", "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 Queue creation succeded."); + //conn will be automatically closed + } + catch (AMQException e) + { + check403Exception(e); + } + } + + public void testClientPublishUsingTransactionSuccess() throws AMQException, URLSyntaxException, Exception + { + try + { + Connection conn = getConnection("test", "client", "guest"); + + Session sess = conn.createSession(true, Session.SESSION_TRANSACTED); + + conn.start(); + + MessageProducer sender = sess.createProducer(sess.createQueue("example.RequestQueue")); + + sender.send(sess.createTextMessage("test")); + + //Send the message using a transaction as this will allow us to retrieve any errors that occur on the broker. + sess.commit(); + + conn.close(); + } + catch (Exception e) + { + fail("Test publish failed:" + e); + } + } + + public void testClientPublishValidQueueSuccess() throws AMQException, URLSyntaxException, 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, true); + + conn.close(); + } + catch (Exception e) + { + fail("Test publish failed:" + e); + } + } + + public void testClientPublishInvalidQueueSuccess() throws AMQException, URLSyntaxException, JMSException, NamingException, Exception + { + 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, true); + + // 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(); + + 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."); + } + catch (JMSException e) + { + check403Exception(e.getLinkedException()); + } + } + + public void testServerConsumeFromNamedQueueValid() throws AMQException, URLSyntaxException, Exception + { + try + { + Connection conn = getConnection("test", "server", "guest"); + + Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + + conn.start(); + + sess.createConsumer(sess.createQueue("example.RequestQueue")); + + conn.close(); + } + catch (Exception e) + { + fail("Test failed due to:" + e.getMessage()); + } + } + + public void testServerConsumeFromNamedQueueInvalid() throws AMQException, URLSyntaxException, NamingException, Exception + { + try + { + Connection conn = getConnection("test", "client", "guest"); + + Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + + conn.start(); + + sess.createConsumer(sess.createQueue("Invalid")); + + fail("Test failed as consumer was created."); + } + catch (JMSException e) + { + check403Exception(e.getLinkedException()); + } + } + + public void testServerConsumeFromTemporaryQueue() throws AMQException, URLSyntaxException, NamingException, 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()); + } + } + + public void testServerCreateNamedQueueValid() throws JMSException, URLSyntaxException, Exception + { + 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(); + } + catch (Exception e) + { + fail("Test failed due to:" + e.getMessage()); + } + } + + public void testServerCreateNamedQueueInvalid() throws JMSException, URLSyntaxException, AMQException, NamingException, 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); + } + } + + public void testServerCreateTemporaryQueueInvalid() throws NamingException, Exception + { + try + { + Connection conn = getConnection("test", "server", "guest"); + Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + + conn.start(); + + session.createTemporaryQueue(); + + fail("Test failed as creation succeded."); + } + catch (JMSException e) + { + check403Exception(e.getLinkedException()); + } + } + + public void testServerCreateAutoDeleteQueueInvalid() throws NamingException, JMSException, AMQException, Exception + { + try + { + Connection connection = getConnection("test", "server", "guest"); + + Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + + connection.start(); + + ((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); + } + } + + /** + * 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 + { + //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); + + Queue responseQueue = clientSession.createTemporaryQueue(); + + MessageConsumer clientResponse = clientSession.createConsumer(responseQueue); + + clientConnection.start(); + + 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(); + } + } + } + + public void testServerPublishInvalidQueueSuccess() throws AMQException, URLSyntaxException, JMSException, NamingException, 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, true); + + // 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()); + } + } + + @Override public String getConfig() { diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/SimpleACLTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/SimpleACLTest.java deleted file mode 100644 index a50817e659..0000000000 --- a/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/SimpleACLTest.java +++ /dev/null @@ -1,644 +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.IOException; - -import javax.jms.Connection; -import javax.jms.DeliveryMode; -import javax.jms.IllegalStateException; -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.MessageConsumer; -import javax.jms.MessageProducer; -import javax.jms.Queue; -import javax.jms.Session; -import javax.jms.TextMessage; -import javax.jms.Topic; -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; - -/** - * Basic access control list tests. - * - * These tests require an access control security plugin to be configured in the broker, and carry out various broker - * operations that will succeed or fail depending on the user and virtual host. See the {@code config-systests-acl-setup.xml} - * configuration file for the SimpleXML version of the ACLs used by the Java broker only, or the various {@code .txt} - * files in the system tests directory for the external version 3 ACL files used by both the Java and C++ brokers. - * <p> - * This class can be extended and the {@link #getConfig()} method overridden to run the same tests with a different type - * of access control mechanism. Extension classes should differ only in the configuration file used, but extra tests can be - * added that are specific to a particular configuration. - * <p> - * The tests perform basic AMQP operations like creating queues or excahnges and publishing and consuming messages, using - * JMS to contact the broker. - * - * @see ExternalACLTest - */ -public class SimpleACLTest extends AbstractACLTestCase -{ - public void testAccessAuthorizedSuccess() throws AMQException, URLSyntaxException, Exception - { - try - { - Connection conn = getConnection("test", "client", "guest"); - Session sess = conn.createSession(true, Session.SESSION_TRANSACTED); - conn.start(); - - //Do something to show connection is active. - sess.rollback(); - - conn.close(); - } - catch (Exception e) - { - fail("Connection was not created due to:" + e); - } - } - - public void testAccessVhostAuthorisedGuestSuccess() throws IOException, 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, true); - ((org.apache.qpid.jms.MessageProducer) sender).send(tempQueue, sess.createTextMessage("test"), - DeliveryMode.NON_PERSISTENT, 0, 0L, false, false, true); - - //consume the messages from the queues - consumer.receive(2000); - tempConsumer.receive(2000); - - conn.close(); - } - catch (Exception e) - { - fail("Test failed due to:" + e.getMessage()); - } - } - - public void testAccessNoRightsFailure() throws Exception - { - try - { - Connection conn = getConnection("test", "guest", "guest"); - Session sess = conn.createSession(true, Session.SESSION_TRANSACTED); - conn.start(); - sess.rollback(); - - fail("Connection was created."); - } - catch (JMSException e) - { - // JMSException -> linkedException -> cause = AMQException (403 or 320) - Exception linkedException = e.getLinkedException(); - assertNotNull("There was no linked exception", linkedException); - Throwable cause = linkedException.getCause(); - assertNotNull("Cause was null", cause); - assertTrue("Wrong linked exception type", cause instanceof AMQException); - AMQConstant errorCode = isBroker010() ? AMQConstant.CONTEXT_IN_USE : AMQConstant.ACCESS_REFUSED; - assertEquals("Incorrect error code received", errorCode, ((AMQException) cause).getErrorCode()); - } - } - - public void testClientDeleteQueueSuccess() 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()); - } - } - - public void testServerDeleteQueueFailure() throws Exception - { - try - { - Connection conn = getConnection("test", "server", "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 (JMSException e) - { - // JMSException -> linedException = AMQException.403 - check403Exception(e.getLinkedException()); - } - } - - 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 testClientConsumeFromNamedQueueFailure() throws NamingException, Exception - { - try - { - Connection conn = getConnection("test", "client", "guest"); - - Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); - - conn.start(); - - sess.createConsumer(sess.createQueue("IllegalQueue")); - - fail("Test failed as consumer was created."); - } - catch (JMSException e) - { - 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 - { - try - { - Connection conn = getConnection("test", "client", "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 Queue creation succeded."); - //conn will be automatically closed - } - catch (AMQException e) - { - check403Exception(e); - } - } - - public void testClientPublishUsingTransactionSuccess() throws AMQException, URLSyntaxException, Exception - { - try - { - Connection conn = getConnection("test", "client", "guest"); - - Session sess = conn.createSession(true, Session.SESSION_TRANSACTED); - - conn.start(); - - MessageProducer sender = sess.createProducer(sess.createQueue("example.RequestQueue")); - - sender.send(sess.createTextMessage("test")); - - //Send the message using a transaction as this will allow us to retrieve any errors that occur on the broker. - sess.commit(); - - conn.close(); - } - catch (Exception e) - { - fail("Test publish failed:" + e); - } - } - - public void testClientPublishValidQueueSuccess() throws AMQException, URLSyntaxException, 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, true); - - conn.close(); - } - catch (Exception e) - { - fail("Test publish failed:" + e); - } - } - - public void testClientPublishInvalidQueueSuccess() throws AMQException, URLSyntaxException, JMSException, NamingException, Exception - { - 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, true); - - // 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(); - - 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."); - } - catch (JMSException e) - { - check403Exception(e.getLinkedException()); - } - } - - public void testServerConsumeFromNamedQueueValid() throws AMQException, URLSyntaxException, Exception - { - try - { - Connection conn = getConnection("test", "server", "guest"); - - Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); - - conn.start(); - - sess.createConsumer(sess.createQueue("example.RequestQueue")); - - conn.close(); - } - catch (Exception e) - { - fail("Test failed due to:" + e.getMessage()); - } - } - - public void testServerConsumeFromNamedQueueInvalid() throws AMQException, URLSyntaxException, NamingException, Exception - { - try - { - Connection conn = getConnection("test", "client", "guest"); - - Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); - - conn.start(); - - sess.createConsumer(sess.createQueue("Invalid")); - - fail("Test failed as consumer was created."); - } - catch (JMSException e) - { - check403Exception(e.getLinkedException()); - } - } - - public void testServerConsumeFromTemporaryQueue() throws AMQException, URLSyntaxException, NamingException, 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()); - } - } - - public void testServerCreateNamedQueueValid() throws JMSException, URLSyntaxException, Exception - { - 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(); - } - catch (Exception e) - { - fail("Test failed due to:" + e.getMessage()); - } - } - - public void testServerCreateNamedQueueInvalid() throws JMSException, URLSyntaxException, AMQException, NamingException, 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); - } - } - - public void testServerCreateTemporaryQueueInvalid() throws NamingException, Exception - { - try - { - Connection conn = getConnection("test", "server", "guest"); - Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); - - conn.start(); - - session.createTemporaryQueue(); - - fail("Test failed as creation succeded."); - } - catch (JMSException e) - { - check403Exception(e.getLinkedException()); - } - } - - public void testServerCreateAutoDeleteQueueInvalid() throws NamingException, JMSException, AMQException, Exception - { - try - { - Connection connection = getConnection("test", "server", "guest"); - - Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); - - connection.start(); - - ((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); - } - } - - /** - * 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 - { - //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); - - Queue responseQueue = clientSession.createTemporaryQueue(); - - MessageConsumer clientResponse = clientSession.createConsumer(responseQueue); - - clientConnection.start(); - - 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(); - } - } - } - - public void testServerPublishInvalidQueueSuccess() throws AMQException, URLSyntaxException, JMSException, NamingException, 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, true); - - // 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()); - } - } -} |