diff options
author | Alex Rudyy <orudyy@apache.org> | 2013-04-19 15:50:21 +0000 |
---|---|---|
committer | Alex Rudyy <orudyy@apache.org> | 2013-04-19 15:50:21 +0000 |
commit | d792f4deff8d3ce6b4672c7156ad56eb4438c01d (patch) | |
tree | 168c7f96f14cd252a237adfd83a7acb968c59715 | |
parent | 31524543f12e083c30d55b72b5ade680ab3f48ae (diff) | |
download | qpid-python-d792f4deff8d3ce6b4672c7156ad56eb4438c01d.tar.gz |
QPID-4752: Make the GroupProvider a full broker-level configuration entry instead of a broker attribute.
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1469916 13f79535-47bb-0310-9956-ffa450edef68
34 files changed, 1256 insertions, 223 deletions
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 a77096fbe8..626dfa1d6c 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 @@ -32,6 +32,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; 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; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.SerializationConfig; @@ -52,6 +53,8 @@ public class HelperServlet extends AbstractServlet _actions.put(listProviderAttributes.getName(), listProviderAttributes); Action listMessageStoreTypes = new ListMessageStoreTypes(); _actions.put(listMessageStoreTypes.getName(), listMessageStoreTypes); + Action groupProviderAttributes = new ListGroupProviderAttributes(); + _actions.put(groupProviderAttributes.getName(), groupProviderAttributes); } @Override diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/action/ListGroupProviderAttributes.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/action/ListGroupProviderAttributes.java new file mode 100644 index 0000000000..d1414faa71 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/action/ListGroupProviderAttributes.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.GroupManagerFactory; +import org.apache.qpid.server.plugin.QpidServiceLoader; + +public class ListGroupProviderAttributes implements Action +{ + private static final String ATTRIBUTES = "attributes"; + private static final String DESCRIPTIONS = "descriptions"; + private Map<String, GroupManagerFactory> _factories; + + public ListGroupProviderAttributes() + { + _factories = new TreeMap<String, GroupManagerFactory>(); + Iterable<GroupManagerFactory> factories = new QpidServiceLoader<GroupManagerFactory>() + .instancesOf(GroupManagerFactory.class); + for (GroupManagerFactory factory : factories) + { + _factories.put(factory.getType(), factory); + } + } + + @Override + public String getName() + { + return ListGroupProviderAttributes.class.getSimpleName(); + } + + @Override + public Object perform(Map<String, Object> request, Broker broker) + { + Map<String, Object> attributes = new TreeMap<String, Object>(); + for (String providerType : _factories.keySet()) + { + GroupManagerFactory factory = _factories.get(providerType); + + Map<String, Object> data = new HashMap<String, Object>(); + data.put(ATTRIBUTES, factory.getAttributeNames()); + Map<String, String> 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/groupprovider/showFileGroupManager.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/groupprovider/showFileGroupManager.html index 734e8b5419..5055cbdc47 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/groupprovider/showFileGroupManager.html +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/groupprovider/showFileGroupManager.html @@ -19,6 +19,8 @@ - --> <div class="FileGroupManager"> + <span style="">Path:</span><span class="path" style="position:absolute; left:6em"></span> + <br/> <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Groups'"> <div class="groups"></div> <button data-dojo-type="dijit.form.Button" class="addGroupButton">Add Group</button> 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 73936b7b3c..e5631745a8 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 @@ -32,6 +32,7 @@ define(["dojo/_base/xhr", "qpid/management/addVirtualHost", "qpid/management/addPort", "qpid/management/addKeystore", + "qpid/management/addGroupProvider", "dojox/grid/enhanced/plugins/Pagination", "dojox/grid/enhanced/plugins/IndirectSelection", "dijit/layout/AccordionContainer", @@ -42,7 +43,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) { + function (xhr, parser, query, connect, properties, updater, util, UpdatableStore, EnhancedGrid, registry, addAuthenticationProvider, addVirtualHost, addPort, addKeystore, addGroupProvider) { function Broker(name, parent, controller) { this.name = name; @@ -88,16 +89,6 @@ define(["dojo/_base/xhr", name: "aclFile"}) } }, { - name: "groupFile", - createWidget: function(brokerData) - { - return new dijit.form.ValidationTextBox({ - required: false, - value: brokerData.groupFile, - label: "Group file location:", - name: "groupFile"}); - } - }, { name: "statisticsReportingPeriod", createWidget: function(brokerData) { return new dijit.form.ValidationTextBox({ @@ -453,6 +444,35 @@ define(["dojo/_base/xhr", "Are you sure you want to delete trust store"); } ); + + var addGroupProviderButton = query(".addGroupProvider", contentPane.containerNode)[0]; + connect.connect(registry.byNode(addGroupProviderButton), "onClick", + function(evt){addGroupProvider.show();}); + + var deleteGroupProvider = query(".deleteGroupProvider", contentPane.containerNode)[0]; + connect.connect(registry.byNode(deleteGroupProvider), "onClick", + function(evt){ + var warning = ""; + var data = that.brokerUpdater.groupProvidersGrid.grid.selection.getSelected(); + if(data.length && data.length > 0) + { + for(var i = 0; i<data.length; i++) + { + if (data[i].type.indexOf("File") != -1) + { + warning = "NOTE: provider deletion will also remove the group file on disk.\n\n" + break; + } + } + } + + util.deleteGridSelections( + that.brokerUpdater, + that.brokerUpdater.groupProvidersGrid.grid, + "rest/groupprovider", + warning + "Are you sure you want to delete group provider"); + } + ); }}); }; @@ -559,7 +579,7 @@ define(["dojo/_base/xhr", that.keyStoresGrid = new UpdatableStore(that.brokerData.keystores, query(".broker-key-stores")[0], [ { name: "Name", field: "name", width: "20%"}, - { name: "Path", field: "path", width: "50%"}, + { name: "Path", field: "path", width: "40%"}, { name: "Type", field: "type", width: "5%"}, { name: "Key Manager Algorithm", field: "keyManagerFactoryAlgorithm", width: "20%"}, { name: "Alias", field: "certificateAlias", width: "15%"} @@ -576,10 +596,10 @@ define(["dojo/_base/xhr", that.trustStoresGrid = new UpdatableStore(that.brokerData.truststores, query(".broker-trust-stores")[0], [ { name: "Name", field: "name", width: "20%"}, - { name: "Path", field: "path", width: "50%"}, + { name: "Path", field: "path", width: "40%"}, { name: "Type", field: "type", width: "5%"}, - { name: "Trust Manager Algorithm", field: "trustManagerFactoryAlgorithm", width: "20%"}, - { name: "Peers only", field: "peersOnly", width: "15%", + { name: "Trust Manager Algorithm", field: "trustManagerFactoryAlgorithm", width: "25%"}, + { name: "Peers only", field: "peersOnly", width: "10%", formatter: function(val){ return "<input type='radio' disabled='disabled' "+(val ? "checked='checked'": "")+" />"; } @@ -593,6 +613,19 @@ define(["dojo/_base/xhr", that.controller.show("truststore", name, brokerObj); }); }, gridProperties, EnhancedGrid); + that.groupProvidersGrid = + new UpdatableStore(that.brokerData.groupproviders, query(".broker-group-providers")[0], + [ { name: "Name", field: "name", width: "50%"}, + { name: "Type", field: "type", width: "50%"} + ], 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("groupprovider", name, brokerObj); + }); + }, gridProperties, EnhancedGrid); }); @@ -688,6 +721,10 @@ define(["dojo/_base/xhr", { that.trustStoresGrid.update(that.brokerData.truststores); } + if (that.groupProvidersGrid) + { + that.groupProvidersGrid.update(that.brokerData.groupproviders); + } }); diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/GroupProvider.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/GroupProvider.js index 4e05f4b0ea..98e01773ef 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/GroupProvider.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/GroupProvider.js @@ -27,10 +27,12 @@ define(["dojo/_base/xhr", "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) { + function (xhr, parser, query, connect, properties, updater, util, UpdatableStore, EnhancedGrid, registry, event) { function GroupProvider(name, parent, controller) { this.name = name; @@ -43,7 +45,7 @@ define(["dojo/_base/xhr", } GroupProvider.prototype.getTitle = function() { - return "GroupProvider"; + return "GroupProvider: " + this.name ; }; GroupProvider.prototype.open = function(contentPane) { @@ -61,6 +63,13 @@ define(["dojo/_base/xhr", that.groupProviderAdapter.update(); + var deleteButton = query(".deleteGroupProviderButton", contentPane.containerNode)[0]; + var deleteWidget = registry.byNode(deleteButton); + connect.connect(deleteWidget, "onClick", + function(evt){ + event.stop(evt); + that.deleteGroupProvider(); + }); }}); }; @@ -68,12 +77,37 @@ define(["dojo/_base/xhr", updater.remove( this.groupProviderAdapter ); }; + GroupProvider.prototype.deleteGroupProvider = function() { + var warnMessage = ""; + if (this.groupProviderAdapter.groupProviderData && this.groupProviderAdapter.groupProviderData.type.indexOf("File") != -1) + { + warnMessage = "NOTE: provider deletion will also remove the group file on disk.\n\n"; + } + if(confirm(warnMessage + "Are you sure you want to delete group provider '" + this.name + "'?")) { + var query = "rest/groupprovider/" +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 GroupProviderUpdater(node, groupProviderObj, controller) { this.controller = controller; this.name = query(".name", node)[0]; + this.type = query(".type", node)[0]; this.query = "rest/groupprovider/"+encodeURIComponent(groupProviderObj.name); - + this.typeUI ={"GroupFile": "FileGroupManager"}; var that = this; xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}) @@ -85,9 +119,10 @@ define(["dojo/_base/xhr", that.updateHeader(); - require(["qpid/management/groupprovider/"+that.groupProviderData.type], + var ui = that.typeUI[that.groupProviderData.type]; + require(["qpid/management/groupprovider/"+ ui], function(SpecificProvider) { - that.details = new SpecificProvider(node, groupProviderObj, controller); + that.details = new SpecificProvider(query(".providerDetails", node)[0], groupProviderObj, controller); that.details.update(); }); @@ -98,6 +133,7 @@ define(["dojo/_base/xhr", GroupProviderUpdater.prototype.updateHeader = function() { this.name.innerHTML = this.groupProviderData[ "name" ]; + this.type.innerHTML = this.groupProviderData[ "type" ]; }; GroupProviderUpdater.prototype.update = function() diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addGroupProvider.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addGroupProvider.js new file mode 100644 index 0000000000..c8cd33fd6a --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addGroupProvider.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 addGroupProvider = {}; + + addGroupProvider.show = function(groupProvider) { + var fields = [{ + name: "name", + createWidget: function(groupProvider) { + return new dijit.form.ValidationTextBox({ + required: true, + value: groupProvider.name, + disabled: groupProvider.name ? true : false, + label: "Name*:", + regexp: "^[\x20-\x2e\x30-\x7F]{1,255}$", + name: "name"}); + } + }, { + name: "type", + createWidget: function(groupProvider) { + + 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=ListGroupProviderAttributes", + 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: groupProvider.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, + groupProvider ? groupProvider : {}, + "rest/groupprovider" + (name ? "/" + encodeURIComponent(name.name) : ""), + groupProvider ? "Edit group provider - " + groupProvider.name : "Add group provider", + groupProvider ? false : true); + }; + return addGroupProvider; + });
\ No newline at end of file diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/groupprovider/FileGroupManager.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/groupprovider/FileGroupManager.js index 44fc9702e2..02276b8713 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/groupprovider/FileGroupManager.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/groupprovider/FileGroupManager.js @@ -82,11 +82,12 @@ define(["dojo/_base/xhr", xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}) .then(function(data) { + that.path = query(".path", node)[0]; that.groupProviderData = data[0]; util.flattenStatistics( that.groupProviderData ); - var groupDiv = query(".groups")[0]; + var groupDiv = query(".groups", node)[0]; var gridProperties = { height: 400, @@ -109,7 +110,15 @@ define(["dojo/_base/xhr", that.groupsGrid = new UpdatableStore(that.groupProviderData.groups, groupDiv, [ { name: "Group Name", field: "name", width: "100%" } - ], null, gridProperties, EnhancedGrid); + ], 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("group", name, groupProviderObj); + }); + }, gridProperties, EnhancedGrid); var addGroupButton = query(".addGroupButton", node)[0]; @@ -167,6 +176,7 @@ define(["dojo/_base/xhr", xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}) .then(function(data) { that.groupProviderData = data[0]; + that.path.innerHTML = that.groupProviderData.path; util.flattenStatistics( that.groupProviderData ); that.groupsGrid.update(that.groupProviderData.groups); 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 9e267f0d5d..4acf42da46 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 @@ -65,10 +65,6 @@ <div class="formLabel-labelCell" style="float:left; width: 250px;">ACL file location:</div> <div id="brokerAttribute.aclFile" style="float:left;"></div> </div> - <div id="brokerAttribute.groupFile.container" style="display: none; clear:both"> - <div class="formLabel-labelCell" style="float:left; width: 250px;">Group file location:</div> - <div id="brokerAttribute.groupFile" style="float:left;"></div> - </div> <div id="brokerAttribute.statisticsReportingPeriod.container" style="display: none; clear:both"> <div class="formLabel-labelCell" style="float:left; width: 250px;">Statistics reporting period:</div> <div id="brokerAttribute.statisticsReportingPeriod" style="float:left;"></div> @@ -189,6 +185,12 @@ <button data-dojo-type="dijit.form.Button" class="deleteTruststore">Delete Trust Store</button> </div> <br/> + <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Group Providers'"> + <div class="broker-group-providers"></div> + <button data-dojo-type="dijit.form.Button" class="addGroupProvider">Add Group Provider</button> + <button data-dojo-type="dijit.form.Button" class="deleteGroupProvider">Delete Group Provider</button> + </div> + <br/> <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Log File', open: false"> <div class="broker-logfile"></div> </div> diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/showGroupProvider.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/showGroupProvider.html index 914857db5c..332c7f5eaa 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/showGroupProvider.html +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/showGroupProvider.html @@ -22,4 +22,10 @@ <span style="">Name:</span><span class="name" style="position:absolute; left:6em"></span> <br/> <span style="">Type:</span><span class="type" style="position:absolute; left:6em"></span> -</div>
\ No newline at end of file + <br/> + <div class="providerDetails"></div> + <div class="dijitDialogPaneActionBar"> + <input class="deleteGroupProviderButton" type="button" value="Delete Group provider" label="Delete Group Provider" dojoType="dijit.form.Button" /> + </div> +</div> +<br/>
\ No newline at end of file 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 be75b4d2e9..9f6bda67df 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 @@ -39,10 +39,10 @@ import org.apache.qpid.server.model.AuthenticationProvider; 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.Port; import org.apache.qpid.server.model.TrustStore; import org.apache.qpid.server.model.adapter.AuthenticationProviderFactory; import org.apache.qpid.server.model.adapter.BrokerAdapter; +import org.apache.qpid.server.model.adapter.GroupProviderFactory; import org.apache.qpid.server.model.adapter.PortFactory; import org.apache.qpid.server.stats.StatisticsGatherer; import org.apache.qpid.server.virtualhost.VirtualHostRegistry; @@ -57,11 +57,13 @@ public class BrokerRecoverer implements ConfiguredObjectRecoverer<Broker> private final PortFactory _portFactory; private final TaskExecutor _taskExecutor; private final BrokerOptions _brokerOptions; + private final GroupProviderFactory _groupProviderFactory; - public BrokerRecoverer(AuthenticationProviderFactory authenticationProviderFactory, PortFactory portFactory, - StatisticsGatherer statisticsGatherer, VirtualHostRegistry virtualHostRegistry, LogRecorder logRecorder, - RootMessageLogger rootMessageLogger, TaskExecutor taskExecutor, BrokerOptions brokerOptions) + public BrokerRecoverer(AuthenticationProviderFactory authenticationProviderFactory, GroupProviderFactory groupProviderFactory, + PortFactory portFactory, StatisticsGatherer statisticsGatherer, VirtualHostRegistry virtualHostRegistry, + LogRecorder logRecorder, RootMessageLogger rootMessageLogger, TaskExecutor taskExecutor, BrokerOptions brokerOptions) { + _groupProviderFactory = groupProviderFactory; _portFactory = portFactory; _authenticationProviderFactory = authenticationProviderFactory; _statisticsGatherer = statisticsGatherer; @@ -77,7 +79,8 @@ public class BrokerRecoverer implements ConfiguredObjectRecoverer<Broker> { StoreConfigurationChangeListener storeChangeListener = new StoreConfigurationChangeListener(entry.getStore()); BrokerAdapter broker = new BrokerAdapter(entry.getId(), entry.getAttributes(), _statisticsGatherer, _virtualHostRegistry, - _logRecorder, _rootMessageLogger, _authenticationProviderFactory, _portFactory, _taskExecutor, entry.getStore(), _brokerOptions); + _logRecorder, _rootMessageLogger, _authenticationProviderFactory, _groupProviderFactory, _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 35209e5b41..89f949d8d8 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 @@ -34,6 +34,7 @@ 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.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.AuthenticationManagerFactory; @@ -52,7 +53,7 @@ public class DefaultRecovererProvider implements RecovererProvider private final RootMessageLogger _rootMessageLogger; private final AuthenticationProviderFactory _authenticationProviderFactory; private final PortFactory _portFactory; - private final QpidServiceLoader<GroupManagerFactory> _groupManagerServiceLoader; + private final GroupProviderFactory _groupProviderFactory; private final QpidServiceLoader<PluginFactory> _pluginFactoryServiceLoader; private final TaskExecutor _taskExecutor; private final BrokerOptions _brokerOptions; @@ -61,12 +62,12 @@ public class DefaultRecovererProvider implements RecovererProvider LogRecorder logRecorder, RootMessageLogger rootMessageLogger, TaskExecutor taskExecutor, BrokerOptions brokerOptions) { _authenticationProviderFactory = new AuthenticationProviderFactory(new QpidServiceLoader<AuthenticationManagerFactory>()); + _groupProviderFactory = new GroupProviderFactory(new QpidServiceLoader<GroupManagerFactory>()); _portFactory = new PortFactory(); _brokerStatisticsGatherer = brokerStatisticsGatherer; _virtualHostRegistry = virtualHostRegistry; _logRecorder = logRecorder; _rootMessageLogger = rootMessageLogger; - _groupManagerServiceLoader = new QpidServiceLoader<GroupManagerFactory>(); _pluginFactoryServiceLoader = new QpidServiceLoader<PluginFactory>(); _taskExecutor = taskExecutor; _brokerOptions = brokerOptions; @@ -77,7 +78,7 @@ public class DefaultRecovererProvider implements RecovererProvider { if (Broker.class.getSimpleName().equals(type)) { - return new BrokerRecoverer(_authenticationProviderFactory, _portFactory, _brokerStatisticsGatherer, _virtualHostRegistry, + return new BrokerRecoverer(_authenticationProviderFactory, _groupProviderFactory, _portFactory, _brokerStatisticsGatherer, _virtualHostRegistry, _logRecorder, _rootMessageLogger, _taskExecutor, _brokerOptions); } else if(VirtualHost.class.getSimpleName().equals(type)) @@ -94,7 +95,7 @@ public class DefaultRecovererProvider implements RecovererProvider } else if(GroupProvider.class.getSimpleName().equals(type)) { - return new GroupProviderRecoverer(_groupManagerServiceLoader); + return new GroupProviderRecoverer(_groupProviderFactory); } else if(KeyStore.class.getSimpleName().equals(type)) { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/GroupProviderRecoverer.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/GroupProviderRecoverer.java index 275a0c736c..00f23b3c1c 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/GroupProviderRecoverer.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/GroupProviderRecoverer.java @@ -24,24 +24,20 @@ import java.util.Map; import org.apache.qpid.server.configuration.ConfigurationEntry; import org.apache.qpid.server.configuration.ConfiguredObjectRecoverer; -import org.apache.qpid.server.configuration.IllegalConfigurationException; import org.apache.qpid.server.configuration.RecovererProvider; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.ConfiguredObject; import org.apache.qpid.server.model.GroupProvider; -import org.apache.qpid.server.model.adapter.GroupProviderAdapter; -import org.apache.qpid.server.plugin.GroupManagerFactory; -import org.apache.qpid.server.plugin.QpidServiceLoader; -import org.apache.qpid.server.security.group.GroupManager; +import org.apache.qpid.server.model.adapter.GroupProviderFactory; public class GroupProviderRecoverer implements ConfiguredObjectRecoverer<GroupProvider> { - private QpidServiceLoader<GroupManagerFactory> _groupManagerServiceLoader; + private GroupProviderFactory _groupProviderFactory; - public GroupProviderRecoverer(QpidServiceLoader<GroupManagerFactory> groupManagerServiceLoader) + public GroupProviderRecoverer(GroupProviderFactory groupProviderFactory) { super(); - _groupManagerServiceLoader = groupManagerServiceLoader; + _groupProviderFactory = groupProviderFactory; } @Override @@ -49,26 +45,9 @@ public class GroupProviderRecoverer implements ConfiguredObjectRecoverer<GroupPr { Broker broker = RecovererHelper.verifyOnlyBrokerIsParent(parents); Map<String, Object> attributes = configurationEntry.getAttributes(); - GroupManager groupManager = createGroupManager(attributes); - if (groupManager == null) - { - throw new IllegalConfigurationException("Cannot create GroupManager from attributes : " + attributes); - } - GroupProviderAdapter groupProviderAdapter = new GroupProviderAdapter(configurationEntry.getId(), groupManager, broker); - return groupProviderAdapter; - } - private GroupManager createGroupManager(Map<String, Object> attributes) - { - for(GroupManagerFactory factory : _groupManagerServiceLoader.instancesOf(GroupManagerFactory.class)) - { - GroupManager groupManager = factory.createInstance(attributes); - if (groupManager != null) - { - return groupManager; - } - } - return null; - } + GroupProvider groupProvider = _groupProviderFactory.recover(configurationEntry.getId(), broker, attributes); + return groupProvider; + } } 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 712b53f627..44adf3414d 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 @@ -86,12 +86,6 @@ public interface Broker extends ConfiguredObject */ String ACL_FILE = "aclFile"; - /* - * A temporary attributes to set the broker group file. - * TODO: Remove them after adding a full support to configure authorization providers via management layers. - */ - String GROUP_FILE = "groupFile"; - // Attributes Collection<String> AVAILABLE_ATTRIBUTES = Collections.unmodifiableList( @@ -134,7 +128,6 @@ public interface Broker extends ConfiguredObject VIRTUALHOST_STORE_TRANSACTION_IDLE_TIMEOUT_WARN, VIRTUALHOST_STORE_TRANSACTION_OPEN_TIMEOUT_CLOSE, VIRTUALHOST_STORE_TRANSACTION_OPEN_TIMEOUT_WARN, - GROUP_FILE, ACL_FILE )); 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 49af66126c..17a8f19cd3 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 @@ -63,8 +63,6 @@ import org.apache.qpid.server.security.SubjectCreator; import org.apache.qpid.server.security.access.Operation; import org.apache.qpid.server.security.auth.manager.AuthenticationManager; import org.apache.qpid.server.security.auth.manager.SimpleAuthenticationManager; -import org.apache.qpid.server.security.group.FileGroupManager; -import org.apache.qpid.server.security.group.GroupManager; import org.apache.qpid.server.stats.StatisticsGatherer; import org.apache.qpid.server.store.MessageStoreCreator; import org.apache.qpid.server.util.MapValueConverter; @@ -97,7 +95,6 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat put(NAME, String.class); put(DEFAULT_VIRTUAL_HOST, String.class); - put(GROUP_FILE, String.class); put(VIRTUALHOST_STORE_TRANSACTION_IDLE_TIMEOUT_CLOSE, Long.class); put(VIRTUALHOST_STORE_TRANSACTION_IDLE_TIMEOUT_WARN, Long.class); put(VIRTUALHOST_STORE_TRANSACTION_OPEN_TIMEOUT_CLOSE, Long.class); @@ -123,7 +120,6 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat public static final long DEFAULT_STORE_TRANSACTION_IDLE_TIMEOUT_WARN = 0l; public static final long DEFAULT_STORE_TRANSACTION_OPEN_TIMEOUT_CLOSE = 0l; public static final long DEFAULT_STORE_TRANSACTION_OPEN_TIMEOUT_WARN = 0l; - private static final String DEFAULT_GROUP_PROVIDER_NAME = "defaultGroupProvider"; @SuppressWarnings("serial") private static final Map<String, Object> DEFAULTS = Collections.unmodifiableMap(new HashMap<String, Object>(){{ @@ -170,6 +166,7 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat private final Map<String, KeyStore> _keyStores = new HashMap<String, KeyStore>(); private final Map<String, TrustStore> _trustStores = new HashMap<String, TrustStore>(); + private final GroupProviderFactory _groupProviderFactory; private final AuthenticationProviderFactory _authenticationProviderFactory; private final PortFactory _portFactory; @@ -183,7 +180,8 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat public BrokerAdapter(UUID id, Map<String, Object> attributes, StatisticsGatherer statisticsGatherer, VirtualHostRegistry virtualHostRegistry, LogRecorder logRecorder, RootMessageLogger rootMessageLogger, AuthenticationProviderFactory authenticationProviderFactory, - PortFactory portFactory, TaskExecutor taskExecutor, ConfigurationEntryStore brokerStore, BrokerOptions brokerOptions) + GroupProviderFactory groupProviderFactory, PortFactory portFactory, TaskExecutor taskExecutor, ConfigurationEntryStore brokerStore, + BrokerOptions brokerOptions) { super(id, DEFAULTS, MapValueConverter.convert(attributes, ATTRIBUTE_TYPES), taskExecutor); _statisticsGatherer = statisticsGatherer; @@ -192,14 +190,13 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat _rootMessageLogger = rootMessageLogger; _statistics = new StatisticsAdapter(statisticsGatherer); _authenticationProviderFactory = authenticationProviderFactory; + _groupProviderFactory = groupProviderFactory; _portFactory = portFactory; _securityManager = new SecurityManager((String)getAttribute(ACL_FILE)); addChangeListener(_securityManager); - createBrokerChildrenFromAttributes(); _supportedStoreTypes = new MessageStoreCreator().getStoreTypes(); _brokerStore = brokerStore; _brokerOptions = brokerOptions; - createBrokerChildrenFromAttributes(); if (_brokerOptions.isManagementMode()) { AuthenticationManager authManager = new SimpleAuthenticationManager(BrokerOptions.MANAGEMENT_MODE_USER_NAME, _brokerOptions.getManagementModePassword()); @@ -209,32 +206,6 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat } } - /* - * A temporary method to create broker children that can be only configured via broker attributes - */ - private void createBrokerChildrenFromAttributes() - { - createGroupProvider(); - - } - - private void createGroupProvider() - { - String groupFile = (String) getAttribute(GROUP_FILE); - if (groupFile != null) - { - GroupManager groupManager = new FileGroupManager(groupFile); - UUID groupProviderId = UUIDGenerator.generateBrokerChildUUID(GroupProvider.class.getSimpleName(), - DEFAULT_GROUP_PROVIDER_NAME); - GroupProviderAdapter groupProviderAdapter = new GroupProviderAdapter(groupProviderId, groupManager, this); - _groupProviders.put(DEFAULT_GROUP_PROVIDER_NAME, groupProviderAdapter); - } - else - { - _groupProviders.remove(DEFAULT_GROUP_PROVIDER_NAME); - } - } - public Collection<VirtualHost> getVirtualHosts() { synchronized(_vhostAdapters) @@ -462,6 +433,10 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat { return (C) createTrustStore(attributes); } + else if(childClass == GroupProvider.class) + { + return (C) createGroupProvider(attributes); + } else { throw new IllegalArgumentException("Cannot create child of class " + childClass.getSimpleName()); @@ -535,6 +510,14 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat authenticationProvider.addChangeListener(this); } + private GroupProvider createGroupProvider(Map<String, Object> attributes) + { + GroupProvider groupProvider = _groupProviderFactory.create(UUID.randomUUID(), this, attributes); + groupProvider.setDesiredState(State.INITIALISING, State.ACTIVE); + addGroupProvider(groupProvider); + return groupProvider; + } + private void addGroupProvider(GroupProvider groupProvider) { synchronized (_groupProviders) @@ -549,9 +532,20 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat groupProvider.addChangeListener(this); } - private boolean deleteGroupProvider(GroupProvider object) + private boolean deleteGroupProvider(GroupProvider groupProvider) { - throw new UnsupportedOperationException("Not implemented yet!"); + GroupProvider removedGroupProvider = null; + synchronized (_groupProviders) + { + removedGroupProvider = _groupProviders.remove(groupProvider.getName()); + } + + if(removedGroupProvider != null) + { + removedGroupProvider.removeChangeListener(this); + } + + return removedGroupProvider != null; } private KeyStore createKeyStore(Map<String, Object> attributes) @@ -724,6 +718,12 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat { removedPort = _portAdapters.remove(portAdapter.getPort()); } + + if (removedPort != null) + { + removedPort.removeChangeListener(this); + } + return removedPort != null; } @@ -734,6 +734,12 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat { removedAuthenticationProvider = _authenticationProviders.remove(authenticationProvider.getId()); } + + if(removedAuthenticationProvider != null) + { + removedAuthenticationProvider.removeChangeListener(this); + } + return removedAuthenticationProvider != null; } @@ -1030,11 +1036,6 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat Object expected = getAttribute(name); if (changeAttribute(name, expected, desired)) { - if (GROUP_FILE.equals(name)) - { - createGroupProvider(); - } - attributeSet(name, expected, desired); } } @@ -1049,12 +1050,6 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat // create a security manager to validate the ACL specified in file new SecurityManager(aclFile); } - String groupFile = (String) convertedAttributes.get(GROUP_FILE); - if (groupFile != null) - { - // create a group manager to validate the groups specified in file - new FileGroupManager(groupFile); - } String defaultVirtualHost = (String) convertedAttributes.get(DEFAULT_VIRTUAL_HOST); if (defaultVirtualHost != null) diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/GroupProviderAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/GroupProviderAdapter.java index 9ad58f9670..a0e5bdb0e8 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/GroupProviderAdapter.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/GroupProviderAdapter.java @@ -24,6 +24,7 @@ import java.security.Principal; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; @@ -48,9 +49,11 @@ public class GroupProviderAdapter extends AbstractAdapter implements { private final GroupManager _groupManager; private final Broker _broker; - public GroupProviderAdapter(UUID id, GroupManager groupManager, Broker broker) + private Collection<String> _supportedAttributes; + + public GroupProviderAdapter(UUID id, Broker broker, GroupManager groupManager, Map<String, Object> attributes, Collection<String> attributeNames) { - super(id, broker.getTaskExecutor()); + super(id, null, null, broker.getTaskExecutor()); if (groupManager == null) { @@ -58,13 +61,37 @@ public class GroupProviderAdapter extends AbstractAdapter implements } _groupManager = groupManager; _broker = broker; + _supportedAttributes = createSupportedAttributes(attributeNames); addParent(Broker.class, broker); + + // 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<String> createSupportedAttributes(Collection<String> factoryAttributes) + { + List<String> attributesNames = new ArrayList<String>(AVAILABLE_ATTRIBUTES); + if (factoryAttributes != null) + { + attributesNames.addAll(factoryAttributes); + } + + return Collections.unmodifiableCollection(attributesNames); } @Override public String getName() { - return _groupManager.getClass().getSimpleName(); + return (String)getAttribute(NAME); } @Override @@ -129,17 +156,13 @@ public class GroupProviderAdapter extends AbstractAdapter implements @Override public Collection<String> getAttributeNames() { - return GroupProvider.AVAILABLE_ATTRIBUTES; + return _supportedAttributes; } @Override public Object getAttribute(String name) { - if (TYPE.equals(name)) - { - return getName(); - } - else if (CREATED.equals(name)) + if (CREATED.equals(name)) { // TODO } @@ -155,10 +178,6 @@ public class GroupProviderAdapter extends AbstractAdapter implements { return LifetimePolicy.PERMANENT; } - else if (NAME.equals(name)) - { - return getName(); - } else if (STATE.equals(name)) { return State.ACTIVE; // TODO @@ -220,11 +239,91 @@ public class GroupProviderAdapter extends AbstractAdapter implements } } + public GroupManager getGroupManager() + { + return _groupManager; + } + private SecurityManager getSecurityManager() { return _broker.getSecurityManager(); } + @Override + protected boolean setState(State currentState, State desiredState) + { + if (desiredState == State.ACTIVE) + { + _groupManager.open(); + return true; + } + else if (desiredState == State.STOPPED) + { + _groupManager.close(); + return true; + } + else if (desiredState == State.DELETED) + { + _groupManager.close(); + _groupManager.onDelete(); + return true; + } + return false; + } + + public Set<Principal> getGroupPrincipalsForUser(String username) + { + return _groupManager.getGroupPrincipalsForUser(username); + } + + @Override + protected void childAdded(ConfiguredObject child) + { + // no-op, prevent storing groups in the broker store + } + + @Override + protected void childRemoved(ConfiguredObject child) + { + // no-op, as per above, groups are not in the store + } + + @Override + protected void authoriseSetDesiredState(State currentState, State desiredState) throws AccessControlException + { + if(desiredState == State.DELETED) + { + if (!_broker.getSecurityManager().authoriseConfiguringBroker(getName(), GroupProvider.class, Operation.DELETE)) + { + throw new AccessControlException("Deletion of groups provider is denied"); + } + } + } + + @Override + protected void authoriseSetAttribute(String name, Object expected, Object desired) throws AccessControlException + { + if (!_broker.getSecurityManager().authoriseConfiguringBroker(getName(), GroupProvider.class, Operation.UPDATE)) + { + throw new AccessControlException("Setting of group provider attributes is denied"); + } + } + + @Override + protected void authoriseSetAttributes(Map<String, Object> attributes) throws AccessControlException + { + if (!_broker.getSecurityManager().authoriseConfiguringBroker(getName(), GroupProvider.class, Operation.UPDATE)) + { + throw new AccessControlException("Setting of group provider attributes is denied"); + } + } + + @Override + protected void changeAttributes(Map<String, Object> attributes) + { + throw new UnsupportedOperationException("Changing attributes on group providers is not supported."); + } + private class GroupAdapter extends AbstractAdapter implements Group { private final String _group; @@ -526,23 +625,5 @@ public class GroupProviderAdapter extends AbstractAdapter implements } } - @Override - protected boolean setState(State currentState, State desiredState) - { - if (desiredState == State.ACTIVE) - { - return true; - } - else if (desiredState == State.STOPPED) - { - return true; - } - // TODO: DELETE state is ignored for now - return false; - } - public Set<Principal> getGroupPrincipalsForUser(String username) - { - return _groupManager.getGroupPrincipalsForUser(username); - } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/GroupProviderFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/GroupProviderFactory.java new file mode 100644 index 0000000000..1d3ccd81b3 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/GroupProviderFactory.java @@ -0,0 +1,118 @@ +/* + * + * 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.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import org.apache.qpid.server.configuration.IllegalConfigurationException; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.GroupProvider; +import org.apache.qpid.server.plugin.GroupManagerFactory; +import org.apache.qpid.server.plugin.QpidServiceLoader; +import org.apache.qpid.server.security.group.GroupManager; + +public class GroupProviderFactory +{ + private final Map<String, GroupManagerFactory> _factories; + private Collection<String> _supportedGroupProviders; + + public GroupProviderFactory(QpidServiceLoader<GroupManagerFactory> groupManagerFactoryServiceLoader) + { + Iterable<GroupManagerFactory> factories = groupManagerFactoryServiceLoader.instancesOf(GroupManagerFactory.class); + + Map<String, GroupManagerFactory> registeredGroupProviderFactories = new HashMap<String, GroupManagerFactory>(); + for (GroupManagerFactory factory : factories) + { + GroupManagerFactory existingFactory = registeredGroupProviderFactories.put(factory.getType(), factory); + if (existingFactory != null) + { + throw new IllegalConfigurationException("Group provider factory of the same type '" + factory.getType() + + "' is already registered using class '" + existingFactory.getClass().getName() + + "', can not register class '" + factory.getClass().getName() + "'"); + } + } + _factories = registeredGroupProviderFactories; + _supportedGroupProviders = Collections.unmodifiableCollection(registeredGroupProviderFactories.keySet()); + } + + /** + * Creates {@link GroupProvider} for given ID, {@link Broker} and attributes. + * <p> + * The configured {@link GroupManagerFactory}'s are used to try to create the {@link GroupProvider}. The first non-null + * instance is returned. The factories are used in non-deterministic order. + */ + public GroupProvider create(UUID id, Broker broker, Map<String, Object> attributes) + { + GroupProviderAdapter authenticationProvider = createGroupProvider(id, broker, attributes); + authenticationProvider.getGroupManager().onCreate(); + return authenticationProvider; + } + + /** + * Recovers {@link GroupProvider} with given ID, {@link Broker} and attributes. + * <p> + * The configured {@link GroupManagerFactory}'s are used to try to create the {@link GroupProvider}. The first non-null + * instance is returned. The factories are used in non-deterministic order. + */ + public GroupProvider recover(UUID id, Broker broker, Map<String, Object> attributes) + { + return createGroupProvider(id, broker, attributes); + } + + public Collection<String> getSupportedGroupProviders() + { + return _supportedGroupProviders; + } + + private GroupProviderAdapter createGroupProvider(UUID id, Broker broker, Map<String, Object> attributes) + { + for (GroupManagerFactory factory : _factories.values()) + { + GroupManager manager = factory.createInstance(attributes); + if (manager != null) + { + verifyGroupManager(manager, broker); + return new GroupProviderAdapter(id, broker, manager, attributes,factory.getAttributeNames()); + } + } + throw new IllegalConfigurationException("No group provider factory found for configuration attributes " + attributes); + } + + private void verifyGroupManager(GroupManager manager, Broker broker) + { + Collection<GroupProvider> groupProviders = broker.getGroupProviders(); + for (GroupProvider groupProvider : groupProviders) + { + if (groupProvider instanceof GroupProviderAdapter) + { + GroupManager providerManager = ((GroupProviderAdapter) groupProvider).getGroupManager(); + if (manager.equals(providerManager)) + { + throw new IllegalConfigurationException("A group provider with the same settings already exists"); + } + } + } + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/plugin/GroupManagerFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/plugin/GroupManagerFactory.java index 5d80ca24fd..2ab9701e2e 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/plugin/GroupManagerFactory.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/plugin/GroupManagerFactory.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.GroupProvider; import org.apache.qpid.server.security.group.GroupManager; public interface GroupManagerFactory { + public static final String ATTRIBUTE_TYPE = GroupProvider.TYPE; + GroupManager createInstance(Map<String, Object> attributes); + + /** + * Returns the authentication provider type + * @return authentication provider type + */ + String getType(); + + /** + * Get the names of attributes the group manager which can be passed into {@link #createInstance(Map)} to create the + * group manager + * + * @return the collection of attribute names + */ + Collection<String> getAttributeNames(); + + /** + * @return returns human readable descriptions for the attributes + */ + Map<String, String> getAttributeDescriptions(); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/group/FileGroupManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/group/FileGroupManager.java index 8295f28f9e..e11a4f83db 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/group/FileGroupManager.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/group/FileGroupManager.java @@ -19,6 +19,7 @@ */ package org.apache.qpid.server.security.group; +import java.io.File; import java.io.IOException; import java.security.Principal; import java.util.Collections; @@ -34,32 +35,26 @@ import org.apache.qpid.server.security.auth.UsernamePrincipal; * This plugin is configured in the following manner: * </p> * <pre> - * <file-group-manager> - * <attributes> - * <attribute> - * <name>groupFile</name> - * <value>${conf}/groups</value> - * </attribute> - * </attributes> - * </file-group-manager> + * "groupproviders":[ + * ... + * { + * "name" : "...", + * "type" : "GroupFile", + * "path" : "path/to/file/with/groups", + * } + * ... + * ] * </pre> */ public class FileGroupManager implements GroupManager { private final FileGroupDatabase _groupDatabase; - + private final String _groupFile; public FileGroupManager(String groupFile) { + _groupFile = groupFile; _groupDatabase = new FileGroupDatabase(); - try - { - _groupDatabase.setGroupFile(groupFile); - } - catch (IOException e) - { - throw new IllegalConfigurationException("Unable to set group file " + groupFile, e); - } } @Override @@ -144,4 +139,101 @@ public class FileGroupManager implements GroupManager } + @Override + public void onDelete() + { + File file = new File(_groupFile); + if (file.exists()) + { + if (!file.delete()) + { + throw new IllegalConfigurationException("Cannot delete group file"); + } + } + } + + @Override + public void onCreate() + { + File file = new File(_groupFile); + if (!file.exists()) + { + File parent = file.getParentFile(); + if (!parent.exists()) + { + parent.mkdirs(); + } + if (parent.exists()) + { + try + { + file.createNewFile(); + } + catch (IOException e) + { + throw new IllegalConfigurationException("Cannot create group file"); + } + } + else + { + throw new IllegalConfigurationException("Cannot create group file"); + } + } + } + + @Override + public void open() + { + try + { + _groupDatabase.setGroupFile(_groupFile); + } + catch (IOException e) + { + throw new IllegalConfigurationException("Unable to set group file " + _groupFile, e); + } + } + + @Override + public void close() + { + // no-op + } + + @Override + public int hashCode() + { + return ((_groupFile == null) ? 0 : _groupFile.hashCode()); + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (obj == null) + { + return false; + } + if (getClass() != obj.getClass()) + { + return false; + } + FileGroupManager other = (FileGroupManager) obj; + if (_groupFile == null) + { + if (other._groupFile != null) + { + return false; + } + else + { + return true; + } + } + return _groupFile.equals(other._groupFile); + } + } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/group/FileGroupManagerFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/group/FileGroupManagerFactory.java index 5c4730a9c8..50f08623cd 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/group/FileGroupManagerFactory.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/group/FileGroupManagerFactory.java @@ -20,32 +20,60 @@ package org.apache.qpid.server.security.group; 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.commons.lang.StringUtils; import org.apache.qpid.server.configuration.IllegalConfigurationException; -import org.apache.qpid.server.model.GroupProvider; import org.apache.qpid.server.plugin.GroupManagerFactory; +import org.apache.qpid.server.util.ResourceBundleLoader; public class FileGroupManagerFactory implements GroupManagerFactory { - static final String FILE_GROUP_MANAGER_TYPE = "file-group-manager"; - static final String FILE = "file"; + public static final String RESOURCE_BUNDLE = "org.apache.qpid.server.security.group.FileGroupProviderAttributeDescriptions"; + + public static final String GROUP_FILE_PROVIDER_TYPE = "GroupFile"; + public static final String PATH = "path"; + + public static final Collection<String> ATTRIBUTES = Collections.<String> unmodifiableList(Arrays.asList( + ATTRIBUTE_TYPE, + PATH + )); @Override public GroupManager createInstance(Map<String, Object> attributes) { - if(!FILE_GROUP_MANAGER_TYPE.equals(getStringAttribute(GroupProvider.TYPE, attributes, null))) + if(attributes == null || !GROUP_FILE_PROVIDER_TYPE.equals(attributes.get(ATTRIBUTE_TYPE))) { return null; } - String groupFile = getStringAttribute(FILE, attributes, null); - if (StringUtils.isBlank(groupFile)) + String groupFile = getStringAttribute(PATH, attributes, null); + if (groupFile == null || "".equals(groupFile.trim())) { throw new IllegalConfigurationException("Path to file containing groups is not specified!"); } + return new FileGroupManager(groupFile); } + @Override + public String getType() + { + return GROUP_FILE_PROVIDER_TYPE; + } + + @Override + public Collection<String> getAttributeNames() + { + return ATTRIBUTES; + } + + @Override + public Map<String, String> getAttributeDescriptions() + { + return ResourceBundleLoader.getResources(RESOURCE_BUNDLE); + } + } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/group/GroupManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/group/GroupManager.java index 6d2df86919..3fd6dd2800 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/group/GroupManager.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/group/GroupManager.java @@ -37,4 +37,12 @@ public interface GroupManager void addUserToGroup(String user, String group); void removeUserFromGroup(String user, String group); + + void open(); + + void close(); + + void onDelete(); + + void onCreate(); } 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 5a8580fd26..5c3f062cae 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 @@ -49,6 +49,7 @@ 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.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.stats.StatisticsGatherer; @@ -70,7 +71,7 @@ public class BrokerRecovererTest extends TestCase { super.setUp(); - _brokerRecoverer = new BrokerRecoverer(mock(AuthenticationProviderFactory.class), mock(PortFactory.class), mock(StatisticsGatherer.class), + _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)); when(_brokerEntry.getId()).thenReturn(_brokerId); when(_brokerEntry.getChildren()).thenReturn(_brokerEntryChildren); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/GroupProviderRecovererTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/GroupProviderRecovererTest.java index 6713574e4b..d6f03a9758 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/GroupProviderRecovererTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/GroupProviderRecovererTest.java @@ -30,6 +30,7 @@ import org.apache.qpid.server.configuration.ConfigurationEntry; import org.apache.qpid.server.configuration.IllegalConfigurationException; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.GroupProvider; +import org.apache.qpid.server.model.adapter.GroupProviderFactory; import org.apache.qpid.server.plugin.GroupManagerFactory; import org.apache.qpid.server.plugin.QpidServiceLoader; import org.apache.qpid.server.security.group.GroupManager; @@ -46,6 +47,7 @@ public class GroupProviderRecovererTest extends TestCase private QpidServiceLoader<GroupManagerFactory> _groupManagerServiceLoader; private Broker _broker; private ConfigurationEntry _configurationEntry; + private GroupProviderFactory _groupProviderFactory; @SuppressWarnings("unchecked") protected void setUp() throws Exception @@ -58,6 +60,7 @@ public class GroupProviderRecovererTest extends TestCase _groupManagerServiceLoader = mock(QpidServiceLoader.class); when(_groupManagerServiceLoader.instancesOf(GroupManagerFactory.class)).thenReturn(Collections.singletonList(_factory )); + _groupProviderFactory = new GroupProviderFactory(_groupManagerServiceLoader); _broker = mock(Broker.class); @@ -70,8 +73,9 @@ public class GroupProviderRecovererTest extends TestCase { GroupManager groupManager = mock(GroupManager.class); String name = groupManager.getClass().getSimpleName(); + _attributes.put(GroupProvider.NAME, name); when(_factory.createInstance(_attributes)).thenReturn(groupManager); - GroupProviderRecoverer groupProviderRecoverer = new GroupProviderRecoverer(_groupManagerServiceLoader); + GroupProviderRecoverer groupProviderRecoverer = new GroupProviderRecoverer(_groupProviderFactory); GroupProvider groupProvider = groupProviderRecoverer.create(null, _configurationEntry, _broker); assertNotNull("Null group provider", groupProvider); assertEquals("Unexpected name", name, groupProvider.getName()); @@ -82,7 +86,7 @@ public class GroupProviderRecovererTest extends TestCase { when(_factory.createInstance(_attributes)).thenReturn(null); - GroupProviderRecoverer groupProviderRecoverer = new GroupProviderRecoverer(_groupManagerServiceLoader); + GroupProviderRecoverer groupProviderRecoverer = new GroupProviderRecoverer(_groupProviderFactory); try { groupProviderRecoverer.create(null, _configurationEntry, _broker); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/group/FileGroupManagerFactoryTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/group/FileGroupManagerFactoryTest.java index 934c0082ea..90308d316b 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/group/FileGroupManagerFactoryTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/group/FileGroupManagerFactoryTest.java @@ -35,8 +35,8 @@ public class FileGroupManagerFactoryTest extends TestCase public void testInstanceCreated() throws Exception { - _configuration.put(GroupProvider.TYPE, FileGroupManagerFactory.FILE_GROUP_MANAGER_TYPE); - _configuration.put(FileGroupManagerFactory.FILE, _emptyButValidGroupFile); + _configuration.put(GroupProvider.TYPE, FileGroupManagerFactory.GROUP_FILE_PROVIDER_TYPE); + _configuration.put(FileGroupManagerFactory.PATH, _emptyButValidGroupFile); GroupManager manager = _factory.createInstance(_configuration); assertNotNull(manager); @@ -60,8 +60,8 @@ public class FileGroupManagerFactoryTest extends TestCase public void testRejectsConfigThatIsMissingAttributeValue() throws Exception { - _configuration.put(GroupProvider.TYPE, FileGroupManagerFactory.FILE_GROUP_MANAGER_TYPE); - _configuration.put(FileGroupManagerFactory.FILE, null); + _configuration.put(GroupProvider.TYPE, FileGroupManagerFactory.GROUP_FILE_PROVIDER_TYPE); + _configuration.put(FileGroupManagerFactory.PATH, null); try { diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/group/FileGroupManagerTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/group/FileGroupManagerTest.java index b83d25b206..152703d548 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/group/FileGroupManagerTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/group/FileGroupManagerTest.java @@ -20,13 +20,11 @@ package org.apache.qpid.server.security.group; import java.io.File; -import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.security.Principal; import java.util.Properties; import java.util.Set; -import org.apache.qpid.server.configuration.IllegalConfigurationException; import org.apache.qpid.server.security.auth.UsernamePrincipal; import org.apache.qpid.test.utils.QpidTestCase; @@ -62,17 +60,26 @@ public class FileGroupManagerTest extends QpidTestCase public void testNonExistentGroupFile() throws Exception { - final String filePath = "/does.not.exist/"; - + final String filePath = TMP_FOLDER + File.separator + "non.existing"; + File file = new File(filePath); + if (file.exists()) + { + file.delete(); + } + assertFalse("File should not exist", file.exists()); try { _manager = new FileGroupManager(filePath); - fail("expected exception was not thrown"); + assertFalse("File should be created", file.exists()); + _manager.onCreate(); + assertTrue("File should be created", file.exists()); + _manager.open(); + Set<Principal> groups = _manager.getGroupPrincipals(); + assertTrue("No group should exist", groups.isEmpty()); } - catch(IllegalConfigurationException ce) + finally { - assertNotNull(ce.getCause()); - assertTrue(ce.getCause() instanceof FileNotFoundException); + file.delete(); } } @@ -80,7 +87,7 @@ public class FileGroupManagerTest extends QpidTestCase { final String groupFileName = writeGroupFile(); _manager = new FileGroupManager(groupFileName); - + _manager.open(); Set<Principal> principals = _manager.getGroupPrincipalsForUser("user1"); assertEquals(1, principals.size()); assertTrue(principals.contains(new GroupPrincipal("myGroup"))); @@ -90,7 +97,7 @@ public class FileGroupManagerTest extends QpidTestCase { final String groupFileName = writeGroupFile(); _manager = new FileGroupManager(groupFileName); - + _manager.open(); Set<Principal> principals = _manager.getUserPrincipalsForGroup("myGroup"); assertEquals(1, principals.size()); assertTrue(principals.contains(new UsernamePrincipal("user1"))); @@ -100,7 +107,7 @@ public class FileGroupManagerTest extends QpidTestCase { final String groupFileName = writeGroupFile(MY_GROUP, MYGROUP_USERS, MY_GROUP2, MYGROUP_USERS); _manager = new FileGroupManager(groupFileName); - + _manager.open(); Set<Principal> principals = _manager.getGroupPrincipals(); assertEquals(2, principals.size()); assertTrue(principals.contains(new GroupPrincipal("myGroup"))); @@ -111,7 +118,7 @@ public class FileGroupManagerTest extends QpidTestCase { final String groupFileName = writeGroupFile(); _manager = new FileGroupManager(groupFileName); - + _manager.open(); Set<Principal> principals = _manager.getGroupPrincipals(); assertEquals(1, principals.size()); @@ -126,7 +133,7 @@ public class FileGroupManagerTest extends QpidTestCase { final String groupFileName = writeGroupFile(MY_GROUP, MYGROUP_USERS); _manager = new FileGroupManager(groupFileName); - + _manager.open(); Set<Principal> principals = _manager.getGroupPrincipals(); assertEquals(1, principals.size()); @@ -140,7 +147,7 @@ public class FileGroupManagerTest extends QpidTestCase { final String groupFileName = writeGroupFile(MY_GROUP, MYGROUP_USERS); _manager = new FileGroupManager(groupFileName); - + _manager.open(); Set<Principal> principals = _manager.getUserPrincipalsForGroup("myGroup"); assertEquals(1, principals.size()); assertFalse(principals.contains(new UsernamePrincipal("user2"))); @@ -156,7 +163,7 @@ public class FileGroupManagerTest extends QpidTestCase { final String groupFileName = writeGroupFile(MY_GROUP, MYGROUP_USERS); _manager = new FileGroupManager(groupFileName); - + _manager.open(); Set<Principal> principals = _manager.getUserPrincipalsForGroup("myGroup"); assertEquals(1, principals.size()); assertTrue(principals.contains(new UsernamePrincipal("user1"))); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/group/FileGroupProviderAttributeDescriptions.properties b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/group/FileGroupProviderAttributeDescriptions.properties new file mode 100644 index 0000000000..2c2d2ab9e3 --- /dev/null +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/group/FileGroupProviderAttributeDescriptions.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* 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 814936f342..f3bce1874e 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 @@ -63,7 +63,7 @@ public abstract class AbstractACLTestCase extends QpidBrokerTestCase implements @Override public void setUp() throws Exception { - getBrokerConfiguration().setBrokerAttribute(Broker.GROUP_FILE, System.getProperty(QPID_HOME) + "/etc/groups-systests"); + getBrokerConfiguration().addGroupFileConfiguration(System.getProperty(QPID_HOME) + "/etc/groups-systests"); // run test specific setup String testSetup = StringUtils.replace(getName(), "test", "setUp"); 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 7fd13ed8aa..0c590ad1d8 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 @@ -64,6 +64,6 @@ public class BrokerRestHttpsTest extends QpidRestTestCase Asserts.assertAttributesPresent(brokerDetails, Broker.AVAILABLE_ATTRIBUTES, Broker.BYTES_RETAINED, Broker.PROCESS_PID, Broker.SUPPORTED_STORE_TYPES, Broker.CREATED, Broker.TIME_TO_LIVE, Broker.UPDATED, - Broker.ACL_FILE, Broker.GROUP_FILE); + Broker.ACL_FILE); } } 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 677b5cb18c..7b1b1ca8be 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 @@ -39,12 +39,20 @@ import org.apache.qpid.test.utils.TestBrokerConfiguration; public class BrokerRestTest extends QpidRestTestCase { - private static final String BROKER_AUTHENTICATIONPROVIDERS_ATTRIBUTE = "authenticationproviders"; private static final String BROKER_PORTS_ATTRIBUTE = "ports"; 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<String, Object> brokerDetails = getRestTestHelper().getJsonAsSingletonList("/rest/broker"); @@ -140,7 +148,6 @@ public class BrokerRestTest extends QpidRestTestCase 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.GROUP_FILE, QpidTestCase.QPID_HOME + File.separator + "etc" + File.separator + "groups-non-existing"); 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); @@ -181,7 +188,6 @@ public class BrokerRestTest extends QpidRestTestCase 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.GROUP_FILE, QpidTestCase.QPID_HOME + File.separator + "etc" + File.separator + "groups"); 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); @@ -205,7 +211,7 @@ public class BrokerRestTest extends QpidRestTestCase { Asserts.assertAttributesPresent(brokerDetails, Broker.AVAILABLE_ATTRIBUTES, Broker.BYTES_RETAINED, Broker.PROCESS_PID, Broker.SUPPORTED_STORE_TYPES, - Broker.CREATED, Broker.TIME_TO_LIVE, Broker.UPDATED, Broker.ACL_FILE, Broker.GROUP_FILE); + Broker.CREATED, Broker.TIME_TO_LIVE, Broker.UPDATED, Broker.ACL_FILE); 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/systest/rest/GroupProviderRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/GroupProviderRestTest.java index 861bf8cb71..ef8e12a929 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/GroupProviderRestTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/GroupProviderRestTest.java @@ -22,20 +22,23 @@ package org.apache.qpid.systest.rest; import java.io.File; import java.io.FileOutputStream; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; -import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.Group; import org.apache.qpid.server.model.GroupProvider; import org.apache.qpid.server.model.LifetimePolicy; import org.apache.qpid.server.model.State; import org.apache.qpid.server.model.UUIDGenerator; +import org.apache.qpid.server.security.group.FileGroupManagerFactory; +import org.apache.qpid.test.utils.TestBrokerConfiguration; +import org.apache.qpid.test.utils.TestFileUtils; public class GroupProviderRestTest extends QpidRestTestCase { - private static final String FILE_GROUP_MANAGER = "FileGroupManager"; + private static final String FILE_GROUP_MANAGER = TestBrokerConfiguration.ENTRY_NAME_GROUP_FILE; private File _groupFile; @Override @@ -43,7 +46,7 @@ public class GroupProviderRestTest extends QpidRestTestCase { _groupFile = createTemporaryGroupFile(); - getBrokerConfiguration().setBrokerAttribute(Broker.GROUP_FILE, _groupFile.getAbsolutePath()); + getBrokerConfiguration().addGroupFileConfiguration(_groupFile.getAbsolutePath()); super.setUp(); } @@ -69,11 +72,11 @@ public class GroupProviderRestTest extends QpidRestTestCase assertEquals("Unexpected number of providers", 1, providerDetails.size()); for (Map<String, Object> provider : providerDetails) { - assertProvider(FILE_GROUP_MANAGER, provider); + assertProvider(FILE_GROUP_MANAGER, FileGroupManagerFactory.GROUP_FILE_PROVIDER_TYPE, provider); Map<String, Object> data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + provider.get(GroupProvider.NAME)); assertNotNull("Cannot load data for " + provider.get(GroupProvider.NAME), data); - assertProvider(FILE_GROUP_MANAGER, data); + assertProvider(FILE_GROUP_MANAGER, FileGroupManagerFactory.GROUP_FILE_PROVIDER_TYPE, data); } } @@ -111,8 +114,178 @@ public class GroupProviderRestTest extends QpidRestTestCase getRestTestHelper().assertNumberOfGroups(data, 0); } + public void testCreateNewFileGroupProviderFromExistingGroupFile() throws Exception + { + String[] groupMemberNames = {"test1","test2"}; + File groupFile = TestFileUtils.createTempFile(this, ".groups", "testusers.users=" + groupMemberNames[0] + "," + groupMemberNames[1]); + try + { + String providerName = getTestName(); + Map<String, Object> attributes = new HashMap<String, Object>(); + attributes.put(GroupProvider.NAME, providerName); + attributes.put(GroupProvider.TYPE, FileGroupManagerFactory.GROUP_FILE_PROVIDER_TYPE); + attributes.put(FileGroupManagerFactory.PATH, groupFile.getAbsolutePath()); + + int responseCode = getRestTestHelper().submitRequest("/rest/groupprovider/" + providerName, "PUT", attributes); + assertEquals("Group provider was not created", 201, responseCode); + + Map<String, Object> data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + providerName + "?depth=2"); + assertProvider(providerName, FileGroupManagerFactory.GROUP_FILE_PROVIDER_TYPE, data); + assertEquals("Unexpected name", providerName, data.get(GroupProvider.NAME)); + assertEquals("Unexpected path", groupFile.getAbsolutePath(), data.get(FileGroupManagerFactory.PATH)); + + @SuppressWarnings("unchecked") + List<Map<String, Object>> groups = (List<Map<String, Object>>) data.get("groups"); + assertEquals("Unexpected group size", 1, groups.size()); + Map<String, Object> group = groups.get(0); + assertEquals("Unexpected group name", "testusers",group.get("name")); + + @SuppressWarnings("unchecked") + List<Map<String, Object>> groupMemberList = (List<Map<String, Object>>) group.get("groupmembers"); + assertEquals("Unexpected group members size", 2, groupMemberList.size()); + + for (String memberName : groupMemberNames) + { + boolean found = false; + for (Map<String, Object> memberData : groupMemberList) + { + Object name = memberData.get("name"); + if (memberName.equals(name)) + { + found = true; + break; + } + } + assertTrue("Cannot find group member " + memberName + " in " + groupMemberList , found); + } + } + finally + { + groupFile.delete(); + } + } + + public void testCreationOfNewFileGroupProviderFailsWhenPathIsMissed() throws Exception + { + String providerName = getTestName(); + Map<String, Object> attributes = new HashMap<String, Object>(); + attributes.put(GroupProvider.NAME, providerName); + attributes.put(GroupProvider.TYPE, FileGroupManagerFactory.GROUP_FILE_PROVIDER_TYPE); + + int responseCode = getRestTestHelper().submitRequest("/rest/groupprovider/" + providerName, "PUT", attributes); + assertEquals("Group provider was created", 409, responseCode); + } + + public void testCreateNewFileGroupProviderFromNonExistingGroupFile() throws Exception + { + File groupFile = new File(TMP_FOLDER + File.separator + getTestName() + File.separator + "groups"); + assertFalse("Group file should not exist", groupFile.exists()); + try + { + String providerName = getTestName(); + Map<String, Object> attributes = new HashMap<String, Object>(); + attributes.put(GroupProvider.NAME, providerName); + attributes.put(GroupProvider.TYPE, FileGroupManagerFactory.GROUP_FILE_PROVIDER_TYPE); + attributes.put(FileGroupManagerFactory.PATH, groupFile.getAbsolutePath()); + + int responseCode = getRestTestHelper().submitRequest("/rest/groupprovider/" + providerName, "PUT", attributes); + assertEquals("Group provider was not created", 201, responseCode); + + Map<String, Object> data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + providerName); + assertEquals("Unexpected name", providerName, data.get(GroupProvider.NAME)); + assertEquals("Unexpected path", groupFile.getAbsolutePath(), data.get(FileGroupManagerFactory.PATH)); + + @SuppressWarnings("unchecked") + List<Map<String, Object>> groups = (List<Map<String, Object>>) data.get("groups"); + assertNull("Unexpected groups", groups); + + assertTrue("Group file has not been created", groupFile.exists()); + } + finally + { + groupFile.delete(); + groupFile.getParentFile().delete(); + } + } + + public void testCreateNewFileGroupProviderForTheSameGroupFileFails() throws Exception + { + File groupFile = TestFileUtils.createTempFile(this, ".groups", "testusers.users=test1,test2"); + String providerName = getTestName(); + try + { + Map<String, Object> attributes = new HashMap<String, Object>(); + attributes.put(GroupProvider.NAME, providerName); + attributes.put(GroupProvider.TYPE, FileGroupManagerFactory.GROUP_FILE_PROVIDER_TYPE); + attributes.put(FileGroupManagerFactory.PATH, groupFile.getAbsolutePath()); + + int responseCode = getRestTestHelper().submitRequest("/rest/groupprovider/" + providerName, "PUT", attributes); + assertEquals("Group provider was not created", 201, responseCode); + + attributes.put(GroupProvider.NAME, providerName + 2); + responseCode = getRestTestHelper().submitRequest("/rest/groupprovider/" + providerName + 2, "PUT", attributes); + assertEquals("Group provider for the same group file was created", 409, responseCode); + } + finally + { + groupFile.delete(); + } + } + + public void testDeleteGroupProvider() throws Exception + { + File groupFile = TestFileUtils.createTempFile(this, ".groups", "testusers.users=test1,test2"); + String providerName = getTestName(); + try + { + Map<String, Object> attributes = new HashMap<String, Object>(); + attributes.put(GroupProvider.NAME, providerName); + attributes.put(GroupProvider.TYPE, FileGroupManagerFactory.GROUP_FILE_PROVIDER_TYPE); + attributes.put(FileGroupManagerFactory.PATH, groupFile.getAbsolutePath()); + + int responseCode = getRestTestHelper().submitRequest("/rest/groupprovider/" + providerName, "PUT", attributes); + assertEquals("Expected to fail because we can have only one password provider", 201, responseCode); + + responseCode = getRestTestHelper().submitRequest("/rest/groupprovider/" + providerName , "DELETE", null); + assertEquals("Group provider was not deleted", 200, responseCode); + + List<Map<String, Object>> providerDetails = getRestTestHelper().getJsonAsList("/rest/groupprovider/" + providerName); + assertEquals("Provider was not deleted", 0, providerDetails.size()); + assertFalse("Groups file should be deleted", groupFile.exists()); + } + finally + { + groupFile.delete(); + } + } + + public void testUpdateGroupProviderAttributesFails() throws Exception + { + File groupFile = TestFileUtils.createTempFile(this, ".groups", "testusers.users=test1,test2"); + String providerName = getTestName(); + try + { + Map<String, Object> attributes = new HashMap<String, Object>(); + attributes.put(GroupProvider.NAME, providerName); + attributes.put(GroupProvider.TYPE, FileGroupManagerFactory.GROUP_FILE_PROVIDER_TYPE); + attributes.put(FileGroupManagerFactory.PATH, groupFile.getAbsolutePath()); + + int responseCode = getRestTestHelper().submitRequest("/rest/groupprovider/" + providerName, "PUT", attributes); + assertEquals("Expected to fail because we can have only one password provider", 201, responseCode); + + File newGroupFile = new File(TMP_FOLDER + File.separator + getTestName() + File.separator + "groups"); + attributes.put(FileGroupManagerFactory.PATH, newGroupFile.getAbsolutePath()); + + responseCode = getRestTestHelper().submitRequest("/rest/groupprovider/" + providerName, "PUT", attributes); + assertEquals("Expected to fail because we can have only one password provider", 409, responseCode); + } + finally + { + groupFile.delete(); + } + } - private void assertProvider(String type, Map<String, Object> provider) + private void assertProvider(String name, String type, Map<String, Object> provider) { Asserts.assertAttributesPresent(provider, GroupProvider.AVAILABLE_ATTRIBUTES, GroupProvider.CREATED, GroupProvider.UPDATED, GroupProvider.DESCRIPTION, @@ -126,9 +299,8 @@ public class GroupProviderRestTest extends QpidRestTestCase assertEquals("Unexpected value of provider attribute " + GroupProvider.TYPE, type, provider.get(GroupProvider.TYPE)); - final String name = (String) provider.get(GroupProvider.NAME); - assertEquals("Unexpected value of provider attribute " + GroupProvider.NAME, type, - name); + assertEquals("Unexpected value of provider attribute " + GroupProvider.NAME, name, + (String) provider.get(GroupProvider.NAME)); @SuppressWarnings("unchecked") List<Map<String, Object>> groups = (List<Map<String, Object>>) provider.get("groups"); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/GroupRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/GroupRestTest.java index d3f93cc0fe..67e50b1bd1 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/GroupRestTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/GroupRestTest.java @@ -26,13 +26,13 @@ import java.util.List; import java.util.Map; import java.util.Properties; -import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.GroupMember; +import org.apache.qpid.test.utils.TestBrokerConfiguration; public class GroupRestTest extends QpidRestTestCase { private static final String GROUP_NAME = "myGroup"; - private static final String FILE_GROUP_MANAGER = "FileGroupManager"; + private static final String FILE_GROUP_MANAGER = TestBrokerConfiguration.ENTRY_NAME_GROUP_FILE; private static final String EXISTING_MEMBER = "user1"; private static final String NEW_MEMBER = "user2"; @@ -43,7 +43,7 @@ public class GroupRestTest extends QpidRestTestCase { _groupFile = createTemporaryGroupFile(); - getBrokerConfiguration().setBrokerAttribute(Broker.GROUP_FILE, _groupFile.getAbsolutePath()); + getBrokerConfiguration().addGroupFileConfiguration(_groupFile.getAbsolutePath()); super.setUp(); } @@ -64,7 +64,7 @@ public class GroupRestTest extends QpidRestTestCase public void testGet() throws Exception { - Map<String, Object> group = getRestTestHelper().getJsonAsSingletonList("/rest/group/FileGroupManager/myGroup"); + Map<String, Object> group = getRestTestHelper().getJsonAsSingletonList("/rest/group/" + FILE_GROUP_MANAGER + "/myGroup"); List<Map<String, Object>> groupmembers = (List<Map<String, Object>>) group.get("groupmembers"); assertEquals(1, groupmembers.size()); @@ -74,23 +74,23 @@ public class GroupRestTest extends QpidRestTestCase public void testCreateNewMemberOfGroup() throws Exception { - Map<String, Object> group = getRestTestHelper().getJsonAsSingletonList("/rest/group/FileGroupManager/myGroup"); + Map<String, Object> group = getRestTestHelper().getJsonAsSingletonList("/rest/group/" + FILE_GROUP_MANAGER + "/myGroup"); getRestTestHelper().assertNumberOfGroupMembers(group, 1); getRestTestHelper().createNewGroupMember(FILE_GROUP_MANAGER, GROUP_NAME, NEW_MEMBER); - group = getRestTestHelper().getJsonAsSingletonList("/rest/group/FileGroupManager/myGroup"); + group = getRestTestHelper().getJsonAsSingletonList("/rest/group/" + FILE_GROUP_MANAGER + "/myGroup"); getRestTestHelper().assertNumberOfGroupMembers(group, 2); } public void testRemoveMemberFromGroup() throws Exception { - Map<String, Object> group = getRestTestHelper().getJsonAsSingletonList("/rest/group/FileGroupManager/myGroup"); + Map<String, Object> group = getRestTestHelper().getJsonAsSingletonList("/rest/group/" + FILE_GROUP_MANAGER + "/myGroup"); getRestTestHelper().assertNumberOfGroupMembers(group, 1); getRestTestHelper().removeMemberFromGroup(FILE_GROUP_MANAGER, GROUP_NAME, EXISTING_MEMBER); - group = getRestTestHelper().getJsonAsSingletonList("/rest/group/FileGroupManager/myGroup"); + group = getRestTestHelper().getJsonAsSingletonList("/rest/group/" + FILE_GROUP_MANAGER + "/myGroup"); getRestTestHelper().assertNumberOfGroupMembers(group, 0); } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/BrokerACLTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/BrokerACLTest.java index ce4c869e66..c8225b37e4 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/BrokerACLTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/BrokerACLTest.java @@ -30,6 +30,7 @@ import java.util.Map; import org.apache.commons.configuration.ConfigurationException; import org.apache.qpid.server.model.AuthenticationProvider; import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.GroupProvider; import org.apache.qpid.server.model.KeyStore; import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.Protocol; @@ -38,6 +39,7 @@ import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.security.acl.AbstractACLTestCase; import org.apache.qpid.server.security.auth.manager.AnonymousAuthenticationManagerFactory; import org.apache.qpid.server.security.auth.manager.PlainPasswordFileAuthenticationManagerFactory; +import org.apache.qpid.server.security.group.FileGroupManagerFactory; import org.apache.qpid.systest.rest.QpidRestTestCase; import org.apache.qpid.test.utils.TestBrokerConfiguration; import org.apache.qpid.test.utils.TestFileUtils; @@ -636,6 +638,122 @@ public class BrokerACLTest extends QpidRestTestCase brokerAttributes.get(Broker.QUEUE_ALERT_REPEAT_GAP)); } + /* === GroupProvider === */ + + public void testCreateGroupProviderAllowed() throws Exception + { + getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); + + String groupProviderName = getTestName(); + + assertGroupProviderExistence(groupProviderName, false); + + int responseCode = createGroupProvider(groupProviderName); + assertEquals("Group provider creation should be allowed", 201, responseCode); + + assertGroupProviderExistence(groupProviderName, true); + } + + public void testCreateGroupProviderDenied() throws Exception + { + getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER); + + String groupProviderName = getTestName(); + + assertGroupProviderExistence(groupProviderName, false); + + int responseCode = createGroupProvider(groupProviderName); + assertEquals("Group provider creation should be denied", 403, responseCode); + + assertGroupProviderExistence(groupProviderName, false); + } + + public void testDeleteGroupProviderDenied() throws Exception + { + getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); + + String groupProviderName = getTestName(); + + assertGroupProviderExistence(groupProviderName, false); + + int responseCode = createGroupProvider(groupProviderName); + assertEquals("Group provider creation should be allowed", 201, responseCode); + + assertGroupProviderExistence(groupProviderName, true); + + getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER); + + responseCode = getRestTestHelper().submitRequest("/rest/groupprovider/" + groupProviderName, "DELETE", null); + assertEquals("Group provider deletion should be denied", 403, responseCode); + + assertGroupProviderExistence(groupProviderName, true); + } + + public void testDeleteGroupProviderAllowed() throws Exception + { + getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); + + String groupProviderName = getTestName(); + + assertGroupProviderExistence(groupProviderName, false); + + int responseCode = createGroupProvider(groupProviderName); + assertEquals("Group provider creation should be allowed", 201, responseCode); + + assertGroupProviderExistence(groupProviderName, true); + + getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); + + responseCode = getRestTestHelper().submitRequest("/rest/groupprovider/" + groupProviderName, "DELETE", null); + assertEquals("Group provider deletion should be allowed", 200, responseCode); + + assertGroupProviderExistence(groupProviderName, false); + } + + public void testSetGroupProviderAttributesAllowed() throws Exception + { + getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); + + String groupProviderName = getTestName(); + + assertGroupProviderExistence(groupProviderName, false); + + int responseCode = createGroupProvider(groupProviderName); + assertEquals("Group provider creation should be allowed", 201, responseCode); + + assertGroupProviderExistence(groupProviderName, true); + + Map<String, Object> attributes = new HashMap<String, Object>(); + attributes.put(GroupProvider.NAME, groupProviderName); + attributes.put(GroupProvider.TYPE, FileGroupManagerFactory.GROUP_FILE_PROVIDER_TYPE); + attributes.put(FileGroupManagerFactory.PATH, "/path/to/file"); + responseCode = getRestTestHelper().submitRequest("/rest/groupprovider/" + groupProviderName, "PUT", attributes); + assertEquals("Setting of group provider attributes should be allowed but not supported", 409, responseCode); + } + + public void testSetGroupProviderAttributesDenied() throws Exception + { + getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); + + String groupProviderName = getTestName(); + + assertGroupProviderExistence(groupProviderName, false); + + int responseCode = createGroupProvider(groupProviderName); + assertEquals("Group provider creation should be allowed", 201, responseCode); + + assertGroupProviderExistence(groupProviderName, true); + + getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER); + + Map<String, Object> attributes = new HashMap<String, Object>(); + attributes.put(GroupProvider.NAME, groupProviderName); + attributes.put(GroupProvider.TYPE, FileGroupManagerFactory.GROUP_FILE_PROVIDER_TYPE); + attributes.put(FileGroupManagerFactory.PATH, "/path/to/file"); + responseCode = getRestTestHelper().submitRequest("/rest/groupprovider/" + groupProviderName, "PUT", attributes); + assertEquals("Setting of group provider attributes should be denied", 403, responseCode); + } + private int createPort(String portName) throws Exception { Map<String, Object> attributes = new HashMap<String, Object>(); @@ -752,4 +870,22 @@ public class BrokerACLTest extends QpidRestTestCase return getRestTestHelper().submitRequest("/rest/truststore/" + name, "PUT", trustStoreAttributes); } + + private void assertGroupProviderExistence(String groupProviderName, boolean exists) throws Exception + { + String path = "/rest/groupprovider/" + groupProviderName; + List<Map<String, Object>> providers = getRestTestHelper().getJsonAsList(path); + assertEquals("Unexpected result", exists, !providers.isEmpty()); + } + + private int createGroupProvider(String groupProviderName) throws Exception + { + File file = TestFileUtils.createTempFile(this, ".groups"); + Map<String, Object> attributes = new HashMap<String, Object>(); + attributes.put(GroupProvider.NAME, groupProviderName); + attributes.put(GroupProvider.TYPE, FileGroupManagerFactory.GROUP_FILE_PROVIDER_TYPE); + attributes.put(FileGroupManagerFactory.PATH, file.getAbsoluteFile()); + + return getRestTestHelper().submitRequest("/rest/groupprovider/" + groupProviderName, "PUT", attributes); + } } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/GroupRestACLTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/GroupRestACLTest.java index 40ea723b1e..3fceb27a4b 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/GroupRestACLTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/GroupRestACLTest.java @@ -29,14 +29,13 @@ import java.util.Properties; import javax.servlet.http.HttpServletResponse; import org.apache.commons.configuration.ConfigurationException; -import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.security.acl.AbstractACLTestCase; import org.apache.qpid.systest.rest.QpidRestTestCase; import org.apache.qpid.test.utils.TestBrokerConfiguration; public class GroupRestACLTest extends QpidRestTestCase { - private static final String FILE_GROUP_MANAGER = "FileGroupManager"; + private static final String FILE_GROUP_MANAGER = TestBrokerConfiguration.ENTRY_NAME_GROUP_FILE; private static final String ALLOWED_GROUP = "allowedGroup"; private static final String DENIED_GROUP = "deniedGroup"; @@ -52,7 +51,7 @@ public class GroupRestACLTest extends QpidRestTestCase public void setUp() throws Exception { _groupFile = createTemporaryGroupFile(); - getBrokerConfiguration().setBrokerAttribute(Broker.GROUP_FILE, _groupFile.getAbsolutePath()); + getBrokerConfiguration().addGroupFileConfiguration(_groupFile.getAbsolutePath()); //DONT call super.setUp(), the tests will start the broker after configuring it } @@ -191,7 +190,7 @@ public class GroupRestACLTest extends QpidRestTestCase private void assertNumberOfGroupMembers(String groupName, int expectedNumberOfMembers) throws IOException { - Map<String, Object> group = getRestTestHelper().getJsonAsSingletonList("/rest/group/FileGroupManager/" + groupName); + Map<String, Object> group = getRestTestHelper().getJsonAsSingletonList("/rest/group/" + FILE_GROUP_MANAGER + "/" + groupName); getRestTestHelper().assertNumberOfGroupMembers(group, expectedNumberOfMembers); } } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/UserRestACLTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/UserRestACLTest.java index 12973113d8..3b81df6fd1 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/UserRestACLTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/UserRestACLTest.java @@ -29,7 +29,6 @@ import java.util.Properties; import javax.servlet.http.HttpServletResponse; import org.apache.commons.configuration.ConfigurationException; -import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.security.acl.AbstractACLTestCase; import org.apache.qpid.systest.rest.QpidRestTestCase; import org.apache.qpid.test.utils.TestBrokerConfiguration; @@ -52,7 +51,7 @@ public class UserRestACLTest extends QpidRestTestCase public void setUp() throws Exception { _groupFile = createTemporaryGroupFile(); - getBrokerConfiguration().setBrokerAttribute(Broker.GROUP_FILE, _groupFile.getAbsolutePath()); + getBrokerConfiguration().addGroupFileConfiguration(_groupFile.getAbsolutePath()); getRestTestHelper().configureTemporaryPasswordFile(this, ALLOWED_USER, DENIED_USER, OTHER_USER); 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 6157947a83..f37ba720b7 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 @@ -33,13 +33,16 @@ 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.AuthenticationProvider; +import org.apache.qpid.server.model.GroupProvider; import org.apache.qpid.server.model.KeyStore; 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.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.group.FileGroupManagerFactory; public class TestBrokerConfiguration { @@ -58,6 +61,7 @@ public class TestBrokerConfiguration public static final String ENTRY_NAME_ANONYMOUS_PROVIDER = "anonymous"; 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"; private MemoryConfigurationEntryStore _store; private boolean _saved; @@ -132,6 +136,16 @@ public class TestBrokerConfiguration return addObjectConfiguration(ENTRY_NAME_HTTP_MANAGEMENT, Plugin.class.getSimpleName(), attributes); } + public UUID addGroupFileConfiguration(String groupFilePath) + { + Map<String, Object> attributes = new HashMap<String, Object>(); + attributes.put(GroupProvider.NAME, ENTRY_NAME_GROUP_FILE); + attributes.put(GroupManagerFactory.ATTRIBUTE_TYPE, FileGroupManagerFactory.GROUP_FILE_PROVIDER_TYPE); + attributes.put(FileGroupManagerFactory.PATH, groupFilePath); + + return addGroupProviderConfiguration(attributes); + } + public UUID addPortConfiguration(Map<String, Object> attributes) { String name = (String) attributes.get(Port.NAME); @@ -150,6 +164,12 @@ public class TestBrokerConfiguration return addObjectConfiguration(name, AuthenticationProvider.class.getSimpleName(), attributes); } + public UUID addGroupProviderConfiguration(Map<String, Object> attributes) + { + String name = (String) attributes.get(GroupProvider.NAME); + return addObjectConfiguration(name, GroupProvider.class.getSimpleName(), attributes); + } + public UUID addTrustStoreConfiguration(Map<String, Object> attributes) { String name = (String) attributes.get(TrustStore.NAME); |