From 5e8136af6e36d5f2689dd07e70095546c0120dbc Mon Sep 17 00:00:00 2001 From: Robert Godfrey Date: Fri, 17 Oct 2014 13:58:04 +0000 Subject: merged from trunk git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/QPID-6125-ProtocolRefactoring@1632579 13f79535-47bb-0310-9956-ffa450edef68 --- .../client/websocket/WebSocketProvider.java | 3 +- .../org/apache/qpid/amqp_1_0/client/SSLUtil.java | 32 +- .../qpid/amqp_1_0/client/TCPTransportProvier.java | 2 +- .../apache/qpid/amqp_1_0/framing/FrameHandler.java | 9 +- .../qpid/management/virtualhostnode/bdb_ha/show.js | 2 +- .../resources/virtualhostnode/bdb_ha/edit.html | 4 +- .../replication/BDBHAVirtualHostNodeRestTest.java | 1 + .../replication/BDBHAVirtualHostRestTest.java | 2 + .../berkeleydb/replication/JMXManagementTest.java | 2 + .../berkeleydb/replication/MultiNodeTest.java | 1 + .../store/berkeleydb/replication/TwoNodeTest.java | 2 + .../main/java/org/apache/qpid/server/Broker.java | 22 + .../store/StoreConfigurationChangeListener.java | 15 +- .../server/logging/messages/BrokerMessages.java | 34 ++ .../logging/messages/Broker_logmessages.properties | 4 +- .../server/model/AbstractConfiguredObject.java | 3 +- .../qpid/server/model/AuthenticationProvider.java | 4 +- .../org/apache/qpid/server/model/BrokerModel.java | 3 +- .../qpid/server/model/BrokerShutdownProvider.java | 2 +- .../server/model/ConfiguredObjectTypeRegistry.java | 5 +- .../qpid/server/model/DefaultVirtualHostAlias.java | 31 ++ .../server/model/FixedVirtualHostNodeAlias.java | 29 ++ .../apache/qpid/server/model/HostNameAlias.java | 33 ++ .../qpid/server/model/PatternMatchingAlias.java | 36 ++ .../java/org/apache/qpid/server/model/Port.java | 4 - .../apache/qpid/server/model/VirtualHostAlias.java | 13 +- .../qpid/server/model/VirtualHostNameAlias.java | 27 ++ .../qpid/server/model/adapter/BrokerAdapter.java | 3 +- .../model/adapter/VirtualHostAliasAdapter.java | 85 ---- .../qpid/server/model/port/AbstractPort.java | 125 +----- .../apache/qpid/server/model/port/AmqpPort.java | 4 +- .../qpid/server/model/port/AmqpPortImpl.java | 92 ++++- .../protocol/MultiVersionProtocolEngine.java | 2 + .../qpid/server/registry/ApplicationRegistry.java | 19 +- .../qpid/server/security/SubjectCreator.java | 4 +- .../manager/AbstractAuthenticationManager.java | 14 +- .../AbstractScramAuthenticationManager.java | 210 +--------- ...odelPasswordManagingAuthenticationProvider.java | 229 +++++++++++ .../auth/manager/MD5AuthenticationProvider.java | 227 +++++++++++ .../server/security/auth/manager/ManagedUser.java | 199 +++++++++ .../auth/manager/PlainAuthenticationProvider.java | 176 ++++++++ .../security/auth/manager/ScramAuthUser.java | 215 ---------- .../store/BrokerStoreUpgraderAndRecoverer.java | 70 ++++ .../store/ConfiguredObjectRecordConverter.java | 3 +- .../server/store/ConfiguredObjectRecordImpl.java | 2 +- .../qpid/server/store/JsonFileConfigStore.java | 3 +- .../VirtualHostStoreUpgraderAndRecoverer.java | 27 ++ .../qpid/server/transport/TCPandSSLTransport.java | 23 +- .../transport/TCPandSSLTransportProvider.java | 4 +- .../qpid/server/transport/TransportProvider.java | 4 +- .../server/virtualhost/AbstractVirtualHost.java | 13 - .../AbstractFixedVirtualHostNodeAlias.java | 56 +++ .../virtualhostalias/AbstractVirtualHostAlias.java | 62 +++ .../DefaultVirtualHostAliasImpl.java | 61 +++ .../server/virtualhostalias/HostNameAliasImpl.java | 193 +++++++++ .../virtualhostalias/PatternMatchingAliasImpl.java | 54 +++ .../virtualhostalias/VirtualHostNameAliasImpl.java | 54 +++ .../virtualhostnode/AbstractVirtualHostNode.java | 5 + .../org/apache/qpid/tools/security/Passwd.java | 70 ---- .../src/main/resources/initial-config.json | 15 +- .../StoreConfigurationChangeListenerTest.java | 5 + .../server/model/AbstractConfiguredObjectTest.java | 26 +- .../server/model/testmodel/TestChildCategory.java | 2 +- .../server/model/testmodel/TestRootCategory.java | 8 + .../qpid/server/security/SubjectCreatorTest.java | 8 +- .../auth/manager/MD5AuthenticationManagerTest.java | 53 +++ .../ManagedAuthenticationManagerTestBase.java | 252 ++++++++++++ .../manager/PlainAuthenticationManagerTest.java | 51 +++ .../ScramSHA1AuthenticationManagerTest.java | 194 +-------- .../auth/sasl/CRAMMD5HexInitialiserTest.java | 10 +- .../qpid/server/store/BrokerRecovererTest.java | 7 +- .../server/transport/TCPandSSLTransportTest.java | 180 +++++++++ .../apache/qpid/server/util/BrokerTestHelper.java | 28 +- .../virtualhostalias/VirtualHostAliasTest.java | 206 ++++++++++ .../org/apache/qpid/tools/security/PasswdTest.java | 38 -- .../qpid/server/protocol/v1_0/Connection_1_0.java | 11 +- .../apache/qpid/server/store/derby/DerbyUtils.java | 1 - .../server/management/plugin/HttpManagement.java | 3 +- .../rest/ConfiguredObjectToMapConverter.java | 3 +- .../src/main/java/resources/js/qpid/common/util.js | 3 +- .../js/qpid/management/AuthenticationProvider.js | 3 +- .../server/jmx/QpidSslRMIServerSocketFactory.java | 4 +- .../transport/websocket/WebSocketProvider.java | 6 +- .../websocket/WebSocketTransportProvider.java | 4 +- java/broker/bin/qpid-passwd | 35 -- .../src/main/java/org/apache/qpid/server/Main.java | 2 +- .../java/org/apache/qpid/client/AMQConnection.java | 80 ++-- .../org/apache/qpid/client/AMQSession_0_8.java | 5 +- .../qpid/configuration/ClientProperties.java | 12 + .../network/IncomingNetworkTransport.java | 8 +- .../transport/network/io/IoNetworkTransport.java | 33 +- .../network/security/SecurityLayerFactory.java | 10 +- .../transport/network/security/ssl/SSLUtil.java | 39 ++ .../qpid/transport/network/TransportTest.java | 13 +- .../1001-MessageSize-Transient-ByteSec.chartdef | 2 +- .../1002-MessageSize-Persistent-ByteSec.chartdef | 2 +- .../1003-MessageSize-Transient-MsgSec.chartdef | 2 +- .../1004-MessageSize-Persistent-MsgSec.chartdef | 2 +- .../1011-VaryingNumberOfProducers-AutoAck.chartdef | 2 +- .../1012-VaryingNumberOfConsumers-AutoAck.chartdef | 2 +- ...-VaryingNumberOfProducers-SessionTrans.chartdef | 2 +- ...-VaryingNumberOfConsumers-SessionTrans.chartdef | 2 +- .../1021-AcknowledgementModes-Persistent.chartdef | 2 +- .../1022-AcknowledgementModes-Transient.chartdef | 2 +- .../etc/chartdefs/1030-BatchSize-Equal.chartdef | 2 +- .../etc/chartdefs/1031-BatchSize-Unequal.chartdef | 2 +- .../etc/chartdefs/1040-QueueTypes.chartdef | 2 +- ...mberOfProducerSessionsSingleConnection.chartdef | 2 +- ...sWithNonOverlappingSelectors-Transient.chartdef | 2 +- ...WithNonOverlappingSelectors-Persistent.chartdef | 2 +- ...mersWithOverlappingSelectors-Transient.chartdef | 2 +- ...ersWithOverlappingSelectors-Persistent.chartdef | 2 +- .../1500-Topic-NumberOfConsumers.chartdef | 2 +- .../chartdefs/1501-Topic-NumberOfTopics.chartdef | 2 +- .../etc/chartdefs/1502-Topic-Persistence.chartdef | 2 +- .../etc/chartdefs/1503-Topic-AckModes.chartdef | 2 +- .../2001-Latency-MessageSize-Transient.chartdef | 2 +- .../2002-Latency-MessageSize-Persistent.chartdef | 2 +- ...31-Latency-VaryingNumberOfParticipants.chartdef | 2 +- java/perftests/etc/testdefs/QueueTypes.json | 12 +- java/perftests/pom.xml | 5 +- java/systests/etc/config-systests.json | 14 +- .../apache/qpid/test/utils/QpidBrokerTestCase.java | 1 + .../qpid/test/utils/TestBrokerConfiguration.java | 51 ++- .../java/org/apache/qpid/client/ssl/SSLTest.java | 23 +- .../org/apache/qpid/scripts/QpidPasswdTest.java | 80 ---- .../auth/manager/ExternalAuthenticationTest.java | 14 + .../MultipleAuthenticationManagersTest.java | 14 + .../systest/management/jmx/UserManagementTest.java | 42 +- .../UserManagementWithBase64MD5PasswordsTest.java | 31 +- .../org/apache/qpid/systest/rest/SaslRestTest.java | 11 +- java/tools/pom.xml | 1 - .../org/apache/qpid/tools/StressTestClient.java | 446 +++++++++++++++++++++ .../main/resources/stress-test-client.properties | 3 + 134 files changed, 3489 insertions(+), 1300 deletions(-) create mode 100644 java/broker-core/src/main/java/org/apache/qpid/server/model/DefaultVirtualHostAlias.java create mode 100644 java/broker-core/src/main/java/org/apache/qpid/server/model/FixedVirtualHostNodeAlias.java create mode 100644 java/broker-core/src/main/java/org/apache/qpid/server/model/HostNameAlias.java create mode 100644 java/broker-core/src/main/java/org/apache/qpid/server/model/PatternMatchingAlias.java create mode 100644 java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHostNameAlias.java delete mode 100644 java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAliasAdapter.java create mode 100644 java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ConfigModelPasswordManagingAuthenticationProvider.java create mode 100644 java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/MD5AuthenticationProvider.java create mode 100644 java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ManagedUser.java create mode 100644 java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/PlainAuthenticationProvider.java delete mode 100644 java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ScramAuthUser.java create mode 100644 java/broker-core/src/main/java/org/apache/qpid/server/virtualhostalias/AbstractFixedVirtualHostNodeAlias.java create mode 100644 java/broker-core/src/main/java/org/apache/qpid/server/virtualhostalias/AbstractVirtualHostAlias.java create mode 100644 java/broker-core/src/main/java/org/apache/qpid/server/virtualhostalias/DefaultVirtualHostAliasImpl.java create mode 100644 java/broker-core/src/main/java/org/apache/qpid/server/virtualhostalias/HostNameAliasImpl.java create mode 100644 java/broker-core/src/main/java/org/apache/qpid/server/virtualhostalias/PatternMatchingAliasImpl.java create mode 100644 java/broker-core/src/main/java/org/apache/qpid/server/virtualhostalias/VirtualHostNameAliasImpl.java delete mode 100644 java/broker-core/src/main/java/org/apache/qpid/tools/security/Passwd.java create mode 100644 java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/MD5AuthenticationManagerTest.java create mode 100644 java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/ManagedAuthenticationManagerTestBase.java create mode 100644 java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/PlainAuthenticationManagerTest.java create mode 100644 java/broker-core/src/test/java/org/apache/qpid/server/transport/TCPandSSLTransportTest.java create mode 100644 java/broker-core/src/test/java/org/apache/qpid/server/virtualhostalias/VirtualHostAliasTest.java delete mode 100644 java/broker-core/src/test/java/org/apache/qpid/tools/security/PasswdTest.java delete mode 100755 java/broker/bin/qpid-passwd delete mode 100644 java/systests/src/test/java/org/apache/qpid/scripts/QpidPasswdTest.java create mode 100644 java/tools/src/main/java/org/apache/qpid/tools/StressTestClient.java create mode 100644 java/tools/src/main/resources/stress-test-client.properties diff --git a/java/amqp-1-0-client-websocket/src/main/java/org/apache/qpid/amqp_1_0/client/websocket/WebSocketProvider.java b/java/amqp-1-0-client-websocket/src/main/java/org/apache/qpid/amqp_1_0/client/websocket/WebSocketProvider.java index cb1701b2fb..af871d2bc4 100644 --- a/java/amqp-1-0-client-websocket/src/main/java/org/apache/qpid/amqp_1_0/client/websocket/WebSocketProvider.java +++ b/java/amqp-1-0-client-websocket/src/main/java/org/apache/qpid/amqp_1_0/client/websocket/WebSocketProvider.java @@ -33,6 +33,7 @@ import org.eclipse.jetty.websocket.WebSocketClient; import org.eclipse.jetty.websocket.WebSocketClientFactory; import org.apache.qpid.amqp_1_0.client.ConnectionException; +import org.apache.qpid.amqp_1_0.client.SSLUtil; import org.apache.qpid.amqp_1_0.client.TransportProvider; import org.apache.qpid.amqp_1_0.codec.FrameWriter; import org.apache.qpid.amqp_1_0.framing.AMQFrame; @@ -71,7 +72,7 @@ class WebSocketProvider implements TransportProvider sslContextFactory.setSslContext(context); - + sslContextFactory.addExcludeProtocols(SSLUtil.SSLV3_PROTOCOL); factory.start(); return factory; diff --git a/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/SSLUtil.java b/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/SSLUtil.java index 70e5d08f15..225293c42e 100644 --- a/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/SSLUtil.java +++ b/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/SSLUtil.java @@ -20,13 +20,6 @@ */ package org.apache.qpid.amqp_1_0.client; -import javax.net.ssl.KeyManager; -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLEngine; -import javax.net.ssl.TrustManager; -import javax.net.ssl.TrustManagerFactory; -import javax.net.ssl.X509ExtendedKeyManager; import java.io.File; import java.io.FileInputStream; import java.io.IOException; @@ -37,10 +30,23 @@ import java.security.KeyStore; import java.security.Principal; import java.security.PrivateKey; import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import javax.net.ssl.KeyManager; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509ExtendedKeyManager; public class SSLUtil { public static final String TRANSPORT_LAYER_SECURITY_CODE = "TLS"; + public static final String SSLV3_PROTOCOL = "SSLv3"; public static SSLContext buildSslContext(final String certAlias, final String keyStorePath, @@ -212,4 +218,16 @@ public class SSLUtil return delegate.chooseEngineServerAlias(keyType, issuers, engine); } } + + public static void removeSSLv3Support(final SSLSocket socket) + { + List enabledProtocols = Arrays.asList(socket.getEnabledProtocols()); + if(enabledProtocols.contains(SSLV3_PROTOCOL)) + { + List allowedProtocols = new ArrayList<>(enabledProtocols); + allowedProtocols.remove(SSLV3_PROTOCOL); + socket.setEnabledProtocols(allowedProtocols.toArray(new String[allowedProtocols.size()])); + } + } + } diff --git a/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/TCPTransportProvier.java b/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/TCPTransportProvier.java index 139ef8fbda..720f12dc0d 100644 --- a/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/TCPTransportProvier.java +++ b/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/TCPTransportProvier.java @@ -74,8 +74,8 @@ class TCPTransportProvier implements TransportProvider if(sslContext != null) { final SSLSocketFactory socketFactory = sslContext.getSocketFactory(); - SSLSocket sslSocket = (SSLSocket) socketFactory.createSocket(address, port); + SSLUtil.removeSSLv3Support(sslSocket); sslSocket.startHandshake(); conn.setExternalPrincipal(sslSocket.getSession().getLocalPrincipal()); _socket=sslSocket; diff --git a/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/framing/FrameHandler.java b/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/framing/FrameHandler.java index bc16ba14e0..3e9dca683e 100644 --- a/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/framing/FrameHandler.java +++ b/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/framing/FrameHandler.java @@ -20,7 +20,9 @@ */ package org.apache.qpid.amqp_1_0.framing; -import org.apache.qpid.amqp_1_0.codec.BinaryWriter; +import java.nio.ByteBuffer; +import java.util.Formatter; + import org.apache.qpid.amqp_1_0.codec.ProtocolHandler; import org.apache.qpid.amqp_1_0.codec.ValueHandler; import org.apache.qpid.amqp_1_0.transport.ConnectionEndpoint; @@ -30,9 +32,6 @@ import org.apache.qpid.amqp_1_0.type.transport.ConnectionError; import org.apache.qpid.amqp_1_0.type.transport.Error; import org.apache.qpid.amqp_1_0.type.transport.Transfer; -import java.nio.ByteBuffer; -import java.util.Formatter; - public class FrameHandler implements ProtocolHandler { private ConnectionEndpoint _connection; @@ -122,7 +121,7 @@ public class FrameHandler implements ProtocolHandler if(size < 8) { - frameParsingError = createFramingError("specified frame size %d smaller than minimum frame header size %d", _size, 8); + frameParsingError = createFramingError("specified frame size %d smaller than minimum frame header size %d", size, 8); state = State.ERROR; break; } diff --git a/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb_ha/show.js b/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb_ha/show.js index e27b640933..9538b6b5b6 100644 --- a/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb_ha/show.js +++ b/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb_ha/show.js @@ -31,7 +31,7 @@ define(["dojo/_base/xhr", "dojo/domReady!"], function (xhr, connect, entities, query, json, registry, EnhancedGrid, UpdatableStore, UserPreferences, util) { - var priorityNames = {'_0': 'Never', '_1': 'Default', '_2': 'Normal', '_3': 'High'}; + var priorityNames = {'_0': 'Never', '_1': 'Default', '_2': 'High', '_3': 'Highest'}; var nodeFields = ["storePath", "groupName", "role", "address", "designatedPrimary", "priority", "quorumOverride"]; function findNode(nodeClass, containerNode) diff --git a/java/bdbstore/src/main/java/resources/virtualhostnode/bdb_ha/edit.html b/java/bdbstore/src/main/java/resources/virtualhostnode/bdb_ha/edit.html index e040420bdb..013ae271ec 100644 --- a/java/bdbstore/src/main/java/resources/virtualhostnode/bdb_ha/edit.html +++ b/java/bdbstore/src/main/java/resources/virtualhostnode/bdb_ha/edit.html @@ -113,8 +113,8 @@ data-dojo-props="data: [ {id: '0', name: 'Never'}, {id: '1', name: 'Default', selected: '1'}, - {id: '2', name: 'Normal'}, - {id: '3', name: 'High'} + {id: '2', name: 'High'}, + {id: '3', name: 'Highest'} ]"> object, ConfiguredObject child) { // exclude VirtualHostNode children from storing in broker store if (!(object instanceof VirtualHostNode)) { child.addChangeListener(this); _store.update(true,child.asObjectRecord()); + + Class categoryClass = child.getCategoryClass(); + Collection> childTypes = child.getModel().getChildTypes(categoryClass); + + for(Class childClass : childTypes) + { + for (ConfiguredObject grandchild : child.getChildren(childClass)) + { + childAdded(child, grandchild); + } + } } } diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/logging/messages/BrokerMessages.java b/java/broker-core/src/main/java/org/apache/qpid/server/logging/messages/BrokerMessages.java index 064c9788b2..cd21f533a4 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/logging/messages/BrokerMessages.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/logging/messages/BrokerMessages.java @@ -57,6 +57,7 @@ public class BrokerMessages public static final String SHUTTING_DOWN_LOG_HIERARCHY = DEFAULT_LOG_HIERARCHY_PREFIX + "broker.shutting_down"; public static final String MANAGEMENT_MODE_LOG_HIERARCHY = DEFAULT_LOG_HIERARCHY_PREFIX + "broker.management_mode"; public static final String STARTUP_LOG_HIERARCHY = DEFAULT_LOG_HIERARCHY_PREFIX + "broker.startup"; + public static final String FATAL_ERROR_LOG_HIERARCHY = DEFAULT_LOG_HIERARCHY_PREFIX + "broker.fatal_error"; public static final String READY_LOG_HIERARCHY = DEFAULT_LOG_HIERARCHY_PREFIX + "broker.ready"; static @@ -75,6 +76,7 @@ public class BrokerMessages Logger.getLogger(SHUTTING_DOWN_LOG_HIERARCHY); Logger.getLogger(MANAGEMENT_MODE_LOG_HIERARCHY); Logger.getLogger(STARTUP_LOG_HIERARCHY); + Logger.getLogger(FATAL_ERROR_LOG_HIERARCHY); Logger.getLogger(READY_LOG_HIERARCHY); _messages = ResourceBundle.getBundle("org.apache.qpid.server.logging.messages.Broker_logmessages", _currentLocale); @@ -491,6 +493,38 @@ public class BrokerMessages }; } + /** + * Log a Broker message of the Format: + *
BRK-1016 : Fatal error : {0} : See log file for more information
+ * Optional values are contained in [square brackets] and are numbered + * sequentially in the method call. + * + */ + public static LogMessage FATAL_ERROR(String param1) + { + String rawMessage = _messages.getString("FATAL_ERROR"); + + final Object[] messageArguments = {param1}; + // Create a new MessageFormat to ensure thread safety. + // Sharing a MessageFormat and using applyPattern is not thread safe + MessageFormat formatter = new MessageFormat(rawMessage, _currentLocale); + + final String message = formatter.format(messageArguments); + + return new LogMessage() + { + public String toString() + { + return message; + } + + public String getLogHierarchy() + { + return FATAL_ERROR_LOG_HIERARCHY; + } + }; + } + /** * Log a Broker message of the Format: *
BRK-1004 : Qpid Broker Ready
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/logging/messages/Broker_logmessages.properties b/java/broker-core/src/main/java/org/apache/qpid/server/logging/messages/Broker_logmessages.properties index d764145ec8..322335a956 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/logging/messages/Broker_logmessages.properties +++ b/java/broker-core/src/main/java/org/apache/qpid/server/logging/messages/Broker_logmessages.properties @@ -52,4 +52,6 @@ MANAGEMENT_MODE = BRK-1012 : Management Mode : User Details : {0} / {1} # 0 - Total message size # 1 - Target memory size FLOW_TO_DISK_ACTIVE = BRK-1014 : Message flow to disk active : Message memory use {0,number,#}KB exceeds threshold {1,number,#.##}KB -FLOW_TO_DISK_INACTIVE = BRK-1015 : Message flow to disk inactive : Message memory use {0,number,#}KB within threshold {1,number,#.##}KB \ No newline at end of file +FLOW_TO_DISK_INACTIVE = BRK-1015 : Message flow to disk inactive : Message memory use {0,number,#}KB within threshold {1,number,#.##}KB + +FATAL_ERROR = BRK-1016 : Fatal error : {0} : See log file for more information \ No newline at end of file diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java index e6f79fef16..4edfbe0331 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java @@ -1361,6 +1361,7 @@ public abstract class AbstractConfiguredObject> im _desiredState = State.DELETED; } setDesiredState(State.DELETED); + } public final void start() { setDesiredState(State.ACTIVE); } @@ -1578,7 +1579,7 @@ public abstract class AbstractConfiguredObject> im @Override public Set getContextKeys(final boolean excludeSystem) { - Map inheritedContext = new HashMap<>(); + Map inheritedContext = new HashMap<>(_model.getTypeRegistry().getDefaultContext()); if(!excludeSystem) { inheritedContext.putAll(System.getenv()); diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java index 021431b756..99ffa38173 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java @@ -48,13 +48,13 @@ public interface AuthenticationProvider> ext * Returns the preferences provider associated with this authentication provider * @return PreferencesProvider */ - PreferencesProvider getPreferencesProvider(); + PreferencesProvider getPreferencesProvider(); /** * Sets the preferences provider * @param preferencesProvider */ - void setPreferencesProvider(PreferencesProvider preferencesProvider); + void setPreferencesProvider(PreferencesProvider preferencesProvider); void recoverUser(User user); diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/BrokerModel.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/BrokerModel.java index 02c9ccf8e1..3dfc272053 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/model/BrokerModel.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/BrokerModel.java @@ -44,7 +44,7 @@ public final class BrokerModel extends Model * 2.0 Introduce VirtualHostNode as a child of a Broker instead of VirtualHost */ public static final int MODEL_MAJOR_VERSION = 2; - public static final int MODEL_MINOR_VERSION = 0; + public static final int MODEL_MINOR_VERSION = 1; public static final String MODEL_VERSION = MODEL_MAJOR_VERSION + "." + MODEL_MINOR_VERSION; private static final Model MODEL_INSTANCE = new BrokerModel(); private final Map, Collection>> _parents = @@ -81,7 +81,6 @@ public final class BrokerModel extends Model addRelationship(VirtualHost.class, Exchange.class); addRelationship(VirtualHost.class, Queue.class); addRelationship(VirtualHost.class, Connection.class); - addRelationship(VirtualHost.class, VirtualHostAlias.class); addRelationship(Port.class, VirtualHostAlias.class); diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/BrokerShutdownProvider.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/BrokerShutdownProvider.java index 5c8ab3e850..7eb0d3cc64 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/model/BrokerShutdownProvider.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/BrokerShutdownProvider.java @@ -22,5 +22,5 @@ package org.apache.qpid.server.model; public interface BrokerShutdownProvider { - void shutdown(); + void shutdown(int exitStatusCode); } diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectTypeRegistry.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectTypeRegistry.java index e377d31baf..ac980568b6 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectTypeRegistry.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectTypeRegistry.java @@ -854,6 +854,9 @@ public class ConfiguredObjectTypeRegistry return map != null ? Collections.unmodifiableMap(map) : Collections.>emptyMap(); } - + public Map getDefaultContext() + { + return Collections.unmodifiableMap(_defaultContext); + } } diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/DefaultVirtualHostAlias.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/DefaultVirtualHostAlias.java new file mode 100644 index 0000000000..5265cf462c --- /dev/null +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/DefaultVirtualHostAlias.java @@ -0,0 +1,31 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.model; + +@ManagedObject( category = false, type = DefaultVirtualHostAlias.TYPE_NAME) +public interface DefaultVirtualHostAlias> extends VirtualHostAlias +{ + + String TYPE_NAME = "defaultAlias"; + + @ManagedAttribute( defaultValue = "500" ) + int getPriority(); +} diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/FixedVirtualHostNodeAlias.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/FixedVirtualHostNodeAlias.java new file mode 100644 index 0000000000..6b41a84d0d --- /dev/null +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/FixedVirtualHostNodeAlias.java @@ -0,0 +1,29 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.model; + +public interface FixedVirtualHostNodeAlias> extends VirtualHostAlias +{ + String VIRTUAL_HOST_NODE = "virtualHostNode"; + + @ManagedAttribute + VirtualHostNode getVirtualHostNode(); +} diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/HostNameAlias.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/HostNameAlias.java new file mode 100644 index 0000000000..1206c0e126 --- /dev/null +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/HostNameAlias.java @@ -0,0 +1,33 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.model; + +@ManagedObject( category = false, type = HostNameAlias.TYPE_NAME) +public interface HostNameAlias> extends FixedVirtualHostNodeAlias +{ + + String TYPE_NAME = "hostnameAlias"; + + @ManagedAttribute( defaultValue = "750" ) + int getPriority(); + + +} diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/PatternMatchingAlias.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/PatternMatchingAlias.java new file mode 100644 index 0000000000..d602858628 --- /dev/null +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/PatternMatchingAlias.java @@ -0,0 +1,36 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.model; + +@ManagedObject( category = false, type = PatternMatchingAlias.TYPE_NAME) +public interface PatternMatchingAlias> extends FixedVirtualHostNodeAlias +{ + + String TYPE_NAME = "patternMatchingAlias"; + + String PATTERN = "pattern"; + + @ManagedAttribute( defaultValue = "200" ) + int getPriority(); + + @ManagedAttribute( mandatory = true) + public String getPattern(); +} diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/Port.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/Port.java index d8b81a25b5..24528b9a4e 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/model/Port.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/Port.java @@ -60,12 +60,8 @@ public interface Port> extends ConfiguredObject @ManagedAttribute Collection getTrustStores(); - //children - Collection getVirtualHostBindings(); Collection getConnections(); void start(); - boolean isLocalMachine(final String host); - } diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHostAlias.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHostAlias.java index 4af5fbfde5..0cd4773d4b 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHostAlias.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHostAlias.java @@ -20,18 +20,17 @@ */ package org.apache.qpid.server.model; -import java.util.Collection; - -@ManagedObject +@ManagedObject( creatable = false ) public interface VirtualHostAlias> extends ConfiguredObject { + String PRIORITY = "priority"; + // parents Port getPort(); - VirtualHost getVirtualHost(); - - // children - Collection getAuthenticationMethods(); + @ManagedAttribute( defaultValue = "100" ) + int getPriority(); + VirtualHostNode getVirtualHostNode(String name); } diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHostNameAlias.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHostNameAlias.java new file mode 100644 index 0000000000..2d114f21a2 --- /dev/null +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHostNameAlias.java @@ -0,0 +1,27 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.model; + +@ManagedObject( category = false, type = VirtualHostNameAlias.TYPE_NAME) +public interface VirtualHostNameAlias> extends VirtualHostAlias +{ + String TYPE_NAME = "nameAlias"; +} diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java index ee008b1642..d413050cef 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java @@ -969,7 +969,8 @@ public class BrokerAdapter extends AbstractConfiguredObject imple BrokerShutdownProvider shutdownProvider = systemConfig.getBrokerShutdownProvider(); if (shutdownProvider != null) { - shutdownProvider.shutdown(); + _eventLogger.message(BrokerMessages.FATAL_ERROR(e.getMessage())); + shutdownProvider.shutdown(1); } else { diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAliasAdapter.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAliasAdapter.java deleted file mode 100644 index 0ea9079ebb..0000000000 --- a/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAliasAdapter.java +++ /dev/null @@ -1,85 +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.model.adapter; - -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -import org.apache.qpid.server.model.AbstractConfiguredObject; -import org.apache.qpid.server.model.AuthenticationMethod; -import org.apache.qpid.server.model.ConfiguredObject; -import org.apache.qpid.server.model.Port; -import org.apache.qpid.server.model.State; -import org.apache.qpid.server.model.VirtualHost; -import org.apache.qpid.server.model.VirtualHostAlias; - -public class VirtualHostAliasAdapter extends AbstractConfiguredObject implements VirtualHostAlias -{ - private VirtualHost _vhost; - private Port _port; - - public VirtualHostAliasAdapter(VirtualHost virtualHost, Port port) - { - super(parentsMap(virtualHost,port), createAttributes(virtualHost, port)); - _vhost = virtualHost; - _port = port; - setState(State.ACTIVE); - } - - private static Map createAttributes(final VirtualHost virtualHost, final Port port) - { - final Map attributes = new HashMap(); - attributes.put(ID, UUID.randomUUID()); - attributes.put(NAME, virtualHost.getName()); - attributes.put(DURABLE, false); - return attributes; - } - - @Override - public Port getPort() - { - return _port; - } - - @Override - public VirtualHost getVirtualHost() - { - return _vhost; - } - - @Override - public Collection getAuthenticationMethods() - { - return Collections.emptySet(); // TODO - Implement - } - - @Override - public Collection getChildren(Class clazz) - { - return Collections.emptySet(); - } - - -} diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java index e2e7eff322..6d8e65cd17 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java @@ -21,23 +21,12 @@ package org.apache.qpid.server.model.port; -import java.net.InetAddress; -import java.net.InterfaceAddress; -import java.net.NetworkInterface; -import java.net.SocketException; -import java.net.UnknownHostException; import java.security.AccessControlException; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.HashSet; -import java.util.List; import java.util.Map; import java.util.Set; -import java.util.concurrent.CopyOnWriteArraySet; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; import org.apache.log4j.Logger; @@ -54,69 +43,12 @@ import org.apache.qpid.server.model.State; import org.apache.qpid.server.model.StateTransition; import org.apache.qpid.server.model.Transport; import org.apache.qpid.server.model.TrustStore; -import org.apache.qpid.server.model.VirtualHost; -import org.apache.qpid.server.model.VirtualHostAlias; -import org.apache.qpid.server.model.VirtualHostNode; import org.apache.qpid.server.security.access.Operation; abstract public class AbstractPort> extends AbstractConfiguredObject implements Port { private static final Logger LOGGER = Logger.getLogger(AbstractPort.class); - private static final Set LOCAL_ADDRESSES = new CopyOnWriteArraySet<>(); - private static final Set LOCAL_ADDRESS_NAMES = new CopyOnWriteArraySet<>(); - private static final Lock ADDRESS_LOCK = new ReentrantLock(); - private static final AtomicBoolean ADDRESSES_COMPUTED = new AtomicBoolean(); - - static - { - Thread thread = new Thread(new Runnable() - { - public void run() - { - Lock lock = ADDRESS_LOCK; - - lock.lock(); - try - { - for (NetworkInterface networkInterface : Collections.list(NetworkInterface.getNetworkInterfaces())) - { - for (InterfaceAddress inetAddress : networkInterface.getInterfaceAddresses()) - { - InetAddress address = inetAddress.getAddress(); - LOCAL_ADDRESSES.add(address); - String hostAddress = address.getHostAddress(); - if (hostAddress != null) - { - LOCAL_ADDRESS_NAMES.add(hostAddress); - } - String hostName = address.getHostName(); - if (hostName != null) - { - LOCAL_ADDRESS_NAMES.add(hostName); - } - String canonicalHostName = address.getCanonicalHostName(); - if (canonicalHostName != null) - { - LOCAL_ADDRESS_NAMES.add(canonicalHostName); - } - } - } - } - catch (SocketException e) - { - // ignore - } - finally - { - ADDRESSES_COMPUTED.set(true); - lock.unlock(); - } - } - }, "Network Address Resolver"); - thread.start(); - } - private final Broker _broker; @ManagedAttributeField @@ -270,27 +202,6 @@ abstract public class AbstractPort> extends AbstractCo return _protocols; } - @Override - public Collection getVirtualHostBindings() - { - List aliases = new ArrayList(); - for(VirtualHostNode vhn : _broker.getVirtualHostNodes()) - { - VirtualHost vh = vhn.getVirtualHost(); - if (vh != null) - { - for(VirtualHostAlias alias : vh.getAliases()) - { - if(alias.getPort().equals(this)) - { - aliases.add(alias); - } - } - } - } - return Collections.unmodifiableCollection(aliases); - } - @Override public Collection getConnections() { @@ -306,7 +217,7 @@ abstract public class AbstractPort> extends AbstractCo } else { - return Collections.emptySet(); + return super.getChildren(clazz); } } @@ -412,38 +323,4 @@ abstract public class AbstractPort> extends AbstractCo } } - public boolean isLocalMachine(final String host) - { - while(!ADDRESSES_COMPUTED.get()) - { - Lock lock = ADDRESS_LOCK; - lock.lock(); - lock.unlock(); - } - - boolean isNetworkAddress = true; - if (!LOCAL_ADDRESS_NAMES.contains(host)) - { - try - { - InetAddress inetAddress = InetAddress.getByName(host); - if (!LOCAL_ADDRESSES.contains(inetAddress)) - { - isNetworkAddress = false; - } - else - { - LOCAL_ADDRESS_NAMES.add(host); - } - } - catch (UnknownHostException e) - { - // ignore - isNetworkAddress = false; - } - } - return isNetworkAddress; - - } - } diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPort.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPort.java index f7eeca354a..ade9055b5a 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPort.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPort.java @@ -20,15 +20,16 @@ */ package org.apache.qpid.server.model.port; +import java.util.Map; import java.util.Set; import org.apache.qpid.server.model.AuthenticationProvider; import org.apache.qpid.server.model.ManagedAttribute; import org.apache.qpid.server.model.ManagedContextDefault; import org.apache.qpid.server.model.ManagedObject; -import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.Protocol; import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.model.VirtualHostAlias; import org.apache.qpid.server.virtualhost.VirtualHostImpl; @ManagedObject( category = false, type = "AMQP") @@ -80,4 +81,5 @@ public interface AmqpPort> extends ClientAuthCapablePort attributes); } diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPortImpl.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPortImpl.java index afe3c9a44e..fd8c402344 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPortImpl.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPortImpl.java @@ -25,35 +25,42 @@ import java.security.GeneralSecurityException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; +import java.util.TreeSet; import javax.net.ssl.KeyManager; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; -import org.apache.qpid.server.util.PortUtil; import org.codehaus.jackson.map.ObjectMapper; import org.apache.qpid.server.configuration.BrokerProperties; import org.apache.qpid.server.configuration.IllegalConfigurationException; import org.apache.qpid.server.logging.messages.BrokerMessages; import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.DefaultVirtualHostAlias; +import org.apache.qpid.server.model.HostNameAlias; import org.apache.qpid.server.model.KeyStore; import org.apache.qpid.server.model.ManagedAttributeField; -import org.apache.qpid.server.model.ManagedContextDefault; import org.apache.qpid.server.model.ManagedObjectFactoryConstructor; import org.apache.qpid.server.model.Protocol; import org.apache.qpid.server.model.State; import org.apache.qpid.server.model.Transport; import org.apache.qpid.server.model.TrustStore; +import org.apache.qpid.server.model.VirtualHostAlias; +import org.apache.qpid.server.model.VirtualHostNameAlias; +import org.apache.qpid.server.model.VirtualHostNode; import org.apache.qpid.server.plugin.ProtocolEngineCreator; import org.apache.qpid.server.plugin.QpidServiceLoader; import org.apache.qpid.server.plugin.TransportProviderFactory; import org.apache.qpid.server.transport.AcceptingTransport; import org.apache.qpid.server.transport.TransportProvider; +import org.apache.qpid.server.util.PortUtil; import org.apache.qpid.server.util.ServerScopedRuntimeException; import org.apache.qpid.server.virtualhost.VirtualHostImpl; import org.apache.qpid.transport.network.security.ssl.QpidMultipleTrustManager; @@ -63,6 +70,29 @@ public class AmqpPortImpl extends AbstractClientAuthCapablePortWithAuthProvider< public static final String DEFAULT_BINDING_ADDRESS = "*"; + + private static final Comparator VIRTUAL_HOST_ALIAS_COMPARATOR = new Comparator() + { + @Override + public int compare(final VirtualHostAlias left, final VirtualHostAlias right) + { + int comparison = left.getPriority() - right.getPriority(); + if (comparison == 0) + { + long createCompare = left.getCreatedTime() - right.getCreatedTime(); + if (createCompare == 0) + { + comparison = left.getName().compareTo(right.getName()); + } + else + { + comparison = createCompare < 0l ? -1 : 1; + } + } + return comparison; + } + }; + @ManagedAttributeField private boolean _tcpNoDelay; @@ -110,16 +140,48 @@ public class AmqpPortImpl extends AbstractClientAuthCapablePortWithAuthProvider< return _receiveBufferSize; } + @Override + protected void onCreate() + { + super.onCreate(); + + Map attributes = new HashMap<>(); + attributes.put(VirtualHostAlias.NAME, "nameAlias"); + attributes.put(VirtualHostAlias.TYPE, VirtualHostNameAlias.TYPE_NAME); + attributes.put(VirtualHostAlias.DURABLE, true); + createVirtualHostAlias(attributes); + + attributes = new HashMap<>(); + attributes.put(VirtualHostAlias.NAME, "defaultAlias"); + attributes.put(VirtualHostAlias.TYPE, DefaultVirtualHostAlias.TYPE_NAME); + attributes.put(VirtualHostAlias.DURABLE, true); + createVirtualHostAlias(attributes); + + + attributes = new HashMap<>(); + attributes.put(VirtualHostAlias.NAME, "hostnameAlias"); + attributes.put(VirtualHostAlias.TYPE, HostNameAlias.TYPE_NAME); + attributes.put(VirtualHostAlias.DURABLE, true); + createVirtualHostAlias(attributes); + + } + @Override public VirtualHostImpl getVirtualHost(String name) { - // TODO - aliases - if(name == null || name.trim().length() == 0) + Collection aliases = new TreeSet<>(VIRTUAL_HOST_ALIAS_COMPARATOR); + + aliases.addAll(getChildren(VirtualHostAlias.class)); + + for(VirtualHostAlias alias : aliases) { - name = _broker.getDefaultVirtualHost(); + VirtualHostNode vhn = alias.getVirtualHostNode(name); + if (vhn != null) + { + return (VirtualHostImpl) vhn.getVirtualHost(); + } } - - return (VirtualHostImpl) _broker.findVirtualHostByName(name); + return null; } @Override @@ -156,7 +218,6 @@ public class AmqpPortImpl extends AbstractClientAuthCapablePortWithAuthProvider< { sslContext = createSslContext(); } - Protocol defaultSupportedProtocolReply = getDefaultAmqpSupportedReply(); _transport = transportProvider.createTransport(transportSet, @@ -188,6 +249,20 @@ public class AmqpPortImpl extends AbstractClientAuthCapablePortWithAuthProvider< } } + @Override + public VirtualHostAlias createVirtualHostAlias(Map attributes) + { + VirtualHostAlias child = addVirtualHostAlias(attributes); + childAdded(child); + return child; + } + + private VirtualHostAlias addVirtualHostAlias(Map attributes) + { + return getObjectFactory().create(VirtualHostAlias.class, attributes, this); + } + + @Override public void validateOnCreate() { @@ -215,6 +290,7 @@ public class AmqpPortImpl extends AbstractClientAuthCapablePortWithAuthProvider< try { SSLContext sslContext = SSLContext.getInstance("TLS"); + KeyManager[] keyManagers = keyStore.getKeyManagers(); TrustManager[] trustManagers; diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java b/java/broker-core/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java index 0eabcd725e..ef45971858 100755 --- a/java/broker-core/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java @@ -45,6 +45,7 @@ import org.apache.qpid.transport.network.NetworkConnection; import org.apache.qpid.transport.network.security.SSLStatus; import org.apache.qpid.transport.network.security.ssl.SSLBufferingSender; import org.apache.qpid.transport.network.security.ssl.SSLReceiver; +import org.apache.qpid.transport.network.security.ssl.SSLUtil; public class MultiVersionProtocolEngine implements ServerProtocolEngine { @@ -480,6 +481,7 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine _engine = _sslContext.createSSLEngine(); _engine.setUseClientMode(false); + SSLUtil.removeSSLv3Support(_engine); if(_needClientAuth) { diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java b/java/broker-core/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java index acfe7856c3..d32f0299d5 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java @@ -32,6 +32,7 @@ import org.apache.qpid.server.logging.MessageLogger; import org.apache.qpid.server.logging.SystemOutMessageLogger; import org.apache.qpid.server.logging.messages.BrokerMessages; import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.State; import org.apache.qpid.server.model.SystemConfig; import org.apache.qpid.server.store.BrokerStoreUpgraderAndRecoverer; import org.apache.qpid.server.store.DurableConfigurationStore; @@ -77,17 +78,17 @@ public class ApplicationRegistry implements IApplicationRegistry logStartupMessages(startupLogger); BrokerStoreUpgraderAndRecoverer upgrader = new BrokerStoreUpgraderAndRecoverer(_systemConfig); - _broker = upgrader.perform(_store); + Broker broker = upgrader.perform(_store); + _broker = broker; - _broker.setEventLogger(startupLogger); - _broker.open(); - - // starting the broker - //_broker.setDesiredState(State.ACTIVE); - - startupLogger.message(BrokerMessages.READY()); - _broker.setEventLogger(eventLogger); + broker.setEventLogger(startupLogger); + broker.open(); + if (broker.getState() == State.ACTIVE) + { + startupLogger.message(BrokerMessages.READY()); + broker.setEventLogger(eventLogger); + } } public void close() diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/security/SubjectCreator.java b/java/broker-core/src/main/java/org/apache/qpid/server/security/SubjectCreator.java index ac8d002577..bbec239d74 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/security/SubjectCreator.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/security/SubjectCreator.java @@ -53,10 +53,10 @@ public class SubjectCreator { private final boolean _secure; private AuthenticationProvider _authenticationProvider; - private Collection _groupProviders; + private Collection> _groupProviders; public SubjectCreator(AuthenticationProvider authenticationProvider, - Collection groupProviders, + Collection> groupProviders, final boolean secure) { _authenticationProvider = authenticationProvider; diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractAuthenticationManager.java b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractAuthenticationManager.java index b2cf1739ab..7f98468726 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractAuthenticationManager.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractAuthenticationManager.java @@ -53,13 +53,13 @@ public abstract class AbstractAuthenticationManager _broker; + private PreferencesProvider _preferencesProvider; @ManagedAttributeField private List _secureOnlyMechanisms; - protected AbstractAuthenticationManager(final Map attributes, final Broker broker) + protected AbstractAuthenticationManager(final Map attributes, final Broker broker) { super(parentsMap(broker), attributes); _broker = broker; @@ -120,13 +120,13 @@ public abstract class AbstractAuthenticationManager getPreferencesProvider() { return _preferencesProvider; } @Override - public void setPreferencesProvider(final PreferencesProvider preferencesProvider) + public void setPreferencesProvider(final PreferencesProvider preferencesProvider) { _preferencesProvider = preferencesProvider; } @@ -143,8 +143,8 @@ public abstract class AbstractAuthenticationManager(attributes); - PreferencesProvider pp = getObjectFactory().create(PreferencesProvider.class, attributes, this); + attributes = new HashMap<>(attributes); + PreferencesProvider pp = getObjectFactory().create(PreferencesProvider.class, attributes, this); _preferencesProvider = pp; return (C)pp; diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractScramAuthenticationManager.java b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractScramAuthenticationManager.java index 152a9086ec..6887cb99d4 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractScramAuthenticationManager.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractScramAuthenticationManager.java @@ -20,52 +20,38 @@ */ package org.apache.qpid.server.security.auth.manager; -import java.io.IOException; -import java.nio.charset.Charset; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.Principal; import java.security.SecureRandom; import java.util.Arrays; import java.util.Collections; -import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; -import javax.security.auth.login.AccountNotFoundException; import javax.security.sasl.SaslException; import javax.security.sasl.SaslServer; import javax.xml.bind.DatatypeConverter; -import org.apache.qpid.server.configuration.updater.Task; -import org.apache.qpid.server.configuration.updater.VoidTaskWithException; import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.model.ConfiguredObject; import org.apache.qpid.server.model.PasswordCredentialManagingAuthenticationProvider; -import org.apache.qpid.server.model.User; -import org.apache.qpid.server.security.access.Operation; 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.PlainAdapterSaslServer; import org.apache.qpid.server.security.auth.sasl.scram.ScramSaslServer; public abstract class AbstractScramAuthenticationManager> - extends AbstractAuthenticationManager + extends ConfigModelPasswordManagingAuthenticationProvider implements PasswordCredentialManagingAuthenticationProvider { - static final Charset ASCII = Charset.forName("ASCII"); public static final String PLAIN = "PLAIN"; private final SecureRandom _random = new SecureRandom(); private int _iterationCount = 4096; - private Map _users = new ConcurrentHashMap(); - protected AbstractScramAuthenticationManager(final Map attributes, final Broker broker) { @@ -102,34 +88,10 @@ public abstract class AbstractScramAuthenticationManager attributes) - { - return runTask(new Task() - { - @Override - public Boolean execute() - { - getSecurityManager().authoriseUserOperation(Operation.CREATE, username); - if (_users.containsKey(username)) - { - throw new IllegalArgumentException("User '" + username + "' already exists"); - } - try - { - Map userAttrs = new HashMap(); - userAttrs.put(User.ID, UUID.randomUUID()); - userAttrs.put(User.NAME, username); - userAttrs.put(User.PASSWORD, createStoredPassword(password)); - userAttrs.put(User.TYPE, ScramAuthUser.SCRAM_USER_TYPE); - ScramAuthUser user = new ScramAuthUser(userAttrs, AbstractScramAuthenticationManager.this); - user.create(); - - return true; - } - catch (SaslException e) - { - throw new IllegalArgumentException(e); - } - } - }); - } - - org.apache.qpid.server.security.SecurityManager getSecurityManager() - { - return getBroker().getSecurityManager(); - } - - @Override - public void deleteUser(final String user) throws AccountNotFoundException - { - runTask(new VoidTaskWithException() - { - @Override - public void execute() throws AccountNotFoundException - { - final ScramAuthUser authUser = getUser(user); - if(authUser != null) - { - authUser.delete(); - } - else - { - throw new AccountNotFoundException("No such user: '" + user + "'"); - } - } - }); - } - - @Override - public void setPassword(final String username, final String password) throws AccountNotFoundException - { - runTask(new VoidTaskWithException() - { - @Override - public void execute() throws AccountNotFoundException - { - - final ScramAuthUser authUser = getUser(username); - if (authUser != null) - { - authUser.setPassword(password); - } - else - { - throw new AccountNotFoundException("No such user: '" + username + "'"); - } - } - }); - - } - - @Override - public Map> getUsers() - { - return runTask(new Task>>() - { - @Override - public Map> execute() - { - - Map> users = new HashMap>(); - for (String user : _users.keySet()) - { - users.put(user, Collections.emptyMap()); - } - return users; - } - }); - } - - @Override - public void reload() throws IOException - { - - } - - @Override - public void recoverUser(final User user) - { - _users.put(user.getName(), (ScramAuthUser) user); - } - - protected String createStoredPassword(final String password) throws SaslException + protected String createStoredPassword(final String password) { byte[] salt = new byte[32]; _random.nextBytes(salt); @@ -366,33 +206,11 @@ public abstract class AbstractScramAuthenticationManager C addChild(final Class childClass, - final Map attributes, - final ConfiguredObject... otherParents) + void validateUser(final ManagedUser managedUser) { - if(childClass == User.class) + if(!ASCII.newEncoder().canEncode(managedUser.getName())) { - String username = (String) attributes.get("name"); - String password = (String) attributes.get("password"); - - if(createUser(username, password,null)) - { - @SuppressWarnings("unchecked") - C user = (C) _users.get(username); - return user; - } - else - { - return null; - - } + throw new IllegalArgumentException("User names are restricted to characters in the ASCII charset"); } - return super.addChild(childClass, attributes, otherParents); } - - Map getUserMap() - { - return _users; - } - } diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ConfigModelPasswordManagingAuthenticationProvider.java b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ConfigModelPasswordManagingAuthenticationProvider.java new file mode 100644 index 0000000000..5126e6978d --- /dev/null +++ b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ConfigModelPasswordManagingAuthenticationProvider.java @@ -0,0 +1,229 @@ +/* + * + * 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.nio.charset.Charset; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +import javax.security.auth.login.AccountNotFoundException; +import javax.security.sasl.SaslException; +import javax.security.sasl.SaslServer; + +import org.apache.qpid.server.configuration.updater.Task; +import org.apache.qpid.server.configuration.updater.VoidTaskWithException; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.PasswordCredentialManagingAuthenticationProvider; +import org.apache.qpid.server.model.User; +import org.apache.qpid.server.security.SecurityManager; +import org.apache.qpid.server.security.access.Operation; +import org.apache.qpid.server.security.auth.AuthenticationResult; +import org.apache.qpid.server.security.auth.UsernamePrincipal; + +public abstract class ConfigModelPasswordManagingAuthenticationProvider> + extends AbstractAuthenticationManager + implements PasswordCredentialManagingAuthenticationProvider +{ + static final Charset ASCII = Charset.forName("ASCII"); + protected Map _users = new ConcurrentHashMap<>(); + + protected ConfigModelPasswordManagingAuthenticationProvider(final Map attributes, + final Broker broker) + { + super(attributes, broker); + } + + ManagedUser getUser(final String username) + { + return _users.get(username); + } + + @Override + public boolean createUser(final String username, final String password, final Map attributes) + { + return runTask(new Task() + { + @Override + public Boolean execute() + { + getSecurityManager().authoriseUserOperation(Operation.CREATE, username); + if (_users.containsKey(username)) + { + throw new IllegalArgumentException("User '" + username + "' already exists"); + } + + Map userAttrs = new HashMap<>(); + userAttrs.put(User.ID, UUID.randomUUID()); + userAttrs.put(User.NAME, username); + userAttrs.put(User.PASSWORD, createStoredPassword(password)); + userAttrs.put(User.TYPE, ManagedUser.MANAGED_USER_TYPE); + ManagedUser user = new ManagedUser(userAttrs, ConfigModelPasswordManagingAuthenticationProvider.this); + user.create(); + + return true; + + } + }); + } + + SecurityManager getSecurityManager() + { + return getBroker().getSecurityManager(); + } + + @Override + public void deleteUser(final String user) throws AccountNotFoundException + { + runTask(new VoidTaskWithException() + { + @Override + public void execute() throws AccountNotFoundException + { + final ManagedUser authUser = getUser(user); + if(authUser != null) + { + authUser.delete(); + } + else + { + throw new AccountNotFoundException("No such user: '" + user + "'"); + } + } + }); + } + + @Override + public Map> getUsers() + { + return runTask(new Task>>() + { + @Override + public Map> execute() + { + + Map> users = new HashMap<>(); + for (String user : _users.keySet()) + { + users.put(user, Collections.emptyMap()); + } + return users; + } + }); + } + + @Override + public void reload() throws IOException + { + + } + + @Override + public void recoverUser(final User user) + { + _users.put(user.getName(), (ManagedUser) user); + } + + @Override + public void setPassword(final String username, final String password) throws AccountNotFoundException + { + runTask(new VoidTaskWithException() + { + @Override + public void execute() throws AccountNotFoundException + { + + final ManagedUser authUser = getUser(username); + if (authUser != null) + { + authUser.setPassword(password); + } + else + { + throw new AccountNotFoundException("No such user: '" + username + "'"); + } + } + }); + + } + + @Override + public AuthenticationResult authenticate(final SaslServer server, final byte[] response) + { + try + { + // Process response from the client + byte[] challenge = server.evaluateResponse(response != null ? response : new byte[0]); + + if (server.isComplete() && (challenge == null || challenge.length == 0)) + { + final String userId = server.getAuthorizationID(); + return new AuthenticationResult(new UsernamePrincipal(userId)); + } + else + { + return new AuthenticationResult(challenge, AuthenticationResult.AuthenticationStatus.CONTINUE); + } + } + catch (SaslException e) + { + return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR, e); + } + } + + protected abstract String createStoredPassword(String password); + + Map getUserMap() + { + return _users; + } + + @Override + public C addChild(final Class childClass, + final Map attributes, + final ConfiguredObject... otherParents) + { + if(childClass == User.class) + { + String username = (String) attributes.get("name"); + String password = (String) attributes.get("password"); + + if(createUser(username, password,null)) + { + @SuppressWarnings("unchecked") + C user = (C) getUser(username); + return user; + } + else + { + return null; + + } + } + return super.addChild(childClass, attributes, otherParents); + } + + abstract void validateUser(final ManagedUser managedUser); +} diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/MD5AuthenticationProvider.java b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/MD5AuthenticationProvider.java new file mode 100644 index 0000000000..cdb2f3dcc7 --- /dev/null +++ b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/MD5AuthenticationProvider.java @@ -0,0 +1,227 @@ +/* + * + * 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.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.Principal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +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.SaslException; +import javax.security.sasl.SaslServer; +import javax.xml.bind.DatatypeConverter; + +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ManagedObject; +import org.apache.qpid.server.model.ManagedObjectFactoryConstructor; +import org.apache.qpid.server.security.auth.AuthenticationResult; +import org.apache.qpid.server.security.auth.UsernamePrincipal; +import org.apache.qpid.server.security.auth.sasl.crammd5.CRAMMD5HashedSaslServer; +import org.apache.qpid.server.security.auth.sasl.crammd5.CRAMMD5HexSaslServer; +import org.apache.qpid.server.security.auth.sasl.plain.PlainAdapterSaslServer; +import org.apache.qpid.server.security.auth.sasl.plain.PlainSaslServer; +import org.apache.qpid.server.util.ServerScopedRuntimeException; + +@ManagedObject( category = false, type = "MD5" ) +public class MD5AuthenticationProvider + extends ConfigModelPasswordManagingAuthenticationProvider +{ + private final List _mechanisms = Collections.unmodifiableList(Arrays.asList(PlainSaslServer.MECHANISM, + CRAMMD5HashedSaslServer.MECHANISM, + CRAMMD5HexSaslServer.MECHANISM)); + + + @ManagedObjectFactoryConstructor + protected MD5AuthenticationProvider(final Map attributes, final Broker broker) + { + super(attributes, broker); + } + + @Override + protected String createStoredPassword(final String password) + { + byte[] data = password.getBytes(StandardCharsets.UTF_8); + MessageDigest md = null; + try + { + md = MessageDigest.getInstance("MD5"); + } + catch (NoSuchAlgorithmException e) + { + throw new ServerScopedRuntimeException("MD5 not supported although Java compliance requires it"); + } + + md.update(data); + return DatatypeConverter.printBase64Binary(md.digest()); + } + + @Override + void validateUser(final ManagedUser managedUser) + { + } + + @Override + public List getMechanisms() + { + return _mechanisms; + } + + @Override + public SaslServer createSaslServer(final String mechanism, + final String localFQDN, + final Principal externalPrincipal) + throws SaslException + { + if(PlainSaslServer.MECHANISM.equals(mechanism)) + { + return new PlainAdapterSaslServer(this); + } + else if(CRAMMD5HashedSaslServer.MECHANISM.equals(mechanism)) + { + //simply delegate to the built in CRAM-MD5 SaslServer + return new CRAMMD5HashedSaslServer(mechanism, "AMQP", localFQDN, null, new MD5Callbackhandler(false)); + } + else if(CRAMMD5HexSaslServer.MECHANISM.equals(mechanism)) + { + //simply delegate to the built in CRAM-MD5 SaslServer + return new CRAMMD5HashedSaslServer(mechanism, "AMQP", localFQDN, null, new MD5Callbackhandler(true)); + } + else + { + throw new SaslException("Unsupported mechanism: " + mechanism); + } + } + + @Override + public AuthenticationResult authenticate(final String username, final String password) + { + ManagedUser user = getUser(username); + AuthenticationResult result; + if(user != null && user.getPassword().equals(createStoredPassword(password))) + { + result = new AuthenticationResult(new UsernamePrincipal(username)); + } + else + { + result = new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR); + } + return result; + } + private static final char[] HEX_CHARACTERS = + {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + + private class MD5Callbackhandler implements CallbackHandler + { + private final boolean _hexify; + private String _username; + + public MD5Callbackhandler(final boolean hexify) + { + _hexify = hexify; + } + + public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException + { + List callbackList = new ArrayList<>(Arrays.asList(callbacks)); + Iterator iter = callbackList.iterator(); + while(iter.hasNext()) + { + Callback callback = iter.next(); + if (callback instanceof NameCallback) + { + _username = ((NameCallback) callback).getDefaultName(); + iter.remove(); + break; + } + } + + if(_username != null) + { + iter = callbackList.iterator(); + while (iter.hasNext()) + { + Callback callback = iter.next(); + if (callback instanceof PasswordCallback) + { + iter.remove(); + ManagedUser user = getUser(_username); + if(user != null) + { + String passwordData = user.getPassword(); + byte[] passwordBytes = DatatypeConverter.parseBase64Binary(passwordData); + char[] password; + if(_hexify) + { + password = new char[passwordBytes.length]; + + for(int i = 0; i < passwordBytes.length; i--) + { + password[2*i] = HEX_CHARACTERS[(((int)passwordBytes[i]) & 0xf0)>>4]; + password[(2*i)+1] = HEX_CHARACTERS[(((int)passwordBytes[i]) & 0x0f)]; + } + } + else + { + password = new char[passwordBytes.length]; + for(int i = 0; i < passwordBytes.length; i++) + { + password[i] = (char) passwordBytes[i]; + } + } + ((PasswordCallback) callback).setPassword(password); + } + else + { + ((PasswordCallback) callback).setPassword(null); + } + break; + } + } + } + + for (Callback callback : callbackList) + { + + if (callback instanceof AuthorizeCallback) + { + ((AuthorizeCallback) callback).setAuthorized(true); + } + else + { + throw new UnsupportedCallbackException(callback); + } + } + } + } +} diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ManagedUser.java b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ManagedUser.java new file mode 100644 index 0000000000..c8884e15a8 --- /dev/null +++ b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ManagedUser.java @@ -0,0 +1,199 @@ +/* + * + * 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.security.AccessControlException; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import org.apache.qpid.server.configuration.updater.VoidTask; +import org.apache.qpid.server.model.AbstractConfiguredObject; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.ManagedAttributeField; +import org.apache.qpid.server.model.ManagedObject; +import org.apache.qpid.server.model.ManagedObjectFactoryConstructor; +import org.apache.qpid.server.model.PreferencesProvider; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.StateTransition; +import org.apache.qpid.server.model.User; +import org.apache.qpid.server.security.access.Operation; + +@ManagedObject( category = false, type = ManagedUser.MANAGED_USER_TYPE) +class ManagedUser extends AbstractConfiguredObject implements User +{ + public static final String MANAGED_USER_TYPE = "managed"; + + private ConfigModelPasswordManagingAuthenticationProvider _authenticationManager; + @ManagedAttributeField + private String _password; + + @ManagedObjectFactoryConstructor + ManagedUser(final Map attributes, ConfigModelPasswordManagingAuthenticationProvider parent) + { + super(parentsMap(parent), attributes); + _authenticationManager = parent; + + setState(State.ACTIVE); + } + + @Override + protected void onOpen() + { + super.onOpen(); + _authenticationManager.getUserMap().put(getName(), this); + } + + @Override + public void onValidate() + { + super.onValidate(); + _authenticationManager.validateUser(this); + if(!isDurable()) + { + throw new IllegalArgumentException(getClass().getSimpleName() + " must be durable"); + } + } + + @Override + protected void validateChange(final ConfiguredObject proxyForValidation, final Set changedAttributes) + { + super.validateChange(proxyForValidation, changedAttributes); + if(changedAttributes.contains(DURABLE) && !proxyForValidation.isDurable()) + { + throw new IllegalArgumentException(getClass().getSimpleName() + " must be durable"); + } + } + + @Override + protected void authoriseSetDesiredState(final State desiredState) throws AccessControlException + { + if(desiredState == State.DELETED) + { + _authenticationManager.getSecurityManager().authoriseUserOperation(Operation.DELETE, getName()); + } + + } + + @StateTransition(currentState = {State.ACTIVE}, desiredState = State.DELETED) + private void doDelete() + { + _authenticationManager.getUserMap().remove(getName()); + deleted(); + } + + + @Override + public void setAttributes(final Map attributes) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + runTask(new VoidTask() + { + + @Override + public void execute() + { + Map modifiedAttributes = new HashMap(attributes); + final String newPassword = (String) attributes.get(User.PASSWORD); + if (attributes.containsKey(User.PASSWORD) + && !newPassword.equals(getActualAttributes().get(User.PASSWORD))) + { + modifiedAttributes.put(User.PASSWORD, + _authenticationManager.createStoredPassword(newPassword)); + + } + ManagedUser.super.setAttributes(modifiedAttributes); + } + }); + + + } + + @Override + public String getPassword() + { + return _password; + } + + @Override + public void setPassword(final String password) + { + _authenticationManager.getSecurityManager().authoriseUserOperation(Operation.UPDATE, getName()); + + changeAttribute(User.PASSWORD, getAttribute(User.PASSWORD), + _authenticationManager.createStoredPassword(password)); + + } + + @Override + public Collection getChildren(final Class clazz) + { + return Collections.emptySet(); + } + + @Override + public Map getPreferences() + { + PreferencesProvider preferencesProvider = _authenticationManager.getPreferencesProvider(); + if (preferencesProvider == null) + { + return null; + } + return preferencesProvider.getPreferences(this.getName()); + } + + @Override + public Object getPreference(String name) + { + Map preferences = getPreferences(); + if (preferences == null) + { + return null; + } + return preferences.get(name); + } + + @Override + public Map setPreferences(Map preferences) + { + PreferencesProvider preferencesProvider = _authenticationManager.getPreferencesProvider(); + if (preferencesProvider == null) + { + return null; + } + return preferencesProvider.setPreferences(this.getName(), preferences); + } + + @Override + public boolean deletePreferences() + { + PreferencesProvider preferencesProvider = _authenticationManager.getPreferencesProvider(); + if (preferencesProvider == null) + { + return false; + } + String[] deleted = preferencesProvider.deletePreferences(this.getName()); + return deleted.length == 1; + } + +} diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/PlainAuthenticationProvider.java b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/PlainAuthenticationProvider.java new file mode 100644 index 0000000000..5c79253ebb --- /dev/null +++ b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/PlainAuthenticationProvider.java @@ -0,0 +1,176 @@ +/* + * + * 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.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +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.qpid.server.model.Broker; +import org.apache.qpid.server.model.ManagedObject; +import org.apache.qpid.server.model.ManagedObjectFactoryConstructor; +import org.apache.qpid.server.security.auth.AuthenticationResult; +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.PlainAdapterSaslServer; +import org.apache.qpid.server.security.auth.sasl.plain.PlainSaslServer; + +@ManagedObject( category = false, type = "Plain" ) +public class PlainAuthenticationProvider + extends ConfigModelPasswordManagingAuthenticationProvider +{ + private final List _mechanisms = Collections.unmodifiableList(Arrays.asList(PlainSaslServer.MECHANISM, + CRAMMD5Initialiser.MECHANISM)); + + + @ManagedObjectFactoryConstructor + protected PlainAuthenticationProvider(final Map attributes, final Broker broker) + { + super(attributes, broker); + } + + @Override + protected String createStoredPassword(final String password) + { + return password; + } + + @Override + void validateUser(final ManagedUser managedUser) + { + // NOOP + } + + @Override + public List getMechanisms() + { + return _mechanisms; + } + + @Override + public SaslServer createSaslServer(final String mechanism, + final String localFQDN, + final Principal externalPrincipal) + throws SaslException + { + if(PlainSaslServer.MECHANISM.equals(mechanism)) + { + return new PlainAdapterSaslServer(this); + } + else if(CRAMMD5Initialiser.MECHANISM.equals(mechanism)) + { + //simply delegate to the built in CRAM-MD5 SaslServer + return Sasl.createSaslServer(mechanism, "AMQP", localFQDN, null, new ServerCallbackHandler()); + } + else + { + throw new SaslException("Unsupported mechanism: " + mechanism); + } + } + + @Override + public AuthenticationResult authenticate(final String username, final String password) + { + ManagedUser user = getUser(username); + AuthenticationResult result; + if(user != null && user.getPassword().equals(password)) + { + result = new AuthenticationResult(new UsernamePrincipal(username)); + } + else + { + result = new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR); + } + return result; + } + + private class ServerCallbackHandler implements CallbackHandler + { + String _username; + + public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException + { + List callbackList = new ArrayList<>(Arrays.asList(callbacks)); + Iterator iter = callbackList.iterator(); + while(iter.hasNext()) + { + Callback callback = iter.next(); + if (callback instanceof NameCallback) + { + _username = ((NameCallback) callback).getDefaultName(); + iter.remove(); + break; + } + } + + if(_username != null) + { + iter = callbackList.iterator(); + while (iter.hasNext()) + { + Callback callback = iter.next(); + if (callback instanceof PasswordCallback) + { + iter.remove(); + ManagedUser user = getUser(_username); + if(user != null) + { + ((PasswordCallback) callback).setPassword(user.getPassword().toCharArray()); + } + else + { + ((PasswordCallback) callback).setPassword(null); + } + break; + } + } + } + + for (Callback callback : callbackList) + { + + if (callback instanceof AuthorizeCallback) + { + ((AuthorizeCallback) callback).setAuthorized(true); + } + else + { + throw new UnsupportedCallbackException(callback); + } + } + } + } +} diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ScramAuthUser.java b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ScramAuthUser.java deleted file mode 100644 index b3de1d1f17..0000000000 --- a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ScramAuthUser.java +++ /dev/null @@ -1,215 +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.manager; - -import java.security.AccessControlException; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -import javax.security.sasl.SaslException; - -import org.apache.qpid.server.configuration.updater.VoidTask; -import org.apache.qpid.server.model.AbstractConfiguredObject; -import org.apache.qpid.server.model.ConfiguredObject; -import org.apache.qpid.server.model.ManagedAttributeField; -import org.apache.qpid.server.model.ManagedObject; -import org.apache.qpid.server.model.ManagedObjectFactoryConstructor; -import org.apache.qpid.server.model.PreferencesProvider; -import org.apache.qpid.server.model.State; -import org.apache.qpid.server.model.StateTransition; -import org.apache.qpid.server.model.User; -import org.apache.qpid.server.security.access.Operation; - -@ManagedObject( category = false, type = ScramAuthUser.SCRAM_USER_TYPE) -class ScramAuthUser extends AbstractConfiguredObject implements User -{ - public static final String SCRAM_USER_TYPE = "scram"; - - private AbstractScramAuthenticationManager _authenticationManager; - @ManagedAttributeField - private String _password; - - @ManagedObjectFactoryConstructor - ScramAuthUser(final Map attributes, AbstractScramAuthenticationManager parent) - { - super(parentsMap(parent), attributes); - _authenticationManager = parent; - if(!ScramSHA1AuthenticationManager.ASCII.newEncoder().canEncode(getName())) - { - throw new IllegalArgumentException("Scram SHA1 user names are restricted to characters in the ASCII charset"); - } - setState(State.ACTIVE); - } - - @Override - protected void onOpen() - { - super.onOpen(); - _authenticationManager.getUserMap().put(getName(), this); - } - - @Override - public void onValidate() - { - super.onValidate(); - if(!isDurable()) - { - throw new IllegalArgumentException(getClass().getSimpleName() + " must be durable"); - } - } - - @Override - protected void validateChange(final ConfiguredObject proxyForValidation, final Set changedAttributes) - { - super.validateChange(proxyForValidation, changedAttributes); - if(changedAttributes.contains(DURABLE) && !proxyForValidation.isDurable()) - { - throw new IllegalArgumentException(getClass().getSimpleName() + " must be durable"); - } - } - - @Override - protected void authoriseSetDesiredState(final State desiredState) throws AccessControlException - { - if(desiredState == State.DELETED) - { - _authenticationManager.getSecurityManager().authoriseUserOperation(Operation.DELETE, getName()); - } - - } - - @StateTransition(currentState = {State.ACTIVE}, desiredState = State.DELETED) - private void doDelete() - { - _authenticationManager.getUserMap().remove(getName()); - deleted(); - } - - - @Override - public void setAttributes(final Map attributes) - throws IllegalStateException, AccessControlException, IllegalArgumentException - { - runTask(new VoidTask() - { - - @Override - public void execute() - { - Map modifiedAttributes = new HashMap(attributes); - final String newPassword = (String) attributes.get(User.PASSWORD); - if (attributes.containsKey(User.PASSWORD) - && !newPassword.equals(getActualAttributes().get(User.PASSWORD))) - { - try - { - modifiedAttributes.put(User.PASSWORD, - _authenticationManager.createStoredPassword(newPassword)); - } - catch (SaslException e) - { - throw new IllegalArgumentException(e); - } - } - ScramAuthUser.super.setAttributes(modifiedAttributes); - } - }); - - - } - - @Override - public String getPassword() - { - return _password; - } - - @Override - public void setPassword(final String password) - { - _authenticationManager.getSecurityManager().authoriseUserOperation(Operation.UPDATE, getName()); - - try - { - changeAttribute(User.PASSWORD, getAttribute(User.PASSWORD), _authenticationManager.createStoredPassword( - password)); - } - catch (SaslException e) - { - throw new IllegalArgumentException(e); - } - } - - @Override - public Collection getChildren(final Class clazz) - { - return Collections.emptySet(); - } - - @Override - public Map getPreferences() - { - PreferencesProvider preferencesProvider = _authenticationManager.getPreferencesProvider(); - if (preferencesProvider == null) - { - return null; - } - return preferencesProvider.getPreferences(this.getName()); - } - - @Override - public Object getPreference(String name) - { - Map preferences = getPreferences(); - if (preferences == null) - { - return null; - } - return preferences.get(name); - } - - @Override - public Map setPreferences(Map preferences) - { - PreferencesProvider preferencesProvider = _authenticationManager.getPreferencesProvider(); - if (preferencesProvider == null) - { - return null; - } - return preferencesProvider.setPreferences(this.getName(), preferences); - } - - @Override - public boolean deletePreferences() - { - PreferencesProvider preferencesProvider = _authenticationManager.getPreferencesProvider(); - if (preferencesProvider == null) - { - return false; - } - String[] deleted = preferencesProvider.deletePreferences(this.getName()); - return deleted.length == 1; - } - -} diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/store/BrokerStoreUpgraderAndRecoverer.java b/java/broker-core/src/main/java/org/apache/qpid/server/store/BrokerStoreUpgraderAndRecoverer.java index be7db10773..08440826be 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/store/BrokerStoreUpgraderAndRecoverer.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/store/BrokerStoreUpgraderAndRecoverer.java @@ -19,6 +19,7 @@ * */ package org.apache.qpid.server.store; + import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -26,12 +27,15 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.UUID; import org.apache.qpid.server.configuration.IllegalConfigurationException; import org.apache.qpid.server.configuration.store.StoreConfigurationChangeListener; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.SystemConfig; +import org.apache.qpid.server.model.VirtualHostAlias; import org.apache.qpid.server.util.Action; public class BrokerStoreUpgraderAndRecoverer @@ -49,6 +53,7 @@ public class BrokerStoreUpgraderAndRecoverer register(new Upgrader_1_1_to_1_2()); register(new Upgrader_1_2_to_1_3()); register(new Upgrader_1_3_to_2_0()); + register(new Upgrader_2_0_to_2_1()); } private void register(StoreUpgraderPhase upgrader) @@ -206,6 +211,71 @@ public class BrokerStoreUpgraderAndRecoverer getNextUpgrader().complete(); } + } + private class Upgrader_2_0_to_2_1 extends StoreUpgraderPhase + { + public Upgrader_2_0_to_2_1() + { + super("modelVersion", "2.0", "2.1"); + } + + @Override + public void configuredObject(ConfiguredObjectRecord record) + { + if(record.getType().equals("Port") && isAmqpPort(record.getAttributes())) + { + createAliasRecord(record, "nameAlias", "nameAlias"); + createAliasRecord(record, "defaultAlias", "defaultAlias"); + createAliasRecord(record, "hostnameAlias", "hostnameAlias"); + + } + else if(record.getType().equals("User") && "scram".equals(record.getAttributes().get("type")) ) + { + Map updatedAttributes = new HashMap(record.getAttributes()); + updatedAttributes.put("type", "managed"); + record = new ConfiguredObjectRecordImpl(record.getId(), record.getType(), updatedAttributes, record.getParents()); + getUpdateMap().put(record.getId(), record); + } + else if (record.getType().equals("Broker")) + { + record = upgradeRootRecord(record); + } + + getNextUpgrader().configuredObject(record); + } + + private boolean isAmqpPort(final Map attributes) + { + Object type = attributes.get(ConfiguredObject.TYPE); + Object protocols = attributes.get(Port.PROTOCOLS); + String protocolString = protocols == null ? null : protocols.toString(); + return "AMQP".equals(type) + || protocolString == null + || !protocolString.matches(".*\\w.*") + || protocolString.contains("AMQP"); + + } + + private void createAliasRecord(ConfiguredObjectRecord parent, String name, String type) + { + Map attributes = new HashMap<>(); + attributes.put(VirtualHostAlias.NAME, name); + attributes.put(VirtualHostAlias.TYPE, type); + + final ConfiguredObjectRecord record = new ConfiguredObjectRecordImpl(UUID.randomUUID(), + "VirtualHostAlias", + attributes, + Collections.singletonMap("Port", parent.getId())); + getUpdateMap().put(record.getId(), record); + getNextUpgrader().configuredObject(record); + } + + @Override + public void complete() + { + getNextUpgrader().complete(); + } + } private static class VirtualHostEntryUpgrader diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/store/ConfiguredObjectRecordConverter.java b/java/broker-core/src/main/java/org/apache/qpid/server/store/ConfiguredObjectRecordConverter.java index 5f1c0b4b7f..8d8b62ffdd 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/store/ConfiguredObjectRecordConverter.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/store/ConfiguredObjectRecordConverter.java @@ -98,7 +98,8 @@ public class ConfiguredObjectRecordConverter for(Class childClass : childClasses) { final String childType = childClass.getSimpleName(); - String attrName = childType.toLowerCase() + "s"; + String singularName = childType.toLowerCase(); + String attrName = singularName + (singularName.endsWith("s") ? "es" : "s"); Object children = data.remove(attrName); if(children != null) { diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/store/ConfiguredObjectRecordImpl.java b/java/broker-core/src/main/java/org/apache/qpid/server/store/ConfiguredObjectRecordImpl.java index 2d1b08aa50..8044afafdc 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/store/ConfiguredObjectRecordImpl.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/store/ConfiguredObjectRecordImpl.java @@ -79,7 +79,7 @@ public class ConfiguredObjectRecordImpl implements ConfiguredObjectRecord @Override public String toString() { - return "ConfiguredObjectRecord [id=" + _id + ", type=" + _type + ", attributes=" + _attributes + "]"; + return "ConfiguredObjectRecord [id=" + _id + ", type=" + _type + ", attributes=" + _attributes + ", parents=" + _parents + "]"; } @Override diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/store/JsonFileConfigStore.java b/java/broker-core/src/main/java/org/apache/qpid/server/store/JsonFileConfigStore.java index 55de8f6852..b3e9d39a55 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/store/JsonFileConfigStore.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/store/JsonFileConfigStore.java @@ -445,7 +445,8 @@ public class JsonFileConfigStore implements DurableConfigurationStore // only add if this is the "first" parent if(_parent.getModel().getParentTypes(childClass).iterator().next() == type) { - String attrName = childClass.getSimpleName().toLowerCase() + "s"; + String singularName = childClass.getSimpleName().toLowerCase(); + String attrName = singularName + (singularName.endsWith("s") ? "es" : "s"); List childIds = _idsByType.get(childClass.getSimpleName()); if(childIds != null) { diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/store/VirtualHostStoreUpgraderAndRecoverer.java b/java/broker-core/src/main/java/org/apache/qpid/server/store/VirtualHostStoreUpgraderAndRecoverer.java index 5565ea6175..f1372882a8 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/store/VirtualHostStoreUpgraderAndRecoverer.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/store/VirtualHostStoreUpgraderAndRecoverer.java @@ -61,6 +61,7 @@ public class VirtualHostStoreUpgraderAndRecoverer register(new Upgrader_0_2_to_0_3()); register(new Upgrader_0_3_to_0_4()); register(new Upgrader_0_4_to_2_0()); + register(new Upgrader_2_0_to_2_1()); Map defaultExchangeIds = new HashMap(); for (String exchangeName : DEFAULT_EXCHANGES.keySet()) @@ -400,6 +401,32 @@ public class VirtualHostStoreUpgraderAndRecoverer } + private class Upgrader_2_0_to_2_1 extends StoreUpgraderPhase + { + public Upgrader_2_0_to_2_1() + { + super("modelVersion", "2.0", "2.1"); + } + + @Override + public void configuredObject(ConfiguredObjectRecord record) + { + + if("VirtualHost".equals(record.getType())) + { + record = upgradeRootRecord(record); + } + getNextUpgrader().configuredObject(record); + } + + @Override + public void complete() + { + getNextUpgrader().complete(); + } + + } + public void perform(DurableConfigurationStore durableConfigurationStore) { String virtualHostCategory = VirtualHost.class.getSimpleName(); diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/transport/TCPandSSLTransport.java b/java/broker-core/src/main/java/org/apache/qpid/server/transport/TCPandSSLTransport.java index e6bf0c1f89..b1f6b84b72 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/transport/TCPandSSLTransport.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/transport/TCPandSSLTransport.java @@ -42,13 +42,13 @@ class TCPandSSLTransport implements AcceptingTransport private Set _transports; private SSLContext _sslContext; private InetSocketAddress _bindingSocketAddress; - private Port _port; + private AmqpPort _port; private Set _supported; private Protocol _defaultSupportedProtocolReply; TCPandSSLTransport(final Set transports, final SSLContext sslContext, - final Port port, + final AmqpPort port, final Set supported, final Protocol defaultSupportedProtocolReply) { @@ -62,12 +62,12 @@ class TCPandSSLTransport implements AcceptingTransport @Override public void start() { - String bindingAddress = (String) _port.getAttribute(Port.BINDING_ADDRESS); + String bindingAddress = ((AmqpPort)_port).getBindingAddress(); if (WILDCARD_ADDRESS.equals(bindingAddress)) { bindingAddress = null; } - Integer port = (Integer) _port.getAttribute(Port.PORT); + int port = _port.getPort(); if ( bindingAddress == null ) { _bindingSocketAddress = new InetSocketAddress(port); @@ -91,6 +91,11 @@ class TCPandSSLTransport implements AcceptingTransport _networkTransport.accept(settings, protocolEngineFactory, _transports.contains(Transport.TCP) ? null : _sslContext); } + public int getAcceptingPort() + { + return _networkTransport.getAcceptingPort(); + } + @Override public void close() { @@ -106,31 +111,31 @@ class TCPandSSLTransport implements AcceptingTransport @Override public boolean wantClientAuth() { - return (Boolean)_port.getAttribute(Port.WANT_CLIENT_AUTH); + return _port.getWantClientAuth(); } @Override public boolean needClientAuth() { - return (Boolean)_port.getAttribute(Port.NEED_CLIENT_AUTH); + return _port.getNeedClientAuth(); } @Override public Boolean getTcpNoDelay() { - return (Boolean)_port.getAttribute(Port.TCP_NO_DELAY); + return _port.isTcpNoDelay(); } @Override public Integer getSendBufferSize() { - return (Integer)_port.getAttribute(AmqpPort.SEND_BUFFER_SIZE); + return _port.getSendBufferSize(); } @Override public Integer getReceiveBufferSize() { - return (Integer)_port.getAttribute(AmqpPort.RECEIVE_BUFFER_SIZE); + return _port.getReceiveBufferSize(); } @Override diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/transport/TCPandSSLTransportProvider.java b/java/broker-core/src/main/java/org/apache/qpid/server/transport/TCPandSSLTransportProvider.java index 7c7d0ea9e6..fa0d9bfcff 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/transport/TCPandSSLTransportProvider.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/transport/TCPandSSLTransportProvider.java @@ -24,16 +24,16 @@ import java.util.Set; import javax.net.ssl.SSLContext; -import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.Protocol; import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.model.port.AmqpPort; class TCPandSSLTransportProvider implements TransportProvider { @Override public AcceptingTransport createTransport(final Set transports, final SSLContext sslContext, - final Port port, + final AmqpPort port, final Set supported, final Protocol defaultSupportedProtocolReply) { diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/transport/TransportProvider.java b/java/broker-core/src/main/java/org/apache/qpid/server/transport/TransportProvider.java index 04b4b44c2e..24061562e5 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/transport/TransportProvider.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/transport/TransportProvider.java @@ -24,15 +24,15 @@ import java.util.Set; import javax.net.ssl.SSLContext; -import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.Protocol; import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.model.port.AmqpPort; public interface TransportProvider { AcceptingTransport createTransport(Set transports, SSLContext sslContext, - Port port, + AmqpPort port, Set supported, Protocol defaultSupportedProtocolReply); } diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java index 48077ba503..56e28bd870 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java @@ -60,7 +60,6 @@ import org.apache.qpid.server.message.MessageSource; import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.model.*; import org.apache.qpid.server.model.adapter.ConnectionAdapter; -import org.apache.qpid.server.model.adapter.VirtualHostAliasAdapter; import org.apache.qpid.server.plugin.QpidServiceLoader; import org.apache.qpid.server.plugin.SystemNodeCreator; import org.apache.qpid.server.protocol.AMQConnectionModel; @@ -284,18 +283,6 @@ public abstract class AbstractVirtualHost> exte _messageStore.addEventListener(this, Event.PERSISTENT_MESSAGE_SIZE_OVERFULL); _messageStore.addEventListener(this, Event.PERSISTENT_MESSAGE_SIZE_UNDERFULL); - - synchronized(_aliases) - { - for(Port port :_broker.getPorts()) - { - if (Protocol.hasAmqpProtocol(port.getProtocols())) - { - _aliases.add(new VirtualHostAliasAdapter(this, port)); - } - } - } - addChangeListener(new StoreUpdatingChangeListener()); } diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostalias/AbstractFixedVirtualHostNodeAlias.java b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostalias/AbstractFixedVirtualHostNodeAlias.java new file mode 100644 index 0000000000..2ec2c4390e --- /dev/null +++ b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostalias/AbstractFixedVirtualHostNodeAlias.java @@ -0,0 +1,56 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.virtualhostalias; + +import java.util.Map; + +import org.apache.qpid.server.model.FixedVirtualHostNodeAlias; +import org.apache.qpid.server.model.ManagedAttributeField; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.VirtualHostNode; + +abstract class AbstractFixedVirtualHostNodeAlias> + extends AbstractVirtualHostAlias implements FixedVirtualHostNodeAlias +{ + @ManagedAttributeField + private VirtualHostNode _virtualHostNode; + + protected AbstractFixedVirtualHostNodeAlias(final Map attributes, + final Port port) + { + super(attributes, port); + } + + + @Override + public VirtualHostNode getVirtualHostNode() + { + return _virtualHostNode; + } + + @Override + public VirtualHostNode getVirtualHostNode(final String name) + { + return matches(name) ? getVirtualHostNode() : null; + } + + protected abstract boolean matches(final String name); +} diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostalias/AbstractVirtualHostAlias.java b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostalias/AbstractVirtualHostAlias.java new file mode 100644 index 0000000000..bf705e5f96 --- /dev/null +++ b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostalias/AbstractVirtualHostAlias.java @@ -0,0 +1,62 @@ +/* + * + * 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.virtualhostalias; + +import java.util.Map; + +import org.apache.qpid.server.model.AbstractConfiguredObject; +import org.apache.qpid.server.model.ManagedAttributeField; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.VirtualHostAlias; + +abstract class AbstractVirtualHostAlias> + extends AbstractConfiguredObject implements VirtualHostAlias +{ + + @ManagedAttributeField + private int _priority; + + protected AbstractVirtualHostAlias(Map attributes, Port port) + { + super(parentsMap(port), attributes); + } + + @Override + public Port getPort() + { + return getParent(Port.class); + } + + @Override + public int getPriority() + { + return _priority; + } + + @Override + public State getState() + { + return State.ACTIVE; + } + +} diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostalias/DefaultVirtualHostAliasImpl.java b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostalias/DefaultVirtualHostAliasImpl.java new file mode 100644 index 0000000000..cab9794375 --- /dev/null +++ b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostalias/DefaultVirtualHostAliasImpl.java @@ -0,0 +1,61 @@ +/* + * + * 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.virtualhostalias; + +import java.util.Map; + +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.DefaultVirtualHostAlias; +import org.apache.qpid.server.model.ManagedObjectFactoryConstructor; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.VirtualHostNode; + +public final class DefaultVirtualHostAliasImpl + extends AbstractVirtualHostAlias + implements DefaultVirtualHostAlias +{ + + @ManagedObjectFactoryConstructor + protected DefaultVirtualHostAliasImpl(final Map attributes, final Port port) + { + super(attributes, port); + } + + @Override + public VirtualHostNode getVirtualHostNode(final String name) + { + if(name == null || name.trim().equals("")) + { + Broker broker = getPort().getParent(Broker.class); + String defaultHostName = broker.getDefaultVirtualHost(); + for(VirtualHostNode vhn : broker.getVirtualHostNodes()) + { + if(vhn.getName().equals(defaultHostName)) + { + return vhn; + } + } + + } + return null; + } + +} diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostalias/HostNameAliasImpl.java b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostalias/HostNameAliasImpl.java new file mode 100644 index 0000000000..9abeac5f31 --- /dev/null +++ b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostalias/HostNameAliasImpl.java @@ -0,0 +1,193 @@ +/* + * + * 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.virtualhostalias; + +import java.net.InetAddress; +import java.net.InterfaceAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.net.UnknownHostException; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.CopyOnWriteArraySet; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.HostNameAlias; +import org.apache.qpid.server.model.ManagedObjectFactoryConstructor; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.VirtualHostNode; +import org.apache.qpid.server.model.port.AmqpPort; + +public class HostNameAliasImpl + extends AbstractFixedVirtualHostNodeAlias + implements HostNameAlias +{ + + private final Set _localAddresses = new CopyOnWriteArraySet<>(); + private final Set _localAddressNames = new CopyOnWriteArraySet<>(); + private final Lock _addressLock = new ReentrantLock(); + private final AtomicBoolean _addressesComputed = new AtomicBoolean(); + + + @ManagedObjectFactoryConstructor + protected HostNameAliasImpl(final Map attributes, final Port port) + { + super(attributes, port); + } + + protected void onOpen() + { + super.onOpen(); + Thread thread = new Thread(new NetworkAddressResolver(), "Network Address Resolver"); + thread.start(); + } + + + @Override + public VirtualHostNode getVirtualHostNode(final String name) + { + VirtualHostNode node = null; + if(matches(name)) + { + node = getVirtualHostNode(); + if(node == null) + { + Broker broker = getPort().getParent(Broker.class); + String defaultHostName = broker.getDefaultVirtualHost(); + for (VirtualHostNode vhn : broker.getVirtualHostNodes()) + { + if (vhn.getName().equals(defaultHostName)) + { + return vhn; + } + } + } + + } + return node; + } + + @Override + protected boolean matches(final String host) + { + while(!_addressesComputed.get()) + { + Lock lock = _addressLock; + lock.lock(); + lock.unlock(); + } + + boolean isNetworkAddress = true; + if (!_localAddressNames.contains(host)) + { + try + { + InetAddress inetAddress = InetAddress.getByName(host); + if (!_localAddresses.contains(inetAddress)) + { + isNetworkAddress = false; + } + else + { + _localAddressNames.add(host); + } + } + catch (UnknownHostException e) + { + // ignore + isNetworkAddress = false; + } + } + return isNetworkAddress; + + } + + private class NetworkAddressResolver implements Runnable + { + public void run() + { + _addressesComputed.set(false); + Lock lock = _addressLock; + + lock.lock(); + String bindingAddress = ((AmqpPort)getPort()).getBindingAddress(); + try + { + Collection inetAddresses; + if(bindingAddress == null || bindingAddress.trim().equals("") || bindingAddress.trim().equals("*")) + { + inetAddresses = getAllInetAddresses(); + } + else + { + inetAddresses = Collections.singleton(InetAddress.getByName(bindingAddress)); + } + for (InetAddress address : inetAddresses) + { + _localAddresses.add(address); + String hostAddress = address.getHostAddress(); + if (hostAddress != null) + { + _localAddressNames.add(hostAddress); + } + String hostName = address.getHostName(); + if (hostName != null) + { + _localAddressNames.add(hostName); + } + String canonicalHostName = address.getCanonicalHostName(); + if (canonicalHostName != null) + { + _localAddressNames.add(canonicalHostName); + } + } + } + catch (SocketException | UnknownHostException e) + { + // ignore + } + finally + { + _addressesComputed.set(true); + lock.unlock(); + } + } + + private Collection getAllInetAddresses() throws SocketException + { + Set addresses = new HashSet<>(); + for (NetworkInterface networkInterface : Collections.list(NetworkInterface.getNetworkInterfaces())) + { + for (InterfaceAddress inetAddress : networkInterface.getInterfaceAddresses()) + { + addresses.add(inetAddress.getAddress()); + } + } + return addresses; + } + } +} diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostalias/PatternMatchingAliasImpl.java b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostalias/PatternMatchingAliasImpl.java new file mode 100644 index 0000000000..df47b1a94e --- /dev/null +++ b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostalias/PatternMatchingAliasImpl.java @@ -0,0 +1,54 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.virtualhostalias; + +import java.util.Map; + +import org.apache.qpid.server.model.ManagedAttributeField; +import org.apache.qpid.server.model.ManagedObjectFactoryConstructor; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.PatternMatchingAlias; + +public final class PatternMatchingAliasImpl + extends AbstractFixedVirtualHostNodeAlias + implements PatternMatchingAlias +{ + @ManagedAttributeField + private String _pattern; + + @ManagedObjectFactoryConstructor + protected PatternMatchingAliasImpl(final Map attributes, final Port port) + { + super(attributes, port); + } + + @Override + protected boolean matches(final String name) + { + return name == null ? "".matches(_pattern) : name.matches(_pattern); + } + + @Override + public String getPattern() + { + return _pattern; + } +} diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostalias/VirtualHostNameAliasImpl.java b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostalias/VirtualHostNameAliasImpl.java new file mode 100644 index 0000000000..f55367a89d --- /dev/null +++ b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostalias/VirtualHostNameAliasImpl.java @@ -0,0 +1,54 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.virtualhostalias; + +import java.util.Map; + +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ManagedObjectFactoryConstructor; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.VirtualHostNameAlias; +import org.apache.qpid.server.model.VirtualHostNode; + +public final class VirtualHostNameAliasImpl + extends AbstractVirtualHostAlias + implements VirtualHostNameAlias +{ + @ManagedObjectFactoryConstructor + protected VirtualHostNameAliasImpl(final Map attributes, final Port port) + { + super(attributes, port); + } + + @Override + public VirtualHostNode getVirtualHostNode(final String name) + { + Broker broker = getPort().getParent(Broker.class); + for(VirtualHostNode vhn : broker.getVirtualHostNodes()) + { + if(vhn.getName().equals(name)) + { + return vhn; + } + } + return null; + } +} diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java index aea07e3ed3..f4c0576d79 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java @@ -107,6 +107,11 @@ public abstract class AbstractVirtualHostNode "); - System.exit(0); - } - - Passwd passwd = new Passwd(); - String output = passwd.getOutput(args[0], args[1]); - System.out.println(output); - } - - public String getOutput(String userName, String password) throws UnsupportedEncodingException, NoSuchAlgorithmException - { - byte[] data = password.getBytes("utf-8"); - - MessageDigest md = MessageDigest.getInstance("MD5"); - - for (byte b : data) - { - md.update(b); - } - - byte[] digest = md.digest(); - - Base64 b64 = new Base64(); - - byte[] encoded = b64.encode(digest); - - String encodedStr = new String(encoded, Charset.forName("utf-8")); - return userName + ":" + encodedStr; - } -} diff --git a/java/broker-core/src/main/resources/initial-config.json b/java/broker-core/src/main/resources/initial-config.json index 5ee820d9ac..012cdc9017 100644 --- a/java/broker-core/src/main/resources/initial-config.json +++ b/java/broker-core/src/main/resources/initial-config.json @@ -20,7 +20,7 @@ */ { "name": "${broker.name}", - "modelVersion": "2.0", + "modelVersion": "2.1", "defaultVirtualHost" : "default", "authenticationproviders" : [ { "name" : "passwordFile", @@ -35,7 +35,18 @@ "ports" : [ { "name" : "AMQP", "port" : "${qpid.amqp_port}", - "authenticationProvider" : "passwordFile" + "authenticationProvider" : "passwordFile", + "secureOnlyMechanisms" : [ ], + "virtualhostaliases" : [ { + "name" : "nameAlias", + "type" : "nameAlias" + }, { + "name" : "defaultAlias", + "type" : "defaultAlias" + }, { + "name" : "hostnameAlias", + "type" : "hostnameAlias" + } ] }, { "name" : "HTTP", "port" : "${qpid.http_port}", diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/configuration/store/StoreConfigurationChangeListenerTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/configuration/store/StoreConfigurationChangeListenerTest.java index 6cfcf430b2..14ff640c57 100644 --- a/java/broker-core/src/test/java/org/apache/qpid/server/configuration/store/StoreConfigurationChangeListenerTest.java +++ b/java/broker-core/src/test/java/org/apache/qpid/server/configuration/store/StoreConfigurationChangeListenerTest.java @@ -27,10 +27,12 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; +import java.util.Collections; import java.util.UUID; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.Model; import org.apache.qpid.server.model.State; import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.model.VirtualHostNode; @@ -69,6 +71,9 @@ public class StoreConfigurationChangeListenerTest extends QpidTestCase when(broker.getCategoryClass()).thenReturn(Broker.class); VirtualHost child = mock(VirtualHost.class); when(child.getCategoryClass()).thenReturn(VirtualHost.class); + Model model = mock(Model.class); + when(model.getChildTypes(any(Class.class))).thenReturn(Collections.>emptyList()); + when(child.getModel()).thenReturn(model); _listener.childAdded(broker, child); verify(_store).update(eq(true), any(ConfiguredObjectRecord.class)); } diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/model/AbstractConfiguredObjectTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/model/AbstractConfiguredObjectTest.java index a1a363d5fe..54a059e067 100644 --- a/java/broker-core/src/test/java/org/apache/qpid/server/model/AbstractConfiguredObjectTest.java +++ b/java/broker-core/src/test/java/org/apache/qpid/server/model/AbstractConfiguredObjectTest.java @@ -24,16 +24,15 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; -import junit.framework.TestCase; - import org.apache.qpid.server.configuration.IllegalConfigurationException; import org.apache.qpid.server.model.testmodel.TestChildCategory; import org.apache.qpid.server.model.testmodel.TestConfiguredObject; import org.apache.qpid.server.model.testmodel.TestModel; import org.apache.qpid.server.model.testmodel.TestRootCategory; import org.apache.qpid.server.store.ConfiguredObjectRecord; +import org.apache.qpid.test.utils.QpidTestCase; -public class AbstractConfiguredObjectTest extends TestCase +public class AbstractConfiguredObjectTest extends QpidTestCase { private final Model _model = TestModel.getInstance(); @@ -169,6 +168,27 @@ public class AbstractConfiguredObjectTest extends TestCase System.clearProperty(sysPropertyName); } + + public void testDefaultContextIsInContextKeys() + { + final String objectName = "myName"; + + Map attributes = new HashMap<>(); + attributes.put(ConfiguredObject.NAME, objectName); + + + TestRootCategory object = _model.getObjectFactory().create(TestRootCategory.class, + attributes); + + + assertTrue("context default not in contextKeys", object.getContextKeys(true).contains(TestRootCategory.TEST_CONTEXT_DEFAULT)); + assertEquals(object.getContextValue(String.class, TestRootCategory.TEST_CONTEXT_DEFAULT), "default"); + + setTestSystemProperty(TestRootCategory.TEST_CONTEXT_DEFAULT, "notdefault"); + assertTrue("context default not in contextKeys", object.getContextKeys(true).contains(TestRootCategory.TEST_CONTEXT_DEFAULT)); + assertEquals(object.getContextValue(String.class, TestRootCategory.TEST_CONTEXT_DEFAULT), "notdefault"); + } + public void testStringAttributeValueFromContextVariableProvidedObjectsContext() { String contextToken = "${myReplacement}"; diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestChildCategory.java b/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestChildCategory.java index d3fe14b7d8..de4b1ae1c2 100644 --- a/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestChildCategory.java +++ b/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestChildCategory.java @@ -24,12 +24,12 @@ import java.util.Set; import org.apache.qpid.server.model.ConfiguredObject; import org.apache.qpid.server.model.ManagedAttribute; +import org.apache.qpid.server.model.ManagedContextDefault; import org.apache.qpid.server.model.ManagedObject; @ManagedObject public interface TestChildCategory> extends ConfiguredObject { - String NON_INTERPOLATED_VALID_VALUE = "${file.separator}"; @ManagedAttribute(validValues = { NON_INTERPOLATED_VALID_VALUE }, defaultValue = "") diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestRootCategory.java b/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestRootCategory.java index 7f804006b2..2359a93b43 100644 --- a/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestRootCategory.java +++ b/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestRootCategory.java @@ -24,6 +24,7 @@ import java.util.Map; import org.apache.qpid.server.model.ConfiguredObject; import org.apache.qpid.server.model.ManagedAttribute; +import org.apache.qpid.server.model.ManagedContextDefault; import org.apache.qpid.server.model.ManagedObject; @ManagedObject( defaultType = "test" ) @@ -35,6 +36,13 @@ public interface TestRootCategory> extends Configu String STRING_VALUE = "stringValue"; String MAP_VALUE = "mapValue"; + + String TEST_CONTEXT_DEFAULT = "TEST_CONTEXT_DEFAULT"; + + @ManagedContextDefault(name = TEST_CONTEXT_DEFAULT) + String testGlobalDefault = "default"; + + @ManagedAttribute String getAutomatedPersistedValue(); diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/security/SubjectCreatorTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/security/SubjectCreatorTest.java index 5366e6d8bf..8e814745b6 100644 --- a/java/broker-core/src/test/java/org/apache/qpid/server/security/SubjectCreatorTest.java +++ b/java/broker-core/src/test/java/org/apache/qpid/server/security/SubjectCreatorTest.java @@ -44,10 +44,10 @@ public class SubjectCreatorTest extends TestCase private static final String USERNAME = "username"; private static final String PASSWORD = "password"; - private AuthenticationProvider _authenticationProvider = mock(AuthenticationProvider.class); + private AuthenticationProvider _authenticationProvider = mock(AuthenticationProvider.class); - private GroupProvider _groupManager1 = mock(GroupProvider.class); - private GroupProvider _groupManager2 = mock(GroupProvider.class); + private GroupProvider _groupManager1 = mock(GroupProvider.class); + private GroupProvider _groupManager2 = mock(GroupProvider.class); private Principal _userPrincipal = mock(Principal.class); private Principal _group1 = mock(Principal.class); @@ -64,7 +64,7 @@ public class SubjectCreatorTest extends TestCase when(_groupManager1.getGroupPrincipalsForUser(USERNAME)).thenReturn(Collections.singleton(_group1)); when(_groupManager2.getGroupPrincipalsForUser(USERNAME)).thenReturn(Collections.singleton(_group2)); - _subjectCreator = new SubjectCreator(_authenticationProvider, new HashSet(Arrays.asList(_groupManager1, _groupManager2)), + _subjectCreator = new SubjectCreator(_authenticationProvider, new HashSet>(Arrays.asList(_groupManager1, _groupManager2)), false); _authenticationResult = new AuthenticationResult(_userPrincipal); when(_authenticationProvider.authenticate(USERNAME, PASSWORD)).thenReturn(_authenticationResult); diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/MD5AuthenticationManagerTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/MD5AuthenticationManagerTest.java new file mode 100644 index 0000000000..aecd318937 --- /dev/null +++ b/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/MD5AuthenticationManagerTest.java @@ -0,0 +1,53 @@ +/* + * + * 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.util.Map; + +public class MD5AuthenticationManagerTest extends ManagedAuthenticationManagerTestBase +{ + @Override + public void setUp() throws Exception + { + super.setUp(); + } + + @Override + protected ConfigModelPasswordManagingAuthenticationProvider createAuthManager(final Map attributesMap) + { + return new MD5AuthenticationProvider(attributesMap, getBroker()); + } + + @Override + protected boolean isPlain() + { + return false; + } + + @Override + public void tearDown() throws Exception + { + super.tearDown(); + } + + + +} diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/ManagedAuthenticationManagerTestBase.java b/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/ManagedAuthenticationManagerTestBase.java new file mode 100644 index 0000000000..dd92d3ebca --- /dev/null +++ b/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/ManagedAuthenticationManagerTestBase.java @@ -0,0 +1,252 @@ +/* + * + * 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 static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import javax.security.auth.login.AccountNotFoundException; +import javax.security.sasl.SaslException; +import javax.security.sasl.SaslServer; + +import org.apache.qpid.server.configuration.updater.CurrentThreadTaskExecutor; +import org.apache.qpid.server.configuration.updater.TaskExecutor; +import org.apache.qpid.server.model.AuthenticationProvider; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.User; +import org.apache.qpid.server.security.SecurityManager; +import org.apache.qpid.server.security.SubjectCreator; +import org.apache.qpid.server.security.auth.AuthenticationResult; +import org.apache.qpid.server.util.BrokerTestHelper; +import org.apache.qpid.test.utils.QpidTestCase; + +abstract class ManagedAuthenticationManagerTestBase extends QpidTestCase +{ + private ConfigModelPasswordManagingAuthenticationProvider _authManager; + + + private Broker _broker; + private SecurityManager _securityManager; + private TaskExecutor _executor; + + @Override + public void setUp() throws Exception + { + super.setUp(); + _executor = new CurrentThreadTaskExecutor(); + _executor.start(); + _broker = BrokerTestHelper.createBrokerMock(); + _securityManager = mock(SecurityManager.class); + when(_broker.getTaskExecutor()).thenReturn(_executor); + when(_broker.getSecurityManager()).thenReturn(_securityManager); + final Map attributesMap = new HashMap(); + attributesMap.put(AuthenticationProvider.NAME, getTestName()); + attributesMap.put(AuthenticationProvider.ID, UUID.randomUUID()); + _authManager = createAuthManager(attributesMap); + _authManager.open(); + } + + + @Override + public void tearDown() throws Exception + { + _executor.stop(); + super.tearDown(); + } + + protected abstract ConfigModelPasswordManagingAuthenticationProvider createAuthManager(final Map attributesMap); + + public Broker getBroker() + { + return _broker; + } + + public ConfigModelPasswordManagingAuthenticationProvider getAuthManager() + { + return _authManager; + } + + + public void testMechanisms() + { + SubjectCreator insecureCreator = _authManager.getSubjectCreator(false); + assertFalse("PLAIN authentication should not be available on an insecure connection", insecureCreator.getMechanisms().contains("PLAIN")); + SubjectCreator secureCreator = _authManager.getSubjectCreator(true); + assertTrue("PLAIN authentication should be available on a secure connection", secureCreator.getMechanisms().contains("PLAIN")); + + try + { + SaslServer saslServer = secureCreator.createSaslServer("PLAIN", "127.0.0.1", null); + assertNotNull(saslServer); + } + catch (SaslException e) + { + fail("Unable to create a SaslServer for PLAIN authentication on a secure connection" + e.getMessage()); + } + + try + { + SaslServer saslServer = insecureCreator.createSaslServer("PLAIN", "127.0.0.1", null); + fail("Erroneously created a SaslServer for PLAIN authentication on an insecure connection"); + } + catch (SaslException e) + { + // Pass + } + + } + + public void testAddChildAndThenDelete() + { + // No children should be present before the test starts + assertEquals("No users should be present before the test starts", 0, _authManager.getChildren(User.class).size()); + assertEquals("No users should be present before the test starts", 0, _authManager.getUsers().size()); + + final Map childAttrs = new HashMap(); + + childAttrs.put(User.NAME, getTestName()); + childAttrs.put(User.PASSWORD, "password"); + User user = _authManager.addChild(User.class, childAttrs); + assertNotNull("User should be created but addChild returned null", user); + assertEquals(getTestName(), user.getName()); + if(!isPlain()) + { + // password shouldn't actually be the given string, but instead hashed value + assertFalse("Password shouldn't actually be the given string, but instead hashed value", + "password".equals(user.getPassword())); + } + + AuthenticationResult authResult = + _authManager.authenticate(getTestName(), "password"); + + assertEquals("User should authenticate with given password", AuthenticationResult.AuthenticationStatus.SUCCESS, authResult.getStatus()); + + assertEquals("Manager should have exactly one user child",1, _authManager.getChildren(User.class).size()); + assertEquals("Manager should have exactly one user child",1, _authManager.getUsers().size()); + + + user.delete(); + + assertEquals("No users should be present after child deletion", 0, _authManager.getChildren(User.class).size()); + + + authResult = _authManager.authenticate(getTestName(), "password"); + assertEquals("User should no longer authenticate with given password", AuthenticationResult.AuthenticationStatus.ERROR, authResult.getStatus()); + + } + + public void testCreateUser() + { + assertEquals("No users should be present before the test starts", 0, _authManager.getChildren(User.class).size()); + assertTrue(_authManager.createUser(getTestName(), "password", Collections.emptyMap())); + assertEquals("Manager should have exactly one user child",1, _authManager.getChildren(User.class).size()); + User user = _authManager.getChildren(User.class).iterator().next(); + assertEquals(getTestName(), user.getName()); + if(!isPlain()) + { + // password shouldn't actually be the given string, but instead salt and the hashed value + assertFalse("Password shouldn't actually be the given string, but instead salt and the hashed value", + "password".equals(user.getPassword())); + } + final Map childAttrs = new HashMap(); + + childAttrs.put(User.NAME, getTestName()); + childAttrs.put(User.PASSWORD, "password"); + try + { + user = _authManager.addChild(User.class, childAttrs); + fail("Should not be able to create a second user with the same name"); + } + catch(IllegalArgumentException e) + { + // pass + } + try + { + _authManager.deleteUser(getTestName()); + } + catch (AccountNotFoundException e) + { + fail("AccountNotFoundException thrown when none was expected: " + e.getMessage()); + } + try + { + _authManager.deleteUser(getTestName()); + fail("AccountNotFoundException not thrown when was expected"); + } + catch (AccountNotFoundException e) + { + // pass + } + } + + protected abstract boolean isPlain(); + + public void testUpdateUser() + { + assertTrue(_authManager.createUser(getTestName(), "password", Collections.emptyMap())); + assertTrue(_authManager.createUser(getTestName()+"_2", "password", Collections.emptyMap())); + assertEquals("Manager should have exactly two user children",2, _authManager.getChildren(User.class).size()); + + AuthenticationResult authResult = _authManager.authenticate(getTestName(), "password"); + + assertEquals("User should authenticate with given password", AuthenticationResult.AuthenticationStatus.SUCCESS, authResult.getStatus()); + authResult = _authManager.authenticate(getTestName()+"_2", "password"); + assertEquals("User should authenticate with given password", AuthenticationResult.AuthenticationStatus.SUCCESS, authResult.getStatus()); + + for(User user : _authManager.getChildren(User.class)) + { + if(user.getName().equals(getTestName())) + { + user.setAttributes(Collections.singletonMap(User.PASSWORD, "newpassword")); + } + } + + authResult = _authManager.authenticate(getTestName(), "newpassword"); + assertEquals("User should authenticate with updated password", AuthenticationResult.AuthenticationStatus.SUCCESS, authResult.getStatus()); + authResult = _authManager.authenticate(getTestName()+"_2", "password"); + assertEquals("User should authenticate with original password", AuthenticationResult.AuthenticationStatus.SUCCESS, authResult.getStatus()); + + authResult = _authManager.authenticate(getTestName(), "password"); + assertEquals("User not authenticate with original password", AuthenticationResult.AuthenticationStatus.ERROR, authResult.getStatus()); + + for(User user : _authManager.getChildren(User.class)) + { + if(user.getName().equals(getTestName())) + { + user.setPassword("newerpassword"); + } + } + + authResult = _authManager.authenticate(getTestName(), "newerpassword"); + assertEquals("User should authenticate with updated password", AuthenticationResult.AuthenticationStatus.SUCCESS, authResult.getStatus()); + + + + } + + +} diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/PlainAuthenticationManagerTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/PlainAuthenticationManagerTest.java new file mode 100644 index 0000000000..f7f60227db --- /dev/null +++ b/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/PlainAuthenticationManagerTest.java @@ -0,0 +1,51 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.security.auth.manager; + +import java.util.Map; + +public class PlainAuthenticationManagerTest extends ManagedAuthenticationManagerTestBase +{ + @Override + public void setUp() throws Exception + { + super.setUp(); + } + + @Override + protected ConfigModelPasswordManagingAuthenticationProvider createAuthManager(final Map attributesMap) + { + return new PlainAuthenticationProvider(attributesMap, getBroker()); + } + + @Override + protected boolean isPlain() + { + return true; + } + + @Override + public void tearDown() throws Exception + { + super.tearDown(); + } + +} diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/ScramSHA1AuthenticationManagerTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/ScramSHA1AuthenticationManagerTest.java index 455b5b5ec2..9a7e59abe0 100644 --- a/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/ScramSHA1AuthenticationManagerTest.java +++ b/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/ScramSHA1AuthenticationManagerTest.java @@ -20,213 +20,43 @@ */ package org.apache.qpid.server.security.auth.manager; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - import java.util.Collections; -import java.util.HashMap; import java.util.Map; -import java.util.UUID; - -import javax.security.auth.login.AccountNotFoundException; -import javax.security.sasl.SaslException; -import javax.security.sasl.SaslServer; - -import org.apache.qpid.server.configuration.updater.CurrentThreadTaskExecutor; -import org.apache.qpid.server.configuration.updater.TaskExecutor; -import org.apache.qpid.server.model.AuthenticationProvider; -import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.model.User; -import org.apache.qpid.server.security.SecurityManager; -import org.apache.qpid.server.security.SubjectCreator; -import org.apache.qpid.server.security.auth.AuthenticationResult; -import org.apache.qpid.server.util.BrokerTestHelper; -import org.apache.qpid.test.utils.QpidTestCase; -public class ScramSHA1AuthenticationManagerTest extends QpidTestCase +public class ScramSHA1AuthenticationManagerTest extends ManagedAuthenticationManagerTestBase { - private ScramSHA1AuthenticationManager _authManager; - private Broker _broker; - private SecurityManager _securityManager; - private TaskExecutor _executor; - @Override public void setUp() throws Exception { super.setUp(); - _executor = new CurrentThreadTaskExecutor(); - _executor.start(); - _broker = BrokerTestHelper.createBrokerMock(); - _securityManager = mock(SecurityManager.class); - when(_broker.getTaskExecutor()).thenReturn(_executor); - when(_broker.getSecurityManager()).thenReturn(_securityManager); - final Map attributesMap = new HashMap(); - attributesMap.put(AuthenticationProvider.NAME, getTestName()); - attributesMap.put(AuthenticationProvider.ID, UUID.randomUUID()); - _authManager = new ScramSHA1AuthenticationManager(attributesMap, _broker); - _authManager.open(); } @Override - public void tearDown() throws Exception - { - _executor.stop(); - super.tearDown(); - } - - public void testMechanisms() + protected ConfigModelPasswordManagingAuthenticationProvider createAuthManager(final Map attributesMap) { - SubjectCreator insecureCreator = _authManager.getSubjectCreator(false); - assertFalse("PLAIN authentication should not be available on an insecure connection", insecureCreator.getMechanisms().contains("PLAIN")); - SubjectCreator secureCreator = _authManager.getSubjectCreator(true); - assertTrue("PLAIN authentication should be available on a secure connection", secureCreator.getMechanisms().contains("PLAIN")); - - try - { - SaslServer saslServer = secureCreator.createSaslServer("PLAIN", "127.0.0.1", null); - assertNotNull(saslServer); - } - catch (SaslException e) - { - fail("Unable to create a SaslServer for PLAIN authentication on a secure connection" + e.getMessage()); - } - - try - { - SaslServer saslServer = insecureCreator.createSaslServer("PLAIN", "127.0.0.1", null); - fail("Erroneously created a SaslServer for PLAIN authentication on an insecure connection"); - } - catch (SaslException e) - { - // Pass - } - + return new ScramSHA1AuthenticationManager(attributesMap, getBroker()); } - public void testAddChildAndThenDelete() + @Override + protected boolean isPlain() { - // No children should be present before the test starts - assertEquals("No users should be present before the test starts", 0, _authManager.getChildren(User.class).size()); - assertEquals("No users should be present before the test starts", 0, _authManager.getUsers().size()); - - final Map childAttrs = new HashMap(); - - childAttrs.put(User.NAME, getTestName()); - childAttrs.put(User.PASSWORD, "password"); - User user = _authManager.addChild(User.class, childAttrs); - assertNotNull("User should be created but addChild returned null", user); - assertEquals(getTestName(), user.getName()); - // password shouldn't actually be the given string, but instead salt and the hashed value - assertFalse("Password shouldn't actually be the given string, but instead salt and the hashed value", "password".equals(user.getPassword())); - - AuthenticationResult authResult = - _authManager.authenticate(getTestName(), "password"); - - assertEquals("User should authenticate with given password", AuthenticationResult.AuthenticationStatus.SUCCESS, authResult.getStatus()); - - assertEquals("Manager should have exactly one user child",1, _authManager.getChildren(User.class).size()); - assertEquals("Manager should have exactly one user child",1, _authManager.getUsers().size()); - - - user.delete(); - - assertEquals("No users should be present after child deletion", 0, _authManager.getChildren(User.class).size()); - - - authResult = _authManager.authenticate(getTestName(), "password"); - assertEquals("User should no longer authenticate with given password", AuthenticationResult.AuthenticationStatus.ERROR, authResult.getStatus()); - + return false; } - public void testCreateUser() + @Override + public void tearDown() throws Exception { - assertEquals("No users should be present before the test starts", 0, _authManager.getChildren(User.class).size()); - assertTrue(_authManager.createUser(getTestName(), "password", Collections.emptyMap())); - assertEquals("Manager should have exactly one user child",1, _authManager.getChildren(User.class).size()); - User user = _authManager.getChildren(User.class).iterator().next(); - assertEquals(getTestName(), user.getName()); - // password shouldn't actually be the given string, but instead salt and the hashed value - assertFalse("Password shouldn't actually be the given string, but instead salt and the hashed value", "password".equals(user.getPassword())); - final Map childAttrs = new HashMap(); - - childAttrs.put(User.NAME, getTestName()); - childAttrs.put(User.PASSWORD, "password"); - try - { - user = _authManager.addChild(User.class, childAttrs); - fail("Should not be able to create a second user with the same name"); - } - catch(IllegalArgumentException e) - { - // pass - } - try - { - _authManager.deleteUser(getTestName()); - } - catch (AccountNotFoundException e) - { - fail("AccountNotFoundException thrown when none was expected: " + e.getMessage()); - } - try - { - _authManager.deleteUser(getTestName()); - fail("AccountNotFoundException not thrown when was expected"); - } - catch (AccountNotFoundException e) - { - // pass - } + super.tearDown(); } - public void testUpdateUser() - { - assertTrue(_authManager.createUser(getTestName(), "password", Collections.emptyMap())); - assertTrue(_authManager.createUser(getTestName()+"_2", "password", Collections.emptyMap())); - assertEquals("Manager should have exactly two user children",2, _authManager.getChildren(User.class).size()); - - AuthenticationResult authResult = _authManager.authenticate(getTestName(), "password"); - - assertEquals("User should authenticate with given password", AuthenticationResult.AuthenticationStatus.SUCCESS, authResult.getStatus()); - authResult = _authManager.authenticate(getTestName()+"_2", "password"); - assertEquals("User should authenticate with given password", AuthenticationResult.AuthenticationStatus.SUCCESS, authResult.getStatus()); - - for(User user : _authManager.getChildren(User.class)) - { - if(user.getName().equals(getTestName())) - { - user.setAttributes(Collections.singletonMap(User.PASSWORD, "newpassword")); - } - } - - authResult = _authManager.authenticate(getTestName(), "newpassword"); - assertEquals("User should authenticate with updated password", AuthenticationResult.AuthenticationStatus.SUCCESS, authResult.getStatus()); - authResult = _authManager.authenticate(getTestName()+"_2", "password"); - assertEquals("User should authenticate with original password", AuthenticationResult.AuthenticationStatus.SUCCESS, authResult.getStatus()); - - authResult = _authManager.authenticate(getTestName(), "password"); - assertEquals("User not authenticate with original password", AuthenticationResult.AuthenticationStatus.ERROR, authResult.getStatus()); - - for(User user : _authManager.getChildren(User.class)) - { - if(user.getName().equals(getTestName())) - { - user.setPassword("newerpassword"); - } - } - - authResult = _authManager.authenticate(getTestName(), "newerpassword"); - assertEquals("User should authenticate with updated password", AuthenticationResult.AuthenticationStatus.SUCCESS, authResult.getStatus()); - - - - } public void testNonASCIIUser() { try { - _authManager.createUser(getTestName()+Character.toString((char)0xa3), "password", Collections.emptyMap()); + getAuthManager().createUser(getTestName() + Character.toString((char) 0xa3), + "password", + Collections.emptyMap()); fail("Expected exception when attempting to create a user with a non ascii name"); } catch(IllegalArgumentException e) diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/sasl/CRAMMD5HexInitialiserTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/sasl/CRAMMD5HexInitialiserTest.java index 3079222b1c..52bf6a39d7 100644 --- a/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/sasl/CRAMMD5HexInitialiserTest.java +++ b/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/sasl/CRAMMD5HexInitialiserTest.java @@ -28,6 +28,7 @@ import java.security.NoSuchAlgorithmException; import javax.security.auth.callback.Callback; import javax.security.auth.callback.NameCallback; import javax.security.auth.callback.PasswordCallback; +import javax.xml.bind.DatatypeConverter; import junit.framework.TestCase; @@ -35,7 +36,6 @@ import org.apache.qpid.server.security.auth.database.Base64MD5PasswordFilePrinci 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. @@ -73,7 +73,13 @@ public class CRAMMD5HexInitialiserTest extends TestCase public void setUp() throws Exception { super.setUp(); - _file = TestFileUtils.createTempFile(this, "password-file", new Passwd().getOutput(TEST_USER , TEST_PASSWORD)); + + MessageDigest md = MessageDigest.getInstance("MD5"); + + md.update(TEST_PASSWORD.getBytes("utf-8")); + + _file = TestFileUtils.createTempFile(this, "password-file", + TEST_USER + ":" + DatatypeConverter.printBase64Binary(md.digest())); } public void tearDown() throws Exception diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/store/BrokerRecovererTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/store/BrokerRecovererTest.java index c220876a23..f4802481cb 100644 --- a/java/broker-core/src/test/java/org/apache/qpid/server/store/BrokerRecovererTest.java +++ b/java/broker-core/src/test/java/org/apache/qpid/server/store/BrokerRecovererTest.java @@ -34,7 +34,6 @@ import java.util.UUID; import junit.framework.TestCase; import org.apache.qpid.server.BrokerOptions; -import org.apache.qpid.server.configuration.IllegalConfigurationException; import org.apache.qpid.server.configuration.updater.CurrentThreadTaskExecutor; import org.apache.qpid.server.configuration.updater.TaskExecutor; import org.apache.qpid.server.logging.EventLogger; @@ -261,7 +260,7 @@ public class BrokerRecovererTest extends TestCase resolveObjects(_brokerEntry); Broker broker = _systemConfig.getBroker(); broker.open(); - verify(_brokerShutdownProvider).shutdown(); + verify(_brokerShutdownProvider).shutdown(1); } } @@ -280,7 +279,7 @@ public class BrokerRecovererTest extends TestCase Broker broker = (Broker) recover.resolve(); broker.open(); - verify(_brokerShutdownProvider).shutdown(); + verify(_brokerShutdownProvider).shutdown(1); } public void testIncorrectModelVersion() throws Exception @@ -298,7 +297,7 @@ public class BrokerRecovererTest extends TestCase _systemConfig.getObjectFactory().recover(_brokerEntry, _systemConfig); Broker broker = (Broker) recover.resolve(); broker.open(); - verify(_brokerShutdownProvider).shutdown(); + verify(_brokerShutdownProvider).shutdown(1); reset(_brokerShutdownProvider); } } diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/transport/TCPandSSLTransportTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/transport/TCPandSSLTransportTest.java new file mode 100644 index 0000000000..d8471e5384 --- /dev/null +++ b/java/broker-core/src/test/java/org/apache/qpid/server/transport/TCPandSSLTransportTest.java @@ -0,0 +1,180 @@ +/* + * + * 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.transport; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.ByteArrayInputStream; +import java.net.InetAddress; +import java.security.KeyStore; +import java.util.Arrays; +import java.util.HashSet; + +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLHandshakeException; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.TrustManagerFactory; +import javax.xml.bind.DatatypeConverter; + +import org.apache.qpid.server.model.Protocol; +import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.model.port.AmqpPort; +import org.apache.qpid.test.utils.QpidTestCase; + +public class TCPandSSLTransportTest extends QpidTestCase +{ + + public void testNoSSLv3SupportOnSSLOnlyPort() throws Exception + { + try + { + checkSSLExcluded("SSLv3", Transport.SSL); + fail("Should not be able to connect using SSLv3"); + } + catch(SSLHandshakeException e) + { + // pass + } + } + + + public void testNoSSLv3SupportOnSharedPort() throws Exception + { + try + { + checkSSLExcluded("SSLv3", Transport.TCP, Transport.SSL); + fail("Should not be able to connect using SSLv3"); + } + catch(SSLHandshakeException e) + { + // pass + } + } + + + public void testTLSSupportOnSharedPort() throws Exception + { + try + { + checkSSLExcluded("TLSv1.1", Transport.TCP, Transport.SSL); + } + catch(SSLHandshakeException e) + { + // pass + fail("Should be able to connect using TLSv1.1"); + + } + } + + + + private void checkSSLExcluded(String clientProtocol, final Transport... transports) throws Exception + { + KeyStore keyStore = KeyStore.getInstance("JKS"); + keyStore.load(new ByteArrayInputStream(DatatypeConverter.parseBase64Binary(keystoreString)), "password".toCharArray()); + + + final SSLContext sslContext = SSLContext.getInstance("TLS"); + KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + kmf.init(keyStore, "password".toCharArray()); + + sslContext.init(kmf.getKeyManagers(), null, null); + + + + final AmqpPort port = mock(AmqpPort.class); + when(port.getPort()).thenReturn(0); + when(port.getSendBufferSize()).thenReturn(64*1024); + when(port.getReceiveBufferSize()).thenReturn(64*1024); + + TCPandSSLTransport transport = new TCPandSSLTransport(new HashSet<>(Arrays.asList(transports)), + sslContext, + port, + new HashSet<>(Arrays.asList(Protocol.AMQP_0_8, + Protocol.AMQP_0_9, + Protocol.AMQP_0_9_1, + Protocol.AMQP_0_10, + Protocol.AMQP_1_0)), + Protocol.AMQP_0_9_1); + + transport.start(); + + SSLContext clientContext = SSLContext.getInstance("TLS"); + TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + tmf.init(keyStore); + + clientContext.init(null, tmf.getTrustManagers(), null); + + + SSLSocket sslSocket = + (SSLSocket) clientContext.getSocketFactory().createSocket(InetAddress.getLoopbackAddress(), + transport.getAcceptingPort()); + + sslSocket.setEnabledProtocols(new String[] {clientProtocol}); + + sslSocket.startHandshake(); + transport.close(); + } + + // self signed cert keystore valid until Oct 2024 + private static String keystoreString = "/u3+7QAAAAIAAAABAAAAAQAKc2VsZnNpZ25lZAAAAUkYmo+uAAAFATCCBP0wDgYKKwYBBAEqAhEB" + + "AQUABIIE6bR+b7FHo2BRT/WG+zDIfO8zOXoGIbuNL2znNMnvEp9xwfMQOkhKxEbVtX8uJ7HSwi1V" + + "bV2it0CA59sgvRt9awmgg+W1CLgkGKNOB+kQZbjL8R8lXmKibw4yU/EFm5rqDqPEXBRBj40TF0aT" + + "GtCCmmLPsH2pGU1wH2Ne/tozk8q7hYK6XMH/i43ZXhS9V2CKzPWrzhXmvjFKCtmYHNLj5nLLE/n0" + + "snqAssBoFSAJKmqkqHQBJNQjm4oqJFSISB8pwDX++0kvOMM7j5ryjVwihsCYuHZ6lh5BntDGF41L" + + "f4XADfv3Fma6nZQKfKs0VU2kAWUmjPpyV1FFq/ua4x6SUdZKS22YIQ3t6iO76TDABbQNyUX+Ge4n" + + "k6clF8MFswKTT0ug7zjb17d36gwl+UznvFqMSE6Zkrr9nNAcSVlQS+JaazXveiVEXTBYCAZgsNw3" + + "3KqlLWliAegnwQCQLOguw7bgusnZ/E61/TL8GTryiwN1mltbnsWkCjMj1AGUBM3sYNwbj87Vdhij" + + "iHJbjcB7q3Dak68khrCTLmqoD43KHBB5g+UMlruXYbE0elWqYpXGjI5cvt4gzfh1V+ira5DOfa4B" + + "Qskv/dh1uj2xAe1YEvF3xmdO2F6Yuzd88VO0aaPGroYPfRmh2M6rEOlwc2Ku/p23FjSWrLyzori8" + + "8/OKV4PM2b/NtY51ztTKWR/eUdX6qTPUJMK5CJiOxKGxk9PDtmsbQY685H6QVDKzTkbaPlP97+Oa" + + "xv3/2RIWR7KJzsxbqiYhX0fevRJw/RY6ZY3NEE5RAmCjzxD+1qDtu0QM/LspgPxyv5oSInAtT23U" + + "BrcNIiQ8jO+6E+fDcVhFSrs6gLGe1BwKYHsosjvup8FETLZgqKY6g1mwECA/Un2agzhI4tGC0O8v" + + "lU4VEZKrXwgy/XQ5C2vwwgLvJh94OfE20Wuf7Jjq8IUPcdF201XeYREE/vSNcBnJf22yPouJMIPk" + + "yNxlAHcapeFUi00yC19FEIpdoW/8pX2k64jx63CwwVckWWOIWlg8N+z9jsiwdjvm5wL2aFU3+wtu" + + "8Nj6Soy7Y3QYAwx17q/nUOJOk5DqLedG+/DKXVs5jghmbQ9wyzqGjGs+xYvSCXtQJygETUU/ddoM" + + "/iK4hhnZL2uqZ0wamef4ibdBbhpoRO8C7mSbi7TbDtcfysZrMb6i5MugR+NwKKzN2DznXItvpgzc" + + "Xm9j7LP8HZcQANa+1o2aIGDqK1fMSAOmBbTWlYkHPDbpoE/lx32iBNL/Aj8aKbtkwy/J2JRvo9m2" + + "uBdLK4DoDeTjqG//AwISrwm9y6xxIIPNQq7GiftN6p9KCI87U5pxqs5yUQ1g/e9DCioLe8O3Vug7" + + "+1jS1ZHWFtb4BBEF3EhkKa1AOVKNu9+M8lcG9tKWUBjnIFTD68a++6B36ShRnIZNbmbRkLC6wWdB" + + "SdyI6FWPxsPvGSF+3wq+n+0bu75N3Xsta5tEOjc67DfnQlyZtP/BIZsKxgEueOcXkjzaXMPYcrlJ" + + "2BInovQSHnSHvQfaBKqj/nKcGaDyydfdxF5fyjRPFYF+fFCWXrFkbQgAst8ymJ//UpLomfw+Ni6f" + + "xx2XQGt3941zhRuXJI2tdvUb2Czzsp0tq+h46d0WOlYQ57Q70weUQRrtARqCKoSp/gNUzQsvd+FO" + + "sUUxKRoJltRYBwAAAAEABVguNTA5AAADdTCCA3EwggJZoAMCAQICBBAXeI4wDQYJKoZIhvcNAQEL" + + "BQAwaDELMAkGA1UEBhMCVUsxETAPBgNVBAgTCFNjb3RsYW5kMRAwDgYDVQQHEwdHbGFzZ293MQ8w" + + "DQYDVQQKEwZBcGFjaGUxDTALBgNVBAsTBFFwaWQxFDASBgNVBAMTC0FwYWNoZSBRcGlkMCAXDTE0" + + "MTAxNjEwNTY1NVoYDzIxMTMwNTEwMTA1NjU1WjBoMQswCQYDVQQGEwJVSzERMA8GA1UECBMIU2Nv" + + "dGxhbmQxEDAOBgNVBAcTB0dsYXNnb3cxDzANBgNVBAoTBkFwYWNoZTENMAsGA1UECxMEUXBpZDEU" + + "MBIGA1UEAxMLQXBhY2hlIFFwaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC520Yd" + + "1GuXh67h7HawvL5/pwTr46P45R0gx+LDGC1Equ9/wvvsVbCPL0JLDTSKl0qpgbJNMH/A740vSilb" + + "FDdqfyOuIkQZN1Ub9CkOaI5uR9RjaC2MfyNUJl7Gp64nSYk9iDX15ddZjsAijUDvET32XzfirlML" + + "dwLXv1Y5dLskV0r6xK4NdLtXi+Ndn+Uy4EllD7VMIFaLt6oG9Vo6mNl0jze7Yz/aYYtWns4x+uG8" + + "WbMgtcXo/VxCyp+4ji06XFerwfkS0zBS1wfvxd5Qb1+4dYovSn1v0AaPvZ0XwG4XErP2/svU01nc" + + "C43Z4neHdsj8Y/kmXLDD8Nc7Mpv/Wm6hAgMBAAGjITAfMB0GA1UdDgQWBBQfKBRPr/QD7PjpM3s4" + + "rD8u6ZxiijANBgkqhkiG9w0BAQsFAAOCAQEAFjyjJ8pbHf6MioZpOOlZh4lz6F+9dW1KyJR0OIc4" + + "FXnYnU/CNzjkwPminuZJoYgXBh+sVFN238YFS3I8ONEQJy8uSH33T81sklXhqnrSk9OlWk1v60wH" + + "NwwNFz5ZuGrGlvk9EFhbC8FgdkXJbz21drAl18i2oJHPdQQNwdc6mwqhpNfjqZ2opfJPbVscX1P/" + + "dbJjfcoZ01fy5687zjpN11G4egwsrya2FZiAw1WPI10OhrJgiGL5aDiDLjauNZmoM7QchUUD1cjE" + + "EwvRkU1MesliLg4y3UqDoV6ooHB4ClE2aKmIdbVB/eP1QrEEkey93ptt1z5fLk1l408AkXQtzyw7" + + "9WC+xnZta0IoYC/vO29IVsok"; +} diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java b/java/broker-core/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java index 8573ae3a42..0bee92a2e9 100644 --- a/java/broker-core/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java +++ b/java/broker-core/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java @@ -28,6 +28,8 @@ import static org.mockito.Mockito.when; import java.net.SocketAddress; import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -110,17 +112,28 @@ public class BrokerTestHelper } public static VirtualHostImpl createVirtualHost(Map attributes) - throws Exception { Broker broker = createBrokerMock(); + return createVirtualHost(attributes, broker); + } + + public static VirtualHostImpl createVirtualHost(final Map attributes, + final Broker broker) + { ConfiguredObjectFactory objectFactory = broker.getObjectFactory(); VirtualHostNode virtualHostNode = mock(VirtualHostNode.class); + when(virtualHostNode.getName()).thenReturn((String) attributes.get(VirtualHostNode.NAME)); when(virtualHostNode.getTaskExecutor()).thenReturn(TASK_EXECUTOR); when(virtualHostNode.getParent(eq(Broker.class))).thenReturn(broker); + Collection> nodes = broker.getVirtualHostNodes(); + nodes = new ArrayList<>(nodes != null ? nodes : Collections.>emptyList()); + nodes.add(virtualHostNode); + when(broker.getVirtualHostNodes()).thenReturn(nodes); + DurableConfigurationStore dcs = mock(DurableConfigurationStore.class); when(virtualHostNode.getConfigurationStore()).thenReturn(dcs); when(virtualHostNode.getParent(eq(VirtualHostNode.class))).thenReturn(virtualHostNode); @@ -128,19 +141,26 @@ public class BrokerTestHelper when(virtualHostNode.getObjectFactory()).thenReturn(objectFactory); when(virtualHostNode.getCategoryClass()).thenReturn(VirtualHostNode.class); when(virtualHostNode.getTaskExecutor()).thenReturn(TASK_EXECUTOR); - AbstractVirtualHost host = (AbstractVirtualHost) objectFactory.create(VirtualHost.class, attributes, virtualHostNode ); + AbstractVirtualHost + host = (AbstractVirtualHost) objectFactory.create(VirtualHost.class, attributes, virtualHostNode ); host.start(); - + when(virtualHostNode.getVirtualHost()).thenReturn(host); return host; } + public static VirtualHostImpl createVirtualHost(String name) throws Exception + { + return createVirtualHost(name, createBrokerMock()); + } + + public static VirtualHostImpl createVirtualHost(String name, Broker broker) throws Exception { Map attributes = new HashMap(); attributes.put(org.apache.qpid.server.model.VirtualHost.TYPE, TestMemoryVirtualHost.VIRTUAL_HOST_TYPE); attributes.put(org.apache.qpid.server.model.VirtualHost.NAME, name); - return createVirtualHost(attributes); + return createVirtualHost(attributes, broker); } public static AMQSessionModel createSession(int channelId, AMQConnectionModel connection) diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/virtualhostalias/VirtualHostAliasTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/virtualhostalias/VirtualHostAliasTest.java new file mode 100644 index 0000000000..1a7e2cdc0d --- /dev/null +++ b/java/broker-core/src/test/java/org/apache/qpid/server/virtualhostalias/VirtualHostAliasTest.java @@ -0,0 +1,206 @@ +/* + * + * 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.virtualhostalias; + +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import org.apache.qpid.server.model.AuthenticationProvider; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ConfiguredObjectFactory; +import org.apache.qpid.server.model.PatternMatchingAlias; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.model.VirtualHostAlias; +import org.apache.qpid.server.model.VirtualHostNode; +import org.apache.qpid.server.model.port.AmqpPort; +import org.apache.qpid.server.util.BrokerTestHelper; +import org.apache.qpid.server.virtualhost.VirtualHostImpl; +import org.apache.qpid.test.utils.QpidTestCase; + +public class VirtualHostAliasTest extends QpidTestCase +{ + private Broker _broker; + private Map> _vhosts; + private AmqpPort _port; + + @Override + public void setUp() throws Exception + { + super.setUp(); + _broker = BrokerTestHelper.createBrokerMock(); + + AuthenticationProvider dummyAuthProvider = mock(AuthenticationProvider.class); + when(dummyAuthProvider.getName()).thenReturn("dummy"); + when(dummyAuthProvider.getId()).thenReturn(UUID.randomUUID()); + when(_broker.getChildren(eq(AuthenticationProvider.class))).thenReturn(Collections.singleton(dummyAuthProvider)); + _vhosts = new HashMap<>(); + for(String name : new String[] { "red", "blue", "purple", "black" }) + { + _vhosts.put(name, BrokerTestHelper.createVirtualHost(name, _broker)); + } + ConfiguredObjectFactory objectFactory = _broker.getObjectFactory(); + when(_broker.getDefaultVirtualHost()).thenReturn("black"); + + final Map attributes = new HashMap<>(); + attributes.put(Port.NAME, getTestName()); + attributes.put(Port.PORT, findFreePort()); + attributes.put(Port.AUTHENTICATION_PROVIDER, "dummy"); + attributes.put(Port.TYPE, "AMQP"); + _port = (AmqpPort) objectFactory.create(Port.class, attributes, _broker ); + + } + + public void testDefaultAliases() + { + VirtualHostImpl vhost = _port.getVirtualHost("red"); + + assertNotNull(vhost); + assertEquals(_vhosts.get("red"), vhost); + + vhost = _port.getVirtualHost("blue"); + + assertNotNull(vhost); + assertEquals(_vhosts.get("blue"), vhost); + + vhost = _port.getVirtualHost("orange!"); + + assertNull(vhost); + + // test the default vhost resolution + vhost = _port.getVirtualHost(""); + + assertNotNull(vhost); + assertEquals(_vhosts.get("black"), vhost); + + + // 127.0.0.1 should always resolve and thus return the default vhost + vhost = _port.getVirtualHost("127.0.0.1"); + + assertNotNull(vhost); + assertEquals(_vhosts.get("black"), vhost); + + } + + public void testPatternMatching() + { + final Map attributes = new HashMap<>(); + attributes.put(VirtualHostAlias.NAME, "matcher"); + attributes.put(VirtualHostAlias.TYPE, PatternMatchingAlias.TYPE_NAME); + attributes.put(PatternMatchingAlias.PATTERN, "orange|pink.*"); + attributes.put(PatternMatchingAlias.VIRTUAL_HOST_NODE, _vhosts.get("purple").getParent(VirtualHostNode.class)); + _port.createVirtualHostAlias(attributes); + + VirtualHostImpl vhost = _port.getVirtualHost("orange"); + + assertNotNull(vhost); + assertEquals(_vhosts.get("purple"), vhost); + + vhost = _port.getVirtualHost("pink"); + + assertNotNull(vhost); + assertEquals(_vhosts.get("purple"), vhost); + + + vhost = _port.getVirtualHost("pinker"); + + assertNotNull(vhost); + assertEquals(_vhosts.get("purple"), vhost); + + + + vhost = _port.getVirtualHost("o.*"); + + assertNull(vhost); + + } + + public void testPriority() + { + + VirtualHostImpl vhost = _port.getVirtualHost("blue"); + + assertNotNull(vhost); + assertEquals(_vhosts.get("blue"), vhost); + + vhost = _port.getVirtualHost("black"); + + assertNotNull(vhost); + assertEquals(_vhosts.get("black"), vhost); + + + + Map attributes = new HashMap<>(); + attributes.put(VirtualHostAlias.NAME, "matcher10"); + attributes.put(VirtualHostAlias.TYPE, PatternMatchingAlias.TYPE_NAME); + attributes.put(VirtualHostAlias.PRIORITY, 10); + attributes.put(PatternMatchingAlias.PATTERN, "bl.*"); + attributes.put(PatternMatchingAlias.VIRTUAL_HOST_NODE, _vhosts.get("purple").getParent(VirtualHostNode.class)); + _port.createVirtualHostAlias(attributes); + + vhost = _port.getVirtualHost("blue"); + + assertNotNull(vhost); + assertEquals(_vhosts.get("purple"), vhost); + + vhost = _port.getVirtualHost("black"); + + assertNotNull(vhost); + assertEquals(_vhosts.get("purple"), vhost); + + + attributes = new HashMap<>(); + attributes.put(VirtualHostAlias.NAME, "matcher5"); + attributes.put(VirtualHostAlias.TYPE, PatternMatchingAlias.TYPE_NAME); + attributes.put(VirtualHostAlias.PRIORITY, 5); + attributes.put(PatternMatchingAlias.PATTERN, ".*u.*"); + attributes.put(PatternMatchingAlias.VIRTUAL_HOST_NODE, _vhosts.get("red").getParent(VirtualHostNode.class)); + _port.createVirtualHostAlias(attributes); + + + + vhost = _port.getVirtualHost("blue"); + + assertNotNull(vhost); + assertEquals(_vhosts.get("red"), vhost); + + vhost = _port.getVirtualHost("black"); + + assertNotNull(vhost); + assertEquals(_vhosts.get("purple"), vhost); + + + + vhost = _port.getVirtualHost("purple"); + + assertNotNull(vhost); + assertEquals(_vhosts.get("red"), vhost); + + + + } +} diff --git a/java/broker-core/src/test/java/org/apache/qpid/tools/security/PasswdTest.java b/java/broker-core/src/test/java/org/apache/qpid/tools/security/PasswdTest.java deleted file mode 100644 index b2a7234c8a..0000000000 --- a/java/broker-core/src/test/java/org/apache/qpid/tools/security/PasswdTest.java +++ /dev/null @@ -1,38 +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.tools.security; - -import junit.framework.TestCase; - -public class PasswdTest extends TestCase -{ - public void testUserGuestAndPasswordGuest() throws Exception - { - Passwd passwd = new Passwd(); - String output = passwd.getOutput("guest", "guest"); - assertEquals("guest:CE4DQ6BIb/BVMN9scFyLtA==", output); - } - - public void testUser1AndPasswordFoo() throws Exception - { - Passwd passwd = new Passwd(); - String output = passwd.getOutput("user1", "foo"); - assertEquals("user1:rL0Y20zC+Fzt72VPzMSk2A==", output); - } -} diff --git a/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Connection_1_0.java b/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Connection_1_0.java index f97a223f4d..377eaab4cf 100644 --- a/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Connection_1_0.java +++ b/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Connection_1_0.java @@ -130,21 +130,12 @@ public class Connection_1_0 implements ConnectionEventListener, AMQConnectionMod public void openReceived() { String host = _conn.getLocalHostname(); - if(host == null || host.trim().equals("")) - { - host = _broker.getDefaultVirtualHost(); - } - _vhost = ((AmqpPort)_port).getVirtualHost(host); - if(_vhost == null && _port.isLocalMachine(host)) - { - _vhost = ((AmqpPort)_port).getVirtualHost(_broker.getDefaultVirtualHost()); - } if(_vhost == null) { final Error err = new Error(); err.setCondition(AmqpError.NOT_FOUND); - err.setDescription("Unknown hostname " + _conn.getLocalHostname()); + err.setDescription("Unknown hostname in connection open: '" + host + "'"); _conn.close(err); _closedOnOpen = true; } diff --git a/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/store/derby/DerbyUtils.java b/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/store/derby/DerbyUtils.java index 9bdce9af1c..b3c449747b 100644 --- a/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/store/derby/DerbyUtils.java +++ b/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/store/derby/DerbyUtils.java @@ -32,7 +32,6 @@ import java.sql.ResultSet; import java.sql.SQLException; import org.apache.qpid.server.store.StoreException; -import org.apache.qpid.util.FileUtils; public class DerbyUtils { diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java index 936cc4789a..6e104f844f 100644 --- a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java +++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java @@ -74,6 +74,7 @@ import org.apache.qpid.server.model.port.HttpPort; import org.apache.qpid.server.model.port.PortManager; import org.apache.qpid.server.util.ServerScopedRuntimeException; import org.apache.qpid.transport.network.security.ssl.QpidMultipleTrustManager; +import org.apache.qpid.transport.network.security.ssl.SSLUtil; @ManagedObject( category = false, type = "MANAGEMENT-HTTP" ) public class HttpManagement extends AbstractPluginAdapter implements HttpManagementConfiguration, PortManager @@ -317,7 +318,7 @@ public class HttpManagement extends AbstractPluginAdapter implem throw new IllegalConfigurationException("Key store is not configured. Cannot start management on HTTPS port without keystore"); } SslContextFactory factory = new SslContextFactory(); - + factory.addExcludeProtocols(SSLUtil.SSLV3_PROTOCOL); boolean needClientCert = port.getNeedClientAuth() || port.getWantClientAuth(); if (needClientCert && trustStores.isEmpty()) diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/ConfiguredObjectToMapConverter.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/ConfiguredObjectToMapConverter.java index 7bde933bb9..7d86bd3c8c 100644 --- a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/ConfiguredObjectToMapConverter.java +++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/ConfiguredObjectToMapConverter.java @@ -268,7 +268,8 @@ public class ConfiguredObjectToMapConverter if (!childObjects.isEmpty()) { - object.put(childClass.getSimpleName().toLowerCase() + "s", childObjects); + String childTypeSingular = childClass.getSimpleName().toLowerCase(); + object.put(childTypeSingular + (childTypeSingular.endsWith("s") ? "es" : "s"), childObjects); } } } diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js index a439e0512a..8da0bafd06 100644 --- a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js +++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js @@ -152,7 +152,8 @@ define(["dojo/_base/xhr", util.isProviderManagingUsers = function(type) { - return (type === "PlainPasswordFile" || type === "Base64MD5PasswordFile" || type === "SCRAM-SHA-1" || type === "SCRAM-SHA-256"); + return (type === "PlainPasswordFile" || type === "Base64MD5PasswordFile" || type === "SCRAM-SHA-1" + || type === "SCRAM-SHA-256" || type === "Plain" || type === "MD5" ); }; util.showSetAttributesDialog = function(attributeWidgetFactories, data, putURL, dialogTitle, category, type, appendNameToUrl) diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/AuthenticationProvider.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/AuthenticationProvider.js index 34e3516180..0653c8fad7 100644 --- a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/AuthenticationProvider.js +++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/AuthenticationProvider.js @@ -139,6 +139,7 @@ define(["dojo/_base/xhr", this.editPreferencesProviderButton = query(".editPreferencesProviderButton", node)[0]; this.deletePreferencesProviderButton = query(".deletePreferencesProviderButton", node)[0]; this.preferencesProviderAttributes = dom.byId("preferencesProviderAttributes") + this.preferencesNode = query(".preferencesProviderDetails", node)[0]; this.query = "api/latest/authenticationprovider/" + encodeURIComponent(authProviderObj.name); @@ -171,7 +172,7 @@ define(["dojo/_base/xhr", else { var preferencesProviderData = that.authProviderData.preferencesproviders? that.authProviderData.preferencesproviders[0]: null; - that.preferencesNode = query(".preferencesProviderDetails", node)[0]; + that.updatePreferencesProvider(preferencesProviderData); } }); diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/QpidSslRMIServerSocketFactory.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/QpidSslRMIServerSocketFactory.java index b0f5abd1a3..5c15a40427 100644 --- a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/QpidSslRMIServerSocketFactory.java +++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/QpidSslRMIServerSocketFactory.java @@ -30,6 +30,8 @@ import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; import javax.rmi.ssl.SslRMIServerSocketFactory; +import org.apache.qpid.transport.network.security.ssl.SSLUtil; + public class QpidSslRMIServerSocketFactory extends SslRMIServerSocketFactory { private final SSLContext _sslContext; @@ -74,7 +76,7 @@ public class QpidSslRMIServerSocketFactory extends SslRMIServerSocketFactory socket.getPort(), true); sslSocket.setUseClientMode(false); - + SSLUtil.removeSSLv3Support(sslSocket); return sslSocket; } }; diff --git a/java/broker-plugins/websocket/src/main/java/org/apache/qpid/server/transport/websocket/WebSocketProvider.java b/java/broker-plugins/websocket/src/main/java/org/apache/qpid/server/transport/websocket/WebSocketProvider.java index d989a73fa2..8e250ef669 100644 --- a/java/broker-plugins/websocket/src/main/java/org/apache/qpid/server/transport/websocket/WebSocketProvider.java +++ b/java/broker-plugins/websocket/src/main/java/org/apache/qpid/server/transport/websocket/WebSocketProvider.java @@ -32,8 +32,6 @@ import java.util.Set; import javax.net.ssl.SSLContext; import javax.servlet.http.HttpServletRequest; -import org.apache.qpid.server.model.port.AmqpPort; -import org.apache.qpid.server.model.port.HttpPort; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.nio.SelectChannelConnector; @@ -48,11 +46,14 @@ import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.Protocol; import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.model.port.AmqpPort; +import org.apache.qpid.server.model.port.HttpPort; import org.apache.qpid.server.protocol.MultiVersionProtocolEngineFactory; import org.apache.qpid.server.transport.AcceptingTransport; import org.apache.qpid.server.util.ServerScopedRuntimeException; import org.apache.qpid.transport.Sender; import org.apache.qpid.transport.network.NetworkConnection; +import org.apache.qpid.transport.network.security.ssl.SSLUtil; class WebSocketProvider implements AcceptingTransport { @@ -103,6 +104,7 @@ class WebSocketProvider implements AcceptingTransport { SslContextFactory factory = new SslContextFactory(); factory.setSslContext(_sslContext); + factory.addExcludeProtocols(SSLUtil.SSLV3_PROTOCOL); factory.setNeedClientAuth(true); connector = new SslSelectChannelConnector(factory); } diff --git a/java/broker-plugins/websocket/src/main/java/org/apache/qpid/server/transport/websocket/WebSocketTransportProvider.java b/java/broker-plugins/websocket/src/main/java/org/apache/qpid/server/transport/websocket/WebSocketTransportProvider.java index 346e29e212..c7578adb91 100644 --- a/java/broker-plugins/websocket/src/main/java/org/apache/qpid/server/transport/websocket/WebSocketTransportProvider.java +++ b/java/broker-plugins/websocket/src/main/java/org/apache/qpid/server/transport/websocket/WebSocketTransportProvider.java @@ -24,9 +24,9 @@ import java.util.Set; import javax.net.ssl.SSLContext; -import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.Protocol; import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.model.port.AmqpPort; import org.apache.qpid.server.transport.AcceptingTransport; import org.apache.qpid.server.transport.TransportProvider; @@ -39,7 +39,7 @@ class WebSocketTransportProvider implements TransportProvider @Override public AcceptingTransport createTransport(final Set transports, final SSLContext sslContext, - final Port port, + final AmqpPort port, final Set supported, final Protocol defaultSupportedProtocolReply) { diff --git a/java/broker/bin/qpid-passwd b/java/broker/bin/qpid-passwd deleted file mode 100755 index 07b7db0cd3..0000000000 --- a/java/broker/bin/qpid-passwd +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env bash -# -# 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. -# - -if [ -z "$QPID_HOME" ]; then - WHEREAMI=`dirname "$0"` - export QPID_HOME=`cd "$WHEREAMI/../" && pwd` -fi - -# Set classpath to include jars from lib dir -QPID_LIBS=$QPID_HOME/lib/* - -# Set other variables used by the qpid-run script before calling -export JAVA=java \ - JAVA_VM=-server \ - JAVA_MEM=-Xmx1024m \ - QPID_CLASSPATH=$QPID_LIBS - -. "${QPID_HOME}/bin/qpid-run" org.apache.qpid.tools.security.Passwd "$@" diff --git a/java/broker/src/main/java/org/apache/qpid/server/Main.java b/java/broker/src/main/java/org/apache/qpid/server/Main.java index d6b8a25b8a..76f8485884 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/Main.java +++ b/java/broker/src/main/java/org/apache/qpid/server/Main.java @@ -454,7 +454,7 @@ public class Main protected void startBroker(final BrokerOptions options) throws Exception { - Broker broker = new Broker(); + Broker broker = new Broker(true); broker.startup(options); } diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java b/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java index 6b3b4601d9..d9298abd0f 100644 --- a/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java +++ b/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java @@ -81,7 +81,8 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect private static final Logger _logger = LoggerFactory.getLogger(AMQConnection.class); private static final AtomicLong CONN_NUMBER_GENERATOR = new AtomicLong(); - private static final long DEFAULT_CLOSE_TIMEOUT = 2000l; + private static final long DEFAULT_CLOSE_TIMEOUT = Long.getLong(ClientProperties.QPID_CLOSE_TIMEOUT, + ClientProperties.DEFAULT_CLOSE_TIMEOUT); private final long _connectionNumber; @@ -880,44 +881,19 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect { try { - long startCloseTime = System.currentTimeMillis(); - - closeAllSessions(null, timeout, startCloseTime); - - //This MUST occur after we have successfully closed all Channels/Sessions - _taskPool.shutdown(); - - if (!_taskPool.isTerminated()) + try { - try - { - // adjust timeout - long taskPoolTimeout = adjustTimeout(timeout, startCloseTime); - - _taskPool.awaitTermination(taskPoolTimeout, TimeUnit.MILLISECONDS); - } - catch (InterruptedException e) - { - _logger.info("Interrupted while shutting down connection thread pool."); - } + closeAllSessions(null, timeout); } - - // adjust timeout - timeout = adjustTimeout(timeout, startCloseTime); - //If the taskpool hasn't shutdown by now then give it shutdownNow. - // This will interupt any running tasks. - if (!_taskPool.isTerminated()) + finally { - List tasks = _taskPool.shutdownNow(); - for (Runnable r : tasks) - { - _logger.warn("Connection close forced taskpool to prevent execution:" + r); - } + //This MUST occur after we have successfully closed all Channels/Sessions + shutdownTaskPool(timeout); } } catch (JMSException e) { - _logger.error("error:", e); + _logger.error("Error closing connection", e); JMSException jmse = new JMSException("Error closing connection: " + e); jmse.setLinkedException(e); jmse.initCause(e); @@ -939,16 +915,32 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect } } - private long adjustTimeout(long timeout, long startTime) + private void shutdownTaskPool(final long timeout) { - long now = System.currentTimeMillis(); - timeout -= now - startTime; - if (timeout < 0) + _taskPool.shutdown(); + + if (!_taskPool.isTerminated()) { - timeout = 0; + try + { + _taskPool.awaitTermination(timeout, TimeUnit.MILLISECONDS); + } + catch (InterruptedException e) + { + _logger.info("Interrupted while shutting down connection thread pool."); + } } - return timeout; + //If the taskpool hasn't shutdown by now then give it shutdownNow. + // This will interrupt any running tasks. + if (!_taskPool.isTerminated()) + { + List tasks = _taskPool.shutdownNow(); + for (Runnable r : tasks) + { + _logger.warn("Connection close forced taskpool to prevent execution:" + r); + } + } } /** @@ -976,7 +968,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect * @param cause if not null, the error that is causing this shutdown

The caller must hold the failover mutex * before calling this method. */ - private void closeAllSessions(Throwable cause, long timeout, long starttime) throws JMSException + private void closeAllSessions(Throwable cause, long timeout) throws JMSException { final LinkedList sessionCopy = new LinkedList(_sessions.values()); final Iterator it = sessionCopy.iterator(); @@ -992,11 +984,6 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect { try { - if (starttime != -1) - { - timeout = adjustTimeout(timeout, starttime); - } - session.close(timeout); } catch (JMSException e) @@ -1042,7 +1029,6 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect public ConnectionConsumer createDurableConnectionConsumer(Topic topic, String subscriptionName, String messageSelector, ServerSessionPool sessionPool, int maxMessages) throws JMSException { - // TODO Auto-generated method stub checkNotClosed(); throw new JmsNotImplementedException(); @@ -1322,7 +1308,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect { try { - closeAllSessions(cause, -1, -1); // FIXME: when doing this end up with RejectedExecutionException from executor. + closeAllSessions(cause, -1); // FIXME: when doing this end up with RejectedExecutionException from executor. } catch (JMSException e) { @@ -1444,7 +1430,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect public AMQShortString getTemporaryQueueExchangeName() { - return _temporaryQueueExchangeName; // To change body of created methods use File | Settings | File Templates. + return _temporaryQueueExchangeName; } public void setTemporaryTopicExchangeName(AMQShortString temporaryTopicExchangeName) diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_8.java b/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_8.java index 8a15fffe84..d86a2739f2 100644 --- a/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_8.java +++ b/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_8.java @@ -32,6 +32,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.UUID; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import javax.jms.Destination; @@ -96,6 +97,7 @@ public class AMQSession_0_8 extends AMQSession( new FailoverProtectedOperation() diff --git a/java/common/src/main/java/org/apache/qpid/configuration/ClientProperties.java b/java/common/src/main/java/org/apache/qpid/configuration/ClientProperties.java index b29e77f14d..86f5ddeeed 100644 --- a/java/common/src/main/java/org/apache/qpid/configuration/ClientProperties.java +++ b/java/common/src/main/java/org/apache/qpid/configuration/ClientProperties.java @@ -133,6 +133,18 @@ public class ClientProperties */ public static final int DEFAULT_SYNC_OPERATION_TIMEOUT = 60000; + /** + * System properties to change the default timeout used whilst closing connections + * and underlying sessions. + */ + public static final String QPID_CLOSE_TIMEOUT = "qpid.close_timeout"; + + /** + * A default timeout value for close operations + */ + public static final int DEFAULT_CLOSE_TIMEOUT = 2000; + + /** * System properties to change the default value used for TCP_NODELAY */ diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/IncomingNetworkTransport.java b/java/common/src/main/java/org/apache/qpid/transport/network/IncomingNetworkTransport.java index 8437ef1a94..e0cd9cac1a 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/network/IncomingNetworkTransport.java +++ b/java/common/src/main/java/org/apache/qpid/transport/network/IncomingNetworkTransport.java @@ -20,14 +20,16 @@ */ package org.apache.qpid.transport.network; +import javax.net.ssl.SSLContext; + import org.apache.qpid.protocol.ProtocolEngineFactory; import org.apache.qpid.transport.NetworkTransportConfiguration; -import javax.net.ssl.SSLContext; - public interface IncomingNetworkTransport extends NetworkTransport { public void accept(NetworkTransportConfiguration config, ProtocolEngineFactory factory, SSLContext sslContext); -} \ No newline at end of file + + public int getAcceptingPort(); +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkTransport.java b/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkTransport.java index 4ccb88bbf8..068e19fbc4 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkTransport.java +++ b/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkTransport.java @@ -27,12 +27,12 @@ import java.net.ServerSocket; import java.net.Socket; import java.net.SocketException; import java.nio.ByteBuffer; -import java.security.Principal; + import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLPeerUnverifiedException; import javax.net.ssl.SSLServerSocket; import javax.net.ssl.SSLServerSocketFactory; -import javax.net.ssl.SSLSocket; + +import org.slf4j.LoggerFactory; import org.apache.qpid.configuration.CommonProperties; import org.apache.qpid.protocol.ProtocolEngine; @@ -41,9 +41,11 @@ import org.apache.qpid.transport.ConnectionSettings; import org.apache.qpid.transport.NetworkTransportConfiguration; import org.apache.qpid.transport.Receiver; import org.apache.qpid.transport.TransportException; -import org.apache.qpid.transport.network.*; - -import org.slf4j.LoggerFactory; +import org.apache.qpid.transport.network.IncomingNetworkTransport; +import org.apache.qpid.transport.network.NetworkConnection; +import org.apache.qpid.transport.network.OutgoingNetworkTransport; +import org.apache.qpid.transport.network.TransportActivity; +import org.apache.qpid.transport.network.security.ssl.SSLUtil; public class IoNetworkTransport implements OutgoingNetworkTransport, IncomingNetworkTransport { @@ -150,6 +152,11 @@ public class IoNetworkTransport implements OutgoingNetworkTransport, IncomingNet } } + public int getAcceptingPort() + { + return _acceptor == null ? -1 : _acceptor.getPort(); + } + private class AcceptingThread extends Thread { private volatile boolean _closed = false; @@ -179,14 +186,19 @@ public class IoNetworkTransport implements OutgoingNetworkTransport, IncomingNet SSLServerSocketFactory socketFactory = _sslContext.getServerSocketFactory(); _serverSocket = socketFactory.createServerSocket(); + SSLServerSocket sslServerSocket = (SSLServerSocket) _serverSocket; + + SSLUtil.removeSSLv3Support(sslServerSocket); + if(config.needClientAuth()) { - ((SSLServerSocket)_serverSocket).setNeedClientAuth(true); + sslServerSocket.setNeedClientAuth(true); } else if(config.wantClientAuth()) { - ((SSLServerSocket)_serverSocket).setWantClientAuth(true); + sslServerSocket.setWantClientAuth(true); } + } _serverSocket.setReuseAddress(true); @@ -215,6 +227,11 @@ public class IoNetworkTransport implements OutgoingNetworkTransport, IncomingNet } } + private int getPort() + { + return _serverSocket.getLocalPort(); + } + @Override public void run() { diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/security/SecurityLayerFactory.java b/java/common/src/main/java/org/apache/qpid/transport/network/security/SecurityLayerFactory.java index bfd1ae8181..2a2f3d8362 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/network/security/SecurityLayerFactory.java +++ b/java/common/src/main/java/org/apache/qpid/transport/network/security/SecurityLayerFactory.java @@ -20,6 +20,11 @@ */ package org.apache.qpid.transport.network.security; +import java.nio.ByteBuffer; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLEngine; + import org.apache.qpid.ssl.SSLContextFactory; import org.apache.qpid.transport.ConnectionSettings; import org.apache.qpid.transport.Receiver; @@ -31,10 +36,6 @@ import org.apache.qpid.transport.network.security.ssl.SSLReceiver; import org.apache.qpid.transport.network.security.ssl.SSLSender; import org.apache.qpid.transport.network.security.ssl.SSLUtil; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLEngine; -import java.nio.ByteBuffer; - public class SecurityLayerFactory { private SecurityLayerFactory() @@ -100,6 +101,7 @@ public class SecurityLayerFactory { _engine = sslCtx.createSSLEngine(); _engine.setUseClientMode(true); + SSLUtil.removeSSLv3Support(_engine); } catch(Exception e) { diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLUtil.java b/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLUtil.java index 487b0c485b..98229fd2a1 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLUtil.java +++ b/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLUtil.java @@ -30,6 +30,8 @@ import java.security.Principal; import java.security.cert.Certificate; import java.security.cert.CertificateParsingException; import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.SortedSet; import java.util.TreeSet; @@ -39,6 +41,8 @@ import javax.naming.ldap.LdapName; import javax.naming.ldap.Rdn; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLPeerUnverifiedException; +import javax.net.ssl.SSLServerSocket; +import javax.net.ssl.SSLSocket; import org.apache.qpid.transport.TransportException; import org.apache.qpid.transport.util.Logger; @@ -47,6 +51,7 @@ public class SSLUtil { private static final Logger log = Logger.get(SSLUtil.class); private static final Integer DNS_NAME_TYPE = 2; + public static final String SSLV3_PROTOCOL = "SSLv3"; private SSLUtil() { @@ -242,4 +247,38 @@ public class SSLUtil } return ks; } + + public static void removeSSLv3Support(final SSLEngine engine) + { + List enabledProtocols = Arrays.asList(engine.getEnabledProtocols()); + if(enabledProtocols.contains(SSLV3_PROTOCOL)) + { + List allowedProtocols = new ArrayList<>(enabledProtocols); + allowedProtocols.remove(SSLV3_PROTOCOL); + engine.setEnabledProtocols(allowedProtocols.toArray(new String[allowedProtocols.size()])); + } + } + + public static void removeSSLv3Support(final SSLSocket socket) + { + List enabledProtocols = Arrays.asList(socket.getEnabledProtocols()); + if(enabledProtocols.contains(SSLV3_PROTOCOL)) + { + List allowedProtocols = new ArrayList<>(enabledProtocols); + allowedProtocols.remove(SSLV3_PROTOCOL); + socket.setEnabledProtocols(allowedProtocols.toArray(new String[allowedProtocols.size()])); + } + } + + + public static void removeSSLv3Support(final SSLServerSocket socket) + { + List enabledProtocols = Arrays.asList(socket.getEnabledProtocols()); + if(enabledProtocols.contains(SSLV3_PROTOCOL)) + { + List allowedProtocols = new ArrayList<>(enabledProtocols); + allowedProtocols.remove(SSLV3_PROTOCOL); + socket.setEnabledProtocols(allowedProtocols.toArray(new String[allowedProtocols.size()])); + } + } } diff --git a/java/common/src/test/java/org/apache/qpid/transport/network/TransportTest.java b/java/common/src/test/java/org/apache/qpid/transport/network/TransportTest.java index bf9a5843d6..3071594be7 100644 --- a/java/common/src/test/java/org/apache/qpid/transport/network/TransportTest.java +++ b/java/common/src/test/java/org/apache/qpid/transport/network/TransportTest.java @@ -21,6 +21,10 @@ package org.apache.qpid.transport.network; +import java.nio.ByteBuffer; + +import javax.net.ssl.SSLContext; + import org.apache.qpid.framing.ProtocolVersion; import org.apache.qpid.protocol.ProtocolEngineFactory; import org.apache.qpid.test.utils.QpidTestCase; @@ -30,9 +34,6 @@ import org.apache.qpid.transport.Receiver; import org.apache.qpid.transport.TransportException; import org.apache.qpid.transport.network.io.IoNetworkTransport; -import javax.net.ssl.SSLContext; -import java.nio.ByteBuffer; - public class TransportTest extends QpidTestCase { @@ -153,5 +154,11 @@ public class TransportTest extends QpidTestCase { throw new UnsupportedOperationException(); } + + @Override + public int getAcceptingPort() + { + return -1; + } } } diff --git a/java/perftests/etc/chartdefs/1001-MessageSize-Transient-ByteSec.chartdef b/java/perftests/etc/chartdefs/1001-MessageSize-Transient-ByteSec.chartdef index 2327fb610f..dd8d0f9918 100644 --- a/java/perftests/etc/chartdefs/1001-MessageSize-Transient-ByteSec.chartdef +++ b/java/perftests/etc/chartdefs/1001-MessageSize-Transient-ByteSec.chartdef @@ -20,7 +20,7 @@ chartType=XYLINE chartTitle=Impact of Message Size Bytes/S chartSubtitle=Transient messages -chartDescription=1P 1C, transient, auto-ack, with message payload between 256-262144 bytes ${baselineName}, single queue. +chartDescription=1P 1C, single queue, transient, auto-ack, with message payload between 256-262144 bytes ${baselineName}. xAxisTitle=Message Size (B) yAxisTitle=Throughput (KB/s) diff --git a/java/perftests/etc/chartdefs/1002-MessageSize-Persistent-ByteSec.chartdef b/java/perftests/etc/chartdefs/1002-MessageSize-Persistent-ByteSec.chartdef index cd7029963b..42b91bacf8 100644 --- a/java/perftests/etc/chartdefs/1002-MessageSize-Persistent-ByteSec.chartdef +++ b/java/perftests/etc/chartdefs/1002-MessageSize-Persistent-ByteSec.chartdef @@ -20,7 +20,7 @@ chartType=XYLINE chartTitle=Impact of Message Size Bytes/S chartSubtitle=Persistent messages -chartDescription=1P 1C, persistent, auto-ack, with message payload between 256-262144 bytes, single queue. +chartDescription=1P 1C, single queue, persistent, session-transacted, with message payload between 256-262144 bytes. xAxisTitle=Message Size (B) yAxisTitle=Throughput (KB/s) diff --git a/java/perftests/etc/chartdefs/1003-MessageSize-Transient-MsgSec.chartdef b/java/perftests/etc/chartdefs/1003-MessageSize-Transient-MsgSec.chartdef index 979136e2ed..bea3be0521 100644 --- a/java/perftests/etc/chartdefs/1003-MessageSize-Transient-MsgSec.chartdef +++ b/java/perftests/etc/chartdefs/1003-MessageSize-Transient-MsgSec.chartdef @@ -20,7 +20,7 @@ chartType=XYLINE chartTitle=Impact of Message Size chartSubtitle=Transient messages -chartDescription=1P 1C, transient, auto-ack, with message payload between 256-262144 bytes, single queue. +chartDescription=1P 1C, single queue, transient, auto-ack, with message payload between 256-262144 bytes. xAxisTitle=Message Size (B) yAxisTitle=Throughput (messages/s) diff --git a/java/perftests/etc/chartdefs/1004-MessageSize-Persistent-MsgSec.chartdef b/java/perftests/etc/chartdefs/1004-MessageSize-Persistent-MsgSec.chartdef index fef5509107..993d54c9ca 100644 --- a/java/perftests/etc/chartdefs/1004-MessageSize-Persistent-MsgSec.chartdef +++ b/java/perftests/etc/chartdefs/1004-MessageSize-Persistent-MsgSec.chartdef @@ -20,7 +20,7 @@ chartType=XYLINE chartTitle=Impact of Message Size chartSubtitle=Persistent messages -chartDescription=1P 1C, persistent, auto-ack, with message payload between 256-262144 bytes, single queue. +chartDescription=1P 1C, single queue, persistent, session-transacted, with message payload between 256-262144 bytes. xAxisTitle=Message Size (B) yAxisTitle=Throughput (messages/s) diff --git a/java/perftests/etc/chartdefs/1011-VaryingNumberOfProducers-AutoAck.chartdef b/java/perftests/etc/chartdefs/1011-VaryingNumberOfProducers-AutoAck.chartdef index 8ad987ea74..af73ff35cd 100644 --- a/java/perftests/etc/chartdefs/1011-VaryingNumberOfProducers-AutoAck.chartdef +++ b/java/perftests/etc/chartdefs/1011-VaryingNumberOfProducers-AutoAck.chartdef @@ -20,7 +20,7 @@ chartType=XYLINE chartTitle=Varying number of producers - auto ack chartSubtitle=Persistent 1KB messages -chartDescription=1,2,5,10 P/Cs, persistent, auto-ack, with message payload 1KB, single queue. +chartDescription=1,2,5,10 P/Cs, single queue, persistent, auto-ack, with message payload 1KB. xAxisTitle=Producers yAxisTitle=Throughput (messages/s) diff --git a/java/perftests/etc/chartdefs/1012-VaryingNumberOfConsumers-AutoAck.chartdef b/java/perftests/etc/chartdefs/1012-VaryingNumberOfConsumers-AutoAck.chartdef index 599c37cf60..64765de1fc 100644 --- a/java/perftests/etc/chartdefs/1012-VaryingNumberOfConsumers-AutoAck.chartdef +++ b/java/perftests/etc/chartdefs/1012-VaryingNumberOfConsumers-AutoAck.chartdef @@ -20,7 +20,7 @@ chartType=XYLINE chartTitle=Varying number of consumers - auto ack chartSubtitle=Persistent 1KB messages -chartDescription=1,2,5,10 P/Cs, persistent, auto-ack, with message payload 1KB, single queue. +chartDescription=1,2,5,10 P/Cs, single queue, persistent, auto-ack, with message payload 1KB. xAxisTitle=Consumers yAxisTitle=Throughput (messages/s) diff --git a/java/perftests/etc/chartdefs/1015-VaryingNumberOfProducers-SessionTrans.chartdef b/java/perftests/etc/chartdefs/1015-VaryingNumberOfProducers-SessionTrans.chartdef index d22594ca89..7561ea33f6 100644 --- a/java/perftests/etc/chartdefs/1015-VaryingNumberOfProducers-SessionTrans.chartdef +++ b/java/perftests/etc/chartdefs/1015-VaryingNumberOfProducers-SessionTrans.chartdef @@ -20,7 +20,7 @@ chartType=XYLINE chartTitle=Varying number of producers - transacted chartSubtitle=Persistent 1KB messages -chartDescription=1,2,5,10 P/Cs, persistent, transacted, with message payload 1KB, single queue. +chartDescription=1,2,5,10 P/Cs, single queue, persistent, transacted, with message payload 1KB. xAxisTitle=Producers yAxisTitle=Throughput (messages/s) diff --git a/java/perftests/etc/chartdefs/1016-VaryingNumberOfConsumers-SessionTrans.chartdef b/java/perftests/etc/chartdefs/1016-VaryingNumberOfConsumers-SessionTrans.chartdef index 0e781177fe..f567ffade6 100644 --- a/java/perftests/etc/chartdefs/1016-VaryingNumberOfConsumers-SessionTrans.chartdef +++ b/java/perftests/etc/chartdefs/1016-VaryingNumberOfConsumers-SessionTrans.chartdef @@ -20,7 +20,7 @@ chartType=XYLINE chartTitle=Varying number of consumers - transacted chartSubtitle=Persistent 1KB messages -chartDescription=1,2,5,10 P/Cs, persistent, transacted, with message payload 1KB, single queue. +chartDescription=1,2,5,10 P/Cs, single queue, persistent, transacted, with message payload 1KB. xAxisTitle=Consumers yAxisTitle=Throughput (messages/s) diff --git a/java/perftests/etc/chartdefs/1021-AcknowledgementModes-Persistent.chartdef b/java/perftests/etc/chartdefs/1021-AcknowledgementModes-Persistent.chartdef index 7d1abe6418..5028ce17fc 100644 --- a/java/perftests/etc/chartdefs/1021-AcknowledgementModes-Persistent.chartdef +++ b/java/perftests/etc/chartdefs/1021-AcknowledgementModes-Persistent.chartdef @@ -20,7 +20,7 @@ chartType=BAR chartTitle=Performance of acknowledgement modes chartSubtitle=Persistent messages (1KB) -chartDescription=1P 1C, persistent, with message payload 1KB, single queue. +chartDescription=1P 1C, single queue, persistent, with message payload 1KB. xAxisTitle=Acknowledge mode (0=session transacted; 1=auto-acknowledge) yAxisTitle=Throughput (messages/s) diff --git a/java/perftests/etc/chartdefs/1022-AcknowledgementModes-Transient.chartdef b/java/perftests/etc/chartdefs/1022-AcknowledgementModes-Transient.chartdef index 662cb8529d..88d5cd9137 100644 --- a/java/perftests/etc/chartdefs/1022-AcknowledgementModes-Transient.chartdef +++ b/java/perftests/etc/chartdefs/1022-AcknowledgementModes-Transient.chartdef @@ -20,7 +20,7 @@ chartType=BAR chartTitle=Performance of acknowledgement modes chartSubtitle=Transient messages (1024b) -chartDescription=1P 1C, transient, with message payload 1KB, single queue. +chartDescription=1P 1C, single queue, transient, with message payload 1KB. xAxisTitle=Acknowledge mode (0=session transacted; 1=auto-acknowledge) yAxisTitle=Throughput (messages/s) diff --git a/java/perftests/etc/chartdefs/1030-BatchSize-Equal.chartdef b/java/perftests/etc/chartdefs/1030-BatchSize-Equal.chartdef index 1b37d50c33..cfc5efb71c 100644 --- a/java/perftests/etc/chartdefs/1030-BatchSize-Equal.chartdef +++ b/java/perftests/etc/chartdefs/1030-BatchSize-Equal.chartdef @@ -20,7 +20,7 @@ chartType=XYLINE chartTitle=Transaction Batch Sizes Equal chartSubtitle=Persistent 1KB messages -chartDescription=1P 1C, persistent, transacted with message payload 1KB with producer/consumer batch size varying between 1-400 messages for both P and C, single queue. +chartDescription=1P 1C, single queue, persistent, transacted with message payload 1KB with producer/consumer batch size varying between 1-400 messages for both P and C. xAxisTitle=Batch Size yAxisTitle=Throughput (messages/s) diff --git a/java/perftests/etc/chartdefs/1031-BatchSize-Unequal.chartdef b/java/perftests/etc/chartdefs/1031-BatchSize-Unequal.chartdef index cd72663552..ac8de3d290 100644 --- a/java/perftests/etc/chartdefs/1031-BatchSize-Unequal.chartdef +++ b/java/perftests/etc/chartdefs/1031-BatchSize-Unequal.chartdef @@ -20,7 +20,7 @@ chartType=XYLINE chartTitle=Transaction Batch Size Unequal chartSubtitle=Persistent 1KB messages -chartDescription=1P 1C, persistent, transacted with message payload 1KB with fixed batch size 1 for one party whilst other varies between 1-400 messages, single queue. +chartDescription=1P 1C, single queue, persistent, transacted with message payload 1KB with fixed batch size 1 for one party whilst other varies between 1-400 messages. xAxisTitle=Batch Size yAxisTitle=Throughput (messages/s) diff --git a/java/perftests/etc/chartdefs/1040-QueueTypes.chartdef b/java/perftests/etc/chartdefs/1040-QueueTypes.chartdef index 3ba42e2c00..64fbda8953 100644 --- a/java/perftests/etc/chartdefs/1040-QueueTypes.chartdef +++ b/java/perftests/etc/chartdefs/1040-QueueTypes.chartdef @@ -20,7 +20,7 @@ chartType=BAR chartTitle=Queue Types chartSubtitle=Persistent 1KB messages -chartDescription=1P 1C, persistent, auto-ack with message payload 1KB. Sorted queue - 160,000 random keys, Priority - iteriates priority 0..9, single queue. +chartDescription=1P 1C, single queue, persistent, session-transacted with message payload 1KB. Sorted queue - 160,000 random keys, Priority - iteriates priority 0..9. xAxisTitle=Queue Types yAxisTitle=Throughput (messages/s) diff --git a/java/perftests/etc/chartdefs/1050-VaryingNumberOfProducerSessionsSingleConnection.chartdef b/java/perftests/etc/chartdefs/1050-VaryingNumberOfProducerSessionsSingleConnection.chartdef index c92974ddc0..7aeeb37508 100644 --- a/java/perftests/etc/chartdefs/1050-VaryingNumberOfProducerSessionsSingleConnection.chartdef +++ b/java/perftests/etc/chartdefs/1050-VaryingNumberOfProducerSessionsSingleConnection.chartdef @@ -20,7 +20,7 @@ chartType=XYLINE chartTitle=Varying number of producer sessions on single connection chartSubtitle=Persistent messages (1024b) -chartDescription=1-80P transacted on single connection, 20C transacted on separate connections, persistent, message payload 1KB, single queue. +chartDescription=1-80P single queue, transacted on single connection, 20C transacted on separate connections, persistent, message payload 1KB. xAxisTitle=Number of producer sessions yAxisTitle=Throughput (KB/s) diff --git a/java/perftests/etc/chartdefs/1300-QueueConsumersWithNonOverlappingSelectors-Transient.chartdef b/java/perftests/etc/chartdefs/1300-QueueConsumersWithNonOverlappingSelectors-Transient.chartdef index 95f717ad95..d806acda4b 100644 --- a/java/perftests/etc/chartdefs/1300-QueueConsumersWithNonOverlappingSelectors-Transient.chartdef +++ b/java/perftests/etc/chartdefs/1300-QueueConsumersWithNonOverlappingSelectors-Transient.chartdef @@ -22,7 +22,7 @@ chartTitle=Impact of non-overlapping selectors on queue consumers with transient chartSubtitle=Transient 1KB messages xAxisTitle=Consumers yAxisTitle=Throughput (messages/s) -chartDescription=Impact of non-overlapping selectors on queue consumers with transient messages, auto-ack, message payload of 1024 bytes, 1 producer, varying number of consumers from 1 to 32, single queue. +chartDescription=Impact of non-overlapping selectors on queue consumers with single queue, transient messages, auto-ack, message payload of 1024 bytes, 1 producer, varying number of consumers from 1 to 32. series.1.statement=SELECT totalNumberOfConsumers, throughputMessagesPerS FROM QueueConsumersWithNonOverlappingSelectors WHERE participantName = 'All' and testName like '%non overlapping - NON_PERSISTENT%' series.1.legend=Current diff --git a/java/perftests/etc/chartdefs/1301-QueueConsumersWithNonOverlappingSelectors-Persistent.chartdef b/java/perftests/etc/chartdefs/1301-QueueConsumersWithNonOverlappingSelectors-Persistent.chartdef index 302b508413..94b354a3c4 100644 --- a/java/perftests/etc/chartdefs/1301-QueueConsumersWithNonOverlappingSelectors-Persistent.chartdef +++ b/java/perftests/etc/chartdefs/1301-QueueConsumersWithNonOverlappingSelectors-Persistent.chartdef @@ -22,7 +22,7 @@ chartTitle=Impact of non-overlapping selectors on queue consumers with persisten chartSubtitle=Persistent 1KB messages xAxisTitle=Consumers yAxisTitle=Throughput (messages/s) -chartDescription=Impact of non-overlapping selectors on queue consumers with persistent messages, auto-ack, message payload of 1024 bytes, 1 producer, varying number of consumers from 1 to 32, single queue. +chartDescription=Impact of non-overlapping selectors on queue consumers with single queue, persistent messages, session-transacted, message payload of 1024 bytes, 1 producer, varying number of consumers from 1 to 32. series.1.statement=SELECT totalNumberOfConsumers, throughputMessagesPerS FROM QueueConsumersWithNonOverlappingSelectors WHERE participantName = 'All' and testName like '%non overlapping - PERSISTENT' diff --git a/java/perftests/etc/chartdefs/1302-QueueConsumersWithOverlappingSelectors-Transient.chartdef b/java/perftests/etc/chartdefs/1302-QueueConsumersWithOverlappingSelectors-Transient.chartdef index c0796ca8a3..319485ffba 100644 --- a/java/perftests/etc/chartdefs/1302-QueueConsumersWithOverlappingSelectors-Transient.chartdef +++ b/java/perftests/etc/chartdefs/1302-QueueConsumersWithOverlappingSelectors-Transient.chartdef @@ -22,7 +22,7 @@ chartTitle=Impact of 50%-overlapping selectors in queue consumers with transient chartSubtitle=Transient 1KB messages xAxisTitle=Consumers yAxisTitle=Throughput (messages/s) -chartDescription=Impact of 50%-overlapping selectors in queue consumers with transient messages, auto-ack, message payload 1KB, 1 producer, varying number of consumers from 2 to 32, single queue. +chartDescription=Impact of 50%-overlapping selectors in queue consumers with single queue, transient messages, auto-ack, message payload 1KB, 1 producer, varying number of consumers from 2 to 32. series.1.statement=SELECT totalNumberOfConsumers,throughputMessagesPerS FROM QueueConsumersWithOverlappingSelectors WHERE participantName = 'All' and testName like '%50_ overlapping - NON_PERSISTENT%' series.1.legend=Current diff --git a/java/perftests/etc/chartdefs/1303-QueueConsumersWithOverlappingSelectors-Persistent.chartdef b/java/perftests/etc/chartdefs/1303-QueueConsumersWithOverlappingSelectors-Persistent.chartdef index a2c75c1037..17cfee2e62 100644 --- a/java/perftests/etc/chartdefs/1303-QueueConsumersWithOverlappingSelectors-Persistent.chartdef +++ b/java/perftests/etc/chartdefs/1303-QueueConsumersWithOverlappingSelectors-Persistent.chartdef @@ -19,7 +19,7 @@ chartType=XYLINE chartTitle=Impact of 50%-overlapping selectors in queue consumers with persistent messages -chartDescription=Impact of 50%-overlapping selectors in queue consumers with persistent messages, auto-ack, message payload of 1KB, 1 producer, varying number of consumers from 2 to 32, single queue. +chartDescription=Impact of 50%-overlapping selectors in queue consumers with single queue, persistent messages, session-transacted, message payload of 1KB, 1 producer, varying number of consumers from 2 to 32. chartSubtitle=Persistent 1KB messages xAxisTitle=Consumers yAxisTitle=Throughput (messages/s) diff --git a/java/perftests/etc/chartdefs/1500-Topic-NumberOfConsumers.chartdef b/java/perftests/etc/chartdefs/1500-Topic-NumberOfConsumers.chartdef index 96f0ce3284..22b6f4c9ca 100644 --- a/java/perftests/etc/chartdefs/1500-Topic-NumberOfConsumers.chartdef +++ b/java/perftests/etc/chartdefs/1500-Topic-NumberOfConsumers.chartdef @@ -20,7 +20,7 @@ chartType=XYLINE chartTitle=Number of topic consumers chartSubtitle=Transient 1KB messages -chartDescription=1P 1-100C transient, transacted, with message payload 1KB, single queue. +chartDescription=1P 1-100C single topic, transient, transacted, with message payload 1KB. xAxisTitle=Numer of consumers yAxisTitle=Throughput (messages/s) diff --git a/java/perftests/etc/chartdefs/1501-Topic-NumberOfTopics.chartdef b/java/perftests/etc/chartdefs/1501-Topic-NumberOfTopics.chartdef index 5eac3d90c9..c0a67243dc 100644 --- a/java/perftests/etc/chartdefs/1501-Topic-NumberOfTopics.chartdef +++ b/java/perftests/etc/chartdefs/1501-Topic-NumberOfTopics.chartdef @@ -20,7 +20,7 @@ chartType=XYLINE chartTitle=Number of topics chartSubtitle=Transient 1KB messages -chartDescription=1,10,50,100 PC, transient, transacted, with each PC pair having own topic, message payload 1KB, single topic. +chartDescription=1,10,50,100 PC, single topic, transient, transacted, with each PC pair having own topic, message payload 1KB. xAxisTitle=Numer of topics yAxisTitle=Throughput (messages/s) diff --git a/java/perftests/etc/chartdefs/1502-Topic-Persistence.chartdef b/java/perftests/etc/chartdefs/1502-Topic-Persistence.chartdef index 25e64ea1c9..1a60ced1cf 100644 --- a/java/perftests/etc/chartdefs/1502-Topic-Persistence.chartdef +++ b/java/perftests/etc/chartdefs/1502-Topic-Persistence.chartdef @@ -20,7 +20,7 @@ chartType=BAR chartTitle=Topic transient/durable subscriptions chartSubtitle=1KB messages -chartDescription=1P 10C, transacted, message payload 1KB, transient messages on non-durable sub, persistent messages on durable sub, single topic, +chartDescription=1P 10C, single topic, transacted, message payload 1KB, transient messages on non-durable sub, persistent messages on durable sub. xAxisTitle=Subscription type (true durable, false non durable) yAxisTitle=Throughput (messages/s) diff --git a/java/perftests/etc/chartdefs/1503-Topic-AckModes.chartdef b/java/perftests/etc/chartdefs/1503-Topic-AckModes.chartdef index 8d549abcc9..c6decf0c4c 100644 --- a/java/perftests/etc/chartdefs/1503-Topic-AckModes.chartdef +++ b/java/perftests/etc/chartdefs/1503-Topic-AckModes.chartdef @@ -20,7 +20,7 @@ chartType=BAR chartTitle=Topic acknowledge modes chartSubtitle=Transient 1KB messages -chartDescription=1P 10C, transient, non-durable subscription, message payload 1KB, single topic. +chartDescription=1P 10C, single topic, transient, non-durable subscription, message payload 1KB. xAxisTitle=Ack Mode (0=transaction 1=auto-ack) yAxisTitle=Throughput (messages/s) diff --git a/java/perftests/etc/chartdefs/2001-Latency-MessageSize-Transient.chartdef b/java/perftests/etc/chartdefs/2001-Latency-MessageSize-Transient.chartdef index bd252d1b6e..7d0738fd7b 100644 --- a/java/perftests/etc/chartdefs/2001-Latency-MessageSize-Transient.chartdef +++ b/java/perftests/etc/chartdefs/2001-Latency-MessageSize-Transient.chartdef @@ -20,7 +20,7 @@ chartType=STATISTICAL_BAR chartTitle=Impact of message size on latency chartSubtitle=Transient messages -chartDescription=1P 1C, transient, auto-ack, with message payload between 256-262144 bytes, single queue. +chartDescription=1P 1C, single queue, transient, auto-ack, with message payload between 256-262144 bytes. xAxisTitle=Message Size (B) yAxisTitle=Latency (millis) diff --git a/java/perftests/etc/chartdefs/2002-Latency-MessageSize-Persistent.chartdef b/java/perftests/etc/chartdefs/2002-Latency-MessageSize-Persistent.chartdef index 36acdb6cd7..5fd5a3c414 100644 --- a/java/perftests/etc/chartdefs/2002-Latency-MessageSize-Persistent.chartdef +++ b/java/perftests/etc/chartdefs/2002-Latency-MessageSize-Persistent.chartdef @@ -20,7 +20,7 @@ chartType=STATISTICAL_BAR chartTitle=Impact of message size on latency chartSubtitle=Persistent messages -chartDescription=1P 1C, persistent, auto-ack, with message payload between 256-262144 bytes, single queue. +chartDescription=1P 1C, single queue, persistent, session-transacted, with message payload between 256-262144 bytes. xAxisTitle=Message Size (B) yAxisTitle=Latency (millis) diff --git a/java/perftests/etc/chartdefs/2031-Latency-VaryingNumberOfParticipants.chartdef b/java/perftests/etc/chartdefs/2031-Latency-VaryingNumberOfParticipants.chartdef index bb19eb2aca..91d3cbe0f7 100644 --- a/java/perftests/etc/chartdefs/2031-Latency-VaryingNumberOfParticipants.chartdef +++ b/java/perftests/etc/chartdefs/2031-Latency-VaryingNumberOfParticipants.chartdef @@ -20,7 +20,7 @@ chartType=STATISTICAL_BAR chartTitle=Latency, varying number of participants chartSubtitle=Persistent 1KB messages -chartDescription=1,2,5,10 P/Cs, persistent, auto-ack, with message payload 1KB, single queue. +chartDescription=1,2,5,10 P/Cs, single queue, persistent, session-transacted, with message payload 1KB. xAxisTitle=Consumers yAxisTitle=Latency (millis) diff --git a/java/perftests/etc/testdefs/QueueTypes.json b/java/perftests/etc/testdefs/QueueTypes.json index 427f3d9795..36f98a7b3a 100644 --- a/java/perftests/etc/testdefs/QueueTypes.json +++ b/java/perftests/etc/testdefs/QueueTypes.json @@ -16029,7 +16029,7 @@ "_sessions": [ { "_sessionName": "session1", - "_acknowledgeMode": 1, + "_acknowledgeMode": 0, "_producers": [ { "_name": "Producer1", @@ -16054,7 +16054,7 @@ "_sessions": [ { "_sessionName": "session1", - "_acknowledgeMode": 1, + "_acknowledgeMode": 0, "_consumers": [ { "_name": "Consumer1", @@ -16087,7 +16087,7 @@ "_sessions": [ { "_sessionName": "session1", - "_acknowledgeMode": 1, + "_acknowledgeMode": 0, "_producers": [ { "_name": "Producer1", @@ -16111,7 +16111,7 @@ "_sessions": [ { "_sessionName": "session1", - "_acknowledgeMode": 1, + "_acknowledgeMode": 0, "_consumers": [ { "_name": "Consumer1", @@ -16154,7 +16154,7 @@ "_sessions": [ { "_sessionName": "session1", - "_acknowledgeMode": 1, + "_acknowledgeMode": 0, "_producers": [ { "_name": "Producer1", @@ -16179,7 +16179,7 @@ "_sessions": [ { "_sessionName": "session1", - "_acknowledgeMode": 1, + "_acknowledgeMode": 0, "_consumers": [ { "_name": "Consumer1", diff --git a/java/perftests/pom.xml b/java/perftests/pom.xml index 7787c82b74..39daa6a4bd 100644 --- a/java/perftests/pom.xml +++ b/java/perftests/pom.xml @@ -179,7 +179,10 @@ - qpid.amqp0-91 + log4j.configurationfile:log4j.properties + + + qpid.amqp.version0-91 qpid.dest_syntaxBURL diff --git a/java/systests/etc/config-systests.json b/java/systests/etc/config-systests.json index 3ef4fa40f8..fa5e7f7724 100644 --- a/java/systests/etc/config-systests.json +++ b/java/systests/etc/config-systests.json @@ -21,7 +21,7 @@ { "name": "Broker", "defaultVirtualHost" : "test", - "modelVersion": "2.0", + "modelVersion": "2.1", "authenticationproviders" : [ { "name" : "plain", "type" : "PlainPasswordFile", @@ -41,7 +41,17 @@ "name" : "amqp", "authenticationProvider" : "plain", "port" : "${test.port}", - "protocols" : "${test.amqp_port_protocols}" + "protocols" : "${test.amqp_port_protocols}", + "virtualhostaliases" : [ { + "name" : "nameAlias", + "type" : "nameAlias" + }, { + "name" : "defaultAlias", + "type" : "defaultAlias" + }, { + "name" : "hostnameAlias", + "type" : "hostnameAlias" + } ] }, { "name" : "http", "authenticationProvider" : "plain", diff --git a/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java b/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java index 386cd80f38..369a76a6c6 100755 --- a/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java +++ b/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java @@ -50,6 +50,7 @@ import javax.naming.NamingException; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; + import org.apache.qpid.AMQException; import org.apache.qpid.client.AMQConnectionFactory; import org.apache.qpid.client.AMQConnectionURL; diff --git a/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java b/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java index c7bcdd2edb..fb254f59ae 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java +++ b/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java @@ -57,6 +57,8 @@ import org.apache.qpid.server.model.Plugin; import org.apache.qpid.server.model.PreferencesProvider; import org.apache.qpid.server.model.SystemConfig; import org.apache.qpid.server.model.UUIDGenerator; +import org.apache.qpid.server.model.VirtualHostAlias; +import org.apache.qpid.server.model.VirtualHostNode; import org.apache.qpid.server.model.adapter.FileBasedGroupProvider; import org.apache.qpid.server.model.adapter.FileBasedGroupProviderImpl; import org.apache.qpid.server.plugin.PluggableFactoryLoader; @@ -254,12 +256,47 @@ public class TestBrokerConfiguration } public UUID[] removeObjectConfiguration(final Class category, - String name) + final String name) { final ConfiguredObjectRecord entry = findObject(category, name); + if (entry != null) { + + if(category == VirtualHostNode.class) + { + final List aliasRecords = new ArrayList<>(); + // remove vhost aliases associated with the vhost + final ConfiguredObjectRecordHandler visitor = new ConfiguredObjectRecordHandler() + { + @Override + public void begin() + { + + } + + @Override + public boolean handle(final ConfiguredObjectRecord record) + { + if (record.getType().equals(VirtualHostAlias.class.getSimpleName()) + && name.equals(record.getAttributes().get(ConfiguredObject.NAME))) + { + aliasRecords.add(record); + } + return true; + } + + @Override + public void end() + { + + } + }; + _store.visitConfiguredObjectRecords(visitor); + _store.remove(aliasRecords.toArray(new ConfiguredObjectRecord[aliasRecords.size()])); + } return _store.remove(entry); + } return null; } @@ -271,6 +308,18 @@ public class TestBrokerConfiguration return id; } + public UUID addObjectConfiguration(final Class parentCategory, final String parentName, + Class type, Map attributes) + { + UUID id = UUIDGenerator.generateRandomUUID(); + ConfiguredObjectRecord entry = + new ConfiguredObjectRecordImpl(id, type.getSimpleName(), attributes, + Collections.singletonMap(parentCategory.getSimpleName(), findObject(parentCategory,parentName).getId())); + + _store.update(true, entry); + return id; + } + public UUID addJmxManagementConfiguration() { Map attributes = new HashMap(); diff --git a/java/systests/src/test/java/org/apache/qpid/client/ssl/SSLTest.java b/java/systests/src/test/java/org/apache/qpid/client/ssl/SSLTest.java index eb61e5a084..1dba5ced9d 100644 --- a/java/systests/src/test/java/org/apache/qpid/client/ssl/SSLTest.java +++ b/java/systests/src/test/java/org/apache/qpid/client/ssl/SSLTest.java @@ -36,15 +36,19 @@ import javax.jms.Connection; import javax.jms.JMSException; import javax.jms.Session; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import org.apache.qpid.client.AMQConnectionURL; import org.apache.qpid.client.AMQTestConnection_0_10; import org.apache.qpid.jms.ConnectionURL; +import org.apache.qpid.server.model.DefaultVirtualHostAlias; import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.model.VirtualHostAlias; +import org.apache.qpid.server.model.VirtualHostNameAlias; import org.apache.qpid.test.utils.QpidBrokerTestCase; import org.apache.qpid.test.utils.TestBrokerConfiguration; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; public class SSLTest extends QpidBrokerTestCase { @@ -215,7 +219,7 @@ public class SSLTest extends QpidBrokerTestCase AMQTestConnection_0_10 con = new AMQTestConnection_0_10(url); org.apache.qpid.transport.Connection transportCon = con.getConnection(); String userID = transportCon.getSecurityLayer().getUserID(); - assertEquals("The correct certificate was not choosen","app1@acme.org",userID); + assertEquals("The correct certificate was not chosen","app1@acme.org",userID); con.close(); url = "amqp://guest:guest@test/?brokerlist='tcp://localhost:" + @@ -225,7 +229,7 @@ public class SSLTest extends QpidBrokerTestCase con = new AMQTestConnection_0_10(url); transportCon = con.getConnection(); userID = transportCon.getSecurityLayer().getUserID(); - assertEquals("The correct certificate was not choosen","app2@acme.org",userID); + assertEquals("The correct certificate was not chosen","app2@acme.org",userID); con.close(); } } @@ -464,6 +468,17 @@ public class SSLTest extends QpidBrokerTestCase sslPortAttributes.put(Port.KEY_STORE, TestBrokerConfiguration.ENTRY_NAME_SSL_KEYSTORE); sslPortAttributes.put(Port.TRUST_STORES, Collections.singleton(TestBrokerConfiguration.ENTRY_NAME_SSL_TRUSTSTORE)); getBrokerConfiguration().addObjectConfiguration(Port.class,sslPortAttributes); + + Map aliasAttributes = new HashMap<>(); + aliasAttributes.put(VirtualHostAlias.NAME, "defaultAlias"); + aliasAttributes.put(VirtualHostAlias.TYPE, DefaultVirtualHostAlias.TYPE_NAME); + getBrokerConfiguration().addObjectConfiguration(Port.class, TestBrokerConfiguration.ENTRY_NAME_SSL_PORT, VirtualHostAlias.class, aliasAttributes); + + aliasAttributes = new HashMap<>(); + aliasAttributes.put(VirtualHostAlias.NAME, "nameAlias"); + aliasAttributes.put(VirtualHostAlias.TYPE, VirtualHostNameAlias.TYPE_NAME); + getBrokerConfiguration().addObjectConfiguration(Port.class, TestBrokerConfiguration.ENTRY_NAME_SSL_PORT, VirtualHostAlias.class, aliasAttributes); + } } diff --git a/java/systests/src/test/java/org/apache/qpid/scripts/QpidPasswdTest.java b/java/systests/src/test/java/org/apache/qpid/scripts/QpidPasswdTest.java deleted file mode 100644 index e483660f4c..0000000000 --- a/java/systests/src/test/java/org/apache/qpid/scripts/QpidPasswdTest.java +++ /dev/null @@ -1,80 +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.scripts; - -import java.io.File; -import java.util.concurrent.TimeUnit; - -import org.apache.qpid.test.utils.Piper; -import org.apache.qpid.test.utils.QpidTestCase; -import org.apache.qpid.util.SystemUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class QpidPasswdTest extends QpidTestCase -{ - private static final Logger LOGGER = LoggerFactory.getLogger(QpidPasswdTest.class); - - private static final String PASSWD_SCRIPT = "qpid-passwd"; - private static final String EXPECTED_OUTPUT = "user1:rL0Y20zC+Fzt72VPzMSk2A=="; - - public void testRunScript() throws Exception - { - if(SystemUtils.isWindows()) - { - return; - } - Process process = null; - try - { - String scriptPath = - QpidTestCase.QPID_HOME + File.separatorChar - + "bin" + File.separatorChar - + PASSWD_SCRIPT; - - LOGGER.info("About to run script: " + scriptPath); - - ProcessBuilder pb = new ProcessBuilder(scriptPath, "user1", "foo"); - pb.redirectErrorStream(true); - process = pb.start(); - - Piper piper = new Piper(process.getInputStream(), System.out, EXPECTED_OUTPUT, EXPECTED_OUTPUT); - piper.start(); - - boolean finishedSuccessfully = piper.await(2, TimeUnit.SECONDS); - assertTrue( - "Script should have completed with expected output " + EXPECTED_OUTPUT + ". Check standard output for actual output.", - finishedSuccessfully); - process.waitFor(); - piper.join(); - - assertEquals("Unexpected exit value from backup script", 0, process.exitValue()); - } - finally - { - if (process != null) - { - process.getErrorStream().close(); - process.getInputStream().close(); - process.getOutputStream().close(); - } - } - - } -} diff --git a/java/systests/src/test/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationTest.java b/java/systests/src/test/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationTest.java index 0d0c1257a2..5522187ee5 100644 --- a/java/systests/src/test/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationTest.java +++ b/java/systests/src/test/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationTest.java @@ -41,9 +41,12 @@ import javax.jms.JMSException; 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.DefaultVirtualHostAlias; import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.Transport; import org.apache.qpid.server.model.TrustStore; +import org.apache.qpid.server.model.VirtualHostAlias; +import org.apache.qpid.server.model.VirtualHostNameAlias; import org.apache.qpid.server.security.FileTrustStore; import org.apache.qpid.test.utils.JMXTestUtils; import org.apache.qpid.test.utils.QpidBrokerTestCase; @@ -346,6 +349,17 @@ public class ExternalAuthenticationTest extends QpidBrokerTestCase sslPortAttributes.put(Port.TRUST_STORES, trustStoreNames); config.addObjectConfiguration(Port.class, sslPortAttributes); + Map aliasAttributes = new HashMap<>(); + aliasAttributes.put(VirtualHostAlias.NAME, "defaultAlias"); + aliasAttributes.put(VirtualHostAlias.TYPE, DefaultVirtualHostAlias.TYPE_NAME); + getBrokerConfiguration().addObjectConfiguration(Port.class, TestBrokerConfiguration.ENTRY_NAME_SSL_PORT, VirtualHostAlias.class, aliasAttributes); + + aliasAttributes = new HashMap<>(); + aliasAttributes.put(VirtualHostAlias.NAME, "nameAlias"); + aliasAttributes.put(VirtualHostAlias.TYPE, VirtualHostNameAlias.TYPE_NAME); + getBrokerConfiguration().addObjectConfiguration(Port.class, TestBrokerConfiguration.ENTRY_NAME_SSL_PORT, VirtualHostAlias.class, aliasAttributes); + + Map externalAuthProviderAttributes = new HashMap(); externalAuthProviderAttributes.put(AuthenticationProvider.NAME, TestBrokerConfiguration.ENTRY_NAME_EXTERNAL_PROVIDER); externalAuthProviderAttributes.put(AuthenticationProvider.TYPE, ExternalAuthenticationManager.PROVIDER_TYPE); diff --git a/java/systests/src/test/java/org/apache/qpid/server/security/auth/manager/MultipleAuthenticationManagersTest.java b/java/systests/src/test/java/org/apache/qpid/server/security/auth/manager/MultipleAuthenticationManagersTest.java index 1c32a3f671..f5e17a0953 100644 --- a/java/systests/src/test/java/org/apache/qpid/server/security/auth/manager/MultipleAuthenticationManagersTest.java +++ b/java/systests/src/test/java/org/apache/qpid/server/security/auth/manager/MultipleAuthenticationManagersTest.java @@ -35,8 +35,11 @@ import javax.jms.JMSException; import org.apache.qpid.AMQException; import org.apache.qpid.client.AMQConnection; import org.apache.qpid.server.model.AuthenticationProvider; +import org.apache.qpid.server.model.DefaultVirtualHostAlias; import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.model.VirtualHostAlias; +import org.apache.qpid.server.model.VirtualHostNameAlias; import org.apache.qpid.test.utils.QpidBrokerTestCase; import org.apache.qpid.test.utils.TestBrokerConfiguration; @@ -61,6 +64,17 @@ public class MultipleAuthenticationManagersTest extends QpidBrokerTestCase sslPortAttributes.put(Port.AUTHENTICATION_PROVIDER, TestBrokerConfiguration.ENTRY_NAME_ANONYMOUS_PROVIDER); config.addObjectConfiguration(Port.class, sslPortAttributes); + Map aliasAttributes = new HashMap<>(); + aliasAttributes.put(VirtualHostAlias.NAME, "defaultAlias"); + aliasAttributes.put(VirtualHostAlias.TYPE, DefaultVirtualHostAlias.TYPE_NAME); + config.addObjectConfiguration(Port.class, TestBrokerConfiguration.ENTRY_NAME_SSL_PORT, VirtualHostAlias.class, aliasAttributes); + + aliasAttributes = new HashMap<>(); + aliasAttributes.put(VirtualHostAlias.NAME, "nameAlias"); + aliasAttributes.put(VirtualHostAlias.TYPE, VirtualHostNameAlias.TYPE_NAME); + getBrokerConfiguration().addObjectConfiguration(Port.class, TestBrokerConfiguration.ENTRY_NAME_SSL_PORT, VirtualHostAlias.class, aliasAttributes); + + // set the ssl system properties setSystemProperty("javax.net.ssl.keyStore", KEYSTORE); setSystemProperty("javax.net.ssl.keyStorePassword", KEYSTORE_PASSWORD); diff --git a/java/systests/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementTest.java b/java/systests/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementTest.java index 25b09f04c3..0bcae6431c 100644 --- a/java/systests/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementTest.java +++ b/java/systests/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementTest.java @@ -35,7 +35,6 @@ import org.apache.qpid.server.security.auth.manager.PlainPasswordDatabaseAuthent import org.apache.qpid.test.utils.JMXTestUtils; import org.apache.qpid.test.utils.QpidBrokerTestCase; import org.apache.qpid.test.utils.TestBrokerConfiguration; -import org.apache.qpid.tools.security.Passwd; /** * System test for User Management. @@ -49,11 +48,9 @@ public class UserManagementTest extends QpidBrokerTestCase private String _testUserName; private File _passwordFile; private UserManagement _userManagement; - private Passwd _passwd; public void setUp() throws Exception { - _passwd = createPasswordEncodingUtility(); _passwordFile = createTemporaryPasswordFileWithJmxAdminUser(); Map newAttributes = new HashMap(); @@ -161,17 +158,6 @@ public class UserManagementTest extends QpidBrokerTestCase assertEquals("unexpected authentication provider type", getAuthenticationManagerType(), actualType); } - protected Passwd createPasswordEncodingUtility() - { - return new Passwd() - { - @Override - public String getOutput(String username, String password) - { - return username + ":" + password; - } - }; - } protected String getAuthenticationManagerType() { @@ -188,21 +174,25 @@ public class UserManagementTest extends QpidBrokerTestCase private void writePasswordFile(File passwordFile, String... userNamePasswordPairs) throws Exception { - FileWriter writer = null; - try + try(FileWriter writer = new FileWriter(passwordFile)) { - writer = new FileWriter(passwordFile); for (int i = 0; i < userNamePasswordPairs.length; i=i+2) { String username = userNamePasswordPairs[i]; String password = userNamePasswordPairs[i+1]; - writer.append(_passwd.getOutput(username, password) + "\n"); + writeUsernamePassword(writer, username, password); } } - finally - { - writer.close(); - } + + } + + protected void writeUsernamePassword(final FileWriter writer, final String username, final String password) + throws IOException + { + writer.append(username); + writer.append(':'); + writer.append(password); + writer.append('\n'); } @@ -218,10 +208,8 @@ public class UserManagementTest extends QpidBrokerTestCase private boolean passwordFileContainsUser(String username) throws IOException { - BufferedReader reader = null; - try + try(BufferedReader reader = new BufferedReader(new FileReader(_passwordFile))) { - reader = new BufferedReader(new FileReader(_passwordFile)); String line = reader.readLine(); while(line != null) { @@ -234,10 +222,6 @@ public class UserManagementTest extends QpidBrokerTestCase return false; } - finally - { - reader.close(); - } } private void assertJmsConnectionSucceeds(String username, String password) throws Exception diff --git a/java/systests/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementWithBase64MD5PasswordsTest.java b/java/systests/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementWithBase64MD5PasswordsTest.java index ff441169b3..96ee2d3ae6 100644 --- a/java/systests/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementWithBase64MD5PasswordsTest.java +++ b/java/systests/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementWithBase64MD5PasswordsTest.java @@ -18,17 +18,42 @@ */ package org.apache.qpid.systest.management.jmx; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +import javax.xml.bind.DatatypeConverter; + import org.apache.qpid.server.security.auth.manager.Base64MD5PasswordDatabaseAuthenticationManager; -import org.apache.qpid.tools.security.Passwd; +import org.apache.qpid.server.util.ServerScopedRuntimeException; public class UserManagementWithBase64MD5PasswordsTest extends UserManagementTest { @Override - protected Passwd createPasswordEncodingUtility() + protected void writeUsernamePassword(final FileWriter writer, final String username, final String password) + throws IOException { - return new Passwd(); + writer.append(username); + writer.append(":"); + byte[] data = password.getBytes(StandardCharsets.UTF_8); + MessageDigest md = null; + try + { + md = MessageDigest.getInstance("MD5"); + } + catch (NoSuchAlgorithmException e) + { + throw new ServerScopedRuntimeException("MD5 not supported although Java compliance requires it"); + } + + md.update(data); + writer.append(DatatypeConverter.printBase64Binary(md.digest())); + writer.append('\n'); } + @Override protected String getAuthenticationManagerType() { diff --git a/java/systests/src/test/java/org/apache/qpid/systest/rest/SaslRestTest.java b/java/systests/src/test/java/org/apache/qpid/systest/rest/SaslRestTest.java index 547b7b1b00..57a958edd0 100644 --- a/java/systests/src/test/java/org/apache/qpid/systest/rest/SaslRestTest.java +++ b/java/systests/src/test/java/org/apache/qpid/systest/rest/SaslRestTest.java @@ -29,11 +29,14 @@ 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.xml.bind.DatatypeConverter; + import org.apache.commons.codec.binary.Base64; import org.codehaus.jackson.JsonParseException; import org.codehaus.jackson.map.JsonMappingException; @@ -41,7 +44,6 @@ import org.codehaus.jackson.map.JsonMappingException; import org.apache.qpid.server.model.AuthenticationProvider; import org.apache.qpid.server.security.auth.manager.Base64MD5PasswordDatabaseAuthenticationManager; import org.apache.qpid.test.utils.TestBrokerConfiguration; -import org.apache.qpid.tools.security.Passwd; public class SaslRestTest extends QpidRestTestCase { @@ -353,7 +355,12 @@ public class SaslRestTest extends QpidRestTestCase String passwordFileEntry; try { - passwordFileEntry = new Passwd().getOutput("admin", "admin"); + + MessageDigest md = MessageDigest.getInstance("MD5"); + + md.update("admin".getBytes("utf-8")); + + passwordFileEntry = "admin" + ":" + DatatypeConverter.printBase64Binary(md.digest()); } catch (NoSuchAlgorithmException e) { diff --git a/java/tools/pom.xml b/java/tools/pom.xml index c46ef2c20f..1c009a56dd 100644 --- a/java/tools/pom.xml +++ b/java/tools/pom.xml @@ -51,7 +51,6 @@ org.apache.geronimo.specs geronimo-jms_1.1_spec ${geronimo-jms-1-1-version} - provided diff --git a/java/tools/src/main/java/org/apache/qpid/tools/StressTestClient.java b/java/tools/src/main/java/org/apache/qpid/tools/StressTestClient.java new file mode 100644 index 0000000000..5bf1864b4f --- /dev/null +++ b/java/tools/src/main/java/org/apache/qpid/tools/StressTestClient.java @@ -0,0 +1,446 @@ +/* + * + * 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.tools; + +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; +import java.util.Random; + +import javax.jms.BytesMessage; +import javax.jms.Connection; +import javax.jms.ConnectionFactory; +import javax.jms.DeliveryMode; +import javax.jms.Destination; +import javax.jms.ExceptionListener; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Session; +import javax.naming.Context; +import javax.naming.InitialContext; + +public class StressTestClient +{ + private static final String QUEUE_NAME_PREFIX = "BURL:direct://amq.direct//stress-test-queue"; + private static final String DURABLE_SUFFIX = "?durable='true'"; + + public static final String CONNECTIONS_ARG = "connections"; + public static final String SESSIONS_ARG = "sessions"; + public static final String CONSUME_IMMEDIATELY_ARG = "consumeImmediately"; + public static final String CONSUMERS_ARG = "consumers"; + public static final String CLOSE_CONSUMERS_ARG = "closeconsumers"; + public static final String PRODUCERS_ARG = "producers"; + public static final String MESSAGE_COUNT_ARG = "messagecount"; + public static final String MESSAGE_SIZE_ARG = "size"; + public static final String SUFFIX_ARG = "suffix"; + public static final String REPETITIONS_ARG = "repetitions"; + public static final String PERSISTENT_ARG = "persistent"; + public static final String RANDOM_ARG = "random"; + public static final String TIMEOUT_ARG = "timeout"; + public static final String DELAYCLOSE_ARG = "delayclose"; + public static final String REPORT_MOD_ARG = "reportmod"; + public static final String LOW_PREFETCH_ARG = "lowprefetch"; + public static final String TRANSACTED_ARG = "transacted"; + public static final String TX_BATCH_ARG = "txbatch"; + + public static final String CONNECTIONS_DEFAULT = "1"; + public static final String SESSIONS_DEFAULT = "1"; + public static final String CONSUME_IMMEDIATELY_DEFAULT = "true"; + public static final String CLOSE_CONSUMERS_DEFAULT = "true"; + public static final String PRODUCERS_DEFAULT = "1"; + public static final String CONSUMERS_DEFAULT = "1"; + public static final String MESSAGE_COUNT_DEFAULT = "1"; + public static final String MESSAGE_SIZE_DEFAULT = "256"; + public static final String SUFFIX_DEFAULT = ""; + public static final String REPETITIONS_DEFAULT = "1"; + public static final String PERSISTENT_DEFAULT = "false"; + public static final String RANDOM_DEFAULT = "true"; + public static final String TIMEOUT_DEFAULT = "30000"; + public static final String DELAYCLOSE_DEFAULT = "0"; + public static final String REPORT_MOD_DEFAULT = "1"; + public static final String LOW_PREFETCH_DEFAULT = "false"; + public static final String TRANSACTED_DEFAULT = "false"; + public static final String TX_BATCH_DEFAULT = "1"; + + private static final String CLASS = "StressTestClient"; + + public static void main(String[] args) + { + Map options = new HashMap<>(); + options.put(CONNECTIONS_ARG, CONNECTIONS_DEFAULT); + options.put(SESSIONS_ARG, SESSIONS_DEFAULT); + options.put(CONSUME_IMMEDIATELY_ARG, CONSUME_IMMEDIATELY_DEFAULT); + options.put(PRODUCERS_ARG, PRODUCERS_DEFAULT); + options.put(CONSUMERS_ARG, CONSUMERS_DEFAULT); + options.put(CLOSE_CONSUMERS_ARG, CLOSE_CONSUMERS_DEFAULT); + options.put(MESSAGE_COUNT_ARG, MESSAGE_COUNT_DEFAULT); + options.put(MESSAGE_SIZE_ARG, MESSAGE_SIZE_DEFAULT); + options.put(SUFFIX_ARG, SUFFIX_DEFAULT); + options.put(REPETITIONS_ARG, REPETITIONS_DEFAULT); + options.put(PERSISTENT_ARG, PERSISTENT_DEFAULT); + options.put(RANDOM_ARG, RANDOM_DEFAULT); + options.put(TIMEOUT_ARG, TIMEOUT_DEFAULT); + options.put(DELAYCLOSE_ARG, DELAYCLOSE_DEFAULT); + options.put(REPORT_MOD_ARG, REPORT_MOD_DEFAULT); + options.put(LOW_PREFETCH_ARG, LOW_PREFETCH_DEFAULT); + options.put(TRANSACTED_ARG, TRANSACTED_DEFAULT); + options.put(TX_BATCH_ARG, TX_BATCH_DEFAULT); + + if(args.length == 1 && + (args[0].equals("-h") || args[0].equals("--help") || args[0].equals("help"))) + { + System.out.println("arg=value options: \n" + options.keySet()); + return; + } + + parseArgumentsIntoConfig(options, args); + + StressTestClient testClient = new StressTestClient(); + testClient.runTest(options); + } + + public static void parseArgumentsIntoConfig(Map initialValues, String[] args) + { + for(String arg: args) + { + String[] splitArg = arg.split("="); + if(splitArg.length != 2) + { + throw new IllegalArgumentException("arguments must have format =: " + arg); + } + + if(initialValues.put(splitArg[0], splitArg[1]) == null) + { + throw new IllegalArgumentException("not a valid configuration property: " + arg); + } + } + } + + + private void runTest(Map options) + { + int numConnections = Integer.parseInt(options.get(CONNECTIONS_ARG)); + int numSessions = Integer.parseInt(options.get(SESSIONS_ARG)); + int numProducers = Integer.parseInt(options.get(PRODUCERS_ARG)); + int numConsumers = Integer.parseInt(options.get(CONSUMERS_ARG)); + boolean closeConsumers = Boolean.valueOf(options.get(CLOSE_CONSUMERS_ARG)); + boolean consumeImmediately = Boolean.valueOf(options.get(CONSUME_IMMEDIATELY_ARG)); + int numMessage = Integer.parseInt(options.get(MESSAGE_COUNT_ARG)); + int messageSize = Integer.parseInt(options.get(MESSAGE_SIZE_ARG)); + int repetitions = Integer.parseInt(options.get(REPETITIONS_ARG)); + String queueString = QUEUE_NAME_PREFIX + options.get(SUFFIX_ARG) + DURABLE_SUFFIX; + int deliveryMode = Boolean.valueOf(options.get(PERSISTENT_ARG)) ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT; + boolean random = Boolean.valueOf(options.get(RANDOM_ARG)); + long recieveTimeout = Long.parseLong(options.get(TIMEOUT_ARG)); + long delayClose = Long.parseLong(options.get(DELAYCLOSE_ARG)); + int reportingMod = Integer.parseInt(options.get(REPORT_MOD_ARG)); + boolean lowPrefetch = Boolean.valueOf(options.get(LOW_PREFETCH_ARG)); + boolean transacted = Boolean.valueOf(options.get(TRANSACTED_ARG)); + int txBatch = Integer.parseInt(options.get(TX_BATCH_ARG)); + + System.out.println(CLASS + ": Using options: " + options); + + System.out.println(CLASS + ": Creating message payload of " + messageSize + " (bytes)"); + byte[] sentBytes = generateMessage(random, messageSize); + + try + { + // Load JNDI properties + Properties properties = new Properties(); + try(InputStream is = this.getClass().getClassLoader().getResourceAsStream("stress-test-client.properties")) + { + properties.load(is); + } + Context ctx = new InitialContext(properties); + + ConnectionFactory conFac; + if(lowPrefetch) + { + System.out.println(CLASS + ": Using lowprefetch connection factory"); + conFac = (ConnectionFactory)ctx.lookup("qpidConnectionfactoryLowPrefetch"); + } + else + { + conFac = (ConnectionFactory)ctx.lookup("qpidConnectionfactory"); + } + + //ensure the queue to be used exists and is bound + System.out.println(CLASS + ": Creating queue: " + queueString); + Connection startupConn = conFac.createConnection(); + Session startupSess = startupConn.createSession(false, Session.AUTO_ACKNOWLEDGE); + Destination startupDestination = startupSess.createQueue(queueString); + MessageConsumer startupConsumer = startupSess.createConsumer(startupDestination); + startupConsumer.close(); + startupSess.close(); + startupConn.close(); + + for(int rep = 1 ; rep <= repetitions; rep++) + { + ArrayList connectionList = new ArrayList<>(); + + for (int co= 1; co<= numConnections ; co++) + { + if( co % reportingMod == 0) + { + System.out.println(CLASS + ": Creating connection " + co); + } + Connection conn = conFac.createConnection(); + conn.setExceptionListener(new ExceptionListener() + { + public void onException(JMSException jmse) + { + System.err.println(CLASS + ": The sample received an exception through the ExceptionListener"); + jmse.printStackTrace(); + System.exit(0); + } + }); + + connectionList.add(conn); + conn.start(); + for (int se= 1; se<= numSessions ; se++) + { + if( se % reportingMod == 0) + { + System.out.println(CLASS + ": Creating Session " + se); + } + try + { + Session sess; + if(transacted) + { + sess = conn.createSession(true, Session.SESSION_TRANSACTED); + } + else + { + sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + } + + BytesMessage message = sess.createBytesMessage(); + + message.writeBytes(sentBytes); + + if(!random && numMessage == 1 && numSessions == 1 && numConnections == 1 && repetitions == 1) + { + //null the array to save memory + sentBytes = null; + } + + Destination destination = sess.createQueue(queueString); + + MessageConsumer consumer = null; + for(int cns = 1 ; cns <= numConsumers ; cns++) + { + if( cns % reportingMod == 0) + { + System.out.println(CLASS + ": Creating Consumer " + cns); + } + consumer = sess.createConsumer(destination); + } + + for(int pr = 1 ; pr <= numProducers ; pr++) + { + if( pr % reportingMod == 0) + { + System.out.println(CLASS + ": Creating Producer " + pr); + } + MessageProducer prod = sess.createProducer(destination); + for(int me = 1; me <= numMessage ; me++) + { + if( me % reportingMod == 0) + { + System.out.println(CLASS + ": Sending Message " + me); + } + prod.send(message, deliveryMode, + Message.DEFAULT_PRIORITY, + Message.DEFAULT_TIME_TO_LIVE); + if(transacted && me % txBatch == 0) + { + sess.commit(); + } + } + } + + if(numConsumers > 0 && consumeImmediately) + { + for(int cs = 1 ; cs <= numMessage ; cs++) + { + if( cs % reportingMod == 0) + { + System.out.println(CLASS + ": Consuming Message " + cs); + } + BytesMessage msg = (BytesMessage) consumer.receive(recieveTimeout); + + if(transacted && cs % txBatch == 0) + { + sess.commit(); + } + + if(msg == null) + { + throw new RuntimeException("Expected message not received in allowed time: " + recieveTimeout); + } + + validateReceivedMessageContent(sentBytes, msg, random, messageSize); + } + + if(closeConsumers) + { + consumer.close(); + } + } + + } + catch (Exception exp) + { + System.err.println(CLASS + ": Caught an Exception: " + exp); + exp.printStackTrace(); + } + + } + } + + if(numConsumers == -1 && !consumeImmediately) + { + System.out.println(CLASS + ": Consuming left over messages, using recieve timeout:" + recieveTimeout); + + Connection conn = conFac.createConnection(); + Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + Destination destination = sess.createQueue(queueString); + MessageConsumer consumer = sess.createConsumer(destination); + conn.start(); + + int count = 0; + while(true) + { + BytesMessage msg = (BytesMessage) consumer.receive(recieveTimeout); + + if(msg == null) + { + System.out.println(CLASS + ": Received " + count + " messages"); + break; + } + else + { + count++; + } + + validateReceivedMessageContent(sentBytes, msg, random, messageSize); + } + + consumer.close(); + sess.close(); + conn.close(); + } + + if(delayClose > 0) + { + System.out.println(CLASS + ": Delaying closing connections: " + delayClose); + Thread.sleep(delayClose); + } + + // Close the connections to the server + System.out.println(CLASS + ": Closing connections"); + + for(int connection = 0 ; connection < connectionList.size() ; connection++) + { + if( (connection+1) % reportingMod == 0) + { + System.out.println(CLASS + ": Closing connection " + (connection+1)); + } + Connection c = connectionList.get(connection); + c.close(); + } + + // Close the JNDI reference + System.out.println(CLASS + ": Closing JNDI context"); + ctx.close(); + } + } + catch (Exception exp) + { + System.err.println(CLASS + ": Caught an Exception: " + exp); + exp.printStackTrace(); + } + } + + + private byte[] generateMessage(boolean random, int messageSize) + { + byte[] sentBytes = new byte[messageSize]; + if(random) + { + //fill the array with numbers from 0-9 + Random rand = new Random(System.currentTimeMillis()); + for(int r = 0 ; r < messageSize ; r++) + { + sentBytes[r] = (byte) (48 + rand.nextInt(10)); + } + } + else + { + //use sequential numbers from 0-9 + for(int r = 0 ; r < messageSize ; r++) + { + sentBytes[r] = (byte) (48 + (r % 10)); + } + } + return sentBytes; + } + + + private void validateReceivedMessageContent(byte[] sentBytes, + BytesMessage msg, boolean random, int messageSize) throws JMSException + { + Long length = msg.getBodyLength(); + + if(length != messageSize) + { + throw new RuntimeException("Incorrect number of bytes received"); + } + + byte[] recievedBytes = new byte[length.intValue()]; + msg.readBytes(recievedBytes); + + if(random) + { + if(!Arrays.equals(sentBytes, recievedBytes)) + { + throw new RuntimeException("Incorrect value of bytes received"); + } + } + else + { + for(int r = 0 ; r < messageSize ; r++) + { + if(! (recievedBytes[r] == (byte) (48 + (r % 10)))) + { + throw new RuntimeException("Incorrect value of bytes received"); + } + } + } + } +} + diff --git a/java/tools/src/main/resources/stress-test-client.properties b/java/tools/src/main/resources/stress-test-client.properties new file mode 100644 index 0000000000..2ef8c258b4 --- /dev/null +++ b/java/tools/src/main/resources/stress-test-client.properties @@ -0,0 +1,3 @@ +java.naming.factory.initial = org.apache.qpid.jndi.PropertiesFileInitialContextFactory +connectionfactory.qpidConnectionfactory = amqp://guest:guest@clientid/?brokerlist='tcp://localhost:5672' +connectionfactory.qpidConnectionfactoryLowPrefetch=amqp://guest:guest@clientid/?brokerlist='tcp://localhost:5672?maxprefetch='10'' -- cgit v1.2.1