From 8735514651a4873dc0b9b0ea4cf0fc58267e6fb3 Mon Sep 17 00:00:00 2001 From: Alex Rudyy Date: Fri, 19 Apr 2013 16:16:20 +0000 Subject: QPID-4753: move ACL config from broker attribute to a top level entity git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1469937 13f79535-47bb-0310-9956-ffa450edef68 --- .../access/plugins/DefaultAccessControl.java | 46 +++- .../plugins/DefaultAccessControlFactory.java | 66 +++-- ...ControlProviderAttributeDescriptions.properties | 19 ++ .../plugins/DefaultAccessControlFactoryTest.java | 34 +-- .../server/management/plugin/HttpManagement.java | 2 + .../plugin/servlet/rest/HelperServlet.java | 3 + .../ListAccessControlProviderAttributes.java | 76 ++++++ .../accesscontrolprovider/showAclFile.html | 24 ++ .../js/qpid/management/AccessControlProvider.js | 131 ++++++++++ .../java/resources/js/qpid/management/Broker.js | 47 +++- .../management/accesscontrolprovider/AclFile.js | 95 +++++++ .../js/qpid/management/addAccessControlProvider.js | 177 +++++++++++++ .../resources/js/qpid/management/controller.js | 6 +- .../java/resources/js/qpid/management/treeView.js | 2 + .../java/resources/showAccessControlProvider.html | 31 +++ .../src/main/java/resources/showBroker.html | 14 +- .../startup/AccessControlProviderRecoverer.java | 54 ++++ .../startup/AuthenticationProviderRecoverer.java | 1 - .../configuration/startup/BrokerRecoverer.java | 11 +- .../startup/DefaultRecovererProvider.java | 13 +- .../store/ManagementModeStoreHandler.java | 6 + .../qpid/server/model/AccessControlProvider.java | 56 ++++ .../java/org/apache/qpid/server/model/Broker.java | 15 +- .../java/org/apache/qpid/server/model/Model.java | 1 + .../adapter/AccessControlProviderAdapter.java | 283 +++++++++++++++++++++ .../adapter/AccessControlProviderFactory.java | 90 +++++++ .../qpid/server/model/adapter/BrokerAdapter.java | 116 +++++++-- .../qpid/server/plugin/AccessControlFactory.java | 23 ++ .../apache/qpid/server/security/AccessControl.java | 21 ++ .../qpid/server/security/SecurityManager.java | 190 ++++++++------ .../access/FileAccessControlProviderConstants.java | 27 ++ .../qpid/server/virtualhost/VirtualHostImpl.java | 2 +- .../configuration/startup/BrokerRecovererTest.java | 6 +- .../store/ConfigurationEntryStoreTestCase.java | 2 - .../store/JsonConfigurationEntryStoreTest.java | 8 +- .../apache/qpid/server/util/BrokerTestHelper.java | 8 +- .../server/virtualhost/VirtualHostImplTest.java | 4 +- .../server/security/acl/AbstractACLTestCase.java | 2 +- .../qpid/systest/rest/BrokerRestHttpsTest.java | 3 +- .../apache/qpid/systest/rest/BrokerRestTest.java | 14 +- .../qpid/test/utils/TestBrokerConfiguration.java | 23 +- 41 files changed, 1525 insertions(+), 227 deletions(-) create mode 100644 qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/FileAccessControlProviderAttributeDescriptions.properties create mode 100644 qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/action/ListAccessControlProviderAttributes.java create mode 100644 qpid/java/broker-plugins/management-http/src/main/java/resources/accesscontrolprovider/showAclFile.html create mode 100644 qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/AccessControlProvider.js create mode 100644 qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/accesscontrolprovider/AclFile.js create mode 100644 qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addAccessControlProvider.js create mode 100644 qpid/java/broker-plugins/management-http/src/main/java/resources/showAccessControlProvider.html create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/AccessControlProviderRecoverer.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/model/AccessControlProvider.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AccessControlProviderAdapter.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AccessControlProviderFactory.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/FileAccessControlProviderConstants.java diff --git a/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControl.java b/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControl.java index 6f7885da94..451b1f9c40 100644 --- a/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControl.java +++ b/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControl.java @@ -29,6 +29,7 @@ import javax.security.auth.Subject; import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.lang.ObjectUtils; import org.apache.log4j.Logger; +import org.apache.qpid.server.configuration.IllegalConfigurationException; import org.apache.qpid.server.security.Result; import org.apache.qpid.server.security.SecurityManager; import org.apache.qpid.server.security.AccessControl; @@ -44,6 +45,7 @@ public class DefaultAccessControl implements AccessControl private static final Logger _logger = Logger.getLogger(DefaultAccessControl.class); private RuleSet _ruleSet; + private File _aclFile; public DefaultAccessControl(String fileName) { @@ -51,10 +53,8 @@ public class DefaultAccessControl implements AccessControl { _logger.debug("Creating AccessControl instance using file: " + fileName); } - File aclFile = new File(fileName); - ConfigurationFile configFile = new PlainConfiguration(aclFile); - _ruleSet = configFile.load(); + _aclFile = new File(fileName); } DefaultAccessControl(RuleSet rs) throws ConfigurationException @@ -62,6 +62,45 @@ public class DefaultAccessControl implements AccessControl _ruleSet = rs; } + public void open() + { + if(_aclFile != null) + { + if (!_aclFile.exists()) + { + throw new IllegalConfigurationException("ACL file '" + _aclFile + "' is not found"); + } + + ConfigurationFile configFile = new PlainConfiguration(_aclFile); + _ruleSet = configFile.load(); + } + } + + @Override + public void close() + { + //no-op + } + + @Override + public void onDelete() + { + //no-op + } + + @Override + public void onCreate() + { + //verify file exists + if(_aclFile != null) + { + if (!_aclFile.exists()) + { + throw new IllegalConfigurationException("ACL file '" + _aclFile + "' is not found"); + } + } + } + public Result getDefault() { return _ruleSet.getDefault(); @@ -119,4 +158,5 @@ public class DefaultAccessControl implements AccessControl return Result.DENIED; } } + } diff --git a/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlFactory.java b/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlFactory.java index a3d7823caf..f4e041a8d2 100644 --- a/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlFactory.java +++ b/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlFactory.java @@ -20,40 +20,60 @@ */ package org.apache.qpid.server.security.access.plugins; -import java.io.File; +import static org.apache.qpid.server.security.access.FileAccessControlProviderConstants.ACL_FILE_PROVIDER_TYPE; +import static org.apache.qpid.server.security.access.FileAccessControlProviderConstants.PATH; +import static org.apache.qpid.server.util.MapValueConverter.getStringAttribute; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; import java.util.Map; import org.apache.qpid.server.configuration.IllegalConfigurationException; import org.apache.qpid.server.plugin.AccessControlFactory; import org.apache.qpid.server.security.AccessControl; +import org.apache.qpid.server.util.ResourceBundleLoader; public class DefaultAccessControlFactory implements AccessControlFactory { - public static final String ATTRIBUTE_ACL_FILE = "aclFile"; + public static final String RESOURCE_BUNDLE = "org.apache.qpid.server.security.access.plugins.FileAccessControlProviderAttributeDescriptions"; + + public static final Collection ATTRIBUTES = Collections. unmodifiableList(Arrays.asList( + ATTRIBUTE_TYPE, + PATH + )); - public AccessControl createInstance(Map aclConfiguration) + public AccessControl createInstance(Map attributes) { - if (aclConfiguration != null) + if(attributes == null || !ACL_FILE_PROVIDER_TYPE.equals(attributes.get(ATTRIBUTE_TYPE))) + { + return null; + } + + String path = getStringAttribute(PATH, attributes, null); + if (path == null || "".equals(path.trim())) { - Object aclFile = aclConfiguration.get(ATTRIBUTE_ACL_FILE); - if (aclFile != null) - { - if (aclFile instanceof String) - { - String aclPath = (String) aclFile; - if (!new File(aclPath).exists()) - { - throw new IllegalConfigurationException("ACL file '" + aclPath + "' is not found"); - } - return new DefaultAccessControl(aclPath); - } - else - { - throw new IllegalConfigurationException("Expected '" + ATTRIBUTE_ACL_FILE + "' attribute value of type String but was " + aclFile.getClass() - + ": " + aclFile); - } - } + throw new IllegalConfigurationException("Path to ACL was not specified!"); } - return null; + + return new DefaultAccessControl(path); + } + + @Override + public String getType() + { + return ACL_FILE_PROVIDER_TYPE; + } + + @Override + public Collection getAttributeNames() + { + return ATTRIBUTES; + } + + @Override + public Map getAttributeDescriptions() + { + return ResourceBundleLoader.getResources(RESOURCE_BUNDLE); } } diff --git a/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/FileAccessControlProviderAttributeDescriptions.properties b/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/FileAccessControlProviderAttributeDescriptions.properties new file mode 100644 index 0000000000..e847e90f57 --- /dev/null +++ b/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/FileAccessControlProviderAttributeDescriptions.properties @@ -0,0 +1,19 @@ +# +# 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. + +path=File location* \ No newline at end of file diff --git a/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlFactoryTest.java b/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlFactoryTest.java index ca1f19098f..2c55652f04 100644 --- a/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlFactoryTest.java +++ b/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlFactoryTest.java @@ -6,7 +6,9 @@ import java.util.Map; import java.util.regex.Pattern; import org.apache.qpid.server.configuration.IllegalConfigurationException; +import org.apache.qpid.server.model.GroupProvider; import org.apache.qpid.server.security.AccessControl; +import org.apache.qpid.server.security.access.FileAccessControlProviderConstants; import org.apache.qpid.test.utils.QpidTestCase; import org.apache.qpid.test.utils.TestFileUtils; @@ -25,8 +27,10 @@ public class DefaultAccessControlFactoryTest extends QpidTestCase File aclFile = TestFileUtils.createTempFile(this, ".acl", "ACL ALLOW all all"); DefaultAccessControlFactory factory = new DefaultAccessControlFactory(); Map attributes = new HashMap(); - attributes.put(DefaultAccessControlFactory.ATTRIBUTE_ACL_FILE, aclFile.getAbsolutePath()); + attributes.put(GroupProvider.TYPE, FileAccessControlProviderConstants.ACL_FILE_PROVIDER_TYPE); + attributes.put(FileAccessControlProviderConstants.PATH, aclFile.getAbsolutePath()); AccessControl acl = factory.createInstance(attributes); + acl.open(); assertNotNull("ACL was not created from acl file: " + aclFile.getAbsolutePath(), acl); } @@ -37,33 +41,17 @@ public class DefaultAccessControlFactoryTest extends QpidTestCase assertFalse("ACL file " + aclFile.getAbsolutePath() + " actually exists but should not", aclFile.exists()); DefaultAccessControlFactory factory = new DefaultAccessControlFactory(); Map attributes = new HashMap(); - attributes.put(DefaultAccessControlFactory.ATTRIBUTE_ACL_FILE, aclFile.getAbsolutePath()); + attributes.put(GroupProvider.TYPE, FileAccessControlProviderConstants.ACL_FILE_PROVIDER_TYPE); + attributes.put(FileAccessControlProviderConstants.PATH, aclFile.getAbsolutePath()); try { - factory.createInstance(attributes); - fail("It should not be possible to create ACL from non existing file"); + AccessControl control = factory.createInstance(attributes); + control.open(); + fail("It should not be possible to create and initialise ACL with non existing file"); } catch (IllegalConfigurationException e) { - assertTrue("Unexpected exception message", Pattern.matches("ACL file '.*' is not found", e.getMessage())); - } - } - - public void testCreateInstanceWhenAclFileIsSpecifiedAsNonString() - { - DefaultAccessControlFactory factory = new DefaultAccessControlFactory(); - Map attributes = new HashMap(); - Integer aclFile = new Integer(0); - attributes.put(DefaultAccessControlFactory.ATTRIBUTE_ACL_FILE, aclFile); - try - { - factory.createInstance(attributes); - fail("It should not be possible to create ACL from Integer"); - } - catch (IllegalConfigurationException e) - { - assertEquals("Unexpected exception message", "Expected '" + DefaultAccessControlFactory.ATTRIBUTE_ACL_FILE - + "' attribute value of type String but was " + Integer.class + ": " + aclFile, e.getMessage()); + assertTrue("Unexpected exception message: " + e.getMessage(), Pattern.matches("ACL file '.*' is not found", e.getMessage())); } } } diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java index b87b1c76f0..2fc54482a4 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java @@ -47,6 +47,7 @@ import org.apache.qpid.server.management.plugin.servlet.rest.MessageServlet; import org.apache.qpid.server.management.plugin.servlet.rest.RestServlet; import org.apache.qpid.server.management.plugin.servlet.rest.SaslServlet; import org.apache.qpid.server.management.plugin.servlet.rest.StructureServlet; +import org.apache.qpid.server.model.AccessControlProvider; import org.apache.qpid.server.model.AuthenticationProvider; import org.apache.qpid.server.model.Binding; import org.apache.qpid.server.model.Broker; @@ -283,6 +284,7 @@ public class HttpManagement extends AbstractPluginAdapter implements HttpManagem addRestServlet(root, "broker"); addRestServlet(root, "virtualhost", VirtualHost.class); addRestServlet(root, "authenticationprovider", AuthenticationProvider.class); + addRestServlet(root, "accesscontrolprovider", AccessControlProvider.class); addRestServlet(root, "user", AuthenticationProvider.class, User.class); addRestServlet(root, "groupprovider", GroupProvider.class); addRestServlet(root, "group", GroupProvider.class, Group.class); diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/HelperServlet.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/HelperServlet.java index 626dfa1d6c..a7066c73d8 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/HelperServlet.java +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/HelperServlet.java @@ -31,6 +31,7 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.apache.qpid.server.management.plugin.servlet.rest.action.ListAccessControlProviderAttributes; import org.apache.qpid.server.management.plugin.servlet.rest.action.ListAuthenticationProviderAttributes; import org.apache.qpid.server.management.plugin.servlet.rest.action.ListGroupProviderAttributes; import org.apache.qpid.server.management.plugin.servlet.rest.action.ListMessageStoreTypes; @@ -55,6 +56,8 @@ public class HelperServlet extends AbstractServlet _actions.put(listMessageStoreTypes.getName(), listMessageStoreTypes); Action groupProviderAttributes = new ListGroupProviderAttributes(); _actions.put(groupProviderAttributes.getName(), groupProviderAttributes); + Action aclProviderAttributes = new ListAccessControlProviderAttributes(); + _actions.put(aclProviderAttributes.getName(), aclProviderAttributes); } @Override diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/action/ListAccessControlProviderAttributes.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/action/ListAccessControlProviderAttributes.java new file mode 100644 index 0000000000..6887217016 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/action/ListAccessControlProviderAttributes.java @@ -0,0 +1,76 @@ +/* + * + * 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.management.plugin.servlet.rest.action; + +import java.util.HashMap; +import java.util.Map; +import java.util.TreeMap; + +import org.apache.qpid.server.management.plugin.servlet.rest.Action; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.plugin.AccessControlFactory; +import org.apache.qpid.server.plugin.QpidServiceLoader; + +public class ListAccessControlProviderAttributes implements Action +{ + private static final String ATTRIBUTES = "attributes"; + private static final String DESCRIPTIONS = "descriptions"; + private Map _factories; + + public ListAccessControlProviderAttributes() + { + _factories = new TreeMap(); + Iterable factories = new QpidServiceLoader() + .instancesOf(AccessControlFactory.class); + for (AccessControlFactory factory : factories) + { + _factories.put(factory.getType(), factory); + } + } + + @Override + public String getName() + { + return ListAccessControlProviderAttributes.class.getSimpleName(); + } + + @Override + public Object perform(Map request, Broker broker) + { + Map attributes = new TreeMap(); + for (String providerType : _factories.keySet()) + { + AccessControlFactory factory = _factories.get(providerType); + + Map data = new HashMap(); + data.put(ATTRIBUTES, factory.getAttributeNames()); + Map resources = factory.getAttributeDescriptions(); + if (resources != null) + { + data.put(DESCRIPTIONS, resources); + } + + attributes.put(factory.getType(), data); + } + return attributes; + } + +} diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/accesscontrolprovider/showAclFile.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/accesscontrolprovider/showAclFile.html new file mode 100644 index 0000000000..182e651a51 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/accesscontrolprovider/showAclFile.html @@ -0,0 +1,24 @@ + +
+ Path: +
+
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/AccessControlProvider.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/AccessControlProvider.js new file mode 100644 index 0000000000..fd8a3ecb0e --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/AccessControlProvider.js @@ -0,0 +1,131 @@ +/* + * + * 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. + * + */ +define(["dojo/_base/xhr", + "dojo/parser", + "dojo/query", + "dojo/_base/connect", + "qpid/common/properties", + "qpid/common/updater", + "qpid/common/util", + "qpid/common/UpdatableStore", + "dojox/grid/EnhancedGrid", + "dijit/registry", + "dojo/_base/event", + "dojox/grid/enhanced/plugins/Pagination", + "dojox/grid/enhanced/plugins/IndirectSelection", + "dojo/domReady!"], + function (xhr, parser, query, connect, properties, updater, util, UpdatableStore, EnhancedGrid, registry, event) { + + function AccessControlProvider(name, parent, controller) { + this.name = name; + this.controller = controller; + this.modelObj = { type: "accesscontrolprovider", name: name }; + if(parent) { + this.modelObj.parent = {}; + this.modelObj.parent[ parent.type] = parent; + } + } + + AccessControlProvider.prototype.getTitle = function() { + return "AccessControlProvider: " + this.name ; + }; + + AccessControlProvider.prototype.open = function(contentPane) { + var that = this; + this.contentPane = contentPane; + xhr.get({url: "showAccessControlProvider.html", + sync: true, + load: function(data) { + contentPane.containerNode.innerHTML = data; + parser.parse(contentPane.containerNode); + + that.accessControlProviderUpdater = new AccessControlProviderUpdater(contentPane.containerNode, that.modelObj, that.controller); + + var deleteButton = query(".deleteAccessControlProviderButton", contentPane.containerNode)[0]; + var deleteWidget = registry.byNode(deleteButton); + connect.connect(deleteWidget, "onClick", + function(evt){ + event.stop(evt); + that.deleteAccessControlProvider(); + }); + }}); + }; + + AccessControlProvider.prototype.close = function() { + if (this.accessControlProviderUpdater.details) + { + this.accessControlProviderUpdater.details.close(); + } + }; + + AccessControlProvider.prototype.deleteAccessControlProvider = function() { + if(confirm("Are you sure you want to delete access control provider '" + this.name + "'?")) { + var query = "rest/accesscontrolprovider/" +encodeURIComponent(this.name); + this.success = true + var that = this; + xhr.del({url: query, sync: true, handleAs: "json"}).then( + function(data) { + that.close(); + that.contentPane.onClose() + that.controller.tabContainer.removeChild(that.contentPane); + that.contentPane.destroyRecursive(); + }, + function(error) {that.success = false; that.failureReason = error;}); + if(!this.success ) { + alert("Error:" + this.failureReason); + } + } + }; + + function AccessControlProviderUpdater(node, groupProviderObj, controller) + { + this.controller = controller; + this.name = query(".name", node)[0]; + this.type = query(".type", node)[0]; + this.query = "rest/accesscontrolprovider/"+encodeURIComponent(groupProviderObj.name); + + var that = this; + + xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}) + .then(function(data) + { + that.accessControlProviderData = data[0]; + + util.flattenStatistics( that.accessControlProviderData ); + + that.updateHeader(); + + var ui = that.accessControlProviderData.type; + require(["qpid/management/accesscontrolprovider/"+ ui], + function(SpecificProvider) { + that.details = new SpecificProvider(query(".providerDetails", node)[0], groupProviderObj, controller); + }); + }); + } + + AccessControlProviderUpdater.prototype.updateHeader = function() + { + this.name.innerHTML = this.accessControlProviderData[ "name" ]; + this.type.innerHTML = this.accessControlProviderData[ "type" ]; + }; + + return AccessControlProvider; + }); diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Broker.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Broker.js index e5631745a8..7ce2e1c0c1 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Broker.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Broker.js @@ -33,6 +33,7 @@ define(["dojo/_base/xhr", "qpid/management/addPort", "qpid/management/addKeystore", "qpid/management/addGroupProvider", + "qpid/management/addAccessControlProvider", "dojox/grid/enhanced/plugins/Pagination", "dojox/grid/enhanced/plugins/IndirectSelection", "dijit/layout/AccordionContainer", @@ -43,7 +44,7 @@ define(["dojo/_base/xhr", "dijit/form/CheckBox", "dojo/store/Memory", "dojo/domReady!"], - function (xhr, parser, query, connect, properties, updater, util, UpdatableStore, EnhancedGrid, registry, addAuthenticationProvider, addVirtualHost, addPort, addKeystore, addGroupProvider) { + function (xhr, parser, query, connect, properties, updater, util, UpdatableStore, EnhancedGrid, registry, addAuthenticationProvider, addVirtualHost, addPort, addKeystore, addGroupProvider, addAccessControlProvider) { function Broker(name, parent, controller) { this.name = name; @@ -79,15 +80,6 @@ define(["dojo/_base/xhr", label: "Default Virtual Host*:", name: "defaultVirtualHost"}) } - }, { - name: "aclFile", - createWidget: function(brokerData) { - return new dijit.form.ValidationTextBox({ - required: false, - value: brokerData.aclFile, - label: "ACL file location:", - name: "aclFile"}) - } }, { name: "statisticsReportingPeriod", createWidget: function(brokerData) { @@ -473,6 +465,21 @@ define(["dojo/_base/xhr", warning + "Are you sure you want to delete group provider"); } ); + + var addAccessControlButton = query(".addAccessControlProvider", contentPane.containerNode)[0]; + connect.connect(registry.byNode(addAccessControlButton), "onClick", + function(evt){addAccessControlProvider.show();}); + + var deleteAccessControlProviderButton = query(".deleteAccessControlProvider", contentPane.containerNode)[0]; + connect.connect(registry.byNode(deleteAccessControlProviderButton), "onClick", + function(evt){ + util.deleteGridSelections( + that.brokerUpdater, + that.brokerUpdater.accessControlProvidersGrid.grid, + "rest/accesscontrolprovider", + "Are you sure you want to delete access control provider"); + } + ); }}); }; @@ -626,7 +633,20 @@ define(["dojo/_base/xhr", that.controller.show("groupprovider", name, brokerObj); }); }, gridProperties, EnhancedGrid); - + var aclData = that.brokerData.accesscontrolproviders ? that.brokerData.accesscontrolproviders :[]; + that.accessControlProvidersGrid = + new UpdatableStore(aclData, query(".broker-access-control-providers")[0], + [ { name: "Name", field: "name", width: "60%"}, + { name: "Type", field: "type", width: "40%"} + ], function(obj) { + connect.connect(obj.grid, "onRowDblClick", obj.grid, + function(evt){ + var idx = evt.rowIndex, + theItem = this.getItem(idx); + var name = obj.dataStore.getValue(theItem,"name"); + that.controller.show("accesscontrolprovider", name, brokerObj); + }); + }, gridProperties, EnhancedGrid); }); xhr.get({url: "rest/logrecords", sync: properties.useSyncGet, handleAs: "json"}) @@ -725,6 +745,11 @@ define(["dojo/_base/xhr", { that.groupProvidersGrid.update(that.brokerData.groupproviders); } + if (that.accessControlProvidersGrid) + { + var data = that.brokerData.accesscontrolproviders ? that.brokerData.accesscontrolproviders :[]; + that.accessControlProvidersGrid.update(data); + } }); diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/accesscontrolprovider/AclFile.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/accesscontrolprovider/AclFile.js new file mode 100644 index 0000000000..56f92c2025 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/accesscontrolprovider/AclFile.js @@ -0,0 +1,95 @@ +/* + * + * 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. + * + */ +define(["dojo/_base/xhr", + "dojo/dom", + "dojo/parser", + "dojo/query", + "dojo/dom-construct", + "dojo/_base/connect", + "dojo/_base/window", + "dojo/_base/event", + "dojo/_base/json", + "dijit/registry", + "qpid/common/util", + "qpid/common/properties", + "qpid/common/updater", + "qpid/common/UpdatableStore", + "dojox/grid/EnhancedGrid", + "dojox/grid/enhanced/plugins/Pagination", + "dojox/grid/enhanced/plugins/IndirectSelection", + "dojox/validate/us", "dojox/validate/web", + "dijit/Dialog", + "dijit/form/TextBox", + "dijit/form/ValidationTextBox", + "dijit/form/TimeTextBox", "dijit/form/Button", + "dijit/form/Form", + "dijit/form/DateTextBox", + "dojo/domReady!"], + function (xhr, dom, parser, query, construct, connect, win, event, json, registry, util, properties, updater, UpdatableStore, EnhancedGrid) { + function AclFile(containerNode, aclProviderObj, controller) { + var node = construct.create("div", null, containerNode, "last"); + var that = this; + this.name = aclProviderObj.name; + xhr.get({url: "accesscontrolprovider/showAclFile.html", + sync: true, + load: function(data) { + node.innerHTML = data; + parser.parse(node); + + that.groupDatabaseUpdater= new AclFileUpdater(node, aclProviderObj, controller); + + updater.add( that.groupDatabaseUpdater); + + that.groupDatabaseUpdater.update(); + + + }}); + } + + AclFile.prototype.close = function() { + updater.remove( this.groupDatabaseUpdater ); + }; + + function AclFileUpdater(node, aclProviderObj, controller) + { + this.controller = controller; + this.query = "rest/accesscontrolprovider/"+encodeURIComponent(aclProviderObj.name); + this.name = aclProviderObj.name; + this.path = query(".path", node)[0]; + } + + AclFileUpdater.prototype.update = function() + { + var that = this; + + xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}) + .then(function(data) { + if (data[0]) + { + that.aclProviderData = data[0]; + that.path.innerHTML = that.aclProviderData.path; + } + }); + + }; + + return AclFile; + }); diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addAccessControlProvider.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addAccessControlProvider.js new file mode 100644 index 0000000000..d20897c1d8 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addAccessControlProvider.js @@ -0,0 +1,177 @@ +/* + * + * 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. + * + */ +define(["dojo/_base/lang", + "dojo/_base/xhr", + "dojo/dom", + "dojo/dom-construct", + "dijit/registry", + "dojo/parser", + "dojo/_base/array", + "dojo/_base/event", + 'dojo/_base/json', + "qpid/common/util", + "dojo/store/Memory", + "dojox/validate/us", + "dojox/validate/web", + "dijit/Dialog", + "dijit/form/CheckBox", + "dijit/form/Textarea", + "dijit/form/ComboBox", + "dijit/form/TextBox", + "dijit/form/ValidationTextBox", + "dijit/form/Button", + "dijit/form/Form", + "dijit/layout/ContentPane", + "dojox/layout/TableContainer", + "dojo/domReady!"], + function (lang, xhr, dom, construct, registry, parser, array, event, json, util) { + + var addAccessControlProvider = {}; + + addAccessControlProvider.show = function(accessControlProvider) { + var fields = [{ + name: "name", + createWidget: function(accessControlProvider) { + return new dijit.form.ValidationTextBox({ + required: true, + value: accessControlProvider.name, + disabled: accessControlProvider.name ? true : false, + label: "Name*:", + regexp: "^[\x20-\x2e\x30-\x7F]{1,255}$", + name: "name"}); + } + }, { + name: "type", + createWidget: function(accessControlProvider) { + + var typeContainer = construct.create("div"); + + var typeListContainer = new dojox.layout.TableContainer({ + cols: 1, + "labelWidth": "300", + customClass: "formLabel", + showLabels: true, + orientation: "horiz" + }); + + typeContainer.appendChild(typeListContainer.domNode); + + var providers = []; + var fieldSetContainers = {}; + xhr.get({ + url: "rest/helper?action=ListAccessControlProviderAttributes", + handleAs: "json", + sync: true + }).then( + function(data) { + var providerIndex = 0; + + for (var providerType in data) { + if (data.hasOwnProperty(providerType)) { + providers[providerIndex++] = {id: providerType, name: providerType}; + + var attributes = data[providerType].attributes; + var descriptions = data[providerType].descriptions; + + var layout = new dojox.layout.TableContainer( { + cols: 1, + "labelWidth": "300", + customClass: "formLabel", + showLabels: true, + orientation: "horiz" + }); + + for(var i=0; i < attributes.length; i++) { + if ("type" == attributes[i]) + { + continue; + } + var labelValue = attributes[i]; + if (descriptions && descriptions[attributes[i]]) + { + labelValue = descriptions[attributes[i]]; + } + var text = new dijit.form.TextBox({ + label: labelValue + ":", + name: attributes[i] + }); + layout.addChild(text); + } + + typeContainer.appendChild(layout.domNode); + fieldSetContainers[providerType] = layout; + } + } + }); + + var providersStore = new dojo.store.Memory({ data: providers }); + + var typeList = new dijit.form.FilteringSelect({ + required: true, + value: accessControlProvider.type, + store: providersStore, + label: "Type*:", + name: "type"}); + + typeListContainer.addChild(typeList); + + var onChangeHandler = function onChangeHandler(newValue){ + for (var i in fieldSetContainers) { + var container = fieldSetContainers[i]; + var descendants = container.getChildren(); + for(var i in descendants){ + var descendant = descendants[i]; + var propName = descendant.name; + if (propName) { + descendant.set("disabled", true); + } + } + container.domNode.style.display = "none"; + } + var container = fieldSetContainers[newValue]; + if (container) + { + container.domNode.style.display = "block"; + var descendants = container.getChildren(); + for(var i in descendants){ + var descendant = descendants[i]; + var propName = descendant.name; + if (propName) { + descendant.set("disabled", false); + } + } + } + }; + typeList.on("change", onChangeHandler); + onChangeHandler(typeList.value); + return new dijit.layout.ContentPane({content: typeContainer, style:{padding: 0}}); + } + }]; + + util.showSetAttributesDialog( + fields, + accessControlProvider ? accessControlProvider : {}, + "rest/accesscontrolprovider" + (name ? "/" + encodeURIComponent(name.name) : ""), + accessControlProvider ? "Edit access control provider - " + accessControlProvider.name : "Add access control provider", + accessControlProvider ? false : true); + }; + return addAccessControlProvider; + }); \ No newline at end of file diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/controller.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/controller.js index c4114739c0..e8a381777f 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/controller.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/controller.js @@ -31,15 +31,17 @@ define(["dojo/dom", "qpid/management/group/Group", "qpid/management/KeyStore", "qpid/management/TrustStore", + "qpid/management/AccessControlProvider", "dojo/ready", "dojo/domReady!"], - function (dom, registry, ContentPane, Broker, VirtualHost, Exchange, Queue, Connection, AuthProvider, GroupProvider, Group, KeyStore, TrustStore, ready) { + function (dom, registry, ContentPane, Broker, VirtualHost, Exchange, Queue, Connection, AuthProvider, GroupProvider, Group, KeyStore, TrustStore, AccessControlProvider, ready) { var controller = {}; var constructors = { broker: Broker, virtualhost: VirtualHost, exchange: Exchange, queue: Queue, connection: Connection, authenticationprovider: AuthProvider, groupprovider: GroupProvider, - group: Group, keystore: KeyStore, truststore: TrustStore }; + group: Group, keystore: KeyStore, truststore: TrustStore, + accesscontrolprovider: AccessControlProvider}; var tabDiv = dom.byId("managedViews"); diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/treeView.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/treeView.js index f96fc13a03..7bb52b938f 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/treeView.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/treeView.js @@ -281,6 +281,8 @@ define(["dojo/_base/xhr", controller.show("keystore", details.keystore, {broker: {type:"broker", name:""}}); } else if (details.type == 'truststore') { controller.show("truststore", details.truststore, {broker: {type:"broker", name:""}}); + } else if (details.type == 'accesscontrolprovider') { + controller.show("accesscontrolprovider", details.accesscontrolprovider, {broker: {type:"broker", name:""}}); } }; diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/showAccessControlProvider.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/showAccessControlProvider.html new file mode 100644 index 0000000000..399425a7de --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/showAccessControlProvider.html @@ -0,0 +1,31 @@ + +
+ Name: +
+ Type: +
+
+
+ +
+
+
\ No newline at end of file diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/showBroker.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/showBroker.html index 4acf42da46..15f7faf318 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/showBroker.html +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/showBroker.html @@ -53,18 +53,10 @@
Broker store location:
- -
+
+
+ + +
+
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/AccessControlProviderRecoverer.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/AccessControlProviderRecoverer.java new file mode 100644 index 0000000000..df80b9fe5f --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/AccessControlProviderRecoverer.java @@ -0,0 +1,54 @@ +/* + * + * 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.configuration.startup; + +import java.util.Map; + +import org.apache.qpid.server.configuration.ConfigurationEntry; +import org.apache.qpid.server.configuration.ConfiguredObjectRecoverer; +import org.apache.qpid.server.configuration.RecovererProvider; +import org.apache.qpid.server.model.AccessControlProvider; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.adapter.AccessControlProviderFactory; + +public class AccessControlProviderRecoverer implements ConfiguredObjectRecoverer +{ + private final AccessControlProviderFactory _accessControlProviderFactory; + + public AccessControlProviderRecoverer(AccessControlProviderFactory authenticationProviderFactory) + { + _accessControlProviderFactory = authenticationProviderFactory; + } + + @Override + public AccessControlProvider create(RecovererProvider recovererProvider, ConfigurationEntry configurationEntry, ConfiguredObject... parents) + { + Broker broker = RecovererHelper.verifyOnlyBrokerIsParent(parents); + Map attributes = configurationEntry.getAttributes(); + AccessControlProvider authenticationProvider = _accessControlProviderFactory.recover( + configurationEntry.getId(), + broker, + attributes); + + return authenticationProvider; + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/AuthenticationProviderRecoverer.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/AuthenticationProviderRecoverer.java index 3290c827c9..81aff002d1 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/AuthenticationProviderRecoverer.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/AuthenticationProviderRecoverer.java @@ -51,5 +51,4 @@ public class AuthenticationProviderRecoverer implements ConfiguredObjectRecovere return authenticationProvider; } - } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/BrokerRecoverer.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/BrokerRecoverer.java index 9f6bda67df..35c96bc993 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/BrokerRecoverer.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/BrokerRecoverer.java @@ -40,6 +40,7 @@ import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.ConfiguredObject; import org.apache.qpid.server.model.KeyStore; import org.apache.qpid.server.model.TrustStore; +import org.apache.qpid.server.model.adapter.AccessControlProviderFactory; import org.apache.qpid.server.model.adapter.AuthenticationProviderFactory; import org.apache.qpid.server.model.adapter.BrokerAdapter; import org.apache.qpid.server.model.adapter.GroupProviderFactory; @@ -54,18 +55,20 @@ public class BrokerRecoverer implements ConfiguredObjectRecoverer private final LogRecorder _logRecorder; private final RootMessageLogger _rootMessageLogger; private final AuthenticationProviderFactory _authenticationProviderFactory; + private final AccessControlProviderFactory _accessControlProviderFactory; private final PortFactory _portFactory; private final TaskExecutor _taskExecutor; private final BrokerOptions _brokerOptions; private final GroupProviderFactory _groupProviderFactory; public BrokerRecoverer(AuthenticationProviderFactory authenticationProviderFactory, GroupProviderFactory groupProviderFactory, - PortFactory portFactory, StatisticsGatherer statisticsGatherer, VirtualHostRegistry virtualHostRegistry, - LogRecorder logRecorder, RootMessageLogger rootMessageLogger, TaskExecutor taskExecutor, BrokerOptions brokerOptions) + AccessControlProviderFactory accessControlProviderFactory, PortFactory portFactory, StatisticsGatherer statisticsGatherer, + VirtualHostRegistry virtualHostRegistry, LogRecorder logRecorder, RootMessageLogger rootMessageLogger, TaskExecutor taskExecutor, BrokerOptions brokerOptions) { _groupProviderFactory = groupProviderFactory; _portFactory = portFactory; _authenticationProviderFactory = authenticationProviderFactory; + _accessControlProviderFactory = accessControlProviderFactory; _statisticsGatherer = statisticsGatherer; _virtualHostRegistry = virtualHostRegistry; _logRecorder = logRecorder; @@ -79,8 +82,8 @@ public class BrokerRecoverer implements ConfiguredObjectRecoverer { StoreConfigurationChangeListener storeChangeListener = new StoreConfigurationChangeListener(entry.getStore()); BrokerAdapter broker = new BrokerAdapter(entry.getId(), entry.getAttributes(), _statisticsGatherer, _virtualHostRegistry, - _logRecorder, _rootMessageLogger, _authenticationProviderFactory, _groupProviderFactory, _portFactory, - _taskExecutor, entry.getStore(), _brokerOptions); + _logRecorder, _rootMessageLogger, _authenticationProviderFactory, _groupProviderFactory, _accessControlProviderFactory, + _portFactory, _taskExecutor, entry.getStore(), _brokerOptions); broker.addChangeListener(storeChangeListener); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/DefaultRecovererProvider.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/DefaultRecovererProvider.java index 89f949d8d8..2de454c34f 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/DefaultRecovererProvider.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/DefaultRecovererProvider.java @@ -25,6 +25,7 @@ import org.apache.qpid.server.configuration.ConfiguredObjectRecoverer; import org.apache.qpid.server.configuration.RecovererProvider; import org.apache.qpid.server.logging.LogRecorder; import org.apache.qpid.server.logging.RootMessageLogger; +import org.apache.qpid.server.model.AccessControlProvider; import org.apache.qpid.server.model.AuthenticationProvider; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.GroupProvider; @@ -33,10 +34,12 @@ import org.apache.qpid.server.model.Plugin; import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.TrustStore; import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.model.adapter.AccessControlProviderFactory; import org.apache.qpid.server.model.adapter.AuthenticationProviderFactory; import org.apache.qpid.server.model.adapter.GroupProviderFactory; import org.apache.qpid.server.model.adapter.PortFactory; import org.apache.qpid.server.configuration.updater.TaskExecutor; +import org.apache.qpid.server.plugin.AccessControlFactory; import org.apache.qpid.server.plugin.AuthenticationManagerFactory; import org.apache.qpid.server.plugin.GroupManagerFactory; import org.apache.qpid.server.plugin.PluginFactory; @@ -52,6 +55,7 @@ public class DefaultRecovererProvider implements RecovererProvider private final LogRecorder _logRecorder; private final RootMessageLogger _rootMessageLogger; private final AuthenticationProviderFactory _authenticationProviderFactory; + private final AccessControlProviderFactory _accessControlProviderFactory; private final PortFactory _portFactory; private final GroupProviderFactory _groupProviderFactory; private final QpidServiceLoader _pluginFactoryServiceLoader; @@ -62,6 +66,7 @@ public class DefaultRecovererProvider implements RecovererProvider LogRecorder logRecorder, RootMessageLogger rootMessageLogger, TaskExecutor taskExecutor, BrokerOptions brokerOptions) { _authenticationProviderFactory = new AuthenticationProviderFactory(new QpidServiceLoader()); + _accessControlProviderFactory = new AccessControlProviderFactory(new QpidServiceLoader()); _groupProviderFactory = new GroupProviderFactory(new QpidServiceLoader()); _portFactory = new PortFactory(); _brokerStatisticsGatherer = brokerStatisticsGatherer; @@ -78,13 +83,17 @@ public class DefaultRecovererProvider implements RecovererProvider { if (Broker.class.getSimpleName().equals(type)) { - return new BrokerRecoverer(_authenticationProviderFactory, _groupProviderFactory, _portFactory, _brokerStatisticsGatherer, _virtualHostRegistry, - _logRecorder, _rootMessageLogger, _taskExecutor, _brokerOptions); + return new BrokerRecoverer(_authenticationProviderFactory, _groupProviderFactory, _accessControlProviderFactory, _portFactory, _brokerStatisticsGatherer, + _virtualHostRegistry, _logRecorder, _rootMessageLogger, _taskExecutor, _brokerOptions); } else if(VirtualHost.class.getSimpleName().equals(type)) { return new VirtualHostRecoverer(_brokerStatisticsGatherer); } + else if(AccessControlProvider.class.getSimpleName().equals(type)) + { + return new AccessControlProviderRecoverer(_accessControlProviderFactory); + } else if(AuthenticationProvider.class.getSimpleName().equals(type)) { return new AuthenticationProviderRecoverer(_authenticationProviderFactory); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandler.java index 24d5edf00f..abf1537ef7 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandler.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandler.java @@ -12,6 +12,7 @@ import org.apache.qpid.server.BrokerOptions; import org.apache.qpid.server.configuration.ConfigurationEntry; import org.apache.qpid.server.configuration.ConfigurationEntryStore; import org.apache.qpid.server.configuration.IllegalConfigurationException; +import org.apache.qpid.server.model.AccessControlProvider; import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.Protocol; import org.apache.qpid.server.model.State; @@ -25,6 +26,7 @@ public class ManagementModeStoreHandler implements ConfigurationEntryStore private static final String MANAGEMENT_MODE_PORT_PREFIX = "MANAGEMENT-MODE-PORT-"; private static final String PORT_TYPE = Port.class.getSimpleName(); private static final String VIRTUAL_HOST_TYPE = VirtualHost.class.getSimpleName(); + private static final String ACCESS_CONTROL_PROVIDER_TYPE = AccessControlProvider.class.getSimpleName(); private static final String ATTRIBUTE_STATE = VirtualHost.STATE; private static final Object MANAGEMENT_MODE_AUTH_PROVIDER = "mm-auth"; @@ -253,6 +255,10 @@ public class ManagementModeStoreHandler implements ConfigurationEntryStore { quiesce = true; } + else if (ACCESS_CONTROL_PROVIDER_TYPE.equals(entryType)) + { + quiesce = true; + } else if (PORT_TYPE.equalsIgnoreCase(entryType)) { if (attributes == null) diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/AccessControlProvider.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/AccessControlProvider.java new file mode 100644 index 0000000000..d96bef0463 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/AccessControlProvider.java @@ -0,0 +1,56 @@ +/* + * 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.model; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; + +import org.apache.qpid.server.security.AccessControl; + +public interface AccessControlProvider extends ConfiguredObject +{ + public static final String ID = "id"; + public static final String DESCRIPTION = "description"; + public static final String NAME = "name"; + public static final String STATE = "state"; + public static final String DURABLE = "durable"; + public static final String LIFETIME_POLICY = "lifetimePolicy"; + public static final String TIME_TO_LIVE = "timeToLive"; + public static final String CREATED = "created"; + public static final String UPDATED = "updated"; + public static final String TYPE = "type"; + + public static final Collection AVAILABLE_ATTRIBUTES = + Collections.unmodifiableList( + Arrays.asList(ID, + NAME, + DESCRIPTION, + STATE, + DURABLE, + LIFETIME_POLICY, + TIME_TO_LIVE, + CREATED, + UPDATED, + TYPE)); + + //retrieve the underlying AccessControl object + AccessControl getAccessControl(); +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Broker.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Broker.java index 2cdc62d2dc..f666eb29f1 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Broker.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Broker.java @@ -21,11 +21,9 @@ package org.apache.qpid.server.model; import java.net.SocketAddress; -import java.security.AccessControlException; import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.Map; import org.apache.qpid.server.logging.LogRecorder; import org.apache.qpid.server.logging.RootMessageLogger; @@ -81,12 +79,6 @@ public interface Broker extends ConfiguredObject String VIRTUALHOST_STORE_TRANSACTION_OPEN_TIMEOUT_CLOSE = "virtualhost.storeTransactionOpenTimeoutClose"; String VIRTUALHOST_STORE_TRANSACTION_OPEN_TIMEOUT_WARN = "virtualhost.storeTransactionOpenTimeoutWarn"; - /* - * A temporary attribute to pass the path to ACL file. - * TODO: It should be a part of AuthorizationProvider. - */ - String ACL_FILE = "aclFile"; - // Attributes Collection AVAILABLE_ATTRIBUTES = Collections.unmodifiableList( @@ -129,8 +121,7 @@ public interface Broker extends ConfiguredObject VIRTUALHOST_STORE_TRANSACTION_IDLE_TIMEOUT_CLOSE, VIRTUALHOST_STORE_TRANSACTION_IDLE_TIMEOUT_WARN, VIRTUALHOST_STORE_TRANSACTION_OPEN_TIMEOUT_CLOSE, - VIRTUALHOST_STORE_TRANSACTION_OPEN_TIMEOUT_WARN, - ACL_FILE + VIRTUALHOST_STORE_TRANSACTION_OPEN_TIMEOUT_WARN )); //children @@ -140,9 +131,7 @@ public interface Broker extends ConfiguredObject Collection getAuthenticationProviders(); - VirtualHost createVirtualHost(String name, State initialState, boolean durable, - LifetimePolicy lifetime, long ttl, Map attributes) - throws AccessControlException, IllegalArgumentException; + Collection getAccessControlProviders(); Collection getGroupProviders(); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Model.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Model.java index bf4c40815a..bccb6b48ee 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Model.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Model.java @@ -52,6 +52,7 @@ public class Model { addRelationship(Broker.class, VirtualHost.class); addRelationship(Broker.class, Port.class); + addRelationship(Broker.class, AccessControlProvider.class); addRelationship(Broker.class, AuthenticationProvider.class); addRelationship(Broker.class, GroupProvider.class); addRelationship(Broker.class, TrustStore.class); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AccessControlProviderAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AccessControlProviderAdapter.java new file mode 100644 index 0000000000..75b80eb56c --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AccessControlProviderAdapter.java @@ -0,0 +1,283 @@ +/* + * + * 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.model.adapter; + +import java.security.AccessControlException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicReference; + +import org.apache.qpid.server.model.AccessControlProvider; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.IllegalStateTransitionException; +import org.apache.qpid.server.model.LifetimePolicy; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.Statistics; +import org.apache.qpid.server.plugin.AccessControlFactory; +import org.apache.qpid.server.security.AccessControl; +import org.apache.qpid.server.security.access.Operation; +import org.apache.qpid.server.util.MapValueConverter; + +public class AccessControlProviderAdapter extends AbstractAdapter implements AccessControlProvider +{ + protected AccessControl _accessControl; + protected final Broker _broker; + + protected Collection _supportedAttributes; + protected Map _factories; + private AtomicReference _state; + + public AccessControlProviderAdapter(UUID id, Broker broker, AccessControl accessControl, Map attributes, Collection attributeNames) + { + super(id, null, null, broker.getTaskExecutor()); + + if (accessControl == null) + { + throw new IllegalArgumentException("AccessControl must not be null"); + } + + _accessControl = accessControl; + _broker = broker; + _supportedAttributes = createSupportedAttributes(attributeNames); + addParent(Broker.class, broker); + + State state = MapValueConverter.getEnumAttribute(State.class, STATE, attributes, State.INITIALISING); + _state = new AtomicReference(state); + + // set attributes now after all attribute names are known + if (attributes != null) + { + for (String name : _supportedAttributes) + { + if (attributes.containsKey(name)) + { + changeAttribute(name, null, attributes.get(name)); + } + } + } + } + + protected Collection createSupportedAttributes(Collection factoryAttributes) + { + List attributesNames = new ArrayList(AVAILABLE_ATTRIBUTES); + if (factoryAttributes != null) + { + attributesNames.addAll(factoryAttributes); + } + + return Collections.unmodifiableCollection(attributesNames); + } + + @Override + public String getName() + { + return (String)getAttribute(AccessControlProvider.NAME); + } + + @Override + public String setName(String currentName, String desiredName) throws IllegalStateException, AccessControlException + { + return null; + } + + @Override + public State getActualState() + { + return _state.get(); + } + + @Override + public boolean isDurable() + { + return true; + } + + @Override + public void setDurable(boolean durable) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + } + + @Override + public LifetimePolicy getLifetimePolicy() + { + return LifetimePolicy.PERMANENT; + } + + @Override + public LifetimePolicy setLifetimePolicy(LifetimePolicy expected, LifetimePolicy desired) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + return null; + } + + @Override + public long getTimeToLive() + { + return 0; + } + + @Override + public long setTimeToLive(long expected, long desired) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + return 0; + } + + @Override + public Statistics getStatistics() + { + return NoStatistics.getInstance(); + } + + @Override + public Collection getAttributeNames() + { + return _supportedAttributes; + } + + @Override + public Object getAttribute(String name) + { + if(CREATED.equals(name)) + { + // TODO + } + else if(DURABLE.equals(name)) + { + return true; + } + else if(ID.equals(name)) + { + return getId(); + } + else if(LIFETIME_POLICY.equals(name)) + { + return LifetimePolicy.PERMANENT; + } + else if(STATE.equals(name)) + { + return getActualState(); + } + else if(TIME_TO_LIVE.equals(name)) + { + // TODO + } + else if(UPDATED.equals(name)) + { + // TODO + } + return super.getAttribute(name); + } + + @Override + public Collection getChildren(Class clazz) + { + return Collections.emptySet(); + } + + @Override + public boolean setState(State currentState, State desiredState) + throws IllegalStateTransitionException, AccessControlException + { + State state = _state.get(); + + if(desiredState == State.DELETED) + { + return _state.compareAndSet(state, State.DELETED); + } + else if (desiredState == State.QUIESCED) + { + return _state.compareAndSet(state, State.QUIESCED); + } + else if(desiredState == State.ACTIVE) + { + if ((state == State.INITIALISING || state == State.QUIESCED) && _state.compareAndSet(state, State.ACTIVE)) + { + _accessControl.open(); + return true; + } + else + { + throw new IllegalStateException("Can't activate access control provider in " + state + " state"); + } + } + else if(desiredState == State.STOPPED) + { + if(_state.compareAndSet(state, State.STOPPED)) + { + _accessControl.close(); + return true; + } + + return false; + } + + return false; + } + + + @Override + protected void changeAttributes(Map attributes) + { + throw new UnsupportedOperationException("Changing attributes on AccessControlProvider is not supported"); + } + + @Override + protected void authoriseSetDesiredState(State currentState, State desiredState) throws AccessControlException + { + if(desiredState == State.DELETED) + { + if (!_broker.getSecurityManager().authoriseConfiguringBroker(getName(), AccessControlProvider.class, Operation.DELETE)) + { + throw new AccessControlException("Deletion of AccessControlProvider is denied"); + } + } + } + + @Override + protected void authoriseSetAttribute(String name, Object expected, Object desired) throws AccessControlException + { + if (!_broker.getSecurityManager().authoriseConfiguringBroker(getName(), AccessControlProvider.class, Operation.UPDATE)) + { + throw new AccessControlException("Setting of AccessControlProvider attributes is denied"); + } + } + + @Override + protected void authoriseSetAttributes(Map attributes) throws AccessControlException + { + if (!_broker.getSecurityManager().authoriseConfiguringBroker(getName(), AccessControlProvider.class, Operation.UPDATE)) + { + throw new AccessControlException("Setting of AccessControlProvider attributes is denied"); + } + } + + public AccessControl getAccessControl() + { + return _accessControl; + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AccessControlProviderFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AccessControlProviderFactory.java new file mode 100644 index 0000000000..6cdf2f2c1a --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AccessControlProviderFactory.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.model.adapter; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import org.apache.qpid.server.model.AccessControlProvider; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.plugin.AccessControlFactory; +import org.apache.qpid.server.plugin.QpidServiceLoader; +import org.apache.qpid.server.security.AccessControl; + +public class AccessControlProviderFactory +{ + private final Iterable _factories; + private Collection _supportedAcessControlProviders; + + public AccessControlProviderFactory(QpidServiceLoader accessControlFactoryServiceLoader) + { + _factories = accessControlFactoryServiceLoader.instancesOf(AccessControlFactory.class); + List supportedAccessControlProviders = new ArrayList(); + for (AccessControlFactory factory : _factories) + { + supportedAccessControlProviders.add(factory.getType()); + } + _supportedAcessControlProviders = Collections.unmodifiableCollection(supportedAccessControlProviders); + } + + /** + * Creates {@link AccessControlProvider} for given ID, {@link Broker} and attributes. + *

+ * The configured {@link AccessControlFactory}'s are used to try to create the {@link AccessControlProvider}. + * The first non-null instance is returned. The factories are used in non-deterministic order. + */ + public AccessControlProvider create(UUID id, Broker broker, Map attributes) + { + AccessControlProvider ac = createAccessControlProvider(id, broker, attributes); + ac.getAccessControl().onCreate(); + + return ac; + } + + public AccessControlProvider recover(UUID id, Broker broker, Map attributes) + { + return createAccessControlProvider(id, broker, attributes); + } + + private AccessControlProvider createAccessControlProvider(UUID id, + Broker broker, Map attributes) + { + for (AccessControlFactory factory : _factories) + { + AccessControl accessControl = factory.createInstance(attributes); + if (accessControl != null) + { + return new AccessControlProviderAdapter(id, broker,accessControl, attributes, factory.getAttributeNames()); + } + } + + throw new IllegalArgumentException("No access control provider factory found for configuration attributes " + attributes); + } + + public Collection getSupportedAuthenticationProviders() + { + return _supportedAcessControlProviders; + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java index b0e57d339a..c715f1989c 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java @@ -43,6 +43,7 @@ import org.apache.qpid.server.logging.RootMessageLogger; import org.apache.qpid.server.logging.actors.BrokerActor; import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.messages.BrokerMessages; +import org.apache.qpid.server.model.AccessControlProvider; import org.apache.qpid.server.model.AuthenticationProvider; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.ConfigurationChangeListener; @@ -92,7 +93,6 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat put(CONNECTION_HEART_BEAT_DELAY, Integer.class); put(STATISTICS_REPORTING_PERIOD, Integer.class); - put(ACL_FILE, String.class); put(NAME, String.class); put(DEFAULT_VIRTUAL_HOST, String.class); @@ -166,9 +166,11 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat private final Map _plugins = new HashMap(); private final Map _keyStores = new HashMap(); private final Map _trustStores = new HashMap(); + private final Map _accessControlProviders = new HashMap(); private final GroupProviderFactory _groupProviderFactory; private final AuthenticationProviderFactory _authenticationProviderFactory; + private final AccessControlProviderFactory _accessControlProviderFactory; private final PortFactory _portFactory; private final SecurityManager _securityManager; @@ -182,8 +184,8 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat public BrokerAdapter(UUID id, Map attributes, StatisticsGatherer statisticsGatherer, VirtualHostRegistry virtualHostRegistry, LogRecorder logRecorder, RootMessageLogger rootMessageLogger, AuthenticationProviderFactory authenticationProviderFactory, - GroupProviderFactory groupProviderFactory, PortFactory portFactory, TaskExecutor taskExecutor, ConfigurationEntryStore brokerStore, - BrokerOptions brokerOptions) + GroupProviderFactory groupProviderFactory, AccessControlProviderFactory accessControlProviderFactory, PortFactory portFactory, TaskExecutor taskExecutor, + ConfigurationEntryStore brokerStore, BrokerOptions brokerOptions) { super(id, DEFAULTS, MapValueConverter.convert(attributes, ATTRIBUTE_TYPES), taskExecutor); _statisticsGatherer = statisticsGatherer; @@ -193,13 +195,13 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat _statistics = new StatisticsAdapter(statisticsGatherer); _authenticationProviderFactory = authenticationProviderFactory; _groupProviderFactory = groupProviderFactory; + _accessControlProviderFactory = accessControlProviderFactory; _portFactory = portFactory; - _securityManager = new SecurityManager((String)getAttribute(ACL_FILE)); - addChangeListener(_securityManager); + _brokerOptions = brokerOptions; + _securityManager = new SecurityManager(this, _brokerOptions.isManagementMode()); _supportedVirtualHostStoreTypes = new MessageStoreCreator().getStoreTypes(); _supportedBrokerStoreTypes = new BrokerConfigurationStoreCreator().getStoreTypes(); _brokerStore = brokerStore; - _brokerOptions = brokerOptions; if (_brokerOptions.isManagementMode()) { AuthenticationManager authManager = new SimpleAuthenticationManager(BrokerOptions.MANAGEMENT_MODE_USER_NAME, _brokerOptions.getManagementModePassword()); @@ -278,17 +280,6 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat } } - public VirtualHost createVirtualHost(final String name, - final State initialState, - final boolean durable, - final LifetimePolicy lifetime, - final long ttl, - final Map attributes) - throws AccessControlException, IllegalArgumentException - { - return null; //TODO - } - private VirtualHost createVirtualHost(final Map attributes) throws AccessControlException, IllegalArgumentException { @@ -388,6 +379,10 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat { return (Collection) getPorts(); } + else if(clazz == AccessControlProvider.class) + { + return (Collection) getAccessControlProviders(); + } else if(clazz == AuthenticationProvider.class) { return (Collection) getAuthenticationProviders(); @@ -424,6 +419,10 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat { return (C) createPort(attributes); } + else if(childClass == AccessControlProvider.class) + { + return (C) createAccessControlProvider(attributes); + } else if(childClass == AuthenticationProvider.class) { return (C) createAuthenticationProvider(attributes); @@ -477,6 +476,64 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat return port; } + private AccessControlProvider createAccessControlProvider(Map attributes) + { + AccessControlProvider accessControlProvider = null; + synchronized (_accessControlProviders) + { + accessControlProvider = _accessControlProviderFactory.create(UUID.randomUUID(), this, attributes); + addAccessControlProvider(accessControlProvider); + } + + boolean quiesce = isManagementMode() ; + accessControlProvider.setDesiredState(State.INITIALISING, quiesce ? State.QUIESCED : State.ACTIVE); + + return accessControlProvider; + } + + /** + * @throws IllegalConfigurationException if an AuthenticationProvider with the same name already exists + */ + private void addAccessControlProvider(AccessControlProvider accessControlProvider) + { + String name = accessControlProvider.getName(); + synchronized (_authenticationProviders) + { + if (_accessControlProviders.containsKey(accessControlProvider.getId())) + { + throw new IllegalConfigurationException("Can't add AccessControlProvider because one with id " + accessControlProvider.getId() + " already exists"); + } + for (AccessControlProvider provider : _accessControlProviders.values()) + { + if (provider.getName().equals(name)) + { + throw new IllegalConfigurationException("Can't add AccessControlProvider because one with name " + name + " already exists"); + } + } + _accessControlProviders.put(accessControlProvider.getId(), accessControlProvider); + } + + accessControlProvider.addChangeListener(this); + accessControlProvider.addChangeListener(_securityManager); + } + + private boolean deleteAccessControlProvider(AccessControlProvider accessControlProvider) + { + AccessControlProvider removedAccessControlProvider = null; + synchronized (_accessControlProviders) + { + removedAccessControlProvider = _accessControlProviders.remove(accessControlProvider.getId()); + } + + if(removedAccessControlProvider != null) + { + removedAccessControlProvider.removeChangeListener(this); + removedAccessControlProvider.removeChangeListener(_securityManager); + } + + return removedAccessControlProvider != null; + } + private AuthenticationProvider createAuthenticationProvider(Map attributes) { AuthenticationProvider authenticationProvider = null; @@ -771,6 +828,7 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat { changeState(_groupProviders, currentState, State.ACTIVE, false); changeState(_authenticationProviders, currentState, State.ACTIVE, false); + changeState(_accessControlProviders, currentState, State.ACTIVE, false); CurrentActor.set(new BrokerActor(getRootMessageLogger())); try @@ -847,6 +905,10 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat { childDeleted = deleteAuthenticationProvider((AuthenticationProvider)object); } + else if(object instanceof AccessControlProvider) + { + childDeleted = deleteAccessControlProvider((AccessControlProvider)object); + } else if(object instanceof Port) { childDeleted = deletePort((Port)object); @@ -921,6 +983,10 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat { addAuthenticationProvider((AuthenticationProvider)object); } + else if(object instanceof AccessControlProvider) + { + addAccessControlProvider((AccessControlProvider)object); + } else if(object instanceof Port) { addPort((Port)object); @@ -1051,13 +1117,6 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat private void validateAttributes(Map convertedAttributes) { - String aclFile = (String) convertedAttributes.get(ACL_FILE); - if (aclFile != null) - { - // create a security manager to validate the ACL specified in file - new SecurityManager(aclFile); - } - String defaultVirtualHost = (String) convertedAttributes.get(DEFAULT_VIRTUAL_HOST); if (defaultVirtualHost != null) { @@ -1129,4 +1188,13 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat { return _brokerOptions.isManagementMode(); } + + @Override + public Collection getAccessControlProviders() + { + synchronized (_accessControlProviders) + { + return new ArrayList(_accessControlProviders.values()); + } + } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/plugin/AccessControlFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/plugin/AccessControlFactory.java index 7708b90efc..0694032db2 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/plugin/AccessControlFactory.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/plugin/AccessControlFactory.java @@ -18,11 +18,34 @@ */ package org.apache.qpid.server.plugin; +import java.util.Collection; import java.util.Map; +import org.apache.qpid.server.model.AccessControlProvider; import org.apache.qpid.server.security.AccessControl; public interface AccessControlFactory { + public static final String ATTRIBUTE_TYPE = AccessControlProvider.TYPE; + AccessControl createInstance(Map attributes); + + /** + * Returns the access control provider type + * @return authentication provider type + */ + String getType(); + + /** + * Get the names of attributes of the access control which can be passed into + * {@link #createInstance(Map)} to create the group manager + * + * @return the collection of attribute names + */ + Collection getAttributeNames(); + + /** + * @return returns human readable descriptions for the attributes + */ + Map getAttributeDescriptions(); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/AccessControl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/AccessControl.java index b4831f83e5..61e928a38c 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/AccessControl.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/AccessControl.java @@ -42,4 +42,25 @@ public interface AccessControl * Authorise an operation on an object defined by a set of properties. */ Result authorise(Operation operation, ObjectType objectType, ObjectProperties properties); + + /** + * Called to open any resources required by the implementation. + */ + void open(); + + /** + * Called to close any resources required by the implementation. + */ + void close(); + + /** + * Called when deleting to allow clearing any resources used by the implementation. + */ + void onDelete(); + + /** + * Called when first creating (but not when recovering after startup) to allow + * creating any resources required by the implementation. + */ + void onCreate(); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/SecurityManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/SecurityManager.java index 3fb3f70f2e..375b731d85 100755 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/SecurityManager.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/SecurityManager.java @@ -23,6 +23,7 @@ import org.apache.log4j.Logger; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.exchange.Exchange; +import org.apache.qpid.server.model.AccessControlProvider; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.ConfigurationChangeListener; import org.apache.qpid.server.model.ConfiguredObject; @@ -30,6 +31,7 @@ import org.apache.qpid.server.model.State; import org.apache.qpid.server.plugin.AccessControlFactory; import org.apache.qpid.server.plugin.QpidServiceLoader; import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.security.access.FileAccessControlProviderConstants; import org.apache.qpid.server.security.access.ObjectProperties; import org.apache.qpid.server.security.access.ObjectType; import org.apache.qpid.server.security.access.Operation; @@ -53,22 +55,13 @@ import static org.apache.qpid.server.security.access.Operation.UNBIND; import javax.security.auth.Subject; import java.net.SocketAddress; -import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; -/** - * The security manager contains references to all loaded {@link AccessControl}s and delegates security decisions to them based - * on virtual host name. The plugins can be external OSGi .jar files that export the required classes or just internal - * objects for simpler plugins. - * - * @see AccessControl - */ public class SecurityManager implements ConfigurationChangeListener { private static final Logger _logger = Logger.getLogger(SecurityManager.class); @@ -78,9 +71,12 @@ public class SecurityManager implements ConfigurationChangeListener public static final ThreadLocal _accessChecksDisabled = new ClearingThreadLocal(false); - private Map _globalPlugins = new ConcurrentHashMap(); - private Map _hostPlugins = new ConcurrentHashMap(); - private Map> _aclConfigurationToPluginNamesMapping = new ConcurrentHashMap>(); + private ConcurrentHashMap _globalPlugins = new ConcurrentHashMap(); + private ConcurrentHashMap _hostPlugins = new ConcurrentHashMap(); + + private boolean _managementMode; + + private Broker _broker; /** * A special ThreadLocal, which calls remove() on itself whenever the value is @@ -128,34 +124,53 @@ public class SecurityManager implements ConfigurationChangeListener } /* - * Used by the VirtualHost to allow deferring to the broker level security plugins if required. + * Used by the Broker. */ - public SecurityManager(SecurityManager parent, String aclFile) + public SecurityManager(Broker broker, boolean managementMode) { - this(aclFile); - - // our global plugins are the parent's host plugins - _globalPlugins = parent._hostPlugins; + _managementMode = managementMode; + _broker = broker; } - public SecurityManager(String aclFile) + /* + * Used by the VirtualHost to allow deferring to the broker level security plugins if required. + */ + public SecurityManager(SecurityManager parent, String aclFile, String vhostName) { - configureACLPlugin(aclFile); + if(!_managementMode) + { + configureVirtualHostAclPlugin(aclFile, vhostName); + + // our global plugins are the parent's host plugins + _globalPlugins = parent._hostPlugins; + } } - private void configureACLPlugin(String aclFile) + private void configureVirtualHostAclPlugin(String aclFile, String vhostName) { - Map attributes = new HashMap(); - attributes.put("aclFile", aclFile); - - for (AccessControlFactory provider : (new QpidServiceLoader()).instancesOf(AccessControlFactory.class)) + if(aclFile != null) { - AccessControl accessControl = provider.createInstance(attributes); - if(accessControl != null) - { - addHostPlugin(accessControl); + Map attributes = new HashMap(); - mapAclConfigurationToPluginName(aclFile, accessControl.getClass().getName()); + attributes.put(AccessControlProvider.TYPE, FileAccessControlProviderConstants.ACL_FILE_PROVIDER_TYPE); + attributes.put(FileAccessControlProviderConstants.PATH, aclFile); + + for (AccessControlFactory provider : (new QpidServiceLoader()).instancesOf(AccessControlFactory.class)) + { + AccessControl accessControl = provider.createInstance(attributes); + accessControl.open(); + if(accessControl != null) + { + String pluginTypeName = getPluginTypeName(accessControl); + _hostPlugins.put(pluginTypeName, accessControl); + + if(_logger.isDebugEnabled()) + { + _logger.debug("Added access control to host plugins with name: " + vhostName); + } + + break; + } } } @@ -165,15 +180,9 @@ public class SecurityManager implements ConfigurationChangeListener } } - private void mapAclConfigurationToPluginName(String aclFile, String pluginName) + private String getPluginTypeName(AccessControl accessControl) { - List pluginNames = _aclConfigurationToPluginNamesMapping.get(aclFile); - if (pluginNames == null) - { - pluginNames = new ArrayList(); - _aclConfigurationToPluginNamesMapping.put(aclFile, pluginNames); - } - pluginNames.add(pluginName); + return accessControl.getClass().getName(); } public static Subject getThreadSubject() @@ -191,15 +200,6 @@ public class SecurityManager implements ConfigurationChangeListener return _logger; } - private static class CachedPropertiesMap extends LinkedHashMap - { - @Override - protected boolean removeEldestEntry(Entry eldest) - { - return size() >= 200; - } - } - private abstract class AccessCheck { abstract Result allowed(AccessControl plugin); @@ -500,16 +500,72 @@ public class SecurityManager implements ConfigurationChangeListener } } - - public void addHostPlugin(AccessControl plugin) - { - _hostPlugins.put(plugin.getClass().getName(), plugin); - } - @Override public void stateChanged(ConfiguredObject object, State oldState, State newState) { - // no op + if(_managementMode) + { + //AccessControl is disabled in ManagementMode + return; + } + + if(object instanceof AccessControlProvider) + { + if(newState == State.ACTIVE) + { + synchronized (_hostPlugins) + { + AccessControl accessControl = ((AccessControlProvider)object).getAccessControl(); + String pluginTypeName = getPluginTypeName(accessControl); + + _hostPlugins.put(pluginTypeName, accessControl); + } + } + else if(newState == State.DELETED) + { + synchronized (_hostPlugins) + { + AccessControl control = ((AccessControlProvider)object).getAccessControl(); + String pluginTypeName = getPluginTypeName(control); + + // Remove the type->control mapping for this type key only if the + // given control is actually referred to. + if(_hostPlugins.containsValue(control)) + { + // If we are removing this control, check if another of the same + // type already exists on the broker and use it in instead. + AccessControl other = null; + Collection providers = _broker.getAccessControlProviders(); + for(AccessControlProvider p : providers) + { + if(p == object || p.getActualState() != State.ACTIVE) + { + //we don't count ourself as another + continue; + } + + AccessControl ac = p.getAccessControl(); + if(pluginTypeName.equals(getPluginTypeName(ac))) + { + other = ac; + break; + } + } + + if(other != null) + { + //Another control of this type was found, use it instead + _hostPlugins.replace(pluginTypeName, control, other); + } + else + { + //No other was found, remove the type entirely + _hostPlugins.remove(pluginTypeName); + } + } + } + } + } } @Override @@ -527,29 +583,7 @@ public class SecurityManager implements ConfigurationChangeListener @Override public void attributeSet(ConfiguredObject object, String attributeName, Object oldAttributeValue, Object newAttributeValue) { - if (object instanceof Broker && Broker.ACL_FILE.equals(attributeName)) - { - // the code below is not thread safe, however, it should be fine in a management mode - // as there will be no user connected - - if (oldAttributeValue != null) - { - List pluginNames = _aclConfigurationToPluginNamesMapping.remove(oldAttributeValue); - if (pluginNames != null) - { - for (String name : pluginNames) - { - _hostPlugins.remove(name); - } - } - } - if (newAttributeValue != null) - { - configureACLPlugin((String)newAttributeValue); - } - _immediatePublishPropsCache.clear(); - _publishPropsCache.clear(); - } + // no op } public boolean authoriseConfiguringBroker(String configuredObjectName, Class configuredObjectType, Operation configuredObjectOperation) diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/FileAccessControlProviderConstants.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/FileAccessControlProviderConstants.java new file mode 100644 index 0000000000..3a98a947df --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/FileAccessControlProviderConstants.java @@ -0,0 +1,27 @@ +/* + * + * 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 FileAccessControlProviderConstants +{ + public static final String ACL_FILE_PROVIDER_TYPE = "AclFile"; + public static final String PATH = "path"; +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java index 8e72afad22..2eab47802a 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java @@ -131,7 +131,7 @@ public class VirtualHostImpl implements VirtualHost, IConnectionRegistry.Registr CurrentActor.get().message(VirtualHostMessages.CREATED(_name)); - _securityManager = new SecurityManager(parentSecurityManager, _vhostConfig.getConfig().getString("security.acl")); + _securityManager = new SecurityManager(parentSecurityManager, _vhostConfig.getConfig().getString("security.acl"), _name); _connectionRegistry = new ConnectionRegistry(); _connectionRegistry.addRegistryChangeListener(this); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/BrokerRecovererTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/BrokerRecovererTest.java index 5c3f062cae..64b432f471 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/BrokerRecovererTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/BrokerRecovererTest.java @@ -48,6 +48,7 @@ import org.apache.qpid.server.model.Plugin; import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.TrustStore; import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.model.adapter.AccessControlProviderFactory; import org.apache.qpid.server.model.adapter.AuthenticationProviderFactory; import org.apache.qpid.server.model.adapter.GroupProviderFactory; import org.apache.qpid.server.model.adapter.PortFactory; @@ -71,8 +72,8 @@ public class BrokerRecovererTest extends TestCase { super.setUp(); - _brokerRecoverer = new BrokerRecoverer(mock(AuthenticationProviderFactory.class), mock(GroupProviderFactory.class), mock(PortFactory.class), mock(StatisticsGatherer.class), - mock(VirtualHostRegistry.class), mock(LogRecorder.class), mock(RootMessageLogger.class), mock(TaskExecutor.class), mock(BrokerOptions.class)); + _brokerRecoverer = new BrokerRecoverer(mock(AuthenticationProviderFactory.class), mock(GroupProviderFactory.class), mock(AccessControlProviderFactory.class), mock(PortFactory.class), + mock(StatisticsGatherer.class), mock(VirtualHostRegistry.class), mock(LogRecorder.class), mock(RootMessageLogger.class), mock(TaskExecutor.class), mock(BrokerOptions.class)); when(_brokerEntry.getId()).thenReturn(_brokerId); when(_brokerEntry.getChildren()).thenReturn(_brokerEntryChildren); @@ -98,7 +99,6 @@ public class BrokerRecovererTest extends TestCase attributes.put(Broker.QUEUE_MAXIMUM_DELIVERY_ATTEMPTS, 2); attributes.put(Broker.QUEUE_DEAD_LETTER_QUEUE_ENABLED, true); attributes.put(Broker.VIRTUALHOST_HOUSEKEEPING_CHECK_PERIOD, 1l); - attributes.put(Broker.ACL_FILE, "/path/to/acl"); attributes.put(Broker.CONNECTION_SESSION_COUNT_LIMIT, 1000); attributes.put(Broker.CONNECTION_HEART_BEAT_DELAY, 2000); attributes.put(Broker.STATISTICS_REPORTING_PERIOD, 4000); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/store/ConfigurationEntryStoreTestCase.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/store/ConfigurationEntryStoreTestCase.java index fc21706bc0..d56481340b 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/store/ConfigurationEntryStoreTestCase.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/store/ConfigurationEntryStoreTestCase.java @@ -70,7 +70,6 @@ public abstract class ConfigurationEntryStoreTestCase extends QpidTestCase _brokerAttributes.put(Broker.QUEUE_MAXIMUM_DELIVERY_ATTEMPTS, 2); _brokerAttributes.put(Broker.QUEUE_DEAD_LETTER_QUEUE_ENABLED, true); _brokerAttributes.put(Broker.VIRTUALHOST_HOUSEKEEPING_CHECK_PERIOD, 1); - _brokerAttributes.put(Broker.ACL_FILE, "/path/to/acl"); _brokerAttributes.put(Broker.CONNECTION_SESSION_COUNT_LIMIT, 1000); _brokerAttributes.put(Broker.CONNECTION_HEART_BEAT_DELAY, 2000); _brokerAttributes.put(Broker.STATISTICS_REPORTING_PERIOD, 4000); @@ -180,7 +179,6 @@ public abstract class ConfigurationEntryStoreTestCase extends QpidTestCase attributes.put(Broker.QUEUE_MAXIMUM_DELIVERY_ATTEMPTS, 12); attributes.put(Broker.QUEUE_DEAD_LETTER_QUEUE_ENABLED, false); attributes.put(Broker.VIRTUALHOST_HOUSEKEEPING_CHECK_PERIOD, 11); - attributes.put(Broker.ACL_FILE, "/path/to/acl1"); attributes.put(Broker.CONNECTION_SESSION_COUNT_LIMIT, 11000); attributes.put(Broker.CONNECTION_HEART_BEAT_DELAY, 12000); attributes.put(Broker.STATISTICS_REPORTING_PERIOD, 14000); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/store/JsonConfigurationEntryStoreTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/store/JsonConfigurationEntryStoreTest.java index 1cb760f611..b30508ee0b 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/store/JsonConfigurationEntryStoreTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/store/JsonConfigurationEntryStoreTest.java @@ -72,20 +72,20 @@ public class JsonConfigurationEntryStoreTest extends ConfigurationEntryStoreTest public void testAttributeIsResolvedFromSystemProperties() { - String aclLocation = "path/to/acl/" + getTestName(); - setTestSystemProperty("my.test.property", aclLocation); + String defaultVhost = getTestName(); + setTestSystemProperty("my.test.property", defaultVhost); ConfigurationEntryStore store = getStore(); ConfigurationEntry brokerConfigEntry = store.getRootEntry(); Map attributes = new HashMap(brokerConfigEntry.getAttributes()); - attributes.put(Broker.ACL_FILE, "${my.test.property}"); + attributes.put(Broker.DEFAULT_VIRTUAL_HOST, "${my.test.property}"); ConfigurationEntry updatedBrokerEntry = new ConfigurationEntry(brokerConfigEntry.getId(), Broker.class.getSimpleName(), attributes, brokerConfigEntry.getChildrenIds(), store); store.save(updatedBrokerEntry); JsonConfigurationEntryStore store2 = new JsonConfigurationEntryStore(_storeFile.getAbsolutePath(), null); - assertEquals("Unresolved ACL value", aclLocation, store2.getRootEntry().getAttributes().get(Broker.ACL_FILE)); + assertEquals("Unresolved default virtualhost value", defaultVhost, store2.getRootEntry().getAttributes().get(Broker.DEFAULT_VIRTUAL_HOST)); } public void testCreateEmptyStore() diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java index 3edbc852a0..4d10058d17 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java @@ -77,7 +77,7 @@ public class BrokerTestHelper RootMessageLogger rootMessageLogger = CurrentActor.get().getRootMessageLogger(); when(broker.getRootMessageLogger()).thenReturn(rootMessageLogger); when(broker.getVirtualHostRegistry()).thenReturn(new VirtualHostRegistry()); - when(broker.getSecurityManager()).thenReturn(new SecurityManager(null)); + when(broker.getSecurityManager()).thenReturn(new SecurityManager(mock(Broker.class), false)); GenericActor.setDefaultMessageLogger(rootMessageLogger); return broker; } @@ -96,14 +96,14 @@ public class BrokerTestHelper throws Exception { StatisticsGatherer statisticsGatherer = mock(StatisticsGatherer.class); - VirtualHost host = new VirtualHostImpl(virtualHostRegistry, statisticsGatherer, new SecurityManager(null), virtualHostConfiguration); + VirtualHost host = new VirtualHostImpl(virtualHostRegistry, statisticsGatherer, new SecurityManager(mock(Broker.class), false), virtualHostConfiguration); virtualHostRegistry.registerVirtualHost(host); return host; } public static VirtualHost createVirtualHost(VirtualHostConfiguration virtualHostConfiguration) throws Exception { - return new VirtualHostImpl(null, mock(StatisticsGatherer.class), new SecurityManager(null), virtualHostConfiguration); + return new VirtualHostImpl(null, mock(StatisticsGatherer.class), new SecurityManager(mock(Broker.class), false), virtualHostConfiguration); } public static VirtualHost createVirtualHost(String name, VirtualHostRegistry virtualHostRegistry) throws Exception @@ -156,7 +156,7 @@ public class BrokerTestHelper public static Exchange createExchange(String hostName) throws Exception { - SecurityManager securityManager = new SecurityManager(null); + SecurityManager securityManager = new SecurityManager(mock(Broker.class), false); VirtualHost virtualHost = mock(VirtualHost.class); when(virtualHost.getName()).thenReturn(hostName); when(virtualHost.getSecurityManager()).thenReturn(securityManager); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/virtualhost/VirtualHostImplTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/virtualhost/VirtualHostImplTest.java index 559a7f8aaf..4e58eae1d2 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/virtualhost/VirtualHostImplTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/virtualhost/VirtualHostImplTest.java @@ -211,7 +211,7 @@ public class VirtualHostImplTest extends QpidTestCase _virtualHostRegistry = broker.getVirtualHostRegistry(); VirtualHostConfiguration configuration = new VirtualHostConfiguration(vhostName, config, broker); - VirtualHost host = new VirtualHostImpl(_virtualHostRegistry, mock(StatisticsGatherer.class), new SecurityManager(null), configuration); + VirtualHost host = new VirtualHostImpl(_virtualHostRegistry, mock(StatisticsGatherer.class), new SecurityManager(mock(Broker.class), false), configuration); _virtualHostRegistry.registerVirtualHost(host); return host; @@ -295,7 +295,7 @@ public class VirtualHostImplTest extends QpidTestCase Configuration config = new PropertiesConfiguration(); config.setProperty("store.type", MemoryMessageStore.TYPE); VirtualHostConfiguration configuration = new VirtualHostConfiguration(virtualHostName, config, broker); - VirtualHost host = new VirtualHostImpl(_virtualHostRegistry, mock(StatisticsGatherer.class), new SecurityManager(null), configuration); + VirtualHost host = new VirtualHostImpl(_virtualHostRegistry, mock(StatisticsGatherer.class), new SecurityManager(mock(Broker.class), false), configuration); _virtualHostRegistry.registerVirtualHost(host); return host; } 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 f3bce1874e..7a3edd316f 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 @@ -110,7 +110,7 @@ public abstract class AbstractACLTestCase extends QpidBrokerTestCase implements if (vhost == null) { - testcase.getBrokerConfiguration().setBrokerAttribute(Broker.ACL_FILE, aclFile.getAbsolutePath()); + testcase.getBrokerConfiguration().addAclFileConfiguration(aclFile.getAbsolutePath()); } else { diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestHttpsTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestHttpsTest.java index 8fe342e394..da38b9be33 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestHttpsTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestHttpsTest.java @@ -63,7 +63,6 @@ public class BrokerRestHttpsTest extends QpidRestTestCase Map brokerDetails = getRestTestHelper().getJsonAsSingletonList("/rest/broker"); Asserts.assertAttributesPresent(brokerDetails, Broker.AVAILABLE_ATTRIBUTES, Broker.BYTES_RETAINED, - Broker.PROCESS_PID, Broker.SUPPORTED_VIRTUALHOST_STORE_TYPES, Broker.CREATED, Broker.TIME_TO_LIVE, Broker.UPDATED, - Broker.ACL_FILE); + Broker.PROCESS_PID, Broker.SUPPORTED_VIRTUALHOST_STORE_TYPES, Broker.CREATED, Broker.TIME_TO_LIVE, Broker.UPDATED); } } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestTest.java index 4bca63204d..0d40eca745 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestTest.java @@ -20,7 +20,6 @@ */ package org.apache.qpid.systest.rest; -import java.io.File; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; @@ -46,15 +45,6 @@ public class BrokerRestTest extends QpidRestTestCase private static final String BROKER_VIRTUALHOSTS_ATTRIBUTE = "virtualhosts"; private static final String BROKER_STATISTICS_ATTRIBUTE = "statistics"; - @Override - public void setUp() throws Exception - { - //Some of the tests manipulate the ACL config, which means the groups need to be in place to make the ACL work - getBrokerConfiguration().addGroupFileConfiguration(QpidTestCase.QPID_HOME + File.separator + "etc" + File.separator + "groups"); - - super.setUp(); - } - public void testGet() throws Exception { Map brokerDetails = getRestTestHelper().getJsonAsSingletonList("/rest/broker"); @@ -149,7 +139,6 @@ public class BrokerRestTest extends QpidRestTestCase invalidAttributes.put(Broker.CONNECTION_SESSION_COUNT_LIMIT, -10); invalidAttributes.put(Broker.CONNECTION_HEART_BEAT_DELAY, -11000); invalidAttributes.put(Broker.STATISTICS_REPORTING_PERIOD, -12000); - invalidAttributes.put(Broker.ACL_FILE, QpidTestCase.QPID_HOME + File.separator + "etc" + File.separator + "non-existing-acl.acl"); invalidAttributes.put(Broker.VIRTUALHOST_STORE_TRANSACTION_IDLE_TIMEOUT_CLOSE, -13000); invalidAttributes.put(Broker.VIRTUALHOST_STORE_TRANSACTION_IDLE_TIMEOUT_WARN, -14000); invalidAttributes.put(Broker.VIRTUALHOST_STORE_TRANSACTION_OPEN_TIMEOUT_CLOSE, -15000); @@ -189,7 +178,6 @@ public class BrokerRestTest extends QpidRestTestCase brokerAttributes.put(Broker.CONNECTION_HEART_BEAT_DELAY, 11000); brokerAttributes.put(Broker.STATISTICS_REPORTING_PERIOD, 12000); brokerAttributes.put(Broker.STATISTICS_REPORTING_RESET_ENABLED, true); - brokerAttributes.put(Broker.ACL_FILE, QpidTestCase.QPID_HOME + File.separator + "etc" + File.separator + "broker_example.acl"); brokerAttributes.put(Broker.VIRTUALHOST_STORE_TRANSACTION_IDLE_TIMEOUT_CLOSE, 13000); brokerAttributes.put(Broker.VIRTUALHOST_STORE_TRANSACTION_IDLE_TIMEOUT_WARN, 14000); brokerAttributes.put(Broker.VIRTUALHOST_STORE_TRANSACTION_OPEN_TIMEOUT_CLOSE, 15000); @@ -213,7 +201,7 @@ public class BrokerRestTest extends QpidRestTestCase { Asserts.assertAttributesPresent(brokerDetails, Broker.AVAILABLE_ATTRIBUTES, Broker.BYTES_RETAINED, Broker.PROCESS_PID, - Broker.CREATED, Broker.TIME_TO_LIVE, Broker.UPDATED, Broker.ACL_FILE); + Broker.CREATED, Broker.TIME_TO_LIVE, Broker.UPDATED); assertEquals("Unexpected value of attribute " + Broker.BUILD_VERSION, QpidProperties.getBuildVersion(), brokerDetails.get(Broker.BUILD_VERSION)); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java index f37ba720b7..a91c9bb752 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java @@ -32,6 +32,7 @@ import java.util.UUID; import org.apache.qpid.server.configuration.ConfigurationEntry; import org.apache.qpid.server.configuration.IllegalConfigurationException; import org.apache.qpid.server.configuration.store.MemoryConfigurationEntryStore; +import org.apache.qpid.server.model.AccessControlProvider; import org.apache.qpid.server.model.AuthenticationProvider; import org.apache.qpid.server.model.GroupProvider; import org.apache.qpid.server.model.KeyStore; @@ -40,8 +41,8 @@ import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.TrustStore; import org.apache.qpid.server.model.UUIDGenerator; import org.apache.qpid.server.model.VirtualHost; -import org.apache.qpid.server.plugin.GroupManagerFactory; import org.apache.qpid.server.plugin.PluginFactory; +import org.apache.qpid.server.security.access.FileAccessControlProviderConstants; import org.apache.qpid.server.security.group.FileGroupManagerFactory; public class TestBrokerConfiguration @@ -62,13 +63,13 @@ public class TestBrokerConfiguration public static final String ENTRY_NAME_SSL_KEYSTORE = "systestsKeyStore"; public static final String ENTRY_NAME_SSL_TRUSTSTORE = "systestsTrustStore"; public static final String ENTRY_NAME_GROUP_FILE = "groupFile"; + public static final String ENTRY_NAME_ACL_FILE = "aclFile"; private MemoryConfigurationEntryStore _store; private boolean _saved; public TestBrokerConfiguration(String storeType, String intialStoreLocation) { - // TODO: add support for DERBY store _store = new MemoryConfigurationEntryStore(intialStoreLocation, null); } @@ -140,12 +141,22 @@ public class TestBrokerConfiguration { Map attributes = new HashMap(); attributes.put(GroupProvider.NAME, ENTRY_NAME_GROUP_FILE); - attributes.put(GroupManagerFactory.ATTRIBUTE_TYPE, FileGroupManagerFactory.GROUP_FILE_PROVIDER_TYPE); + attributes.put(GroupProvider.TYPE, FileGroupManagerFactory.GROUP_FILE_PROVIDER_TYPE); attributes.put(FileGroupManagerFactory.PATH, groupFilePath); return addGroupProviderConfiguration(attributes); } + public UUID addAclFileConfiguration(String aclFilePath) + { + Map attributes = new HashMap(); + attributes.put(AccessControlProvider.NAME, ENTRY_NAME_ACL_FILE); + attributes.put(AccessControlProvider.TYPE, FileAccessControlProviderConstants.ACL_FILE_PROVIDER_TYPE); + attributes.put(FileAccessControlProviderConstants.PATH, aclFilePath); + + return addAccessControlConfiguration(attributes); + } + public UUID addPortConfiguration(Map attributes) { String name = (String) attributes.get(Port.NAME); @@ -170,6 +181,12 @@ public class TestBrokerConfiguration return addObjectConfiguration(name, GroupProvider.class.getSimpleName(), attributes); } + public UUID addAccessControlConfiguration(Map attributes) + { + String name = (String) attributes.get(AccessControlProvider.NAME); + return addObjectConfiguration(name, AccessControlProvider.class.getSimpleName(), attributes); + } + public UUID addTrustStoreConfiguration(Map attributes) { String name = (String) attributes.get(TrustStore.NAME); -- cgit v1.2.1