From 48e49bef0775e91625ba7b5c03823dbaca943bf7 Mon Sep 17 00:00:00 2001 From: Robert Gemmell Date: Mon, 31 May 2010 16:03:41 +0000 Subject: QPID-2606: Access Control Modifications Applied patch from Andrew Kennedy git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk/qpid@949781 13f79535-47bb-0310-9956-ffa450edef68 --- .../qpid/server/security/access/ACLManager.java | 323 ------------- .../qpid/server/security/access/ACLPlugin.java | 70 --- .../server/security/access/ACLPluginFactory.java | 33 -- .../qpid/server/security/access/AccessResult.java | 65 --- .../qpid/server/security/access/AccessRights.java | 63 --- .../qpid/server/security/access/Accessable.java | 27 -- .../security/access/AuthorizationManager.java | 27 -- .../server/security/access/ObjectProperties.java | 315 ++++++++++++ .../qpid/server/security/access/ObjectType.java | 90 ++++ .../qpid/server/security/access/Operation.java | 49 ++ .../qpid/server/security/access/Permission.java | 35 +- .../server/security/access/VirtualHostAccess.java | 68 --- .../access/management/AMQUserManagementMBean.java | 538 --------------------- .../security/access/plugins/AbstractACLPlugin.java | 99 ---- .../server/security/access/plugins/AllowAll.java | 68 ++- .../security/access/plugins/BasicACLPlugin.java | 110 ----- .../security/access/plugins/BasicPlugin.java | 51 ++ .../server/security/access/plugins/DenyAll.java | 85 ++-- .../security/access/plugins/LegacyAccess.java | 81 ++++ .../access/plugins/LegacyAccessPlugin.java | 71 --- 20 files changed, 706 insertions(+), 1562 deletions(-) delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/access/ACLManager.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/access/ACLPlugin.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/access/ACLPluginFactory.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/access/AccessResult.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/access/AccessRights.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/access/Accessable.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/access/AuthorizationManager.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectType.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/access/Operation.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/access/VirtualHostAccess.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/access/management/AMQUserManagementMBean.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/AbstractACLPlugin.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/BasicACLPlugin.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/BasicPlugin.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/LegacyAccess.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/LegacyAccessPlugin.java (limited to 'java/broker/src/main/java/org/apache/qpid/server/security/access') diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/access/ACLManager.java b/java/broker/src/main/java/org/apache/qpid/server/security/access/ACLManager.java deleted file mode 100644 index 7d6ae285c5..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/security/access/ACLManager.java +++ /dev/null @@ -1,323 +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 java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Map; -import java.util.Map.Entry; - -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.SecurityConfiguration; -import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.plugins.PluginManager; -import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.security.access.ACLPlugin.AuthzResult; -import org.apache.qpid.server.security.PrincipalHolder; -import org.apache.qpid.server.virtualhost.VirtualHost; - -public class ACLManager -{ - private static final Logger _logger = Logger.getLogger(ACLManager.class); - private PluginManager _pluginManager; - private Map _allSecurityPlugins = new HashMap(); - private Map _globalPlugins = new HashMap(); - private Map _hostPlugins = new HashMap(); - - public ACLManager(SecurityConfiguration configuration, PluginManager manager) throws ConfigurationException - { - this(configuration, manager, null); - } - - public ACLManager(SecurityConfiguration configuration, PluginManager manager, ACLPluginFactory securityPlugin) throws ConfigurationException - { - _pluginManager = manager; - - if (manager == null) // No plugin manager, no plugins - { - return; - } - - _allSecurityPlugins = _pluginManager.getSecurityPlugins(); - if (securityPlugin != null) - { - _allSecurityPlugins.put(securityPlugin.getClass().getName(), securityPlugin); - } - - configureGlobalPlugins(configuration); - } - - public void configureHostPlugins(SecurityConfiguration hostConfig) throws ConfigurationException - { - _hostPlugins = configurePlugins(hostConfig); - } - - public void configureGlobalPlugins(SecurityConfiguration configuration) throws ConfigurationException - { - _globalPlugins = configurePlugins(configuration); - } - - public Map configurePlugins(SecurityConfiguration hostConfig) throws ConfigurationException - { - Configuration securityConfig = hostConfig.getConfiguration(); - Map plugins = new HashMap(); - Iterator keys = securityConfig.getKeys(); - Collection handledTags = new HashSet(); - while (keys.hasNext()) - { - // Splitting the string is necessary here because of the way that getKeys() returns only - // bottom level children - String tag = ((String) keys.next()).split("\\.", 2)[0]; - if (!handledTags.contains(tag)) - { - for (ACLPluginFactory plugin : _allSecurityPlugins.values()) - { - if (plugin.supportsTag(tag)) - { - _logger.info("Plugin handling security section "+tag+" is "+plugin); - handledTags.add(tag); - plugins.put(plugin.getClass().getName(), plugin.newInstance(securityConfig)); - } - } - } - if (!handledTags.contains(tag)) - { - _logger.warn("No plugin handled security section "+tag); - } - } - return plugins; - } - - public static Logger getLogger() - { - return _logger; - } - - private abstract class AccessCheck - { - abstract AuthzResult allowed(ACLPlugin plugin); - } - - private boolean checkAllPlugins(AccessCheck checker) - { - AuthzResult result = AuthzResult.ABSTAIN; - HashMap remainingPlugins = new HashMap(); - remainingPlugins.putAll(_globalPlugins); - for (Entry plugin : _hostPlugins.entrySet()) - { - result = checker.allowed(plugin.getValue()); - if (result == AuthzResult.DENIED) - { - // Something vetoed the access, we're done - return false; - } - else if (result == AuthzResult.ALLOWED) - { - // Remove plugin from global check list since - // host allow overrides global allow - remainingPlugins.remove(plugin.getKey()); - } - } - - for (ACLPlugin plugin : remainingPlugins.values()) - { - result = checker.allowed(plugin); - if (result == AuthzResult.DENIED) - { - return false; - } - } - return true; - } - - public boolean authoriseBind(final PrincipalHolder session, final Exchange exch, final AMQQueue queue, - final AMQShortString routingKey) - { - return checkAllPlugins(new AccessCheck() - { - - @Override - AuthzResult allowed(ACLPlugin plugin) - { - return plugin.authoriseBind(session, exch, queue, routingKey); - } - - }); - } - - public boolean authoriseConnect(final PrincipalHolder session, final VirtualHost virtualHost) - { - return checkAllPlugins(new AccessCheck() - { - - @Override - AuthzResult allowed(ACLPlugin plugin) - { - return plugin.authoriseConnect(session, virtualHost); - } - - }); - } - - public boolean authoriseConsume(final PrincipalHolder session, final boolean noAck, final AMQQueue queue) - { - return checkAllPlugins(new AccessCheck() - { - - @Override - AuthzResult allowed(ACLPlugin plugin) - { - return plugin.authoriseConsume(session, noAck, queue); - } - - }); - } - - public boolean authoriseConsume(final PrincipalHolder session, final boolean exclusive, final boolean noAck, - final boolean noLocal, final boolean nowait, final AMQQueue queue) - { - return checkAllPlugins(new AccessCheck() - { - - @Override - AuthzResult allowed(ACLPlugin plugin) - { - return plugin.authoriseConsume(session, exclusive, noAck, noLocal, nowait, queue); - } - - }); - } - - public boolean authoriseCreateExchange(final PrincipalHolder session, final boolean autoDelete, - final boolean durable, final AMQShortString exchangeName, final boolean internal, final boolean nowait, - final boolean passive, final AMQShortString exchangeType) - { - return checkAllPlugins(new AccessCheck() - { - - @Override - AuthzResult allowed(ACLPlugin plugin) - { - return plugin.authoriseCreateExchange(session, autoDelete, durable, exchangeName, internal, nowait, - passive, exchangeType); - } - - }); - } - - public boolean authoriseCreateQueue(final PrincipalHolder session, final boolean autoDelete, - final boolean durable, final boolean exclusive, final boolean nowait, final boolean passive, - final AMQShortString queue) - { - return checkAllPlugins(new AccessCheck() - { - - @Override - AuthzResult allowed(ACLPlugin plugin) - { - return plugin.authoriseCreateQueue(session, autoDelete, durable, exclusive, nowait, passive, queue); - } - - }); - } - - public boolean authoriseDelete(final PrincipalHolder session, final AMQQueue queue) - { - return checkAllPlugins(new AccessCheck() - { - - @Override - AuthzResult allowed(ACLPlugin plugin) - { - return plugin.authoriseDelete(session, queue); - } - - }); - } - - public boolean authoriseDelete(final PrincipalHolder session, final Exchange exchange) - { - return checkAllPlugins(new AccessCheck() - { - - @Override - AuthzResult allowed(ACLPlugin plugin) - { - return plugin.authoriseDelete(session, exchange); - } - - }); - } - - public boolean authorisePublish(final PrincipalHolder session, final boolean immediate, final boolean mandatory, - final AMQShortString routingKey, final Exchange e) - { - return checkAllPlugins(new AccessCheck() - { - - @Override - AuthzResult allowed(ACLPlugin plugin) - { - return plugin.authorisePublish(session, immediate, mandatory, routingKey, e); - } - - }); - } - - public boolean authorisePurge(final PrincipalHolder session, final AMQQueue queue) - { - return checkAllPlugins(new AccessCheck() - { - - @Override - AuthzResult allowed(ACLPlugin plugin) - { - return plugin.authorisePurge(session, queue); - } - - }); - } - - public boolean authoriseUnbind(final PrincipalHolder session, final Exchange exch, - final AMQShortString routingKey, final AMQQueue queue) - { - return checkAllPlugins(new AccessCheck() - { - - @Override - AuthzResult allowed(ACLPlugin plugin) - { - return plugin.authoriseUnbind(session, exch, routingKey, queue); - } - - }); - } - - public void addHostPlugin(ACLPlugin aclPlugin) - { - _hostPlugins.put(aclPlugin.getClass().getName(), aclPlugin); - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/access/ACLPlugin.java b/java/broker/src/main/java/org/apache/qpid/server/security/access/ACLPlugin.java deleted file mode 100644 index cf8a3fede9..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/security/access/ACLPlugin.java +++ /dev/null @@ -1,70 +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.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.server.security.PrincipalHolder; - -public interface ACLPlugin -{ - public enum AuthzResult - { - ALLOWED, - DENIED, - ABSTAIN - } - - void setConfiguration(Configuration config) throws ConfigurationException; - - // These return true if the plugin thinks the action should be allowed, and false if not. - - AuthzResult authoriseBind(PrincipalHolder session, Exchange exch, AMQQueue queue, AMQShortString routingKey); - - AuthzResult authoriseCreateExchange(PrincipalHolder session, boolean autoDelete, boolean durable, - AMQShortString exchangeName, boolean internal, boolean nowait, boolean passive, AMQShortString exchangeType); - - AuthzResult authoriseCreateQueue(PrincipalHolder session, boolean autoDelete, boolean durable, boolean exclusive, - boolean nowait, boolean passive, AMQShortString queue); - - AuthzResult authoriseConnect(PrincipalHolder session, VirtualHost virtualHost); - - AuthzResult authoriseConsume(PrincipalHolder session, boolean noAck, AMQQueue queue); - - AuthzResult authoriseConsume(PrincipalHolder session, boolean exclusive, boolean noAck, boolean noLocal, - boolean nowait, AMQQueue queue); - - AuthzResult authoriseDelete(PrincipalHolder session, AMQQueue queue); - - AuthzResult authoriseDelete(PrincipalHolder session, Exchange exchange); - - AuthzResult authorisePublish(PrincipalHolder session, boolean immediate, boolean mandatory, - AMQShortString routingKey, Exchange e); - - AuthzResult authorisePurge(PrincipalHolder session, AMQQueue queue); - - AuthzResult authoriseUnbind(PrincipalHolder session, Exchange exch, AMQShortString routingKey, AMQQueue queue); - -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/access/ACLPluginFactory.java b/java/broker/src/main/java/org/apache/qpid/server/security/access/ACLPluginFactory.java deleted file mode 100644 index 256f093477..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/security/access/ACLPluginFactory.java +++ /dev/null @@ -1,33 +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.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationException; - -public interface ACLPluginFactory -{ - - public boolean supportsTag(String name); - - public ACLPlugin newInstance(Configuration config) throws ConfigurationException; - -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/access/AccessResult.java b/java/broker/src/main/java/org/apache/qpid/server/security/access/AccessResult.java deleted file mode 100644 index d722da4ae0..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/security/access/AccessResult.java +++ /dev/null @@ -1,65 +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; - -public class AccessResult -{ - public enum AccessStatus - { - GRANTED, REFUSED - } - - private String _authorizer; - private AccessStatus _status; - - public AccessResult(ACLPlugin authorizer, AccessStatus status) - { - _status = status; - _authorizer = authorizer.getClass().getSimpleName(); - } - - public void setAuthorizer(ACLPlugin authorizer) - { - _authorizer += authorizer.getClass().getSimpleName(); - } - - public String getAuthorizer() - { - return _authorizer; - } - - public void setStatus(AccessStatus status) - { - _status = status; - } - - public AccessStatus getStatus() - { - return _status; - } - - public void addAuthorizer(ACLPlugin accessManager) - { - _authorizer = accessManager.getClass().getSimpleName() + "->" + _authorizer; - } - - -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/access/AccessRights.java b/java/broker/src/main/java/org/apache/qpid/server/security/access/AccessRights.java deleted file mode 100644 index 1b79a5a0e0..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/security/access/AccessRights.java +++ /dev/null @@ -1,63 +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; - -public class AccessRights -{ - public enum Rights - { - ANY, - READ, - WRITE, - READWRITE - } - - Rights _right; - - public AccessRights(Rights right) - { - _right = right; - } - - public boolean allows(Rights rights) - { - switch (_right) - { - case ANY: - return (rights.equals(Rights.WRITE) - || rights.equals(Rights.READ) - || rights.equals(Rights.READWRITE) - || rights.equals(Rights.ANY)); - case READ: - return rights.equals(Rights.READ) || rights.equals(Rights.ANY); - case WRITE: - return rights.equals(Rights.WRITE) || rights.equals(Rights.ANY); - case READWRITE: - return true; - } - return false; - } - - public Rights getRights() - { - return _right; - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/access/Accessable.java b/java/broker/src/main/java/org/apache/qpid/server/security/access/Accessable.java deleted file mode 100644 index f51cf24caa..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/security/access/Accessable.java +++ /dev/null @@ -1,27 +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; - -public interface Accessable -{ - void setAccessableName(String name); - String getAccessableName(); -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/access/AuthorizationManager.java b/java/broker/src/main/java/org/apache/qpid/server/security/access/AuthorizationManager.java deleted file mode 100644 index 895ed52222..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/security/access/AuthorizationManager.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.apache.qpid.server.security.access; -/* - * - * 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. - * - */ - - -public class AuthorizationManager -{ - -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java b/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java new file mode 100644 index 0000000000..af47ed6bf9 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java @@ -0,0 +1,315 @@ +/* + * 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 java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import org.apache.commons.lang.StringUtils; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.server.exchange.Exchange; +import org.apache.qpid.server.queue.AMQQueue; + +/** + * An set of properties for an access control v2 rule {@link ObjectType}. + * + * The {@link #matches(ObjectProperties)} method is intended to be used when determining precedence of rules, and + * {@link #equals(Object)} and {@link #hashCode()} are intended for use in maps. This is due to the wildcard matching + * described above. + */ +public class ObjectProperties extends HashMap +{ + /** serialVersionUID */ + private static final long serialVersionUID = -1356019341374170495L; + + public static final String STAR= "*"; + + public static final ObjectProperties EMPTY = new ObjectProperties(); + + public enum Property + { + ROUTING_KEY, + NAME, + QUEUE_NAME, + OWNER, + TYPE, + ALTERNATE, + IMMEDIATE, + INTERNAL, + NO_WAIT, + NO_LOCAL, + NO_ACK, + PASSIVE, + DURABLE, + EXCLUSIVE, + TEMPORARY, + AUTO_DELETE, + COMPONENT, + PACKAGE, + CLASS; + + public static Property parse(String text) + { + for (Property property : values()) + { + if (property.getName().equalsIgnoreCase(text)) + { + return property; + } + } + throw new IllegalArgumentException("Not a valid property: " + text); + } + + public String getName() + { + return StringUtils.remove(name(), '_').toLowerCase(); + } + + public static List getPropertyNames() + { + List properties = new ArrayList(); + for (Property property : values()) + { + properties.add(property.getName()); + } + return properties; + } + } + + public static List getAllPropertyNames() + { + List properties = new ArrayList(); + for (Property property : Property.values()) + { + properties.add(StringUtils.remove(property.name(), '_').toLowerCase()); + } + return properties; + } + + public ObjectProperties() + { + super(); + } + + public ObjectProperties(ObjectProperties copy) + { + super(); + + putAll(copy); + } + + public ObjectProperties(String name) + { + super(); + + setName(name); + } + + + public ObjectProperties(AMQShortString name) + { + super(); + + setName(name); + } + + public ObjectProperties(AMQQueue queue) + { + super(); + + setName(queue.getName()); + + put(Property.AUTO_DELETE, queue.isAutoDelete()); + put(Property.TEMPORARY, queue.isAutoDelete()); + put(Property.DURABLE, queue.isDurable()); + put(Property.EXCLUSIVE, queue.isExclusive()); + if (queue.getAlternateExchange() != null) + { + put(Property.ALTERNATE, queue.getAlternateExchange().getName()); + } + if (queue.getOwner() != null) + { + put(Property.OWNER, queue.getOwner()); + } + else if (queue.getPrincipalHolder() != null) + { + put(Property.OWNER, queue.getPrincipalHolder().getPrincipal().getName()); + } + } + + public ObjectProperties(Exchange exch, AMQQueue queue, AMQShortString routingKey) + { + this(queue); + + setName(exch.getName()); + + put(Property.QUEUE_NAME, queue.getName()); + put(Property.ROUTING_KEY, routingKey); + } + + public ObjectProperties(Exchange exch, AMQShortString routingKey) + { + this(exch.getName(), routingKey.asString()); + } + + public ObjectProperties(String exchangeName, String routingKey, Boolean immediate) + { + this(exchangeName, routingKey); + + put(Property.IMMEDIATE, immediate); + } + + public ObjectProperties(String exchangeName, String routingKey) + { + super(); + + setName(exchangeName); + + put(Property.ROUTING_KEY, routingKey); + } + + public ObjectProperties(Boolean autoDelete, Boolean durable, AMQShortString exchangeName, + Boolean internal, Boolean nowait, Boolean passive, AMQShortString exchangeType) + { + super(); + + setName(exchangeName); + + put(Property.AUTO_DELETE, autoDelete); + put(Property.TEMPORARY, autoDelete); + put(Property.DURABLE, durable); + put(Property.INTERNAL, internal); + put(Property.NO_WAIT, nowait); + put(Property.PASSIVE, passive); + put(Property.TYPE, exchangeType); + } + + public ObjectProperties(Boolean autoDelete, Boolean durable, Boolean exclusive, Boolean nowait, Boolean passive, + AMQShortString queueName, String owner) + { + super(); + + setName(queueName); + + put(Property.AUTO_DELETE, autoDelete); + put(Property.TEMPORARY, autoDelete); + put(Property.DURABLE, durable); + put(Property.EXCLUSIVE, exclusive); + put(Property.NO_WAIT, nowait); + put(Property.PASSIVE, passive); + put(Property.OWNER, owner); + } + + public ObjectProperties(Boolean exclusive, Boolean noAck, Boolean noLocal, Boolean nowait, AMQQueue queue) + { + this(queue); + + put(Property.NO_LOCAL, noLocal); + put(Property.NO_ACK, noAck); + put(Property.EXCLUSIVE, exclusive); + put(Property.NO_WAIT, nowait); + } + + public List getPropertyNames() + { + List properties = new ArrayList(); + for (Property property : keySet()) + { + properties.add(property.getName()); + } + return properties; + } + + public Boolean isSet(Property key) + { + return containsKey(key) && Boolean.valueOf(get(key)); + } + + public String getName() + { + return get(Property.NAME); + } + + public void setName(String name) + { + put(Property.NAME, name); + } + + public void setName(AMQShortString name) + { + put(Property.NAME, name); + } + + public String put(Property key, AMQShortString value) + { + return put(key, value == null ? "" : value.asString()); + } + + @Override + public String put(Property key, String value) + { + return super.put(key, value == null ? "" : value.trim()); + } + + public void put(Property key, Boolean value) + { + if (value != null) + { + super.put(key, Boolean.toString(value)); + } + } + + public boolean matches(ObjectProperties properties) + { + if (properties.keySet().isEmpty()) + { + return true; + } + + if (!keySet().containsAll(properties.keySet())) + { + return false; + } + + for (Property key : properties.keySet()) + { + String ruleValue = properties.get(key); + String thisValue = get(key); + + if (!valueMatches(thisValue, ruleValue)) + { + return false; + } + } + + return true; + } + + private boolean valueMatches(String thisValue, String ruleValue) + { + return (StringUtils.isEmpty(ruleValue) + || StringUtils.equals(thisValue, ruleValue)) + || ruleValue.equals(STAR) + || (ruleValue.endsWith(STAR) + && thisValue != null + && thisValue.length() > ruleValue.length() + && thisValue.startsWith(ruleValue.substring(0, ruleValue.length() - 2))); + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectType.java b/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectType.java new file mode 100644 index 0000000000..66ef388976 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectType.java @@ -0,0 +1,90 @@ +/* + * 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 static org.apache.qpid.server.security.access.Operation.*; + +import java.util.EnumSet; +import java.util.Set; + +/** + * An enumeration of all possible object types that can form part of an access control v2 rule. + * + * Each object type is valid only for a certain set of {@link Operation}s, which are passed as a list to + * the constructor, and can be checked using the {@link #isAllowed(Operation)} method. + */ +public enum ObjectType +{ + ALL(Operation.ALL), + VIRTUALHOST(ACCESS), + QUEUE(CREATE, DELETE, PURGE, CONSUME), + TOPIC(CREATE, DELETE, PURGE, CONSUME), + EXCHANGE(ACCESS, CREATE, DELETE, BIND, UNBIND, PUBLISH), + BROKER(ACCESS), + LINK, // Not allowed in the Java broker + ROUTE, // Not allowed in the Java broker + METHOD(Operation.ALL, ACCESS, UPDATE, EXECUTE), + OBJECT(ACCESS); + + private EnumSet _actions; + + private ObjectType() + { + _actions = EnumSet.noneOf(Operation.class); + } + + private ObjectType(Operation operation) + { + if (operation == Operation.ALL) + { + _actions = EnumSet.allOf(Operation.class); + } + else + { + _actions = EnumSet.of(operation); + } + } + + private ObjectType(Operation first, Operation...rest) + { + _actions = EnumSet.of(first, rest); + } + + public Set getActions() + { + return _actions; + } + + public boolean isAllowed(Operation operation) + { + return _actions.contains(operation); + } + + public static ObjectType parse(String text) + { + for (ObjectType object : values()) + { + if (object.name().equalsIgnoreCase(text)) + { + return object; + } + } + throw new IllegalArgumentException("Not a valid object type: " + text); + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/access/Operation.java b/java/broker/src/main/java/org/apache/qpid/server/security/access/Operation.java new file mode 100644 index 0000000000..7077257d01 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/security/access/Operation.java @@ -0,0 +1,49 @@ +/* + * 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; + +/** + * An enumeration of all possible actions that can form part of an access control v2 rule. + */ +public enum Operation +{ + ALL, + CONSUME, + PUBLISH, + CREATE, + ACCESS, + BIND, + UNBIND, + DELETE, + PURGE, + UPDATE, + EXECUTE; + + public static Operation parse(String text) + { + for (Operation operation : values()) + { + if (operation.name().equalsIgnoreCase(text)) + { + return operation; + } + } + throw new IllegalArgumentException("Not a valid operation: " + text); + } +} \ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/access/Permission.java b/java/broker/src/main/java/org/apache/qpid/server/security/access/Permission.java index b65b0cdc6c..49b3a331f9 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/security/access/Permission.java +++ b/java/broker/src/main/java/org/apache/qpid/server/security/access/Permission.java @@ -20,19 +20,28 @@ */ package org.apache.qpid.server.security.access; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.queue.AMQQueue; +import org.apache.commons.lang.StringUtils; +/** + * An enumeration of all possible permissions that can be applied to an access control v2 rule. + */ public enum Permission { - CONSUME, - PUBLISH, - CREATEQUEUE, - CREATEEXCHANGE, - ACCESS, - BIND, - UNBIND, - DELETE, - PURGE -} + ALLOW, + ALLOW_LOG, + DENY, + DENY_LOG; + + public static Permission parse(String text) + { + + for (Permission permission : values()) + { + if (permission.name().equalsIgnoreCase(StringUtils.replaceChars(text, '-', '_'))) + { + return permission; + } + } + throw new IllegalArgumentException("Not a valid permission: " + text); + } +} \ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/access/VirtualHostAccess.java b/java/broker/src/main/java/org/apache/qpid/server/security/access/VirtualHostAccess.java deleted file mode 100644 index 13151a66b8..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/security/access/VirtualHostAccess.java +++ /dev/null @@ -1,68 +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; - -public class VirtualHostAccess -{ - private String _vhost; - private AccessRights _rights; - - public VirtualHostAccess(String vhostaccess) - { - //format () - int hostend = vhostaccess.indexOf('('); - - if (hostend == -1) - { - throw new IllegalArgumentException("VirtualHostAccess format string contains no access _rights"); - } - - _vhost = vhostaccess.substring(0, hostend); - - String rights = vhostaccess.substring(hostend); - - if (rights.indexOf('r') != -1) - { - if (rights.indexOf('w') != -1) - { - _rights = new AccessRights(AccessRights.Rights.READWRITE); - } - else - { - _rights = new AccessRights(AccessRights.Rights.READ); - } - } - else if (rights.indexOf('w') != -1) - { - _rights = new AccessRights(AccessRights.Rights.WRITE); - } - } - - public AccessRights getAccessRights() - { - return _rights; - } - - public String getVirtualHost() - { - return _vhost; - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/access/management/AMQUserManagementMBean.java b/java/broker/src/main/java/org/apache/qpid/server/security/access/management/AMQUserManagementMBean.java deleted file mode 100644 index 5a2965cb32..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/security/access/management/AMQUserManagementMBean.java +++ /dev/null @@ -1,538 +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.management; - -import org.apache.qpid.management.common.mbeans.UserManagement; -import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription; -import org.apache.qpid.management.common.mbeans.annotations.MBeanOperation; -import org.apache.qpid.server.management.AMQManagedObject; -import org.apache.qpid.server.management.MBeanInvocationHandlerImpl; -import org.apache.qpid.server.security.auth.database.PrincipalDatabase; -import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal; -import org.apache.qpid.util.FileUtils; -import org.apache.log4j.Logger; -import org.apache.commons.configuration.ConfigurationException; - -import javax.management.JMException; -import javax.management.remote.JMXPrincipal; -import javax.management.openmbean.TabularData; -import javax.management.openmbean.TabularDataSupport; -import javax.management.openmbean.TabularType; -import javax.management.openmbean.SimpleType; -import javax.management.openmbean.CompositeType; -import javax.management.openmbean.OpenType; -import javax.management.openmbean.OpenDataException; -import javax.management.openmbean.CompositeData; -import javax.management.openmbean.CompositeDataSupport; -import javax.security.auth.login.AccountNotFoundException; -import javax.security.auth.Subject; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.FileOutputStream; -import java.util.Properties; -import java.util.List; -import java.util.Enumeration; -import java.util.Random; -import java.util.Set; -import java.util.concurrent.locks.ReentrantLock; -import java.security.Principal; -import java.security.AccessControlContext; -import java.security.AccessController; - -/** MBean class for AMQUserManagementMBean. It implements all the management features exposed for managing users. */ -@MBeanDescription("User Management Interface") -public class AMQUserManagementMBean extends AMQManagedObject implements UserManagement -{ - - private static final Logger _logger = Logger.getLogger(AMQUserManagementMBean.class); - - private PrincipalDatabase _principalDatabase; - private Properties _accessRights; - private File _accessFile; - - private ReentrantLock _accessRightsUpdate = new ReentrantLock(); - - // Setup for the TabularType - static TabularType _userlistDataType; // Datatype for representing User Lists - static CompositeType _userDataType; // Composite type for representing User - - static - { - OpenType[] userItemTypes = new OpenType[4]; // User item types. - userItemTypes[0] = SimpleType.STRING; // For Username - userItemTypes[1] = SimpleType.BOOLEAN; // For Rights - Read - userItemTypes[2] = SimpleType.BOOLEAN; // For Rights - Write - userItemTypes[3] = SimpleType.BOOLEAN; // For Rights - Admin - - try - { - _userDataType = - new CompositeType("User", "User Data", COMPOSITE_ITEM_NAMES, COMPOSITE_ITEM_DESCRIPTIONS, userItemTypes); - - _userlistDataType = new TabularType("Users", "List of users", _userDataType, TABULAR_UNIQUE_INDEX); - } - catch (OpenDataException e) - { - _logger.error("Tabular data setup for viewing users incorrect."); - _userlistDataType = null; - } - } - - - public AMQUserManagementMBean() throws JMException - { - super(UserManagement.class, UserManagement.TYPE); - } - - public String getObjectInstanceName() - { - return UserManagement.TYPE; - } - - public boolean setPassword(String username, String password) - { - return setPassword(username, password.toCharArray()); - } - - public boolean setPassword(String username, char[] password) - { - try - { - //delegate password changes to the Principal Database - return _principalDatabase.updatePassword(new UsernamePrincipal(username), password); - } - catch (AccountNotFoundException e) - { - _logger.warn("Attempt to set password of non-existant user'" + username + "'"); - return false; - } - } - - public boolean setRights(String username, boolean read, boolean write, boolean admin) - { - - Object oldRights = null; - if ((oldRights =_accessRights.get(username)) == null) - { - // If the user doesn't exist in the access rights file check that they at least have an account. - if (_principalDatabase.getUser(username) == null) - { - return false; - } - } - - try - { - _accessRightsUpdate.lock(); - - // Update the access rights - if (admin) - { - _accessRights.put(username, MBeanInvocationHandlerImpl.ADMIN); - } - else - { - if (read | write) - { - if (read) - { - _accessRights.put(username, MBeanInvocationHandlerImpl.READONLY); - } - if (write) - { - _accessRights.put(username, MBeanInvocationHandlerImpl.READWRITE); - } - } - else - { - _accessRights.remove(username); - } - } - - //save the rights file - try - { - saveAccessFile(); - } - catch (IOException e) - { - _logger.warn("Problem occured saving '" + _accessFile + "', the access right changes will not be preserved: " + e); - - //the rights file was not successfully saved, restore user rights to previous value - _logger.warn("Reverting attempted rights update for user'" + username + "'"); - if (oldRights != null) - { - _accessRights.put(username, oldRights); - } - else - { - _accessRights.remove(username); - } - - return false; - } - } - finally - { - if (_accessRightsUpdate.isHeldByCurrentThread()) - { - _accessRightsUpdate.unlock(); - } - } - - return true; - } - - public boolean createUser(String username, String password, boolean read, boolean write, boolean admin) - { - return createUser(username, password.toCharArray(), read, write, admin); - } - - public boolean createUser(String username, char[] password, boolean read, boolean write, boolean admin) - { - if (_principalDatabase.createPrincipal(new UsernamePrincipal(username), password)) - { - if (!setRights(username, read, write, admin)) - { - //unable to set rights for user, remove account - try - { - _principalDatabase.deletePrincipal(new UsernamePrincipal(username)); - } - catch (AccountNotFoundException e) - { - //ignore - } - return false; - } - else - { - return true; - } - } - - return false; - } - - public boolean deleteUser(String username) - { - try - { - if (_principalDatabase.deletePrincipal(new UsernamePrincipal(username))) - { - try - { - _accessRightsUpdate.lock(); - - _accessRights.remove(username); - - try - { - saveAccessFile(); - } - catch (IOException e) - { - _logger.warn("Problem occured saving '" + _accessFile + "', the access right changes will not be preserved: " + e); - return false; - } - } - finally - { - if (_accessRightsUpdate.isHeldByCurrentThread()) - { - _accessRightsUpdate.unlock(); - } - } - } - } - catch (AccountNotFoundException e) - { - _logger.warn("Attempt to delete user (" + username + ") that doesn't exist"); - return false; - } - - return true; - } - - public boolean reloadData() - { - try - { - loadAccessFile(); - _principalDatabase.reload(); - } - catch (ConfigurationException e) - { - _logger.warn("Reload failed due to:" + e); - return false; - } - catch (IOException e) - { - _logger.warn("Reload failed due to:" + e); - return false; - } - // Reload successful - return true; - } - - - @MBeanOperation(name = "viewUsers", description = "All users with access rights to the system.") - public TabularData viewUsers() - { - // Table of users - // Username(string), Access rights Read,Write,Admin(bool,bool,bool) - - if (_userlistDataType == null) - { - _logger.warn("TabluarData not setup correctly"); - return null; - } - - List users = _principalDatabase.getUsers(); - - TabularDataSupport userList = new TabularDataSupport(_userlistDataType); - - try - { - // Create the tabular list of message header contents - for (Principal user : users) - { - // Create header attributes list - - String rights = (String) _accessRights.get(user.getName()); - - Boolean read = false; - Boolean write = false; - Boolean admin = false; - - if (rights != null) - { - read = rights.equals(MBeanInvocationHandlerImpl.READONLY) - || rights.equals(MBeanInvocationHandlerImpl.READWRITE); - write = rights.equals(MBeanInvocationHandlerImpl.READWRITE); - admin = rights.equals(MBeanInvocationHandlerImpl.ADMIN); - } - - Object[] itemData = {user.getName(), read, write, admin}; - CompositeData messageData = new CompositeDataSupport(_userDataType, COMPOSITE_ITEM_NAMES, itemData); - userList.put(messageData); - } - } - catch (OpenDataException e) - { - _logger.warn("Unable to create user list due to :" + e); - return null; - } - - return userList; - } - - /*** Broker Methods **/ - - /** - * setPrincipalDatabase - * - * @param database set The Database to use for user lookup - */ - public void setPrincipalDatabase(PrincipalDatabase database) - { - _principalDatabase = database; - } - - /** - * setAccessFile - * - * @param accessFile the file to use for updating. - * - * @throws java.io.IOException If the file cannot be accessed - * @throws org.apache.commons.configuration.ConfigurationException - * if checks on the file fail. - */ - public void setAccessFile(String accessFile) throws IOException, ConfigurationException - { - if (accessFile != null) - { - _accessFile = new File(accessFile); - if (!_accessFile.exists()) - { - throw new ConfigurationException("'" + _accessFile + "' does not exist"); - } - - if (!_accessFile.canRead()) - { - throw new ConfigurationException("Cannot read '" + _accessFile + "'."); - } - - if (!_accessFile.canWrite()) - { - _logger.warn("Unable to write to access rights file '" + _accessFile + "', changes will not be preserved."); - } - - loadAccessFile(); - } - else - { - _logger.warn("Access rights file specified is null. Access rights not changed."); - } - } - - private void loadAccessFile() throws IOException, ConfigurationException - { - if(_accessFile == null) - { - _logger.error("No jmx access rights file has been specified."); - return; - } - - if(_accessFile.exists()) - { - try - { - _accessRightsUpdate.lock(); - - Properties accessRights = new Properties(); - accessRights.load(new FileInputStream(_accessFile)); - checkAccessRights(accessRights); - setAccessRights(accessRights); - } - finally - { - if (_accessRightsUpdate.isHeldByCurrentThread()) - { - _accessRightsUpdate.unlock(); - } - } - } - else - { - _logger.error("Specified jmxaccess rights file '" + _accessFile + "' does not exist."); - } - } - - private void checkAccessRights(Properties accessRights) - { - Enumeration values = accessRights.propertyNames(); - - while (values.hasMoreElements()) - { - String user = (String) values.nextElement(); - - if (_principalDatabase.getUser(user) == null) - { - _logger.warn("Access rights contains user '" + user + "' but there is no authentication data for that user"); - } - } - } - - private void saveAccessFile() throws IOException - { - try - { - _accessRightsUpdate.lock(); - - // Create temporary file - Random r = new Random(); - File tmp; - do - { - tmp = new File(_accessFile.getPath() + r.nextInt() + ".tmp"); - } - while(tmp.exists()); - - tmp.deleteOnExit(); - - FileOutputStream output = new FileOutputStream(tmp); - _accessRights.store(output, "Generated by AMQUserManagementMBean Console : Last edited by user:" + getCurrentJMXUser()); - output.close(); - - // Swap temp file to main rights file. - File old = new File(_accessFile.getAbsoluteFile() + ".old"); - if (old.exists()) - { - old.delete(); - } - - if(!_accessFile.renameTo(old)) - { - //unable to rename the existing file to the backup name - _logger.error("Could not backup the existing management rights file"); - throw new IOException("Could not backup the existing management rights file"); - } - - if(!tmp.renameTo(_accessFile)) - { - //failed to rename the new file to the required filename - - if(!old.renameTo(_accessFile)) - { - //unable to return the backup to required filename - _logger.error("Could not rename the new management rights file into place, and unable to restore original file"); - throw new IOException("Could not rename the new management rights file into place, and unable to restore original file"); - } - - _logger.error("Could not rename the new management rights file into place"); - throw new IOException("Could not rename the new management rights file into place"); - } - } - finally - { - if (_accessRightsUpdate.isHeldByCurrentThread()) - { - _accessRightsUpdate.unlock(); - } - } - - } - - private String getCurrentJMXUser() - { - AccessControlContext acc = AccessController.getContext(); - - Subject subject = Subject.getSubject(acc); - if (subject == null) - { - return "Unknown user, authentication Subject was null"; - } - - // Retrieve JMXPrincipal from Subject - Set principals = subject.getPrincipals(JMXPrincipal.class); - if (principals == null || principals.isEmpty()) - { - return "Unknown user principals were null"; - } - - Principal principal = principals.iterator().next(); - return principal.getName(); - } - - /** - * user=read user=write user=readwrite user=admin - * - * @param accessRights The properties list of access rights to process - */ - private void setAccessRights(Properties accessRights) - { - _logger.debug("Setting Access Rights:" + accessRights); - _accessRights = accessRights; - MBeanInvocationHandlerImpl.setAccessRights(_accessRights); - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/AbstractACLPlugin.java b/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/AbstractACLPlugin.java deleted file mode 100644 index f99f3a60f7..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/AbstractACLPlugin.java +++ /dev/null @@ -1,99 +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.framing.AMQShortString; -import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.security.access.ACLPlugin; -import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.server.security.PrincipalHolder; - -/** - * This ACLPlugin abstains from all votes. Useful if your plugin only cares about a few operations. - */ -public abstract class AbstractACLPlugin implements ACLPlugin -{ - - private static final AuthzResult DEFAULT_ANSWER = AuthzResult.ABSTAIN; - - public AuthzResult authoriseBind(PrincipalHolder session, Exchange exch, AMQQueue queue, - AMQShortString routingKey) - { - return DEFAULT_ANSWER; - } - - public AuthzResult authoriseConnect(PrincipalHolder session, VirtualHost virtualHost) - { - return DEFAULT_ANSWER; - } - - public AuthzResult authoriseConsume(PrincipalHolder session, boolean noAck, AMQQueue queue) - { - return DEFAULT_ANSWER; - } - - public AuthzResult authoriseConsume(PrincipalHolder session, boolean exclusive, boolean noAck, boolean noLocal, - boolean nowait, AMQQueue queue) - { - return DEFAULT_ANSWER; - } - - public AuthzResult authoriseCreateExchange(PrincipalHolder session, boolean autoDelete, boolean durable, - AMQShortString exchangeName, boolean internal, boolean nowait, boolean passive, AMQShortString exchangeType) - { - // TODO Auto-generated method stub - return null; - } - - public AuthzResult authoriseCreateQueue(PrincipalHolder session, boolean autoDelete, boolean durable, - boolean exclusive, boolean nowait, boolean passive, AMQShortString queue) - { - return DEFAULT_ANSWER; - } - - public AuthzResult authoriseDelete(PrincipalHolder session, AMQQueue queue) - { - return DEFAULT_ANSWER; - } - - public AuthzResult authoriseDelete(PrincipalHolder session, Exchange exchange) - { - return DEFAULT_ANSWER; - } - - public AuthzResult authorisePublish(PrincipalHolder session, boolean immediate, boolean mandatory, - AMQShortString routingKey, Exchange e) - { - return DEFAULT_ANSWER; - } - - public AuthzResult authorisePurge(PrincipalHolder session, AMQQueue queue) - { - return DEFAULT_ANSWER; - } - - public AuthzResult authoriseUnbind(PrincipalHolder session, Exchange exch, AMQShortString routingKey, - AMQQueue queue) - { - return DEFAULT_ANSWER; - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/AllowAll.java b/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/AllowAll.java index 4af178574b..82963bbadc 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/AllowAll.java +++ b/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/AllowAll.java @@ -15,40 +15,72 @@ * 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.qpid.server.security.access.ACLPlugin; -import org.apache.qpid.server.security.access.ACLPluginFactory; +import org.apache.commons.configuration.ConfigurationException; +import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; +import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory; +import org.apache.qpid.server.security.Result; +import org.apache.qpid.server.security.SecurityPluginFactory; -public class AllowAll extends BasicACLPlugin +/** Always allow. */ +public class AllowAll extends BasicPlugin { + public static class AllowAllConfiguration extends ConfigurationPlugin { + public static final ConfigurationPluginFactory FACTORY = new ConfigurationPluginFactory() + { + public List getParentPaths() + { + return Arrays.asList("security", "virtualhosts.virtualhost.security"); + } - public static final ACLPluginFactory FACTORY = new ACLPluginFactory() + public ConfigurationPlugin newInstance(String path, Configuration config) throws ConfigurationException + { + ConfigurationPlugin instance = new AllowAllConfiguration(); + instance.setConfiguration(path, config); + return instance; + } + }; + + public String[] getElementsProcessed() + { + return new String[] { "allow-all" }; + } + } + + public static final SecurityPluginFactory FACTORY = new SecurityPluginFactory() { - public boolean supportsTag(String name) + public AllowAll newInstance(ConfigurationPlugin config) throws ConfigurationException { - return false; + AllowAll plugin = new AllowAll(config); + plugin.configure(); + return plugin; } - public ACLPlugin newInstance(Configuration config) + public String getPluginName() { - return new AllowAll(); + return AllowAll.class.getName(); } - }; - public String getPluginName() - { - return this.getClass().getSimpleName(); + public Class getPluginClass() + { + return AllowAll.class; + } + }; + + @Override + public Result getDefault() + { + return Result.ALLOWED; } - @Override - protected AuthzResult getResult() + public AllowAll(ConfigurationPlugin config) { - // Always allow - return AuthzResult.ALLOWED; + _config = config.getConfiguration(AllowAllConfiguration.class); } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/BasicACLPlugin.java b/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/BasicACLPlugin.java deleted file mode 100644 index d0df354d78..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/BasicACLPlugin.java +++ /dev/null @@ -1,110 +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.commons.configuration.Configuration; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.security.access.ACLPlugin; -import org.apache.qpid.server.security.PrincipalHolder; -import org.apache.qpid.server.virtualhost.VirtualHost; - -public abstract class BasicACLPlugin implements ACLPlugin -{ - - // Returns true or false if the plugin should authorise or deny the request - protected abstract AuthzResult getResult(); - - public AuthzResult authoriseBind(PrincipalHolder session, Exchange exch, - AMQQueue queue, AMQShortString routingKey) - { - return getResult(); - } - - public AuthzResult authoriseConnect(PrincipalHolder session, - VirtualHost virtualHost) - { - return getResult(); - } - - public AuthzResult authoriseConsume(PrincipalHolder session, boolean noAck, - AMQQueue queue) - { - return getResult(); - } - - public AuthzResult authoriseConsume(PrincipalHolder session, - boolean exclusive, boolean noAck, boolean noLocal, boolean nowait, - AMQQueue queue) - { - return getResult(); - } - - public AuthzResult authoriseCreateExchange(PrincipalHolder session, - boolean autoDelete, boolean durable, AMQShortString exchangeName, - boolean internal, boolean nowait, boolean passive, - AMQShortString exchangeType) - { - return getResult(); - } - - public AuthzResult authoriseCreateQueue(PrincipalHolder session, - boolean autoDelete, boolean durable, boolean exclusive, - boolean nowait, boolean passive, AMQShortString queue) - { - return getResult(); - } - - public AuthzResult authoriseDelete(PrincipalHolder session, AMQQueue queue) - { - return getResult(); - } - - public AuthzResult authoriseDelete(PrincipalHolder session, Exchange exchange) - { - return getResult(); - } - - public AuthzResult authorisePublish(PrincipalHolder session, - boolean immediate, boolean mandatory, AMQShortString routingKey, - Exchange e) - { - return getResult(); - } - - public AuthzResult authorisePurge(PrincipalHolder session, AMQQueue queue) - { - return getResult(); - } - - public AuthzResult authoriseUnbind(PrincipalHolder session, Exchange exch, - AMQShortString routingKey, AMQQueue queue) - { - return getResult(); - } - - public void setConfiguration(Configuration config) - { - // no-op - } - -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/BasicPlugin.java b/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/BasicPlugin.java new file mode 100644 index 0000000000..5fc1ef7795 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/BasicPlugin.java @@ -0,0 +1,51 @@ +/* + * + * 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.commons.configuration.ConfigurationException; +import org.apache.qpid.server.security.AbstractPlugin; +import org.apache.qpid.server.security.Result; +import org.apache.qpid.server.security.SecurityPlugin; +import org.apache.qpid.server.security.access.ObjectProperties; +import org.apache.qpid.server.security.access.ObjectType; +import org.apache.qpid.server.security.access.Operation; + +/** + * This {@link SecurityPlugin} simply abstains from all authorisation requests and ignores configuration. + */ +public class BasicPlugin extends AbstractPlugin +{ + public Result access(ObjectType objectType, Object instance) + { + return getDefault(); + } + + public Result authorise(Operation operation, ObjectType objectType, ObjectProperties properties) + { + return getDefault(); + } + + @Override + public void configure() throws ConfigurationException + { + // Not used + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/DenyAll.java b/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/DenyAll.java index 77d3c4bcdf..24af215a0c 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/DenyAll.java +++ b/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/DenyAll.java @@ -15,61 +15,72 @@ * 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.qpid.AMQConnectionException; -import org.apache.qpid.framing.AMQMethodBody; -import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.security.access.ACLManager; -import org.apache.qpid.server.security.access.ACLPlugin; -import org.apache.qpid.server.security.access.ACLPluginFactory; -import org.apache.qpid.server.security.access.AccessResult; -import org.apache.qpid.server.security.access.Permission; +import org.apache.commons.configuration.ConfigurationException; +import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; +import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory; +import org.apache.qpid.server.security.Result; +import org.apache.qpid.server.security.SecurityPluginFactory; -public class DenyAll extends BasicACLPlugin +/** Always Deny. */ +public class DenyAll extends BasicPlugin { - public static final ACLPluginFactory FACTORY = new ACLPluginFactory() - { - public boolean supportsTag(String name) + public static class DenyAllConfiguration extends ConfigurationPlugin { + public static final ConfigurationPluginFactory FACTORY = new ConfigurationPluginFactory() { - return false; - } + public List getParentPaths() + { + return Arrays.asList("security", "virtualhosts.virtualhost.security"); + } - public ACLPlugin newInstance(Configuration config) + public ConfigurationPlugin newInstance(String path, Configuration config) throws ConfigurationException + { + ConfigurationPlugin instance = new DenyAllConfiguration(); + instance.setConfiguration(path, config); + return instance; + } + }; + + public String[] getElementsProcessed() { - return new DenyAll(); + return new String[] { "deny-all" }; } - }; + } - public AccessResult authorise(AMQProtocolSession session, - Permission permission, AMQMethodBody body, Object... parameters) - throws AMQConnectionException + public static final SecurityPluginFactory FACTORY = new SecurityPluginFactory() { + public DenyAll newInstance(ConfigurationPlugin config) throws ConfigurationException + { + DenyAll plugin = new DenyAll(config); + plugin.configure(); + return plugin; + } - if (ACLManager.getLogger().isInfoEnabled()) + public String getPluginName() { - ACLManager.getLogger().info( - "Denying user:" + session.getPrincipal()); + return DenyAll.class.getName(); } - throw body.getConnectionException(AMQConstant.ACCESS_REFUSED, - "DenyAll Plugin"); - } - public String getPluginName() - { - return getClass().getSimpleName(); + public Class getPluginClass() + { + return DenyAll.class; + } + }; + + @Override + public Result getDefault() + { + return Result.DENIED; } - @Override - protected AuthzResult getResult() + public DenyAll(ConfigurationPlugin config) throws ConfigurationException { - // Always deny - return AuthzResult.DENIED; + _config = config.getConfiguration(DenyAllConfiguration.class); } - } diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/LegacyAccess.java b/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/LegacyAccess.java new file mode 100644 index 0000000000..2c0994b52a --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/LegacyAccess.java @@ -0,0 +1,81 @@ +/* + * 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.VirtualHostConfiguration; +import org.apache.qpid.server.configuration.ServerConfiguration; +import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory; +import org.apache.qpid.server.security.SecurityPluginFactory; + +/** Always Abstain. */ +public class LegacyAccess extends BasicPlugin +{ + public static class LegacyAccessConfiguration extends ConfigurationPlugin { + public static final ConfigurationPluginFactory FACTORY = new ConfigurationPluginFactory() + { + public List getParentPaths() + { + return Arrays.asList("security", "virtualhosts.virtualhost.security"); + } + + public ConfigurationPlugin newInstance(String path, Configuration config) throws ConfigurationException + { + ConfigurationPlugin instance = new LegacyAccessConfiguration(); + instance.setConfiguration(path, config); + return instance; + } + }; + + public String[] getElementsProcessed() + { + return new String[] { "principal-databases", "access", "msg-auth", "false", "jmx" }; + } + } + + public static final SecurityPluginFactory FACTORY = new SecurityPluginFactory() + { + public LegacyAccess newInstance(ConfigurationPlugin config) throws ConfigurationException + { + LegacyAccess plugin = new LegacyAccess(config); + plugin.configure(); + return plugin; + } + + public String getPluginName() + { + return LegacyAccess.class.getName(); + } + + public Class getPluginClass() + { + return LegacyAccess.class; + } + }; + + public LegacyAccess(ConfigurationPlugin config) throws ConfigurationException + { + _config = config.getConfiguration(LegacyAccessConfiguration.class); + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/LegacyAccessPlugin.java b/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/LegacyAccessPlugin.java deleted file mode 100644 index fc1bc048d4..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/LegacyAccessPlugin.java +++ /dev/null @@ -1,71 +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.Collection; -import java.util.HashSet; - -import org.apache.commons.configuration.Configuration; -import org.apache.qpid.server.security.access.ACLPlugin; -import org.apache.qpid.server.security.access.ACLPluginFactory; - -/** - * - * Used to suppress warnings in legacy config files that have things in which aren't handled by a plugin directly. - * - */ -public class LegacyAccessPlugin extends BasicACLPlugin -{ - public static final ACLPluginFactory FACTORY = new ACLPluginFactory() - { - private Collection maskedTags = new HashSet(); - { - maskedTags.add("principal-databases"); - maskedTags.add("access"); - maskedTags.add("msg-auth"); - maskedTags.add("false"); - maskedTags.add("jmx"); - } - - public boolean supportsTag(String name) - { - return maskedTags .contains(name); - } - - public ACLPlugin newInstance(Configuration config) - { - return new LegacyAccessPlugin(); - } - }; - - public String getPluginName() - { - return getClass().getSimpleName(); - } - - @Override - protected AuthzResult getResult() - { - // Always abstain - return AuthzResult.ABSTAIN; - } - -} -- cgit v1.2.1