diff options
author | Alex Rudyy <orudyy@apache.org> | 2013-04-17 10:53:55 +0000 |
---|---|---|
committer | Alex Rudyy <orudyy@apache.org> | 2013-04-17 10:53:55 +0000 |
commit | 532bc2b78fb4a136fe035d68e3146ec7b2fa40aa (patch) | |
tree | 11a46855f979d79063eb2d61a7fceac31e727041 | |
parent | b4af6b6cd3abbbbde7ce1c2799ffde2a1bbcff91 (diff) | |
download | qpid-python-532bc2b78fb4a136fe035d68e3146ec7b2fa40aa.tar.gz |
QPID-4746, QPID-4747: remove the defaultAuthenticationProvider attribute from broker and add an overriding authentication provider for management mode
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1468830 13f79535-47bb-0310-9956-ffa450edef68
54 files changed, 1059 insertions, 660 deletions
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java index 3cc382596a..b87b1c76f0 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java @@ -22,6 +22,7 @@ package org.apache.qpid.server.management.plugin; import java.io.File; import java.lang.reflect.Type; +import java.net.SocketAddress; import java.util.Collection; import java.util.Collections; import java.util.EnumSet; @@ -67,6 +68,7 @@ import org.apache.qpid.server.model.User; import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.model.adapter.AbstractPluginAdapter; import org.apache.qpid.server.plugin.PluginFactory; +import org.apache.qpid.server.security.SubjectCreator; import org.apache.qpid.server.util.MapValueConverter; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.DispatcherType; @@ -407,24 +409,34 @@ public class HttpManagement extends AbstractPluginAdapter implements HttpManagem return Collections.unmodifiableCollection(AVAILABLE_ATTRIBUTES); } + @Override public boolean isHttpsSaslAuthenticationEnabled() { return (Boolean)getAttribute(HTTPS_SASL_AUTHENTICATION_ENABLED); } + @Override public boolean isHttpSaslAuthenticationEnabled() { return (Boolean)getAttribute(HTTP_SASL_AUTHENTICATION_ENABLED); } + @Override public boolean isHttpsBasicAuthenticationEnabled() { return (Boolean)getAttribute(HTTPS_BASIC_AUTHENTICATION_ENABLED); } + @Override public boolean isHttpBasicAuthenticationEnabled() { return (Boolean)getAttribute(HTTP_BASIC_AUTHENTICATION_ENABLED); } + @Override + public SubjectCreator getSubjectCreator(SocketAddress localAddress) + { + return _broker.getSubjectCreator(localAddress); + } + } diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagementConfiguration.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagementConfiguration.java index 104fe42f46..56919e2e6b 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagementConfiguration.java +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagementConfiguration.java @@ -20,6 +20,10 @@ */ package org.apache.qpid.server.management.plugin; +import java.net.SocketAddress; + +import org.apache.qpid.server.security.SubjectCreator; + public interface HttpManagementConfiguration { boolean isHttpsSaslAuthenticationEnabled(); @@ -29,4 +33,6 @@ public interface HttpManagementConfiguration boolean isHttpsBasicAuthenticationEnabled(); boolean isHttpBasicAuthenticationEnabled(); + + SubjectCreator getSubjectCreator(SocketAddress localAddress); } diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagementUtil.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagementUtil.java index 68ec9f532c..4c6e5bf63e 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagementUtil.java +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagementUtil.java @@ -85,13 +85,13 @@ public class HttpManagementUtil } public static void checkRequestAuthenticatedAndAccessAuthorized(HttpServletRequest request, Broker broker, - HttpManagementConfiguration management) + HttpManagementConfiguration managementConfig) { HttpSession session = request.getSession(); Subject subject = getAuthorisedSubject(session); if (subject == null) { - subject = tryToAuthenticate(request, broker, management); + subject = tryToAuthenticate(request, managementConfig); if (subject == null) { throw new SecurityException("Only authenticated users can access the management interface"); @@ -164,11 +164,11 @@ public class HttpManagementUtil session.setAttribute(ATTR_LOGIN_LOGOUT_REPORTER, new LoginLogoutReporter(logActor, subject)); } - private static Subject tryToAuthenticate(HttpServletRequest request, Broker broker, HttpManagementConfiguration management) + private static Subject tryToAuthenticate(HttpServletRequest request, HttpManagementConfiguration managementConfig) { Subject subject = null; SocketAddress localAddress = getSocketAddress(request); - SubjectCreator subjectCreator = broker.getSubjectCreator(localAddress); + SubjectCreator subjectCreator = managementConfig.getSubjectCreator(localAddress); String remoteUser = request.getRemoteUser(); if (remoteUser != null || subjectCreator.isAnonymousAuthenticationAllowed()) @@ -186,11 +186,11 @@ public class HttpManagementUtil boolean isBasicAuthSupported = false; if (request.isSecure()) { - isBasicAuthSupported = management.isHttpsBasicAuthenticationEnabled(); + isBasicAuthSupported = managementConfig.isHttpsBasicAuthenticationEnabled(); } else { - isBasicAuthSupported = management.isHttpBasicAuthenticationEnabled(); + isBasicAuthSupported = managementConfig.isHttpBasicAuthenticationEnabled(); } if (isBasicAuthSupported) { diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/addPort.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/addPort.html index 391783c6d8..b800d8e067 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/addPort.html +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/addPort.html @@ -26,19 +26,21 @@ <input type="text" required="true" name="name" id="formAddPort.name" placeholder="Name" data-dojo-props="label: 'Name*:'" dojoType="dijit.form.ValidationTextBox" missingMessage="A name must be supplied" regexp="^[\x20-\x2e\x30-\x7F]{1,255}$"/> - <input data-dojo-type="dijit.form.NumberSpinner" id="formAddPort.port" required="true" data-dojo-props="label: 'Port Number*:'" + <input data-dojo-type="dijit.form.NumberSpinner" id="formAddPort.port" required="true" data-dojo-props="label: 'Port Number*:', placeHolder: 'Enter port number'" name="port" smallDelta="1" constraints="{min:1,max:65535,places:0, pattern: '#####'}" missingMessage="A port number must be supplied" /> - <select id="formAddPort.authenticationProvider" data-dojo-type="dijit.form.FilteringSelect" - data-dojo-props="name:'authenticationProvider',label:'Authentication Provider:', searchAttr: 'name', required: false, placeHolder: 'Default', value: '' "> - </select> <select id="formAddPort.type" data-dojo-type="dijit.form.FilteringSelect" - data-dojo-props="name: 'type', value: '',placeHolder: 'Select Port Type', label: 'Port Type:'"> + data-dojo-props="name: 'type', value: '',placeHolder: 'Select Port Type', label: 'Port Type*:'"> <option value="AMQP" selected="selected">AMQP</option> <option value="JMX">JMX</option> <option value="HTTP">HTTP</option> </select> </div> + <div id="formAddPort:fieldsAuthenticationProvider"> + <select id="formAddPort.authenticationProvider" data-dojo-type="dijit.form.FilteringSelect" + data-dojo-props="name:'authenticationProvider',label:'Authentication Provider*:', searchAttr: 'name', required: true, placeHolder: 'Select Provider'"> + </select> + </div> <div id="formAddPort:fieldsAMQP"> <input id="formAddPort.bindingAddress" type="text" name="bindingAddress" placeholder="*" dojoType="dijit.form.TextBox" data-dojo-props="label: 'Binding address:'"/> @@ -82,7 +84,7 @@ </select> </div> <div id="formAddPort:fieldsClientAuth"> - <div id="formAddPort:fieldsClientAuth2"> + <div id="formAddPort:fieldsClientAuthCheckboxes"> <input id="formAddPort.needClientAuth" type="checkbox" name="needClientAuth" dojoType="dijit.form.CheckBox" data-dojo-props="label: 'Need SSL Client Certificate:'" /> <input id="formAddPort.wantClientAuth" type="checkbox" name="wantClientAuth" diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/index.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/index.html index c4fbe77b08..c0a512d829 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/index.html +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/index.html @@ -77,7 +77,7 @@ <div id="header" class="header" style="float: left; width: 300px"></div> <div id="login" style="float: right"></div> </div> - <div data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region:'leading', splitter: true"> + <div data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region:'leading', splitter: true" style="width:20%"> <div qpid-type="treeView" qpid-props="query: 'rest/structure'" ></div> </div> <div id="managedViews" data-dojo-type="dijit.layout.TabContainer" data-dojo-props="region:'center', tabPosition: 'top'"> 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 b07b68c835..fe5f238148 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 @@ -233,7 +233,7 @@ define(["dojo/_base/xhr", checked: brokerData["queue.deadLetterQueueEnabled"], value: "true", label: "Dead letter queue enabled:", - name: "queue.deadLetterQueueEnabled", + name: "queue.deadLetterQueueEnabled" }); } }, { @@ -247,7 +247,7 @@ define(["dojo/_base/xhr", value: brokerData["queue.flowControlSizeBytes"], placeholder: "Size in bytes", label: "Flow control threshold (bytes):", - name: "queue.flowControlSizeBytes", + name: "queue.flowControlSizeBytes" }); } }, { @@ -261,7 +261,7 @@ define(["dojo/_base/xhr", value: brokerData["queue.flowResumeSizeBytes"], placeholder: "Size in bytes", label: "Flow resume threshold (bytes):", - name: "queue.flowResumeSizeBytes", + name: "queue.flowResumeSizeBytes" }); } }, { @@ -530,7 +530,7 @@ define(["dojo/_base/xhr", new UpdatableStore(that.brokerData.ports, query(".broker-ports")[0], [ { name: "Name", field: "name", width: "150px"}, { name: "State", field: "state", width: "60px"}, - { name: "Authentication", field: "authenticationProvider", width: "100px"}, + { name: "Auth Provider", field: "authenticationProvider", width: "100px"}, { name: "Address", field: "bindingAddress", width: "70px"}, { name: "Port", field: "port", width: "50px"}, { name: "Transports", field: "transports", width: "100px"}, diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addPort.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addPort.js index c60ad5bb79..c3bfac5285 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addPort.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addPort.js @@ -224,25 +224,47 @@ define(["dojo/_base/xhr", { protocolsWidget.set("disabled", (isAMQP && defaultsAMQPProtocols.checked)); } + var transportWidget = registry.byId("formAddPort.transports"); + var disableTransportWidget = false; + var toggleSsl = true; + var isRMI = (newValue == "JMX" && registry.byId("formAddPort.protocolsJMX").value == "RMI"); + if (isRMI) + { + if (transportWidget.value != "TCP") + { + transportWidget.set("value", "TCP"); - var disabled = (newValue == "JMX" && registry.byId("formAddPort.protocolsJMX").value == "RMI"); - if (disabled && transportWidget.value != "TCP") + // changing of transport widget value will cause the call to toggleSslWidgets + toggleSsl = false; + } + disableTransportWidget = true; + } + else if (newValue == "HTTP" && registry.byId("formAddPort.protocolsHTTP").value == "HTTPS") { - transportWidget.set("value", "TCP"); + if (transportWidget.value != "SSL") + { + transportWidget.set("value", "SSL"); + + // changing of transport widget value will cause the call to toggleSslWidgets + toggleSsl = false; + } + disableTransportWidget = true; } - else + if (toggleSsl) { - toggleSslWidgets(newValue, transportWidget.value); + toggleSslWidgets(newValue, transportWidget.value); } - transportWidget.set("disabled", disabled); - + transportWidget.set("disabled", disableTransportWidget); + registry.byId("formAddPort.authenticationProvider").set("disabled", isRMI); + registry.byId("formAddPort:fieldsAuthenticationProvider").domNode.style.display = isRMI? "none" : "block"; }); theForm = registry.byId("formAddPort"); var containers = ["formAddPort:fields", "formAddPort:fieldsTransportSSL", "formAddPort:fieldsAMQP", - "formAddPort:fieldsJMX", "formAddPort:fieldsHTTP", "formAddPort:transport", "formAddPort:fieldsClientAuth2"]; + "formAddPort:fieldsJMX", "formAddPort:fieldsHTTP", "formAddPort:transport", + "formAddPort:fieldsClientAuthCheckboxes", "formAddPort:fieldsAuthenticationProvider"]; var labelWidthValue = "200"; for(var i = 0; i < containers.length; i++) { @@ -258,9 +280,24 @@ define(["dojo/_base/xhr", } registry.byId("formAddPort.protocolsJMX").on("change", function(newValue){ + var isRMI = newValue == "RMI"; + var transportWidget = registry.byId("formAddPort.transports"); + if (isRMI && transportWidget.value != "TCP") + { + transportWidget.set("value", "TCP"); + } + transportWidget.set("disabled", isRMI); + registry.byId("formAddPort:fieldsAuthenticationProvider").domNode.style.display = isRMI? "none" : "block"; + registry.byId("formAddPort.authenticationProvider").set("disabled", isRMI); + }); + + registry.byId("formAddPort.protocolsHTTP").on("change", function(newValue){ + var isHTTPS = newValue == "HTTPS"; var transportWidget = registry.byId("formAddPort.transports"); - transportWidget.set("value", "TCP"); - transportWidget.set("disabled", newValue == "RMI"); + if (isHTTPS && transportWidget.value != "SSL") { + transportWidget.set("value", "SSL"); + } + transportWidget.set("disabled", isHTTPS); }); theForm.on("submit", function(e) { diff --git a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/HttpManagementTest.java b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/HttpManagementTest.java new file mode 100644 index 0000000000..55606af117 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/HttpManagementTest.java @@ -0,0 +1,105 @@ +/* + * + * 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; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.security.SubjectCreator; +import org.apache.qpid.test.utils.QpidTestCase; + +public class HttpManagementTest extends QpidTestCase +{ + private UUID _id; + private Broker _broker; + private HttpManagement _management; + + @Override + public void setUp() throws Exception + { + super.setUp(); + _id = UUID.randomUUID(); + _broker = mock(Broker.class); + Map<String, Object> attributes = new HashMap<String, Object>(); + attributes.put(HttpManagement.HTTP_BASIC_AUTHENTICATION_ENABLED, false); + attributes.put(HttpManagement.HTTPS_BASIC_AUTHENTICATION_ENABLED, true); + attributes.put(HttpManagement.HTTP_SASL_AUTHENTICATION_ENABLED, false); + attributes.put(HttpManagement.HTTPS_SASL_AUTHENTICATION_ENABLED, true); + attributes.put(HttpManagement.NAME, getTestName()); + attributes.put(HttpManagement.TIME_OUT, 10000l); + _management = new HttpManagement(_id, _broker, attributes); + } + + public void testGetBroker() + { + assertEquals("Unexpected broker", _broker, _management.getBroker()); + } + + public void testGetSessionTimeout() + { + assertEquals("Unexpected session timeout", 10000l, _management.getSessionTimeout()); + } + + public void testGetName() + { + assertEquals("Unexpected name", getTestName(), _management.getName()); + } + + public void testIsHttpsSaslAuthenticationEnabled() + { + assertEquals("Unexpected value for the https sasl enabled attribute", true, + _management.isHttpsSaslAuthenticationEnabled()); + } + + public void testIsHttpSaslAuthenticationEnabled() + { + assertEquals("Unexpected value for the http sasl enabled attribute", false, _management.isHttpSaslAuthenticationEnabled()); + } + + public void testIsHttpsBasicAuthenticationEnabled() + { + assertEquals("Unexpected value for the https basic authentication enabled attribute", true, + _management.isHttpsBasicAuthenticationEnabled()); + } + + public void testIsHttpBasicAuthenticationEnabled() + { + assertEquals("Unexpected value for the http basic authentication enabled attribute", false, + _management.isHttpBasicAuthenticationEnabled()); + } + + public void testGetSubjectCreator() + { + SocketAddress localAddress = InetSocketAddress.createUnresolved("localhost", 8080); + SubjectCreator subjectCreator = mock(SubjectCreator.class); + when(_broker.getSubjectCreator(localAddress)).thenReturn(subjectCreator); + SubjectCreator httpManagementSubjectCreator = _management.getSubjectCreator(localAddress); + assertEquals("Unexpected subject creator", subjectCreator, httpManagementSubjectCreator); + } + +} diff --git a/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagedObjectRegistry.java b/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagedObjectRegistry.java index 62e88193bb..d094134e11 100644 --- a/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagedObjectRegistry.java +++ b/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagedObjectRegistry.java @@ -29,7 +29,7 @@ import org.apache.qpid.server.model.KeyStore; import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.Transport; -import org.apache.qpid.server.security.auth.rmi.RMIPasswordAuthenticator; +import org.apache.qpid.server.security.auth.jmx.JMXPasswordAuthenticator; import org.apache.qpid.ssl.SSLContextFactory; import javax.management.JMException; @@ -160,7 +160,7 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry int jmxPortConnectorServer = _connectorPort.getPort(); //add a JMXAuthenticator implementation the env map to authenticate the RMI based JMX connector server - RMIPasswordAuthenticator rmipa = new RMIPasswordAuthenticator(_broker, new InetSocketAddress(jmxPortConnectorServer)); + JMXPasswordAuthenticator rmipa = new JMXPasswordAuthenticator(_broker, new InetSocketAddress(jmxPortConnectorServer)); HashMap<String,Object> connectorEnv = new HashMap<String,Object>(); connectorEnv.put(JMXConnectorServer.AUTHENTICATOR, rmipa); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/Broker.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/Broker.java index 5f0c7c7d3c..dd0fde5f7a 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/Broker.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/Broker.java @@ -134,7 +134,7 @@ public class Broker _applicationRegistry = new ApplicationRegistry(store); try { - _applicationRegistry.initialise(); + _applicationRegistry.initialise(options); } catch(Exception e) { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/BrokerOptions.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/BrokerOptions.java index 8a8f7606a2..5c2a8fd090 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/BrokerOptions.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/BrokerOptions.java @@ -25,6 +25,7 @@ import java.io.File; import org.apache.qpid.server.configuration.BrokerProperties; import org.apache.qpid.server.configuration.ConfigurationEntryStore; import org.apache.qpid.server.configuration.store.MemoryConfigurationEntryStore; +import org.apache.qpid.server.util.StringUtil; public class BrokerOptions { @@ -34,6 +35,8 @@ public class BrokerOptions public static final String DEFAULT_LOG_CONFIG_FILE = "etc/log4j.xml"; public static final String DEFAULT_INITIAL_CONFIG_LOCATION = BrokerOptions.class.getClassLoader().getResource(DEFAULT_INITIAL_CONFIG_NAME).toExternalForm(); + public static final String MANAGEMENT_MODE_USER_NAME = "mm_admin"; + private static final int MANAGEMENT_MODE_PASSWORD_LENGTH = 10; private String _logConfigFile; private Integer _logWatchFrequency = 0; @@ -48,6 +51,7 @@ public class BrokerOptions private int _managementModeRmiPort; private int _managementModeConnectorPort; private int _managementModeHttpPort; + private String _managementModePassword; private String _workingDir; private boolean _skipLoggingConfiguration; private boolean _overwriteConfigurationStore; @@ -57,6 +61,21 @@ public class BrokerOptions return _logConfigFile; } + public String getManagementModePassword() + { + if(_managementModePassword == null) + { + _managementModePassword = new StringUtil().randomAlphaNumericString(MANAGEMENT_MODE_PASSWORD_LENGTH); + } + + return _managementModePassword; + } + + public void setManagementModePassword(String managementModePassword) + { + _managementModePassword = managementModePassword; + } + public void setLogConfigFile(final String logConfigFile) { _logConfigFile = logConfigFile; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java index 28827a8bb5..46612613dd 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java @@ -81,6 +81,8 @@ public class Main .withDescription("override jmx connector port in management mode").withLongOpt("management-mode-jmx-connector-port").create("mmjmx"); private static final Option OPTION_MM_HTTP_PORT = OptionBuilder.withArgName("port").hasArg() .withDescription("override http management port in management mode").withLongOpt("management-mode-http-port").create("mmhttp"); + private static final Option OPTION_MM_PASSWORD = OptionBuilder.withArgName("password").hasArg() + .withDescription("Set the password for the management mode user " + BrokerOptions.MANAGEMENT_MODE_USER_NAME).withLongOpt("management-mode-password").create("mmpass"); private static final Options OPTIONS = new Options(); @@ -100,6 +102,7 @@ public class Main OPTIONS.addOption(OPTION_MM_RMI_PORT); OPTIONS.addOption(OPTION_MM_CONNECTOR_PORT); OPTIONS.addOption(OPTION_MM_HTTP_PORT); + OPTIONS.addOption(OPTION_MM_PASSWORD); } protected CommandLine _commandLine; @@ -256,6 +259,12 @@ public class Main boolean quiesceVhosts = _commandLine.hasOption(OPTION_MM_QUIESCE_VHOST.getOpt()); options.setManagementModeQuiesceVirtualHosts(quiesceVhosts); + + String password = _commandLine.getOptionValue(OPTION_MM_PASSWORD.getOpt()); + if (password != null) + { + options.setManagementModePassword(password); + } } setExceptionHandler(); 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 7251abfab0..be75b4d2e9 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 @@ -26,6 +26,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import org.apache.qpid.server.BrokerOptions; import org.apache.qpid.server.configuration.ConfigurationEntry; import org.apache.qpid.server.configuration.ConfiguredObjectRecoverer; import org.apache.qpid.server.configuration.IllegalConfigurationException; @@ -55,10 +56,11 @@ public class BrokerRecoverer implements ConfiguredObjectRecoverer<Broker> private final AuthenticationProviderFactory _authenticationProviderFactory; private final PortFactory _portFactory; private final TaskExecutor _taskExecutor; + private final BrokerOptions _brokerOptions; public BrokerRecoverer(AuthenticationProviderFactory authenticationProviderFactory, PortFactory portFactory, StatisticsGatherer statisticsGatherer, VirtualHostRegistry virtualHostRegistry, LogRecorder logRecorder, - RootMessageLogger rootMessageLogger, TaskExecutor taskExecutor) + RootMessageLogger rootMessageLogger, TaskExecutor taskExecutor, BrokerOptions brokerOptions) { _portFactory = portFactory; _authenticationProviderFactory = authenticationProviderFactory; @@ -67,6 +69,7 @@ public class BrokerRecoverer implements ConfiguredObjectRecoverer<Broker> _logRecorder = logRecorder; _rootMessageLogger = rootMessageLogger; _taskExecutor = taskExecutor; + _brokerOptions = brokerOptions; } @Override @@ -74,38 +77,37 @@ 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()); + _logRecorder, _rootMessageLogger, _authenticationProviderFactory, _portFactory, _taskExecutor, entry.getStore(), _brokerOptions); broker.addChangeListener(storeChangeListener); //Recover the SSL keystores / truststores first, then others that depend on them Map<String, Collection<ConfigurationEntry>> childEntries = new HashMap<String, Collection<ConfigurationEntry>>(entry.getChildren()); - Map<String, Collection<ConfigurationEntry>> sslChildEntries = new HashMap<String, Collection<ConfigurationEntry>>(childEntries); + Map<String, Collection<ConfigurationEntry>> priorityChildEntries = new HashMap<String, Collection<ConfigurationEntry>>(childEntries); List<String> types = new ArrayList<String>(childEntries.keySet()); for(String type : types) { - if(KeyStore.class.getSimpleName().equals(type) || TrustStore.class.getSimpleName().equals(type)) + if(KeyStore.class.getSimpleName().equals(type) || TrustStore.class.getSimpleName().equals(type) + || AuthenticationProvider.class.getSimpleName().equals(type)) { childEntries.remove(type); } else { - sslChildEntries.remove(type); + priorityChildEntries.remove(type); } } - for (String type : sslChildEntries.keySet()) + for (String type : priorityChildEntries.keySet()) { - recoverType(recovererProvider, storeChangeListener, broker, sslChildEntries, type); + recoverType(recovererProvider, storeChangeListener, broker, priorityChildEntries, type); } for (String type : childEntries.keySet()) { recoverType(recovererProvider, storeChangeListener, broker, childEntries, type); } - wireUpConfiguredObjects(broker, entry.getAttributes()); - return broker; } @@ -132,58 +134,4 @@ public class BrokerRecoverer implements ConfiguredObjectRecoverer<Broker> object.addChangeListener(storeChangeListener); } } - - private void wireUpConfiguredObjects(BrokerAdapter broker, Map<String, Object> brokerAttributes) - { - AuthenticationProvider defaultAuthenticationProvider = null; - Collection<AuthenticationProvider> authenticationProviders = broker.getAuthenticationProviders(); - int numberOfAuthenticationProviders = authenticationProviders.size(); - if (numberOfAuthenticationProviders == 0) - { - throw new IllegalConfigurationException("No authentication provider was configured"); - } - else if (numberOfAuthenticationProviders == 1) - { - defaultAuthenticationProvider = authenticationProviders.iterator().next(); - } - else - { - String name = (String) brokerAttributes.get(Broker.DEFAULT_AUTHENTICATION_PROVIDER); - if (name == null) - { - throw new IllegalConfigurationException("Multiple authentication providers defined, but no default was configured."); - } - - defaultAuthenticationProvider = getAuthenticationProviderByName(broker, name); - } - broker.setDefaultAuthenticationProvider(defaultAuthenticationProvider); - - Collection<Port> ports = broker.getPorts(); - for (Port port : ports) - { - String authenticationProviderName = (String) port.getAttribute(Port.AUTHENTICATION_PROVIDER); - AuthenticationProvider provider = null; - if (authenticationProviderName != null) - { - provider = getAuthenticationProviderByName(broker, authenticationProviderName); - } - else - { - provider = defaultAuthenticationProvider; - } - port.setAuthenticationProvider(provider); - } - } - - private AuthenticationProvider getAuthenticationProviderByName(BrokerAdapter broker, String authenticationProviderName) - { - AuthenticationProvider provider = broker.findAuthenticationProviderByName(authenticationProviderName); - if (provider == null) - { - throw new IllegalConfigurationException("Cannot find the authentication provider with name: " - + authenticationProviderName); - } - return provider; - } - } 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 15cb229d8a..35209e5b41 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 @@ -20,6 +20,7 @@ */ package org.apache.qpid.server.configuration.startup; +import org.apache.qpid.server.BrokerOptions; import org.apache.qpid.server.configuration.ConfiguredObjectRecoverer; import org.apache.qpid.server.configuration.RecovererProvider; import org.apache.qpid.server.logging.LogRecorder; @@ -54,9 +55,10 @@ public class DefaultRecovererProvider implements RecovererProvider private final QpidServiceLoader<GroupManagerFactory> _groupManagerServiceLoader; private final QpidServiceLoader<PluginFactory> _pluginFactoryServiceLoader; private final TaskExecutor _taskExecutor; + private final BrokerOptions _brokerOptions; public DefaultRecovererProvider(StatisticsGatherer brokerStatisticsGatherer, VirtualHostRegistry virtualHostRegistry, - LogRecorder logRecorder, RootMessageLogger rootMessageLogger, TaskExecutor taskExecutor) + LogRecorder logRecorder, RootMessageLogger rootMessageLogger, TaskExecutor taskExecutor, BrokerOptions brokerOptions) { _authenticationProviderFactory = new AuthenticationProviderFactory(new QpidServiceLoader<AuthenticationManagerFactory>()); _portFactory = new PortFactory(); @@ -67,6 +69,7 @@ public class DefaultRecovererProvider implements RecovererProvider _groupManagerServiceLoader = new QpidServiceLoader<GroupManagerFactory>(); _pluginFactoryServiceLoader = new QpidServiceLoader<PluginFactory>(); _taskExecutor = taskExecutor; + _brokerOptions = brokerOptions; } @Override @@ -75,7 +78,7 @@ public class DefaultRecovererProvider implements RecovererProvider if (Broker.class.getSimpleName().equals(type)) { return new BrokerRecoverer(_authenticationProviderFactory, _portFactory, _brokerStatisticsGatherer, _virtualHostRegistry, - _logRecorder, _rootMessageLogger, _taskExecutor); + _logRecorder, _rootMessageLogger, _taskExecutor, _brokerOptions); } else if(VirtualHost.class.getSimpleName().equals(type)) { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandler.java index 6733c8ee2d..24d5edf00f 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandler.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandler.java @@ -26,6 +26,7 @@ public class ManagementModeStoreHandler implements ConfigurationEntryStore private static final String PORT_TYPE = Port.class.getSimpleName(); private static final String VIRTUAL_HOST_TYPE = VirtualHost.class.getSimpleName(); private static final String ATTRIBUTE_STATE = VirtualHost.STATE; + private static final Object MANAGEMENT_MODE_AUTH_PROVIDER = "mm-auth"; private final ConfigurationEntryStore _store; private final Map<UUID, ConfigurationEntry> _cliEntries; @@ -208,6 +209,10 @@ public class ManagementModeStoreHandler implements ConfigurationEntryStore attributes.put(Port.PORT, port); attributes.put(Port.PROTOCOLS, Collections.singleton(protocol)); attributes.put(Port.NAME, MANAGEMENT_MODE_PORT_PREFIX + protocol.name()); + if (protocol != Protocol.RMI) + { + attributes.put(Port.AUTHENTICATION_PROVIDER, MANAGEMENT_MODE_AUTH_PROVIDER); + } ConfigurationEntry portEntry = new ConfigurationEntry(UUID.randomUUID(), PORT_TYPE, attributes, Collections.<UUID> emptySet(), this); if (LOGGER.isDebugEnabled()) diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/messages/Broker_logmessages.properties b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/messages/Broker_logmessages.properties index 1aa7815c39..76c1fa1b5b 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/messages/Broker_logmessages.properties +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/messages/Broker_logmessages.properties @@ -45,4 +45,6 @@ STATS_MSGS = BRK-1009 : {0,choice,0#delivered|1#received} : {1,number,#.###} msg PLATFORM = BRK-1010 : Platform : JVM : {0} version: {1} OS : {2} version: {3} arch: {4} # 0 Maximum Memory -MAX_MEMORY = BRK-1011 : Maximum Memory : {0,number} bytes
\ No newline at end of file +MAX_MEMORY = BRK-1011 : Maximum Memory : {0,number} bytes + +MANAGEMENT_MODE = BRK-1012 : Management Mode : User Details : {0} / {1}
\ No newline at end of file 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 0e230bd552..712b53f627 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 @@ -53,7 +53,6 @@ public interface Broker extends ConfiguredObject String STATE = "state"; String TIME_TO_LIVE = "timeToLive"; String UPDATED = "updated"; - String DEFAULT_AUTHENTICATION_PROVIDER = "defaultAuthenticationProvider"; String DEFAULT_VIRTUAL_HOST = "defaultVirtualHost"; String STATISTICS_REPORTING_PERIOD = "statisticsReportingPeriod"; String STATISTICS_REPORTING_RESET_ENABLED = "statisticsReportingResetEnabled"; @@ -112,7 +111,6 @@ public interface Broker extends ConfiguredObject STATE, TIME_TO_LIVE, UPDATED, - DEFAULT_AUTHENTICATION_PROVIDER, DEFAULT_VIRTUAL_HOST, QUEUE_ALERT_THRESHOLD_MESSAGE_AGE, QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES, @@ -151,8 +149,6 @@ public interface Broker extends ConfiguredObject LifetimePolicy lifetime, long ttl, Map<String, Object> attributes) throws AccessControlException, IllegalArgumentException; - AuthenticationProvider getDefaultAuthenticationProvider(); - Collection<GroupProvider> getGroupProviders(); /** @@ -172,6 +168,8 @@ public interface Broker extends ConfiguredObject */ LogRecorder getLogRecorder(); + AuthenticationProvider findAuthenticationProviderByName(String authenticationProviderName); + VirtualHost findVirtualHostByName(String name); KeyStore findKeyStoreByName(String name); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Port.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Port.java index 7ff5f04ee7..60d62e3f27 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Port.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Port.java @@ -93,7 +93,6 @@ public interface Port extends ConfiguredObject AccessControlException, IllegalArgumentException; - Collection<Protocol> getProtocols(); void addProtocol(Protocol protocol) throws IllegalStateException, @@ -104,12 +103,9 @@ public interface Port extends ConfiguredObject AccessControlException, IllegalArgumentException; + AuthenticationProvider getAuthenticationProvider(); //children Collection<VirtualHostAlias> getVirtualHostBindings(); Collection<Connection> getConnections(); - - AuthenticationProvider getAuthenticationProvider(); - - void setAuthenticationProvider(AuthenticationProvider authenticationProvider); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderAdapter.java index f788923b3a..8d601460ad 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderAdapter.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderAdapter.java @@ -219,10 +219,6 @@ public abstract class AuthenticationProviderAdapter<T extends AuthenticationMana String providerName = getName(); // verify that provider is not in use - if (providerName.equals(_broker.getAttribute(Broker.DEFAULT_AUTHENTICATION_PROVIDER))) - { - throw new IntegrityViolationException("Authentication provider '" + providerName + "' is set as default and cannot be deleted"); - } Collection<Port> ports = new ArrayList<Port>(_broker.getPorts()); for (Port port : ports) { 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 ae30f70877..49af66126c 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 @@ -33,14 +33,15 @@ import java.util.UUID; import org.apache.log4j.Logger; import org.apache.qpid.common.QpidProperties; +import org.apache.qpid.server.BrokerOptions; import org.apache.qpid.server.configuration.ConfigurationEntryStore; import org.apache.qpid.server.configuration.IllegalConfigurationException; -import org.apache.qpid.server.configuration.store.ManagementModeStoreHandler; import org.apache.qpid.server.configuration.updater.TaskExecutor; import org.apache.qpid.server.logging.LogRecorder; import org.apache.qpid.server.logging.RootMessageLogger; import org.apache.qpid.server.logging.actors.BrokerActor; import org.apache.qpid.server.logging.actors.CurrentActor; +import org.apache.qpid.server.logging.messages.BrokerMessages; import org.apache.qpid.server.model.AuthenticationProvider; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.ConfigurationChangeListener; @@ -56,9 +57,12 @@ import org.apache.qpid.server.model.Statistics; 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.model.adapter.AuthenticationProviderAdapter.SimpleAuthenticationProviderAdapter; import org.apache.qpid.server.security.SecurityManager; 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; @@ -92,7 +96,6 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat put(ACL_FILE, String.class); put(NAME, String.class); put(DEFAULT_VIRTUAL_HOST, String.class); - put(DEFAULT_AUTHENTICATION_PROVIDER, String.class); put(GROUP_FILE, String.class); put(VIRTUALHOST_STORE_TRANSACTION_IDLE_TIMEOUT_CLOSE, Long.class); @@ -168,7 +171,6 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat private final Map<String, TrustStore> _trustStores = new HashMap<String, TrustStore>(); private final AuthenticationProviderFactory _authenticationProviderFactory; - private AuthenticationProvider _defaultAuthenticationProvider; private final PortFactory _portFactory; private final SecurityManager _securityManager; @@ -176,11 +178,12 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat private final Collection<String> _supportedStoreTypes; private final ConfigurationEntryStore _brokerStore; - private boolean _managementMode; + private AuthenticationProvider _managementAuthenticationProvider; + private BrokerOptions _brokerOptions; public BrokerAdapter(UUID id, Map<String, Object> attributes, StatisticsGatherer statisticsGatherer, VirtualHostRegistry virtualHostRegistry, LogRecorder logRecorder, RootMessageLogger rootMessageLogger, AuthenticationProviderFactory authenticationProviderFactory, - PortFactory portFactory, TaskExecutor taskExecutor, ConfigurationEntryStore brokerStore) + PortFactory portFactory, TaskExecutor taskExecutor, ConfigurationEntryStore brokerStore, BrokerOptions brokerOptions) { super(id, DEFAULTS, MapValueConverter.convert(attributes, ATTRIBUTE_TYPES), taskExecutor); _statisticsGatherer = statisticsGatherer; @@ -195,7 +198,15 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat createBrokerChildrenFromAttributes(); _supportedStoreTypes = new MessageStoreCreator().getStoreTypes(); _brokerStore = brokerStore; - _managementMode = brokerStore instanceof ManagementModeStoreHandler; + _brokerOptions = brokerOptions; + createBrokerChildrenFromAttributes(); + if (_brokerOptions.isManagementMode()) + { + AuthenticationManager authManager = new SimpleAuthenticationManager(BrokerOptions.MANAGEMENT_MODE_USER_NAME, _brokerOptions.getManagementModePassword()); + AuthenticationProvider authenticationProvider = new SimpleAuthenticationProviderAdapter(UUID.randomUUID(), this, + authManager, Collections.<String, Object> emptyMap(), Collections.<String> emptySet()); + _managementAuthenticationProvider = authenticationProvider; + } } /* @@ -204,6 +215,7 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat private void createBrokerChildrenFromAttributes() { createGroupProvider(); + } private void createGroupProvider() @@ -250,6 +262,10 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat public AuthenticationProvider findAuthenticationProviderByName(String authenticationProviderName) { + if (isManagementMode()) + { + return _managementAuthenticationProvider; + } Collection<AuthenticationProvider> providers = getAuthenticationProviders(); for (AuthenticationProvider authenticationProvider : providers) { @@ -278,17 +294,6 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat } @Override - public AuthenticationProvider getDefaultAuthenticationProvider() - { - return _defaultAuthenticationProvider; - } - - public void setDefaultAuthenticationProvider(AuthenticationProvider provider) - { - _defaultAuthenticationProvider = provider; - } - - @Override public Collection<GroupProvider> getGroupProviders() { synchronized (_groupProviders) @@ -766,6 +771,11 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat changeState(_portAdapters, currentState,State.ACTIVE, false); changeState(_plugins, currentState,State.ACTIVE, false); + + if (isManagementMode()) + { + CurrentActor.get().message(BrokerMessages.MANAGEMENT_MODE(BrokerOptions.MANAGEMENT_MODE_USER_NAME, _brokerOptions.getManagementModePassword())); + } return true; } else if (desiredState == State.STOPPED) @@ -956,7 +966,7 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat public SubjectCreator getSubjectCreator(SocketAddress localAddress) { InetSocketAddress inetSocketAddress = (InetSocketAddress)localAddress; - AuthenticationProvider provider = _defaultAuthenticationProvider; + AuthenticationProvider provider = null; Collection<Port> ports = getPorts(); for (Port p : ports) { @@ -966,6 +976,12 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat break; } } + + if(provider == null) + { + throw new IllegalConfigurationException("Unable to determine authentication provider for address: " + localAddress); + } + return provider.getSubjectCreator(); } @@ -1002,7 +1018,6 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat @Override protected void changeAttributes(Map<String, Object> attributes) { - //TODO: Add management mode check Map<String, Object> convertedAttributes = MapValueConverter.convert(attributes, ATTRIBUTE_TYPES); validateAttributes(convertedAttributes); @@ -1019,13 +1034,6 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat { createGroupProvider(); } - else if (DEFAULT_AUTHENTICATION_PROVIDER.equals(name)) - { - if (!_defaultAuthenticationProvider.getName().equals(desired)) - { - _defaultAuthenticationProvider = findAuthenticationProviderByName((String)desired); - } - } attributeSet(name, expected, desired); } @@ -1048,16 +1056,6 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat new FileGroupManager(groupFile); } - String defaultAuthenticationProvider = (String) convertedAttributes.get(DEFAULT_AUTHENTICATION_PROVIDER); - if (defaultAuthenticationProvider != null) - { - AuthenticationProvider provider = findAuthenticationProviderByName(defaultAuthenticationProvider); - if (provider == null) - { - throw new IllegalConfigurationException("Authentication provider with name " + defaultAuthenticationProvider - + " canot be set as a default as it does not exist"); - } - } String defaultVirtualHost = (String) convertedAttributes.get(DEFAULT_VIRTUAL_HOST); if (defaultVirtualHost != null) { @@ -1127,6 +1125,6 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat @Override public boolean isManagementMode() { - return _managementMode; + return _brokerOptions.isManagementMode(); } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java index 0c1249d20e..af6b1421a7 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java @@ -82,6 +82,24 @@ public class PortAdapter extends AbstractAdapter implements Port super(id, defaults, MapValueConverter.convert(attributes, ATTRIBUTE_TYPES), taskExecutor); _broker = broker; State state = MapValueConverter.getEnumAttribute(State.class, STATE, attributes, State.INITIALISING); + + Collection<Protocol> protocols = getProtocols(); + boolean rmiRegistry = protocols != null && protocols.contains(Protocol.RMI); + if (!rmiRegistry) + { + String authProvider = (String)getAttribute(Port.AUTHENTICATION_PROVIDER); + if (authProvider == null) + { + throw new IllegalConfigurationException("An authentication provider must be specified for port : " + getName()); + } + _authenticationProvider = broker.findAuthenticationProviderByName(authProvider); + + if(_authenticationProvider == null) + { + throw new IllegalConfigurationException("The authentication provider '" + authProvider + "' could not be found for port : " + getName()); + } + } + _state = new AtomicReference<State>(state); addParent(Broker.class, broker); } @@ -350,11 +368,6 @@ public class PortAdapter extends AbstractAdapter implements Port return _authenticationProvider; } - public void setAuthenticationProvider(AuthenticationProvider authenticationProvider) - { - _authenticationProvider = authenticationProvider; - } - @Override protected void changeAttributes(Map<String, Object> attributes) { @@ -451,6 +464,14 @@ public class PortAdapter extends AbstractAdapter implements Port + authenticationProviderName + "'"); } } + else + { + if (protocols != null && !protocols.contains(Protocol.RMI)) + { + throw new IllegalConfigurationException("An authentication provider must be specified"); + } + } + super.changeAttributes(converted); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java index 1379b375cf..fa5024c1fe 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java @@ -27,6 +27,7 @@ import java.util.TimerTask; import org.apache.log4j.Logger; import org.apache.qpid.common.Closeable; import org.apache.qpid.common.QpidProperties; +import org.apache.qpid.server.BrokerOptions; import org.apache.qpid.server.configuration.BrokerProperties; import org.apache.qpid.server.configuration.ConfigurationEntryStore; import org.apache.qpid.server.configuration.ConfiguredObjectRecoverer; @@ -89,7 +90,7 @@ public class ApplicationRegistry implements IApplicationRegistry initialiseStatistics(); } - public void initialise() throws Exception + public void initialise(BrokerOptions brokerOptions) throws Exception { // Create the RootLogger to be used during broker operation boolean statusUpdatesEnabled = Boolean.parseBoolean(System.getProperty(BrokerProperties.PROPERTY_STATUS_UPDATES, "true")); @@ -112,7 +113,7 @@ public class ApplicationRegistry implements IApplicationRegistry _taskExecutor = new TaskExecutor(); _taskExecutor.start(); - RecovererProvider provider = new DefaultRecovererProvider((StatisticsGatherer)this, _virtualHostRegistry, _logRecorder, _rootMessageLogger, _taskExecutor); + RecovererProvider provider = new DefaultRecovererProvider((StatisticsGatherer)this, _virtualHostRegistry, _logRecorder, _rootMessageLogger, _taskExecutor, brokerOptions); ConfiguredObjectRecoverer<? extends ConfiguredObject> brokerRecoverer = provider.getRecoverer(Broker.class.getSimpleName()); _broker = (Broker) brokerRecoverer.create(provider, _store.getRootEntry()); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java index d12258d194..7341922bd0 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java @@ -20,17 +20,14 @@ */ package org.apache.qpid.server.registry; +import org.apache.qpid.server.BrokerOptions; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.stats.StatisticsGatherer; public interface IApplicationRegistry extends StatisticsGatherer { - /** - * Initialise the application registry. All initialisation must be done in this method so that any components - * that need access to the application registry itself for initialisation are able to use it. Attempting to - * initialise in the constructor will lead to failures since the registry reference will not have been set. - */ - void initialise() throws Exception; + + void initialise(BrokerOptions brokerOptions) throws Exception; /** * Shutdown this Registry diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/jmx/JMXPasswordAuthenticator.java index abb8677e90..bf8d489e61 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/jmx/JMXPasswordAuthenticator.java @@ -18,7 +18,7 @@ * under the License. * */ -package org.apache.qpid.server.security.auth.rmi; +package org.apache.qpid.server.security.auth.jmx; import java.net.SocketAddress; @@ -31,7 +31,7 @@ import org.apache.qpid.server.security.auth.SubjectAuthenticationResult; import javax.management.remote.JMXAuthenticator; import javax.security.auth.Subject; -public class RMIPasswordAuthenticator implements JMXAuthenticator +public class JMXPasswordAuthenticator implements JMXAuthenticator { static final String UNABLE_TO_LOOKUP = "The broker was unable to lookup the user details"; static final String SHOULD_BE_STRING_ARRAY = "User details should be String[]"; @@ -45,7 +45,7 @@ public class RMIPasswordAuthenticator implements JMXAuthenticator private final Broker _broker; private final SocketAddress _address; - public RMIPasswordAuthenticator(Broker broker, SocketAddress address) + public JMXPasswordAuthenticator(Broker broker, SocketAddress address) { _broker = broker; _address = address; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleAuthenticationManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleAuthenticationManager.java new file mode 100644 index 0000000000..903f54dd8e --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleAuthenticationManager.java @@ -0,0 +1,214 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.qpid.server.security.auth.manager; + +import java.io.IOException; +import java.security.Principal; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.NameCallback; +import javax.security.auth.callback.PasswordCallback; +import javax.security.auth.callback.UnsupportedCallbackException; +import javax.security.sasl.AuthorizeCallback; +import javax.security.sasl.Sasl; +import javax.security.sasl.SaslException; +import javax.security.sasl.SaslServer; + +import org.apache.log4j.Logger; +import org.apache.qpid.server.security.auth.AuthenticationResult; +import org.apache.qpid.server.security.auth.UsernamePrincipal; +import org.apache.qpid.server.security.auth.sasl.plain.PlainPasswordCallback; +import org.apache.qpid.server.security.auth.sasl.plain.PlainSaslServer; + +public class SimpleAuthenticationManager implements AuthenticationManager +{ + private static final Logger _logger = Logger.getLogger(SimpleAuthenticationManager.class); + + private static final String PLAIN_MECHANISM = "PLAIN"; + private static final String CRAM_MD5_MECHANISM = "CRAM-MD5"; + + private Map<String, String> _users; + + public SimpleAuthenticationManager(String userName, String userPassword) + { + this(Collections.singletonMap(userName, userPassword)); + } + + public SimpleAuthenticationManager(Map<String, String> users) + { + _users = new HashMap<String, String>(users); + } + + @Override + public void initialise() + { + } + + @Override + public String getMechanisms() + { + return PLAIN_MECHANISM + " " + CRAM_MD5_MECHANISM; + } + + @Override + public SaslServer createSaslServer(String mechanism, String localFQDN, Principal externalPrincipal) throws SaslException + { + if (PLAIN_MECHANISM.equals(mechanism)) + { + return new PlainSaslServer(new SimplePlainCallbackHandler()); + } + else if (CRAM_MD5_MECHANISM.equals(mechanism)) + { + return Sasl.createSaslServer(mechanism, "AMQP", localFQDN, null, new SimpleCramMd5CallbackHandler()); + } + else + { + throw new SaslException("Unknown mechanism: " + mechanism); + } + } + + @Override + public AuthenticationResult authenticate(SaslServer server, byte[] response) + { + try + { + // Process response from the client + byte[] challenge = server.evaluateResponse(response != null ? response : new byte[0]); + + if (server.isComplete()) + { + String authorizationID = server.getAuthorizationID(); + _logger.debug("Authenticated as " + authorizationID); + + return new AuthenticationResult(new UsernamePrincipal(authorizationID)); + } + else + { + return new AuthenticationResult(challenge, AuthenticationResult.AuthenticationStatus.CONTINUE); + } + } + catch (SaslException e) + { + return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR, e); + } + } + + @Override + public AuthenticationResult authenticate(String username, String password) + { + if (_users.containsKey(username)) + { + String userPassword = _users.get(username); + if (userPassword.equals(password)) + { + return new AuthenticationResult(new UsernamePrincipal(username)); + } + } + return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR); + } + + @Override + public void close() + { + } + + @Override + public void onCreate() + { + // nothing to do, no external resource is required + } + + @Override + public void onDelete() + { + // nothing to do, no external resource is used + } + + private class SimpleCramMd5CallbackHandler implements CallbackHandler + { + public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException + { + String username = null; + for (Callback callback : callbacks) + { + if (callback instanceof NameCallback) + { + username = ((NameCallback) callback).getDefaultName(); + } + else if (callback instanceof PasswordCallback) + { + if (_users.containsKey(username)) + { + String password = _users.get(username); + ((PasswordCallback) callback).setPassword(password.toCharArray()); + } + else + { + throw new SaslException("Authentication failed"); + } + } + else if (callback instanceof AuthorizeCallback) + { + ((AuthorizeCallback) callback).setAuthorized(true); + } + else + { + throw new UnsupportedCallbackException(callback); + } + } + } + } + + private class SimplePlainCallbackHandler implements CallbackHandler + { + public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException + { + String username = null; + for (Callback callback : callbacks) + { + if (callback instanceof NameCallback) + { + username = ((NameCallback) callback).getDefaultName(); + } + else if (callback instanceof PlainPasswordCallback) + { + if (_users.containsKey(username)) + { + PlainPasswordCallback plainPasswordCallback = (PlainPasswordCallback) callback; + String password = plainPasswordCallback.getPlainPassword(); + plainPasswordCallback.setAuthenticated(password.equals(_users.get(username))); + } + } + else if (callback instanceof AuthorizeCallback) + { + ((AuthorizeCallback) callback).setAuthorized(true); + } + else + { + throw new UnsupportedCallbackException(callback); + } + } + } + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/util/StringUtil.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/util/StringUtil.java new file mode 100644 index 0000000000..aa17a9493b --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/util/StringUtil.java @@ -0,0 +1,44 @@ +/* + * + * 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.util; + +import java.util.Random; + +public class StringUtil +{ + private static final String NUMBERS = "0123456789"; + private static final String LETTERS = "abcdefghijklmnopqrstuvwxwy"; + private static final String OTHERS = "_-"; + private static final char[] CHARACTERS = (NUMBERS + LETTERS + LETTERS.toUpperCase() + OTHERS).toCharArray(); + + private Random _random = new Random(); + + public String randomAlphaNumericString(int maxLength) + { + char[] result = new char[maxLength]; + for (int i = 0; i < maxLength; i++) + { + result[i] = (char) CHARACTERS[_random.nextInt(CHARACTERS.length)]; + } + return new String(result); + } + +} diff --git a/qpid/java/broker/src/main/resources/initial-config.json b/qpid/java/broker/src/main/resources/initial-config.json index 44f8fed789..fde3c3a96e 100644 --- a/qpid/java/broker/src/main/resources/initial-config.json +++ b/qpid/java/broker/src/main/resources/initial-config.json @@ -21,7 +21,6 @@ { "name": "QpidBroker", "storeVersion": 1, - "defaultAuthenticationProvider" : "passwordFile", "defaultVirtualHost" : "default", "authenticationproviders" : [ { "name" : "passwordFile", @@ -30,10 +29,12 @@ } ], "ports" : [ { "name" : "AMQP", - "port" : 5672 + "port" : 5672, + "authenticationProvider" : "passwordFile" }, { "name" : "HTTP", "port" : 8080, + "authenticationProvider" : "passwordFile", "protocols" : [ "HTTP" ] }, { "name" : "RMI_REGISTRY", @@ -42,6 +43,7 @@ }, { "name" : "JMX_CONNECTOR", "port" : 9099, + "authenticationProvider" : "passwordFile", "protocols" : [ "JMX_RMI" ] }], "virtualhosts" : [ { diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/BrokerOptionsTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/BrokerOptionsTest.java index c1acf81a1a..08031c36a4 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/BrokerOptionsTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/BrokerOptionsTest.java @@ -220,4 +220,10 @@ public class BrokerOptionsTest extends QpidTestCase _options.setOverwriteConfigurationStore(true); assertTrue(_options.isOverwriteConfigurationStore()); } + + public void testManagementModePassword() + { + _options.setManagementModePassword("test"); + assertEquals("Unexpected management mode password", "test", _options.getManagementModePassword()); + } } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/MainTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/MainTest.java index aab919a828..d7579e2b2a 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/MainTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/MainTest.java @@ -171,6 +171,28 @@ public class MainTest extends QpidTestCase assertEquals(0, options.getManagementModeHttpPort()); } + public void testManagementModePassword() + { + String password = getTestName(); + BrokerOptions options = startDummyMain("-mm -mmpass " + password); + assertTrue(options.isManagementMode()); + assertEquals(password, options.getManagementModePassword()); + + options = startDummyMain("-mm --management-mode-password " + password); + assertTrue(options.isManagementMode()); + assertEquals(password, options.getManagementModePassword()); + + options = startDummyMain("-mmpass " + password); + assertNotNull(options.getManagementModePassword()); + } + + public void testDefaultManagementModePassword() + { + BrokerOptions options = startDummyMain("-mm"); + assertTrue(options.isManagementMode()); + assertNotNull(options.getManagementModePassword()); + } + private BrokerOptions startDummyMain(String commandLine) { return (new TestMain(commandLine.split("\\s"))).getOptions(); 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 3a41b61961..5a8580fd26 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 @@ -20,10 +20,8 @@ */ package org.apache.qpid.server.configuration.startup; -import static org.mockito.Mockito.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import static org.mockito.Mockito.verify; import java.util.Arrays; import java.util.Collection; @@ -35,9 +33,9 @@ import java.util.UUID; import junit.framework.TestCase; +import org.apache.qpid.server.BrokerOptions; 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.logging.LogRecorder; import org.apache.qpid.server.logging.RootMessageLogger; @@ -73,7 +71,7 @@ public class BrokerRecovererTest extends TestCase super.setUp(); _brokerRecoverer = new BrokerRecoverer(mock(AuthenticationProviderFactory.class), mock(PortFactory.class), mock(StatisticsGatherer.class), - mock(VirtualHostRegistry.class), mock(LogRecorder.class), mock(RootMessageLogger.class), mock(TaskExecutor.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); @@ -89,7 +87,6 @@ public class BrokerRecovererTest extends TestCase { Map<String, Object> attributes = new HashMap<String, Object>(); attributes.put(Broker.DEFAULT_VIRTUAL_HOST, "test"); - attributes.put(Broker.DEFAULT_AUTHENTICATION_PROVIDER, "authenticationProvider1"); attributes.put(Broker.QUEUE_ALERT_THRESHOLD_MESSAGE_AGE, 9l); attributes.put(Broker.QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES, 8l); attributes.put(Broker.QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_BYTES, 7l); @@ -172,24 +169,6 @@ public class BrokerRecovererTest extends TestCase assertEquals(Collections.singletonList(port), broker.getPorts()); } - public void testCreateBrokerWithoutAuthenticationProviderThrowsException() - { - assertNotNull("expected to remove the base entry", _brokerEntryChildren.remove(AuthenticationProvider.class.getSimpleName())); - assertTrue("should be empty", _brokerEntryChildren.isEmpty()); - - RecovererProvider recovererProvider = createRecoveryProvider(new ConfigurationEntry[0], new ConfiguredObject[0]); - - try - { - _brokerRecoverer.create(recovererProvider, _brokerEntry); - fail("should have thrown an exception due to missing authentication provider configuration"); - } - catch(IllegalConfigurationException e) - { - //expected - } - } - public void testCreateBrokerWithOneAuthenticationProvider() { RecovererProvider recovererProvider = createRecoveryProvider(new ConfigurationEntry[]{_authenticationProviderEntry1}, @@ -202,29 +181,6 @@ public class BrokerRecovererTest extends TestCase assertEquals(Collections.singletonList(_authenticationProvider1), broker.getAuthenticationProviders()); } - public void testCreateBrokerWithMultipleAuthenticationProvidersAndNoDefaultThrowsException() - { - AuthenticationProvider authenticationProvider2 = mock(AuthenticationProvider.class); - when(authenticationProvider2.getName()).thenReturn("authenticationProvider2"); - ConfigurationEntry authenticationProviderEntry2 = mock(ConfigurationEntry.class); - _brokerEntryChildren.put(AuthenticationProvider.class.getSimpleName(), Arrays.asList(_authenticationProviderEntry1, authenticationProviderEntry2)); - - Map<String,Object> emptyBrokerAttributes = new HashMap<String,Object>(); - when(_brokerEntry.getAttributes()).thenReturn(emptyBrokerAttributes); - - RecovererProvider recovererProvider = createRecoveryProvider(new ConfigurationEntry[]{authenticationProviderEntry2, _authenticationProviderEntry1}, - new ConfiguredObject[]{authenticationProvider2, _authenticationProvider1}); - try - { - _brokerRecoverer.create(recovererProvider, _brokerEntry); - fail("should have thrown an exception due to missing authentication provider default"); - } - catch(IllegalConfigurationException e) - { - //expected - } - } - public void testCreateBrokerWithMultipleAuthenticationProvidersAndPorts() { //Create a second authentication provider @@ -233,13 +189,10 @@ public class BrokerRecovererTest extends TestCase ConfigurationEntry authenticationProviderEntry2 = mock(ConfigurationEntry.class); _brokerEntryChildren.put(AuthenticationProvider.class.getSimpleName(), Arrays.asList(_authenticationProviderEntry1, authenticationProviderEntry2)); - //Set the default authentication provider Map<String,Object> brokerAtttributes = new HashMap<String,Object>(); when(_brokerEntry.getAttributes()).thenReturn(brokerAtttributes); - brokerAtttributes.put(Broker.DEFAULT_AUTHENTICATION_PROVIDER, "authenticationProvider2"); - //Add a couple ports, one with a defined authentication provider and - //one without (which should then use the default) + //Add a couple ports ConfigurationEntry portEntry1 = mock(ConfigurationEntry.class); Port port1 = mock(Port.class); when(port1.getName()).thenReturn("port1"); @@ -249,6 +202,7 @@ public class BrokerRecovererTest extends TestCase Port port2 = mock(Port.class); when(port2.getName()).thenReturn("port2"); when(port2.getPort()).thenReturn(5672); + when(port2.getAttribute(Port.AUTHENTICATION_PROVIDER)).thenReturn("authenticationProvider2"); _brokerEntryChildren.put(Port.class.getSimpleName(), Arrays.asList(portEntry1, portEntry2)); RecovererProvider recovererProvider = createRecoveryProvider( @@ -258,47 +212,12 @@ public class BrokerRecovererTest extends TestCase Broker broker = _brokerRecoverer.create(recovererProvider, _brokerEntry); assertNotNull(broker); - assertEquals("Unexpected number of authentication providers", 2,broker.getAuthenticationProviders().size()); + assertEquals("Unexpected number of authentication providers", 2, broker.getAuthenticationProviders().size()); Collection<Port> ports = broker.getPorts(); assertEquals("Unexpected number of ports", 2, ports.size()); assertTrue(ports.contains(port1)); assertTrue(ports.contains(port2)); - - verify(port1).setAuthenticationProvider(any(AuthenticationProvider.class)); - verify(port1).setAuthenticationProvider(_authenticationProvider1); - - verify(port2).setAuthenticationProvider(any(AuthenticationProvider.class)); - verify(port2).setAuthenticationProvider(authenticationProvider2); - } - - public void testCreateBrokerAssignsGroupAccessorToAuthenticationProviders() - { - //Create a second authentication provider - AuthenticationProvider authenticationProvider2 = mock(AuthenticationProvider.class); - when(authenticationProvider2.getName()).thenReturn("authenticationProvider2"); - ConfigurationEntry authenticationProviderEntry2 = mock(ConfigurationEntry.class); - _brokerEntryChildren.put(AuthenticationProvider.class.getSimpleName(), Arrays.asList(_authenticationProviderEntry1, authenticationProviderEntry2)); - - //Set the default authentication provider - Map<String,Object> brokerAtttributes = new HashMap<String,Object>(); - when(_brokerEntry.getAttributes()).thenReturn(brokerAtttributes); - brokerAtttributes.put(Broker.DEFAULT_AUTHENTICATION_PROVIDER, "authenticationProvider2"); - - //Create a group provider - ConfigurationEntry groupProviderEntry = mock(ConfigurationEntry.class); - GroupProvider groupProvider = mock(GroupProvider.class); - _brokerEntryChildren.put(GroupProvider.class.getSimpleName(), Arrays.asList(groupProviderEntry)); - - RecovererProvider recovererProvider = createRecoveryProvider( - new ConfigurationEntry[]{groupProviderEntry, authenticationProviderEntry2, _authenticationProviderEntry1}, - new ConfiguredObject[]{groupProvider, authenticationProvider2, _authenticationProvider1}); - - Broker broker = _brokerRecoverer.create(recovererProvider, _brokerEntry); - - assertNotNull(broker); - assertEquals("Unexpected number of authentication providers", 2, broker.getAuthenticationProviders().size()); - } public void testCreateBrokerWithGroupProvider() diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/DefaultRecovererProviderTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/DefaultRecovererProviderTest.java index 96f2474c2d..b958ba1f56 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/DefaultRecovererProviderTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/DefaultRecovererProviderTest.java @@ -23,6 +23,7 @@ package org.apache.qpid.server.configuration.startup; import static org.mockito.Mockito.mock; import junit.framework.TestCase; +import org.apache.qpid.server.BrokerOptions; import org.apache.qpid.server.configuration.ConfiguredObjectRecoverer; import org.apache.qpid.server.logging.LogRecorder; import org.apache.qpid.server.logging.RootMessageLogger; @@ -54,7 +55,7 @@ public class DefaultRecovererProviderTest extends TestCase RootMessageLogger rootMessageLogger = mock(RootMessageLogger.class); TaskExecutor taskExecutor = mock(TaskExecutor.class); - DefaultRecovererProvider provider = new DefaultRecovererProvider(statisticsGatherer, virtualHostRegistry, logRecorder, rootMessageLogger, taskExecutor); + DefaultRecovererProvider provider = new DefaultRecovererProvider(statisticsGatherer, virtualHostRegistry, logRecorder, rootMessageLogger, taskExecutor, mock(BrokerOptions.class)); for (String configuredObjectType : supportedTypes) { ConfiguredObjectRecoverer<?> recovever = provider.getRecoverer(configuredObjectType); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/store/ConfigurationEntryStoreTestCase.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/store/ConfigurationEntryStoreTestCase.java index 7d253d56f0..fc21706bc0 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/store/ConfigurationEntryStoreTestCase.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/store/ConfigurationEntryStoreTestCase.java @@ -60,7 +60,6 @@ public abstract class ConfigurationEntryStoreTestCase extends QpidTestCase _brokerId = UUID.randomUUID(); _brokerAttributes = new HashMap<String, Object>(); _brokerAttributes.put(Broker.DEFAULT_VIRTUAL_HOST, "test"); - _brokerAttributes.put(Broker.DEFAULT_AUTHENTICATION_PROVIDER, "authenticationProvider1"); _brokerAttributes.put(Broker.QUEUE_ALERT_THRESHOLD_MESSAGE_AGE, 9); _brokerAttributes.put(Broker.QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES, 8); _brokerAttributes.put(Broker.QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_BYTES, 7); @@ -171,7 +170,6 @@ public abstract class ConfigurationEntryStoreTestCase extends QpidTestCase ConfigurationEntry brokerConfigEntry = _store.getRootEntry(); Map<String, Object> attributes = new HashMap<String, Object>(); attributes.put(Broker.DEFAULT_VIRTUAL_HOST, "test"); - attributes.put(Broker.DEFAULT_AUTHENTICATION_PROVIDER, "authenticationProvider1"); attributes.put(Broker.QUEUE_ALERT_THRESHOLD_MESSAGE_AGE, 19); attributes.put(Broker.QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES, 18); attributes.put(Broker.QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_BYTES, 17); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/model/BrokerShutdownTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/model/BrokerShutdownTest.java index 7c1db6348b..eb5c672eb8 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/model/BrokerShutdownTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/model/BrokerShutdownTest.java @@ -23,6 +23,7 @@ package org.apache.qpid.server.model; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import org.apache.qpid.server.BrokerOptions; import org.apache.qpid.server.configuration.ConfigurationEntry; import org.apache.qpid.server.configuration.ConfigurationEntryStore; import org.apache.qpid.server.configuration.ConfiguredObjectRecoverer; @@ -121,7 +122,7 @@ public class BrokerShutdownTest extends QpidTestCase RootMessageLogger rootMessageLogger = mock(RootMessageLogger.class); // recover the broker from the store - RecovererProvider provider = new DefaultRecovererProvider(statisticsGatherer, virtualHostRegistry, logRecorder, rootMessageLogger, _taskExecutor); + RecovererProvider provider = new DefaultRecovererProvider(statisticsGatherer, virtualHostRegistry, logRecorder, rootMessageLogger, _taskExecutor, mock(BrokerOptions.class)); ConfiguredObjectRecoverer<? extends ConfiguredObject> brokerRecoverer = provider.getRecoverer(Broker.class.getSimpleName()); Broker broker = (Broker) brokerRecoverer.create(provider, store.getRootEntry()); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/PortFactoryTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/PortFactoryTest.java index 53fb1a0620..54826b8c88 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/PortFactoryTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/PortFactoryTest.java @@ -36,6 +36,7 @@ import java.util.UUID; import org.apache.qpid.server.configuration.BrokerProperties; import org.apache.qpid.server.configuration.IllegalConfigurationException; +import org.apache.qpid.server.model.AuthenticationProvider; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.KeyStore; import org.apache.qpid.server.model.Port; @@ -58,19 +59,22 @@ public class PortFactoryTest extends QpidTestCase private Broker _broker = mock(Broker.class); private KeyStore _keyStore = mock(KeyStore.class); private TrustStore _trustStore = mock(TrustStore.class); - + private String _authProviderName = "authProvider"; + private AuthenticationProvider _authProvider = mock(AuthenticationProvider.class); private PortFactory _portFactory; @Override protected void setUp() throws Exception { + when(_broker.findAuthenticationProviderByName(_authProviderName)).thenReturn(_authProvider); + setTestSystemProperty(BrokerProperties.PROPERTY_BROKER_DEFAULT_AMQP_PROTOCOL_EXCLUDES, null); setTestSystemProperty(BrokerProperties.PROPERTY_BROKER_DEFAULT_AMQP_PROTOCOL_INCLUDES, null); _portFactory = new PortFactory(); _attributes.put(Port.PORT, _portNumber); _attributes.put(Port.TRANSPORTS, _tcpStringSet); - + _attributes.put(Port.AUTHENTICATION_PROVIDER, _authProviderName); _attributes.put(Port.TCP_NO_DELAY, "true"); _attributes.put(Port.RECEIVE_BUFFER_SIZE, "1"); _attributes.put(Port.SEND_BUFFER_SIZE, "2"); @@ -111,6 +115,7 @@ public class PortFactoryTest extends QpidTestCase { Map<String, Object> attributes = new HashMap<String, Object>(); attributes.put(Port.PORT, 1); + attributes.put(Port.AUTHENTICATION_PROVIDER, _authProviderName); Port port = _portFactory.createPort(_portId, _broker, attributes); assertNotNull(port); @@ -273,6 +278,7 @@ public class PortFactoryTest extends QpidTestCase Set<String> nonAmqpStringSet = Collections.singleton(Protocol.JMX_RMI.name()); _attributes = new HashMap<String, Object>(); _attributes.put(Port.PROTOCOLS, nonAmqpStringSet); + _attributes.put(Port.AUTHENTICATION_PROVIDER, _authProviderName); _attributes.put(Port.PORT, _portNumber); _attributes.put(Port.TRANSPORTS, _tcpStringSet); @@ -298,6 +304,7 @@ public class PortFactoryTest extends QpidTestCase Set<String> nonAmqpStringSet = Collections.singleton(Protocol.JMX_RMI.name()); _attributes = new HashMap<String, Object>(); _attributes.put(Port.PROTOCOLS, nonAmqpStringSet); + _attributes.put(Port.AUTHENTICATION_PROVIDER, _authProviderName); _attributes.put(Port.PORT, _portNumber); Port port = _portFactory.createPort(_portId, _broker, _attributes); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabase.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabase.java deleted file mode 100644 index c41b9bf081..0000000000 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabase.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * - */ -package org.apache.qpid.server.security.auth.database; - -import org.apache.qpid.server.security.auth.sasl.AuthenticationProviderInitialiser; -import org.apache.qpid.server.security.auth.UsernamePrincipal; -import org.apache.qpid.server.security.auth.sasl.crammd5.CRAMMD5Initialiser; -import org.apache.qpid.server.security.auth.sasl.plain.PlainInitialiser; - -import javax.security.auth.callback.PasswordCallback; -import javax.security.auth.login.AccountNotFoundException; - -import java.io.File; -import java.io.IOException; -import java.security.Principal; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Properties; - -public class PropertiesPrincipalDatabase implements PrincipalDatabase -{ - private Properties _users; - - private Map<String, AuthenticationProviderInitialiser> _saslServers; - - public PropertiesPrincipalDatabase(Properties users) - { - _users = users; - - _saslServers = new HashMap<String, AuthenticationProviderInitialiser>(); - - /** - * Create Authenticators for Properties Principal Database. - */ - - // Accept MD5 incomming and use plain comparison with the file - PlainInitialiser cram = new PlainInitialiser(); - cram.initialise(this); - // Accept Plain incomming and hash it for comparison to the file. - CRAMMD5Initialiser plain = new CRAMMD5Initialiser(); - plain.initialise(this, CRAMMD5Initialiser.HashDirection.INCOMMING); - - _saslServers.put(plain.getMechanismName(), cram); - _saslServers.put(cram.getMechanismName(), plain); - } - - public void setPassword(Principal principal, PasswordCallback callback) throws IOException, AccountNotFoundException - { - if (principal == null) - { - throw new IllegalArgumentException("principal must not be null"); - } - - - - final String pwd = _users.getProperty(principal.getName()); - - if (pwd != null) - { - callback.setPassword(pwd.toCharArray()); - } - else - { - throw new AccountNotFoundException("No account found for principal " + principal); - } - } - - public boolean verifyPassword(String principal, char[] password) throws AccountNotFoundException - { - //fixme this is not correct as toCharArray is not safe based on the type of string. - char[] pwd = _users.getProperty(principal).toCharArray(); - - return compareCharArray(pwd, password); - } - - public boolean updatePassword(Principal principal, char[] password) throws AccountNotFoundException - { - return false; // updates denied - } - - public boolean createPrincipal(Principal principal, char[] password) - { - return false; // updates denied - } - - public boolean deletePrincipal(Principal principal) throws AccountNotFoundException - { - return false; // updates denied - } - - private boolean compareCharArray(char[] a, char[] b) - { - boolean equal = false; - if (a.length == b.length) - { - equal = true; - int index = 0; - while (equal && index < a.length) - { - equal = a[index] == b[index]; - index++; - } - } - return equal; - } - - - public Map<String, AuthenticationProviderInitialiser> getMechanisms() - { - return _saslServers; - } - - public List<Principal> getUsers() - { - return new LinkedList<Principal>(); //todo - } - - public Principal getUser(String username) - { - if (_users.getProperty(username) != null) - { - return new UsernamePrincipal(username); - } - else - { - return null; - } - } - - public void reload() throws IOException - { - //No file to update from, so do nothing. - } - - @Override - public void open(File passwordFile) - { - throw new UnsupportedOperationException(); - } -} diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticatorTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/jmx/JMXPasswordAuthenticatorTest.java index 52b525dd80..a4dd97e6a1 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticatorTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/jmx/JMXPasswordAuthenticatorTest.java @@ -18,7 +18,7 @@ * under the License. * */ -package org.apache.qpid.server.security.auth.rmi; +package org.apache.qpid.server.security.auth.jmx; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.any; @@ -38,14 +38,15 @@ import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.security.SubjectCreator; import org.apache.qpid.server.security.auth.AuthenticationResult; import org.apache.qpid.server.security.auth.AuthenticationResult.AuthenticationStatus; +import org.apache.qpid.server.security.auth.jmx.JMXPasswordAuthenticator; import org.apache.qpid.server.security.auth.SubjectAuthenticationResult; import org.apache.qpid.server.security.SecurityManager; /** - * Tests the RMIPasswordAuthenticator and its collaboration with the AuthenticationManager. + * Tests the JMXPasswordAuthenticator and its collaboration with the AuthenticationManager. * */ -public class RMIPasswordAuthenticatorTest extends TestCase +public class JMXPasswordAuthenticatorTest extends TestCase { private static final String USERNAME = "guest"; private static final String PASSWORD = "password"; @@ -55,7 +56,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase private final Subject _loginSubject = new Subject(); private final String[] _credentials = new String[] {USERNAME, PASSWORD}; - private RMIPasswordAuthenticator _rmipa; + private JMXPasswordAuthenticator _rmipa; private SubjectCreator _usernamePasswordOkaySuvjectCreator = createMockSubjectCreator(true, null); private SubjectCreator _badPasswordSubjectCreator = createMockSubjectCreator(false, null); @@ -63,7 +64,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase protected void setUp() throws Exception { when(_broker.getSecurityManager()).thenReturn(_securityManager); - _rmipa = new RMIPasswordAuthenticator(_broker, new InetSocketAddress(8999)); + _rmipa = new JMXPasswordAuthenticator(_broker, new InetSocketAddress(8999)); } /** @@ -93,7 +94,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase catch (SecurityException se) { assertEquals("Unexpected exception message", - RMIPasswordAuthenticator.INVALID_CREDENTIALS, se.getMessage()); + JMXPasswordAuthenticator.INVALID_CREDENTIALS, se.getMessage()); } } @@ -110,7 +111,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase catch (SecurityException se) { assertEquals("Unexpected exception message", - RMIPasswordAuthenticator.USER_NOT_AUTHORISED_FOR_MANAGEMENT, se.getMessage()); + JMXPasswordAuthenticator.USER_NOT_AUTHORISED_FOR_MANAGEMENT, se.getMessage()); } } @@ -164,7 +165,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase catch (SecurityException se) { assertEquals("Unexpected exception message", - RMIPasswordAuthenticator.SHOULD_BE_STRING_ARRAY, se.getMessage()); + JMXPasswordAuthenticator.SHOULD_BE_STRING_ARRAY, se.getMessage()); } } @@ -185,7 +186,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase catch (SecurityException se) { assertEquals("Unexpected exception message", - RMIPasswordAuthenticator.SHOULD_HAVE_2_ELEMENTS, se.getMessage()); + JMXPasswordAuthenticator.SHOULD_HAVE_2_ELEMENTS, se.getMessage()); } // Test handling of null credentials @@ -199,7 +200,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase catch (SecurityException se) { assertEquals("Unexpected exception message", - RMIPasswordAuthenticator.CREDENTIALS_REQUIRED, se.getMessage()); + JMXPasswordAuthenticator.CREDENTIALS_REQUIRED, se.getMessage()); } try @@ -212,7 +213,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase catch (SecurityException se) { assertEquals("Unexpected exception message", - RMIPasswordAuthenticator.SHOULD_BE_NON_NULL, se.getMessage()); + JMXPasswordAuthenticator.SHOULD_BE_NON_NULL, se.getMessage()); } try @@ -225,7 +226,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase catch (SecurityException se) { assertEquals("Unexpected exception message", - RMIPasswordAuthenticator.SHOULD_BE_NON_NULL, se.getMessage()); + JMXPasswordAuthenticator.SHOULD_BE_NON_NULL, se.getMessage()); } } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/SimpleAuthenticationManagerTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/SimpleAuthenticationManagerTest.java new file mode 100644 index 0000000000..5868f44b8f --- /dev/null +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/SimpleAuthenticationManagerTest.java @@ -0,0 +1,140 @@ +package org.apache.qpid.server.security.auth.manager; + +import java.security.Principal; +import java.util.Set; + +import javax.security.sasl.SaslException; +import javax.security.sasl.SaslServer; + +import org.apache.qpid.server.security.auth.AuthenticationResult; +import org.apache.qpid.server.security.auth.AuthenticationResult.AuthenticationStatus; +import org.apache.qpid.server.security.auth.sasl.SaslUtil; +import org.apache.qpid.server.security.auth.sasl.plain.PlainSaslServer; +import org.apache.qpid.test.utils.QpidTestCase; + +public class SimpleAuthenticationManagerTest extends QpidTestCase +{ + private static final String TEST_USER = "testUser"; + private static final String TEST_PASSWORD = "testPassword"; + private AuthenticationManager _authenticationManager; + + public void setUp() throws Exception + { + super.setUp(); + _authenticationManager = new SimpleAuthenticationManager(TEST_USER, TEST_PASSWORD); + } + + public void testGetMechanisms() + { + assertEquals("Unexpected mechanisms", "PLAIN CRAM-MD5", _authenticationManager.getMechanisms()); + } + + public void testCreateSaslServerForUnsupportedMechanisms() throws Exception + { + String[] unsupported = new String[] { "EXTERNAL", "CRAM-MD5-HEX", "CRAM-MD5-HASHED", "ANONYMOUS", "GSSAPI"}; + for (int i = 0; i < unsupported.length; i++) + { + String mechanism = unsupported[i]; + try + { + _authenticationManager.createSaslServer(mechanism, "test", null); + fail("Mechanism " + mechanism + " should not be supported by SimpleAuthenticationManager"); + } + catch (SaslException e) + { + // pass + } + } + } + + public void testAuthenticateWithPlainSaslServer() throws Exception + { + AuthenticationResult result = authenticatePlain(TEST_USER, TEST_PASSWORD); + assertAuthenticated(result); + } + + public void testAuthenticateWithPlainSaslServerInvalidPassword() throws Exception + { + AuthenticationResult result = authenticatePlain(TEST_USER, "wrong-password"); + assertUnauthenticated(result); + } + + public void testAuthenticateWithPlainSaslServerInvalidUsername() throws Exception + { + AuthenticationResult result = authenticatePlain("wrong-user", TEST_PASSWORD); + assertUnauthenticated(result); + } + + public void testAuthenticateWithCramMd5SaslServer() throws Exception + { + AuthenticationResult result = authenticateCramMd5(TEST_USER, TEST_PASSWORD); + assertAuthenticated(result); + } + + public void testAuthenticateWithCramMd5SaslServerInvalidPassword() throws Exception + { + AuthenticationResult result = authenticateCramMd5(TEST_USER, "wrong-password"); + assertUnauthenticated(result); + } + + public void testAuthenticateWithCramMd5SaslServerInvalidUsername() throws Exception + { + AuthenticationResult result = authenticateCramMd5("wrong-user", TEST_PASSWORD); + assertUnauthenticated(result); + } + + public void testAuthenticateValidCredentials() + { + AuthenticationResult result = _authenticationManager.authenticate(TEST_USER, TEST_PASSWORD); + assertEquals("Unexpected authentication result", AuthenticationStatus.SUCCESS, result.getStatus()); + assertAuthenticated(result); + } + + public void testAuthenticateInvalidPassword() + { + AuthenticationResult result = _authenticationManager.authenticate(TEST_USER, "invalid"); + assertUnauthenticated(result); + } + + public void testAuthenticateInvalidUserName() + { + AuthenticationResult result = _authenticationManager.authenticate("invalid", TEST_PASSWORD); + assertUnauthenticated(result); + } + + private void assertAuthenticated(AuthenticationResult result) + { + assertEquals("Unexpected authentication result", AuthenticationStatus.SUCCESS, result.getStatus()); + Principal principal = result.getMainPrincipal(); + assertEquals("Unexpected principal name", TEST_USER, principal.getName()); + Set<Principal> principals = result.getPrincipals(); + assertEquals("Unexpected principals size", 1, principals.size()); + assertEquals("Unexpected principal name", TEST_USER, principals.iterator().next().getName()); + } + + private void assertUnauthenticated(AuthenticationResult result) + { + assertEquals("Unexpected authentication result", AuthenticationStatus.ERROR, result.getStatus()); + assertNull("Unexpected principal", result.getMainPrincipal()); + Set<Principal> principals = result.getPrincipals(); + assertEquals("Unexpected principals size", 0, principals.size()); + } + + private AuthenticationResult authenticatePlain(String userName, String userPassword) throws SaslException, Exception + { + PlainSaslServer ss = (PlainSaslServer) _authenticationManager.createSaslServer("PLAIN", "test", null); + byte[] response = SaslUtil.generatePlainClientResponse(userName, userPassword); + + return _authenticationManager.authenticate(ss, response); + } + + private AuthenticationResult authenticateCramMd5(String userName, String userPassword) throws SaslException, Exception + { + SaslServer ss = _authenticationManager.createSaslServer("CRAM-MD5", "test", null); + byte[] challenge = ss.evaluateResponse(new byte[0]); + byte[] response = SaslUtil.generateCramMD5ClientResponse(userName, userPassword, challenge); + + AuthenticationResult result = _authenticationManager.authenticate(ss, response); + return result; + } +} diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/CRAMMD5HexInitialiserTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/CRAMMD5HexInitialiserTest.java index e408fd73d5..3079222b1c 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/CRAMMD5HexInitialiserTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/CRAMMD5HexInitialiserTest.java @@ -20,88 +20,94 @@ */ package org.apache.qpid.server.security.auth.sasl; -import junit.framework.TestCase; - -import org.apache.qpid.server.security.auth.database.PropertiesPrincipalDatabase; -import org.apache.qpid.server.security.auth.sasl.crammd5.CRAMMD5HexInitialiser; +import java.io.File; +import java.io.UnsupportedEncodingException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import javax.security.auth.callback.Callback; import javax.security.auth.callback.NameCallback; import javax.security.auth.callback.PasswordCallback; -import javax.security.auth.callback.UnsupportedCallbackException; -import java.io.IOException; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.Properties; + +import junit.framework.TestCase; + +import org.apache.qpid.server.security.auth.database.Base64MD5PasswordFilePrincipalDatabase; +import org.apache.qpid.server.security.auth.database.PrincipalDatabase; +import org.apache.qpid.server.security.auth.sasl.crammd5.CRAMMD5HexInitialiser; +import org.apache.qpid.test.utils.TestFileUtils; +import org.apache.qpid.tools.security.Passwd; /** * These tests ensure that the Hex wrapping that the initialiser performs does actually operate when the handle method is called. */ public class CRAMMD5HexInitialiserTest extends TestCase { - public void testHex() - { - //Create User details for testing - String user = "testUser"; - String password = "testPassword"; + private static final String TEST_PASSWORD = "testPassword"; + private static final String TEST_USER = "testUser"; + private File _file; - perform(user, password); - } - - public void testHashedHex() + public void testHashedHex() throws Exception { - //Create User details for testing - String user = "testUser"; - String password = "testPassword"; - - //Create a hashed password that we then attempt to put through the call back mechanism. - try - { - password = new String(MessageDigest.getInstance("MD5").digest(password.getBytes())); - } - catch (NoSuchAlgorithmException e) - { - fail(e.getMessage()); - } - - perform(user, password); + perform(TEST_USER, getHash(TEST_PASSWORD)); } - public void perform(String user, String password) + public void perform(String user, char[] password) throws Exception { CRAMMD5HexInitialiser initialiser = new CRAMMD5HexInitialiser(); - //Use properties to create a PrincipalDatabase - Properties users = new Properties(); - users.put(user, password); - - PropertiesPrincipalDatabase db = new PropertiesPrincipalDatabase(users); - + PrincipalDatabase db = new Base64MD5PasswordFilePrincipalDatabase(); + db.open(_file); initialiser.initialise(db); - //setup the callbacks PasswordCallback passwordCallback = new PasswordCallback("password:", false); NameCallback usernameCallback = new NameCallback("user:", user); Callback[] callbacks = new Callback[]{usernameCallback, passwordCallback}; - //Check the - try + assertNull("The password was not null before the handle call.", passwordCallback.getPassword()); + initialiser.getCallbackHandler().handle(callbacks); + + assertArrayEquals(toHex(password), passwordCallback.getPassword()); + } + + public void setUp() throws Exception + { + super.setUp(); + _file = TestFileUtils.createTempFile(this, "password-file", new Passwd().getOutput(TEST_USER , TEST_PASSWORD)); + } + + public void tearDown() throws Exception + { + if (_file != null) { - assertNull("The password was not null before the handle call.", passwordCallback.getPassword()); - initialiser.getCallbackHandler().handle(callbacks); + _file.delete(); } - catch (IOException e) + super.tearDown(); + } + + private char[] getHash(String text) throws NoSuchAlgorithmException, UnsupportedEncodingException + { + + byte[] data = text.getBytes("utf-8"); + + MessageDigest md = MessageDigest.getInstance("MD5"); + + for (byte b : data) { - fail(e.getMessage()); + md.update(b); } - catch (UnsupportedCallbackException e) + + byte[] digest = md.digest(); + + char[] hash = new char[digest.length]; + + int index = 0; + for (byte b : digest) { - fail(e.getMessage()); + hash[index++] = (char) b; } - //Hex the password we initialised with and compare it with the passwordCallback - assertArrayEquals(toHex(password.toCharArray()), passwordCallback.getPassword()); + return hash; } private void assertArrayEquals(char[] expected, char[] actual) @@ -135,4 +141,5 @@ public class CRAMMD5HexInitialiserTest extends TestCase return hex; } + } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/SaslUtil.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/SaslUtil.java new file mode 100644 index 0000000000..251ebc4c81 --- /dev/null +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/SaslUtil.java @@ -0,0 +1,85 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.security.auth.sasl; + +import java.security.MessageDigest; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; + +public class SaslUtil +{ + + private static byte SEPARATOR = 0; + + public static byte[] generatePlainClientResponse(String userName, String userPassword) throws Exception + { + byte[] password = userPassword.getBytes("UTF8"); + byte user[] = userName.getBytes("UTF8"); + byte response[] = new byte[password.length + user.length + 2]; + int size = 0; + response[size++] = SEPARATOR; + System.arraycopy(user, 0, response, size, user.length); + size += user.length; + response[size++] = SEPARATOR; + System.arraycopy(password, 0, response, size, password.length); + return response; + } + + public static byte[] generateCramMD5HexClientResponse(String userName, String userPassword, byte[] challengeBytes) + throws Exception + { + String macAlgorithm = "HmacMD5"; + byte[] digestedPasswordBytes = MessageDigest.getInstance("MD5").digest(userPassword.getBytes("UTF-8")); + byte[] hexEncodedDigestedPasswordBytes = toHex(digestedPasswordBytes).getBytes("UTF-8"); + Mac mac = Mac.getInstance(macAlgorithm); + mac.init(new SecretKeySpec(hexEncodedDigestedPasswordBytes, macAlgorithm)); + final byte[] messageAuthenticationCode = mac.doFinal(challengeBytes); + String responseAsString = userName + " " + toHex(messageAuthenticationCode); + return responseAsString.getBytes(); + } + + public static byte[] generateCramMD5ClientResponse(String userName, String userPassword, byte[] challengeBytes) + throws Exception + { + String macAlgorithm = "HmacMD5"; + Mac mac = Mac.getInstance(macAlgorithm); + mac.init(new SecretKeySpec(userPassword.getBytes("UTF-8"), macAlgorithm)); + final byte[] messageAuthenticationCode = mac.doFinal(challengeBytes); + String responseAsString = userName + " " + toHex(messageAuthenticationCode); + return responseAsString.getBytes(); + } + + public static String toHex(byte[] data) + { + StringBuffer hash = new StringBuffer(); + for (int i = 0; i < data.length; i++) + { + String hex = Integer.toHexString(0xFF & data[i]); + if (hex.length() == 1) + { + hash.append('0'); + } + hash.append(hex); + } + return hash.toString(); + } +} diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/util/StringUtilTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/util/StringUtilTest.java new file mode 100644 index 0000000000..93b4172792 --- /dev/null +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/util/StringUtilTest.java @@ -0,0 +1,38 @@ +package org.apache.qpid.server.util; + +import org.apache.qpid.server.util.StringUtil; +import org.apache.qpid.test.utils.QpidTestCase; + +public class StringUtilTest extends QpidTestCase +{ + private StringUtil _util; + + @Override + public void setUp() throws Exception + { + super.setUp(); + _util = new StringUtil(); + } + + public void testRandomAlphaNumericStringInt() + { + String password = _util.randomAlphaNumericString(10); + assertEquals("Unexpected password string length", 10, password.length()); + assertCharacters(password); + } + + private void assertCharacters(String password) + { + String numbers = "0123456789"; + String letters = "abcdefghijklmnopqrstuvwxwy"; + String others = "_-"; + String expectedCharacters = (numbers + letters + letters.toUpperCase() + others); + char[] chars = password.toCharArray(); + for (int i = 0; i < chars.length; i++) + { + char ch = chars[i]; + assertTrue("Unexpected character " + ch, expectedCharacters.indexOf(ch) != -1); + } + } + +} diff --git a/qpid/java/systests/etc/config-systests.json b/qpid/java/systests/etc/config-systests.json index ec3d17dbec..6bfaf08113 100644 --- a/qpid/java/systests/etc/config-systests.json +++ b/qpid/java/systests/etc/config-systests.json @@ -20,7 +20,6 @@ */ { "name": "QpidBroker", - "defaultAuthenticationProvider" : "plain", "defaultVirtualHost" : "test", "authenticationproviders" : [ { "name" : "plain", @@ -39,9 +38,11 @@ } ], "ports" : [ { "name" : "amqp", + "authenticationProvider" : "plain", "port" : "${test.port}" }, { "name" : "http", + "authenticationProvider" : "plain", "port" : "${test.hport}", "protocols" : [ "HTTP" ] }, { @@ -50,6 +51,7 @@ "protocols" : [ "RMI" ] }, { "name" : "jmx", + "authenticationProvider" : "plain", "port" : "${test.cport}", "protocols" : [ "JMX_RMI" ] }], @@ -67,4 +69,4 @@ "name" : "jmxManagement" } ] */ -}
\ No newline at end of file +} diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/client/ssl/SSLTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/client/ssl/SSLTest.java index e2cd3e254e..71b763685e 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/client/ssl/SSLTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/client/ssl/SSLTest.java @@ -362,6 +362,7 @@ public class SSLTest extends QpidBrokerTestCase Map<String, Object> sslPortAttributes = new HashMap<String, Object>(); sslPortAttributes.put(Port.TRANSPORTS, Collections.singleton(Transport.SSL)); sslPortAttributes.put(Port.PORT, DEFAULT_SSL_PORT); + sslPortAttributes.put(Port.AUTHENTICATION_PROVIDER, TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER); sslPortAttributes.put(Port.NEED_CLIENT_AUTH, needClientAuth); sslPortAttributes.put(Port.WANT_CLIENT_AUTH, wantClientAuth); sslPortAttributes.put(Port.NAME, TestBrokerConfiguration.ENTRY_NAME_SSL_PORT); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/BrokerLoggingTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/BrokerLoggingTest.java index c5f5e06ae1..7773586073 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/BrokerLoggingTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/BrokerLoggingTest.java @@ -95,9 +95,7 @@ public class BrokerLoggingTest extends AbstractTestLogging { String TESTID="BRK-1006"; - // This logging startup code only occurs when you run a Java broker, - // that broker must be started via Main so not an InVM broker. - if (isJavaBroker() && isExternalBroker()) + if (isJavaBroker()) { startBroker(); @@ -165,8 +163,6 @@ public class BrokerLoggingTest extends AbstractTestLogging */ public void testBrokerStartupDefaultLog4j() throws Exception { - // This logging startup code only occurs when you run a Java broker, - // that broker must be started via Main so not an InVM broker. if (isJavaBroker() && isExternalBroker() && !isInternalBroker()) { String TESTID = "BRK-1007"; @@ -256,7 +252,7 @@ public class BrokerLoggingTest extends AbstractTestLogging public void testBrokerStartupCustomLog4j() throws Exception { // This logging startup code only occurs when you run a Java broker - if (isJavaBroker() && isExternalBroker()) + if (isJavaBroker()) { String customLog4j = getBrokerCommandLog4JFile().getAbsolutePath(); @@ -344,7 +340,7 @@ public class BrokerLoggingTest extends AbstractTestLogging { // This logging startup code only occurs when you run a Java broker, // that broker must be started via Main so not an InVM broker. - if (isJavaBroker() && isExternalBroker()) + if (isJavaBroker()) { String TESTID = "BRK-1001"; @@ -426,9 +422,7 @@ public class BrokerLoggingTest extends AbstractTestLogging */ public void testBrokerStartupListeningTCPDefault() throws Exception { - // This logging startup code only occurs when you run a Java broker, - // that broker must be started via Main so not an InVM broker. - if (isJavaBroker() && isExternalBroker()) + if (isJavaBroker()) { String TESTID = "BRK-1002"; @@ -484,7 +478,7 @@ public class BrokerLoggingTest extends AbstractTestLogging //3 String message = getMessageString(log); assertTrue("Expected Listen log not correct" + message, - message.endsWith("Listening on [TCP] port " + getPort())); + message.endsWith("Listening on TCP port " + getPort())); validation = true; } @@ -534,9 +528,7 @@ public class BrokerLoggingTest extends AbstractTestLogging */ public void testBrokerStartupListeningTCPSSL() throws Exception { - // This logging startup code only occurs when you run a Java broker, - // that broker must be started via Main so not an InVM broker. - if (isJavaBroker() && isExternalBroker()) + if (isJavaBroker()) { String TESTID = "BRK-1002"; @@ -545,6 +537,8 @@ public class BrokerLoggingTest extends AbstractTestLogging sslPortAttributes.put(Port.TRANSPORTS, Collections.singleton(Transport.SSL)); sslPortAttributes.put(Port.PORT, DEFAULT_SSL_PORT); sslPortAttributes.put(Port.NAME, TestBrokerConfiguration.ENTRY_NAME_SSL_PORT); + sslPortAttributes.put(Port.AUTHENTICATION_PROVIDER, TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER); + sslPortAttributes.put(Port.KEY_STORE, TestBrokerConfiguration.ENTRY_NAME_SSL_KEYSTORE); getBrokerConfiguration().addPortConfiguration(sslPortAttributes); startBroker(); @@ -599,12 +593,12 @@ public class BrokerLoggingTest extends AbstractTestLogging //Check the first String message = getMessageString(getLog(listenMessages .get(0))); assertTrue("Expected Listen log not correct" + message, - message.endsWith("Listening on [TCP] port " + getPort())); + message.endsWith("Listening on TCP port " + getPort())); // Check the third, ssl listen. message = getMessageString(getLog(listenMessages .get(2))); assertTrue("Expected Listen log not correct" + message, - message.endsWith("Listening on [SSL] port " + DEFAULT_SSL_PORT)); + message.endsWith("Listening on SSL port " + DEFAULT_SSL_PORT)); //4 Test ports open testSocketOpen(getPort()); @@ -643,9 +637,7 @@ public class BrokerLoggingTest extends AbstractTestLogging */ public void testBrokerStartupReady() throws Exception { - // This logging startup code only occurs when you run a Java broker, - // that broker must be started via Main so not an InVM broker. - if (isJavaBroker() && isExternalBroker()) + if (isJavaBroker()) { String TESTID = "BRK-1004"; @@ -731,9 +723,7 @@ public class BrokerLoggingTest extends AbstractTestLogging */ public void testBrokerShutdownListeningTCPDefault() throws Exception { - // This logging startup code only occurs when you run a Java broker, - // that broker must be started via Main so not an InVM broker. - if (isJavaBroker() && isExternalBroker()) + if (isJavaBroker() && isInternalBroker()) { String TESTID = "BRK-1003"; @@ -825,9 +815,7 @@ public class BrokerLoggingTest extends AbstractTestLogging */ public void testBrokerShutdownListeningTCPSSL() throws Exception { - // This logging startup code only occurs when you run a Java broker, - // that broker must be started via Main so not an InVM broker. - if (isJavaBroker() && isExternalBroker()) + if (isJavaBroker() && isInternalBroker()) { String TESTID = "BRK-1003"; @@ -836,6 +824,8 @@ public class BrokerLoggingTest extends AbstractTestLogging sslPortAttributes.put(Port.TRANSPORTS, Collections.singleton(Transport.SSL)); sslPortAttributes.put(Port.PORT, DEFAULT_SSL_PORT); sslPortAttributes.put(Port.NAME, TestBrokerConfiguration.ENTRY_NAME_SSL_PORT); + sslPortAttributes.put(Port.AUTHENTICATION_PROVIDER, TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER); + sslPortAttributes.put(Port.KEY_STORE, TestBrokerConfiguration.ENTRY_NAME_SSL_KEYSTORE); getBrokerConfiguration().addPortConfiguration(sslPortAttributes); startBroker(); @@ -877,7 +867,7 @@ public class BrokerLoggingTest extends AbstractTestLogging // Check second, ssl, listen. message = getMessageString(getLog(listenMessages.get(1))); assertTrue("Expected shutdown log not correct" + message, - message.endsWith("TCP/SSL port " + DEFAULT_SSL_PORT)); + message.endsWith("SSL port " + DEFAULT_SSL_PORT)); //4 //Test Port closed @@ -913,9 +903,7 @@ public class BrokerLoggingTest extends AbstractTestLogging */ public void testBrokerShutdownStopped() throws Exception { - // This logging startup code only occurs when you run a Java broker, - // that broker must be started via Main so not an InVM broker. - if (isJavaBroker() && isExternalBroker()) + if (isJavaBroker() && isInternalBroker()) { String TESTID = "BRK-1005"; diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/VirtualHostLoggingTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/VirtualHostLoggingTest.java index 1ea105ae1a..25dd5fd2f8 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/VirtualHostLoggingTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/VirtualHostLoggingTest.java @@ -105,22 +105,25 @@ public class VirtualHostLoggingTest extends AbstractTestLogging */ public void testVirtualhostClosure() throws Exception { - stopBroker(); + if (isJavaBroker() && isInternalBroker()) + { + stopBroker(); - // Wait for the correct VHT message to arrive. - waitForMessage(VHT_PREFIX + "1002"); + // Wait for the correct VHT message to arrive. + waitForMessage(VHT_PREFIX + "1002"); - // Validate each vhost logs a closure - List<String> results = findMatches(VHT_PREFIX + "1002"); + // Validate each vhost logs a closure + List<String> results = findMatches(VHT_PREFIX + "1002"); - try - { - assertEquals("Each vhost did not close their store.", 1, results.size()); - } - catch (AssertionFailedError afe) - { - dumpLogs(results, _monitor); - throw afe; + try + { + assertEquals("Each vhost did not close their store.", 1, results.size()); + } + catch (AssertionFailedError afe) + { + dumpLogs(results, _monitor); + throw afe; + } } } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationTest.java index 711765c159..6cc4ec17c7 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationTest.java @@ -42,7 +42,6 @@ import org.apache.commons.configuration.ConfigurationException; import org.apache.qpid.client.AMQConnectionURL; import org.apache.qpid.management.common.mbeans.ManagedConnection; import org.apache.qpid.server.model.AuthenticationProvider; -import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.Transport; import org.apache.qpid.server.model.TrustStore; @@ -67,7 +66,6 @@ public class ExternalAuthenticationTest extends QpidBrokerTestCase public void testExternalAuthenticationManagerOnSSLPort() throws Exception { setCommonBrokerSSLProperties(true); - getBrokerConfiguration().setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_SSL_PORT, Port.AUTHENTICATION_PROVIDER, TestBrokerConfiguration.ENTRY_NAME_EXTERNAL_PROVIDER); super.setUp(); setClientKeystoreProperties(); @@ -94,13 +92,13 @@ public class ExternalAuthenticationTest extends QpidBrokerTestCase } /** - * Tests that when EXTERNAL authentication manager is set as the default, clients presenting certificates are able to connect. - * Also, checks a client with valid username and password but not using ssl is unable to connect to the non SSL port. + * Tests that when EXTERNAL authentication manager is set on the non-SSL port, clients with valid username and password + * but not using ssl are unable to connect to the non-SSL port. */ - public void testExternalAuthenticationManagerAsDefault() throws Exception + public void testExternalAuthenticationManagerOnNonSslPort() throws Exception { setCommonBrokerSSLProperties(true); - getBrokerConfiguration().setBrokerAttribute(Broker.DEFAULT_AUTHENTICATION_PROVIDER, TestBrokerConfiguration.ENTRY_NAME_EXTERNAL_PROVIDER); + getBrokerConfiguration().setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_AMQP_PORT, Port.AUTHENTICATION_PROVIDER, TestBrokerConfiguration.ENTRY_NAME_EXTERNAL_PROVIDER); super.setUp(); setClientKeystoreProperties(); @@ -115,25 +113,15 @@ public class ExternalAuthenticationTest extends QpidBrokerTestCase { // pass } - - try - { - getExternalSSLConnection(false); - } - catch (JMSException e) - { - fail("Should be able to create a connection to the SSL port. " + e.getMessage()); - } } /** - * Tests that when EXTERNAL authentication manager is set as the default, clients without certificates are unable to connect to the SSL port + * Tests that when EXTERNAL authentication manager is used, clients without certificates are unable to connect to the SSL port * even with valid username and password. */ public void testExternalAuthenticationManagerWithoutClientKeyStore() throws Exception { setCommonBrokerSSLProperties(false); - getBrokerConfiguration().setBrokerAttribute(Broker.DEFAULT_AUTHENTICATION_PROVIDER, TestBrokerConfiguration.ENTRY_NAME_EXTERNAL_PROVIDER); super.setUp(); setClientTrustoreProperties(); @@ -156,7 +144,6 @@ public class ExternalAuthenticationTest extends QpidBrokerTestCase public void testExternalAuthenticationDeniesUntrustedClientCert() throws Exception { setCommonBrokerSSLProperties(true); - getBrokerConfiguration().setBrokerAttribute(Broker.DEFAULT_AUTHENTICATION_PROVIDER, TestBrokerConfiguration.ENTRY_NAME_EXTERNAL_PROVIDER); super.setUp(); setUntrustedClientKeystoreProperties(); @@ -219,8 +206,6 @@ public class ExternalAuthenticationTest extends QpidBrokerTestCase sslTrustStoreAttributes.put(TrustStore.PEERS_ONLY, true); getBrokerConfiguration().addTrustStoreConfiguration(sslTrustStoreAttributes); - getBrokerConfiguration().setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_SSL_PORT, Port.AUTHENTICATION_PROVIDER, TestBrokerConfiguration.ENTRY_NAME_EXTERNAL_PROVIDER); - super.setUp(); setClientKeystoreProperties(); @@ -267,7 +252,6 @@ public class ExternalAuthenticationTest extends QpidBrokerTestCase JMXTestUtils jmxUtils = new JMXTestUtils(this); setCommonBrokerSSLProperties(true); - getBrokerConfiguration().setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_SSL_PORT, Port.AUTHENTICATION_PROVIDER, TestBrokerConfiguration.ENTRY_NAME_EXTERNAL_PROVIDER); getBrokerConfiguration().addJmxManagementConfiguration(); super.setUp(); @@ -301,7 +285,6 @@ public class ExternalAuthenticationTest extends QpidBrokerTestCase JMXTestUtils jmxUtils = new JMXTestUtils(this); setCommonBrokerSSLProperties(true); - getBrokerConfiguration().setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_SSL_PORT, Port.AUTHENTICATION_PROVIDER, TestBrokerConfiguration.ENTRY_NAME_EXTERNAL_PROVIDER); getBrokerConfiguration().setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_EXTERNAL_PROVIDER, ExternalAuthenticationManagerFactory.ATTRIBUTE_USE_FULL_DN, "true"); getBrokerConfiguration().addJmxManagementConfiguration(); @@ -354,6 +337,7 @@ public class ExternalAuthenticationTest extends QpidBrokerTestCase private void setCommonBrokerSSLProperties(boolean needClientAuth, Collection<String> trustStoreNames) throws ConfigurationException { TestBrokerConfiguration config = getBrokerConfiguration(); + Map<String, Object> sslPortAttributes = new HashMap<String, Object>(); sslPortAttributes.put(Port.TRANSPORTS, Collections.singleton(Transport.SSL)); sslPortAttributes.put(Port.PORT, DEFAULT_SSL_PORT); @@ -364,9 +348,11 @@ public class ExternalAuthenticationTest extends QpidBrokerTestCase config.addPortConfiguration(sslPortAttributes); Map<String, Object> externalAuthProviderAttributes = new HashMap<String, Object>(); - externalAuthProviderAttributes.put(AuthenticationManagerFactory.ATTRIBUTE_TYPE, ExternalAuthenticationManagerFactory.PROVIDER_TYPE); externalAuthProviderAttributes.put(AuthenticationProvider.NAME, TestBrokerConfiguration.ENTRY_NAME_EXTERNAL_PROVIDER); + externalAuthProviderAttributes.put(AuthenticationManagerFactory.ATTRIBUTE_TYPE, ExternalAuthenticationManagerFactory.PROVIDER_TYPE); config.addAuthenticationProviderConfiguration(externalAuthProviderAttributes); + + config.setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_SSL_PORT, Port.AUTHENTICATION_PROVIDER, TestBrokerConfiguration.ENTRY_NAME_EXTERNAL_PROVIDER); } private void setUntrustedClientKeystoreProperties() 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 7d4576db06..88a99ccf2b 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 @@ -126,7 +126,6 @@ public class BrokerRestTest extends QpidRestTestCase public void testPutToUpdateWithInvalidAttributeValues() throws Exception { Map<String, Object> invalidAttributes = new HashMap<String, Object>(); - invalidAttributes.put(Broker.DEFAULT_AUTHENTICATION_PROVIDER, "non-existing-provider"); invalidAttributes.put(Broker.DEFAULT_VIRTUAL_HOST, "non-existing-host"); invalidAttributes.put(Broker.QUEUE_ALERT_THRESHOLD_MESSAGE_AGE, -1000); invalidAttributes.put(Broker.QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES, -2000); @@ -166,7 +165,6 @@ public class BrokerRestTest extends QpidRestTestCase private Map<String, Object> getValidBrokerAttributes() { Map<String, Object> brokerAttributes = new HashMap<String, Object>(); - brokerAttributes.put(Broker.DEFAULT_AUTHENTICATION_PROVIDER, ANONYMOUS_AUTHENTICATION_PROVIDER); brokerAttributes.put(Broker.DEFAULT_VIRTUAL_HOST, TEST3_VIRTUALHOST); brokerAttributes.put(Broker.QUEUE_ALERT_THRESHOLD_MESSAGE_AGE, 1000); brokerAttributes.put(Broker.QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES, 2000); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/KeyStoreRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/KeyStoreRestTest.java index 149ddcfcbb..c38d9bb396 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/KeyStoreRestTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/KeyStoreRestTest.java @@ -115,6 +115,7 @@ public class KeyStoreRestTest extends QpidRestTestCase sslPortAttributes.put(Port.TRANSPORTS, Collections.singleton(Transport.SSL)); sslPortAttributes.put(Port.PORT, DEFAULT_SSL_PORT); sslPortAttributes.put(Port.NAME, TestBrokerConfiguration.ENTRY_NAME_SSL_PORT); + sslPortAttributes.put(Port.AUTHENTICATION_PROVIDER, TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER); sslPortAttributes.put(Port.KEY_STORE, name); getBrokerConfiguration().addPortConfiguration(sslPortAttributes); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/PortRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/PortRestTest.java index 8ec9e50fa9..be4dea6e81 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/PortRestTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/PortRestTest.java @@ -78,6 +78,7 @@ public class PortRestTest extends QpidRestTestCase Map<String, Object> attributes = new HashMap<String, Object>(); attributes.put(Port.NAME, portName); attributes.put(Port.PORT, findFreePort()); + attributes.put(Port.AUTHENTICATION_PROVIDER, TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER); int responseCode = getRestTestHelper().submitRequest("/rest/port/" + portName, "PUT", attributes); assertEquals("Unexpected response code", 201, responseCode); @@ -138,6 +139,7 @@ public class PortRestTest extends QpidRestTestCase Map<String, Object> attributes = new HashMap<String, Object>(); attributes.put(Port.NAME, portName); attributes.put(Port.PORT, findFreePort()); + attributes.put(Port.AUTHENTICATION_PROVIDER, TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER); int responseCode = getRestTestHelper().submitRequest("/rest/port/" + portName, "PUT", attributes); assertEquals("Unexpected response code for port creation", 201, responseCode); @@ -161,25 +163,6 @@ public class PortRestTest extends QpidRestTestCase responseCode = getRestTestHelper().submitRequest("/rest/port/" + portName, "PUT", attributes); assertEquals("Port cannot be updated in non management mode", 409, responseCode); - - restartBrokerInManagementMode(); - - responseCode = getRestTestHelper().submitRequest("/rest/port/" + portName, "PUT", attributes); - assertEquals("Port should be allwed to update in a management mode", 200, responseCode); - - portDetails = getRestTestHelper().getJsonAsList("/rest/port/" + portName); - assertNotNull("Port details cannot be null", portDetails); - assertEquals("Unexpected number of ports with name " + portName, 1, portDetails.size()); - port = portDetails.get(0); - - assertEquals("Unexpected authentication provider", TestBrokerConfiguration.ENTRY_NAME_ANONYMOUS_PROVIDER, port.get(Port.AUTHENTICATION_PROVIDER)); - Object protocols = port.get(Port.PROTOCOLS); - assertNotNull("Protocols attribute is not found", protocols); - assertTrue("Protocol attribute value is not collection:" + protocols, protocols instanceof Collection); - @SuppressWarnings("unchecked") - Collection<String> protocolsCollection = ((Collection<String>)protocols); - assertEquals("Unexpected protocols size", 1, protocolsCollection.size()); - assertEquals("Unexpected protocols", Protocol.AMQP_0_9_1.name(), protocolsCollection.iterator().next()); } public void testPutUpdateOpenedAmqpPortFails() throws Exception @@ -199,6 +182,7 @@ public class PortRestTest extends QpidRestTestCase public void testUpdatePortTransportFromTCPToSSLWhenKeystoreIsConfigured() throws Exception { restartBrokerInManagementMode(); + getRestTestHelper().setManagementModeCredentials(); String portName = TestBrokerConfiguration.ENTRY_NAME_AMQP_PORT; Map<String, Object> attributes = new HashMap<String, Object>(); @@ -210,6 +194,7 @@ public class PortRestTest extends QpidRestTestCase assertEquals("Transport has not been changed to SSL " , 200, responseCode); restartBroker(); + getRestTestHelper().setUsernameAndPassword("webadmin", "webadmin"); Map<String, Object> port = getRestTestHelper().getJsonAsSingletonList("/rest/port/" + portName); @@ -225,6 +210,7 @@ public class PortRestTest extends QpidRestTestCase public void testUpdateTransportFromTCPToSSLWithoutKeystoreConfiguredFails() throws Exception { restartBrokerInManagementMode(); + getRestTestHelper().setManagementModeCredentials(); String portName = TestBrokerConfiguration.ENTRY_NAME_AMQP_PORT; Map<String, Object> attributes = new HashMap<String, Object>(); @@ -241,6 +227,7 @@ public class PortRestTest extends QpidRestTestCase Map<String, Object> attributes = new HashMap<String, Object>(); attributes.put(Port.NAME, portName); attributes.put(Port.PORT, DEFAULT_SSL_PORT); + attributes.put(Port.AUTHENTICATION_PROVIDER, TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER); attributes.put(Port.TRANSPORTS, Collections.singleton(Transport.SSL)); attributes.put(Port.KEY_STORE, TestBrokerConfiguration.ENTRY_NAME_SSL_KEYSTORE); attributes.put(Port.TRUST_STORES, Collections.singleton(TestBrokerConfiguration.ENTRY_NAME_SSL_TRUSTSTORE)); @@ -249,6 +236,7 @@ public class PortRestTest extends QpidRestTestCase assertEquals("SSL port was not added", 201, responseCode); restartBrokerInManagementMode(); + getRestTestHelper().setManagementModeCredentials(); attributes.put(Port.NEED_CLIENT_AUTH, true); attributes.put(Port.WANT_CLIENT_AUTH, true); @@ -257,6 +245,7 @@ public class PortRestTest extends QpidRestTestCase assertEquals("Attributes for need/want client auth are not set", 200, responseCode); restartBroker(); + getRestTestHelper().setUsernameAndPassword("webadmin", "webadmin"); Map<String, Object> port = getRestTestHelper().getJsonAsSingletonList("/rest/port/" + portName); assertEquals("Unexpected " + Port.NEED_CLIENT_AUTH, true, port.get(Port.NEED_CLIENT_AUTH)); assertEquals("Unexpected " + Port.WANT_CLIENT_AUTH, true, port.get(Port.WANT_CLIENT_AUTH)); @@ -267,6 +256,7 @@ public class PortRestTest extends QpidRestTestCase new HashSet<String>(trustStores)); restartBrokerInManagementMode(); + getRestTestHelper().setManagementModeCredentials(); attributes = new HashMap<String, Object>(); attributes.put(Port.NAME, portName); @@ -285,6 +275,7 @@ public class PortRestTest extends QpidRestTestCase assertEquals("Should be able to change transport to TCP ", 200, responseCode); restartBroker(); + getRestTestHelper().setUsernameAndPassword("webadmin", "webadmin"); port = getRestTestHelper().getJsonAsSingletonList("/rest/port/" + portName); assertEquals("Unexpected " + Port.NEED_CLIENT_AUTH, false, port.get(Port.NEED_CLIENT_AUTH)); assertEquals("Unexpected " + Port.WANT_CLIENT_AUTH, false, port.get(Port.WANT_CLIENT_AUTH)); @@ -298,6 +289,7 @@ public class PortRestTest extends QpidRestTestCase public void testUpdateSettingWantNeedCertificateFailsForNonSSLPort() throws Exception { restartBrokerInManagementMode(); + getRestTestHelper().setManagementModeCredentials(); String portName = TestBrokerConfiguration.ENTRY_NAME_AMQP_PORT; Map<String, Object> attributes = new HashMap<String, Object>(); @@ -316,6 +308,7 @@ public class PortRestTest extends QpidRestTestCase public void testUpdatePortAuthenticationProvider() throws Exception { restartBrokerInManagementMode(); + getRestTestHelper().setManagementModeCredentials(); String portName = TestBrokerConfiguration.ENTRY_NAME_AMQP_PORT; Map<String, Object> attributes = new HashMap<String, Object>(); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/RestTestHelper.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/RestTestHelper.java index 9628423a00..c15e5d7285 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/RestTestHelper.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/RestTestHelper.java @@ -51,6 +51,7 @@ import junit.framework.Assert; import org.apache.commons.codec.binary.Base64; import org.apache.commons.configuration.ConfigurationException; import org.apache.log4j.Logger; +import org.apache.qpid.server.BrokerOptions; import org.apache.qpid.server.security.auth.manager.AbstractPrincipalDatabaseAuthManagerFactory; import org.apache.qpid.ssl.SSLContextFactory; import org.apache.qpid.test.utils.QpidBrokerTestCase; @@ -400,6 +401,11 @@ public class RestTestHelper _password = password; } + public void setManagementModeCredentials() + { + setUsernameAndPassword(BrokerOptions.MANAGEMENT_MODE_USER_NAME, QpidBrokerTestCase.MANAGEMENT_MODE_PASSWORD); + } + /** * Create password file that follows the convention username=password, which is deleted by {@link #tearDown()} */ diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/SaslRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/SaslRestTest.java index a5b1c4ff74..1c05f17e25 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/SaslRestTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/SaslRestTest.java @@ -20,20 +20,20 @@ */ package org.apache.qpid.systest.rest; +import static org.apache.qpid.server.security.auth.sasl.SaslUtil.generateCramMD5ClientResponse; +import static org.apache.qpid.server.security.auth.sasl.SaslUtil.generateCramMD5HexClientResponse; +import static org.apache.qpid.server.security.auth.sasl.SaslUtil.generatePlainClientResponse; + import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.OutputStream; import java.net.HttpURLConnection; -import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.HashMap; import java.util.List; import java.util.Map; -import javax.crypto.Mac; -import javax.crypto.spec.SecretKeySpec; - import org.apache.commons.codec.binary.Base64; import org.apache.commons.configuration.ConfigurationException; import org.apache.qpid.server.plugin.AuthenticationManagerFactory; @@ -345,59 +345,6 @@ public class SaslRestTest extends QpidRestTestCase } } - private static byte SEPARATOR = 0; - - private byte[] generatePlainClientResponse(String userName, String userPassword) throws Exception - { - byte[] password = userPassword.getBytes("UTF8"); - byte user[] = userName.getBytes("UTF8"); - byte response[] = new byte[password.length + user.length + 2 ]; - int size = 0; - response[size++] = SEPARATOR; - System.arraycopy(user, 0, response, size, user.length); - size += user.length; - response[size++] = SEPARATOR; - System.arraycopy(password, 0, response, size, password.length); - return response; - } - - private byte[] generateCramMD5HexClientResponse(String userName, String userPassword, byte[] challengeBytes) throws Exception - { - String macAlgorithm = "HmacMD5"; - byte[] digestedPasswordBytes = MessageDigest.getInstance("MD5").digest(userPassword.getBytes("UTF-8")); - byte[] hexEncodedDigestedPasswordBytes = toHex(digestedPasswordBytes).getBytes("UTF-8"); - Mac mac = Mac.getInstance(macAlgorithm); - mac.init(new SecretKeySpec(hexEncodedDigestedPasswordBytes, macAlgorithm)); - final byte[] messageAuthenticationCode = mac.doFinal(challengeBytes); - String responseAsString = userName + " " + toHex(messageAuthenticationCode); - return responseAsString.getBytes(); - } - - private byte[] generateCramMD5ClientResponse(String userName, String userPassword, byte[] challengeBytes) throws Exception - { - String macAlgorithm = "HmacMD5"; - Mac mac = Mac.getInstance(macAlgorithm); - mac.init(new SecretKeySpec(userPassword.getBytes("UTF-8"), macAlgorithm)); - final byte[] messageAuthenticationCode = mac.doFinal(challengeBytes); - String responseAsString = userName + " " + toHex(messageAuthenticationCode); - return responseAsString.getBytes(); - } - - private String toHex(byte[] data) - { - StringBuffer hash = new StringBuffer(); - for (int i = 0; i < data.length; i++) - { - String hex = Integer.toHexString(0xFF & data[i]); - if (hex.length() == 1) - { - hash.append('0'); - } - hash.append(hex); - } - return hash.toString(); - } - private void configureBase64MD5FilePrincipalDatabase() throws IOException, ConfigurationException { // generate user password entry diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/TrustStoreRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/TrustStoreRestTest.java index 87e7367235..8b788780d6 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/TrustStoreRestTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/TrustStoreRestTest.java @@ -114,6 +114,7 @@ public class TrustStoreRestTest extends QpidRestTestCase sslPortAttributes.put(Port.TRANSPORTS, Collections.singleton(Transport.SSL)); sslPortAttributes.put(Port.PORT, DEFAULT_SSL_PORT); sslPortAttributes.put(Port.NAME, TestBrokerConfiguration.ENTRY_NAME_SSL_PORT); + sslPortAttributes.put(Port.AUTHENTICATION_PROVIDER, TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER); sslPortAttributes.put(Port.KEY_STORE, TestBrokerConfiguration.ENTRY_NAME_SSL_KEYSTORE); sslPortAttributes.put(Port.TRUST_STORES, Collections.singleton(name)); getBrokerConfiguration().addPortConfiguration(sslPortAttributes); 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 8806289bd0..ce4c869e66 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 @@ -260,8 +260,6 @@ public class BrokerACLTest extends QpidRestTestCase String portName = TestBrokerConfiguration.ENTRY_NAME_AMQP_PORT; assertPortExists(portName); - restartBrokerInManagementMode(); - getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER); int responseCode = getRestTestHelper().submitRequest("/rest/port/" + portName, "DELETE", null); @@ -270,15 +268,14 @@ public class BrokerACLTest extends QpidRestTestCase assertPortExists(portName); } - public void testDeletePortAllowed() throws Exception + // TODO: test disabled until allowing the deletion of active ports outside management mode + public void DISABLED_testDeletePortAllowed() throws Exception { getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); String portName = TestBrokerConfiguration.ENTRY_NAME_AMQP_PORT; assertPortExists(portName); - restartBrokerInManagementMode(); - getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); int responseCode = getRestTestHelper().submitRequest("/rest/port/" + portName, "DELETE", null); @@ -287,7 +284,8 @@ public class BrokerACLTest extends QpidRestTestCase assertPortDoesNotExist(portName); } - public void testSetPortAttributesAllowed() throws Exception + // TODO: test disabled until allowing the updating of active ports outside management mode + public void DISABLED_testSetPortAttributesAllowed() throws Exception { getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); @@ -298,7 +296,6 @@ public class BrokerACLTest extends QpidRestTestCase assertPortExists(portName); - restartBrokerInManagementMode(); Map<String, Object> attributes = new HashMap<String, Object>(); attributes.put(Port.NAME, portName); @@ -322,8 +319,6 @@ public class BrokerACLTest extends QpidRestTestCase assertPortExists(portName); - restartBrokerInManagementMode(); - getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER); Map<String, Object> attributes = new HashMap<String, Object>(); @@ -600,42 +595,45 @@ public class BrokerACLTest extends QpidRestTestCase { getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); - String defaultAuthenticationProvider = TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER; + int initialAlertRepeatGap = 30000; + int updatedAlertRepeatGap = 29999; + Map<String, Object> brokerAttributes = getRestTestHelper().getJsonAsSingletonList("/rest/broker"); - assertEquals("Unexpected authentication provider", defaultAuthenticationProvider, - brokerAttributes.get(Broker.DEFAULT_AUTHENTICATION_PROVIDER)); - restartBrokerInManagementMode(); + assertEquals("Unexpected alert repeat gap", initialAlertRepeatGap, + brokerAttributes.get(Broker.QUEUE_ALERT_REPEAT_GAP)); Map<String, Object> newAttributes = new HashMap<String, Object>(); - newAttributes.put(Broker.DEFAULT_AUTHENTICATION_PROVIDER, ANONYMOUS_AUTHENTICATION_PROVIDER); + newAttributes.put(Broker.QUEUE_ALERT_REPEAT_GAP, updatedAlertRepeatGap); + int responseCode = getRestTestHelper().submitRequest("/rest/broker", "PUT", newAttributes); assertEquals("Setting of port attribites should be allowed", 200, responseCode); brokerAttributes = getRestTestHelper().getJsonAsSingletonList("/rest/broker"); - assertEquals("Unexpected default authentication provider attribute value", ANONYMOUS_AUTHENTICATION_PROVIDER, - brokerAttributes.get(Broker.DEFAULT_AUTHENTICATION_PROVIDER)); + assertEquals("Unexpected default alert repeat gap", updatedAlertRepeatGap, + brokerAttributes.get(Broker.QUEUE_ALERT_REPEAT_GAP)); } public void testSetBrokerAttributesDenied() throws Exception { getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); - String defaultAuthenticationProvider = TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER; + int initialAlertRepeatGap = 30000; + int updatedAlertRepeatGap = 29999; Map<String, Object> brokerAttributes = getRestTestHelper().getJsonAsSingletonList("/rest/broker"); - assertEquals("Unexpected authentication provider", defaultAuthenticationProvider, - brokerAttributes.get(Broker.DEFAULT_AUTHENTICATION_PROVIDER)); - restartBrokerInManagementMode(); + assertEquals("Unexpected alert repeat gap", initialAlertRepeatGap, + brokerAttributes.get(Broker.QUEUE_ALERT_REPEAT_GAP)); getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER); Map<String, Object> newAttributes = new HashMap<String, Object>(); - newAttributes.put(Broker.DEFAULT_AUTHENTICATION_PROVIDER, ANONYMOUS_AUTHENTICATION_PROVIDER); + newAttributes.put(Broker.QUEUE_ALERT_REPEAT_GAP, updatedAlertRepeatGap); + int responseCode = getRestTestHelper().submitRequest("/rest/broker", "PUT", newAttributes); assertEquals("Setting of port attribites should be allowed", 403, responseCode); brokerAttributes = getRestTestHelper().getJsonAsSingletonList("/rest/broker"); - assertEquals("Unexpected default authentication provider attribute value", defaultAuthenticationProvider, - brokerAttributes.get(Broker.DEFAULT_AUTHENTICATION_PROVIDER)); + assertEquals("Unexpected default alert repeat gap", initialAlertRepeatGap, + brokerAttributes.get(Broker.QUEUE_ALERT_REPEAT_GAP)); } private int createPort(String portName) throws Exception diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java index b005a9748c..c14c724419 100755 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java @@ -184,6 +184,7 @@ public class QpidBrokerTestCase extends QpidTestCase protected List<Connection> _connections = new ArrayList<Connection>(); public static final String QUEUE = "queue"; public static final String TOPIC = "topic"; + public static final String MANAGEMENT_MODE_PASSWORD = "mm_password"; /** Map to hold test defined environment properties */ private Map<String, String> _env; @@ -467,6 +468,10 @@ public class QpidBrokerTestCase extends QpidTestCase options.setConfigurationStoreType(_brokerStoreType); options.setConfigurationStoreLocation(testConfig); options.setManagementMode(managementMode); + if (managementMode) + { + options.setManagementModePassword(MANAGEMENT_MODE_PASSWORD); + } //Set the log config file, relying on the log4j.configuration system property //set on the JVM by the JUnit runner task in module.xml. @@ -486,9 +491,11 @@ public class QpidBrokerTestCase extends QpidTestCase String[] cmd = _brokerCommandHelper.getBrokerCommand(port, testConfig, _brokerStoreType, _logConfigFile); if (managementMode) { - String[] newCmd = new String[cmd.length + 1]; + String[] newCmd = new String[cmd.length + 3]; System.arraycopy(cmd, 0, newCmd, 0, cmd.length); newCmd[cmd.length] = "-mm"; + newCmd[cmd.length + 1] = "-mmpass"; + newCmd[cmd.length + 2] = MANAGEMENT_MODE_PASSWORD; cmd = newCmd; } _logger.info("Starting spawn broker using command: " + StringUtils.join(cmd, ' ')); diff --git a/qpid/java/test-profiles/Excludes b/qpid/java/test-profiles/Excludes index 9c07fea574..7a6089004e 100644 --- a/qpid/java/test-profiles/Excludes +++ b/qpid/java/test-profiles/Excludes @@ -17,16 +17,4 @@ // under the License. // -// -// QPID-2031 : Broker is not cleanly shutdown by QpidTestCase -// -org.apache.qpid.server.logging.BrokerLoggingTest#testBrokerShutdownListeningTCPDefault -org.apache.qpid.server.logging.BrokerLoggingTest#testBrokerShutdownListeningTCPSSL -org.apache.qpid.server.logging.BrokerLoggingTest#testBrokerShutdownStopped -org.apache.qpid.server.logging.VirtualHostLoggingTest#testVirtualhostClosure -org.apache.qpid.server.logging.MemoryMessageStoreLoggingTest#testMessageStoreClose - -// QPID-3424 : Test fails to start external broker due to Derby Exception. -org.apache.qpid.server.logging.DerbyMessageStoreLoggingTest#* - org.apache.qpid.client.ssl.SSLTest#testVerifyLocalHostLocalDomain |