diff options
| author | Alex Rudyy <orudyy@apache.org> | 2013-04-17 10:53:55 +0000 |
|---|---|---|
| committer | Alex Rudyy <orudyy@apache.org> | 2013-04-17 10:53:55 +0000 |
| commit | 532bc2b78fb4a136fe035d68e3146ec7b2fa40aa (patch) | |
| tree | 11a46855f979d79063eb2d61a7fceac31e727041 /qpid/java/broker/src | |
| parent | b4af6b6cd3abbbbde7ce1c2799ffde2a1bbcff91 (diff) | |
| download | qpid-python-532bc2b78fb4a136fe035d68e3146ec7b2fa40aa.tar.gz | |
QPID-4746, QPID-4747: remove the defaultAuthenticationProvider attribute from broker and add an overriding authentication provider for management mode
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1468830 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'qpid/java/broker/src')
31 files changed, 768 insertions, 450 deletions
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/Broker.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/Broker.java index 5f0c7c7d3c..dd0fde5f7a 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/Broker.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/Broker.java @@ -134,7 +134,7 @@ public class Broker _applicationRegistry = new ApplicationRegistry(store); try { - _applicationRegistry.initialise(); + _applicationRegistry.initialise(options); } catch(Exception e) { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/BrokerOptions.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/BrokerOptions.java index 8a8f7606a2..5c2a8fd090 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/BrokerOptions.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/BrokerOptions.java @@ -25,6 +25,7 @@ import java.io.File; import org.apache.qpid.server.configuration.BrokerProperties; import org.apache.qpid.server.configuration.ConfigurationEntryStore; import org.apache.qpid.server.configuration.store.MemoryConfigurationEntryStore; +import org.apache.qpid.server.util.StringUtil; public class BrokerOptions { @@ -34,6 +35,8 @@ public class BrokerOptions public static final String DEFAULT_LOG_CONFIG_FILE = "etc/log4j.xml"; public static final String DEFAULT_INITIAL_CONFIG_LOCATION = BrokerOptions.class.getClassLoader().getResource(DEFAULT_INITIAL_CONFIG_NAME).toExternalForm(); + public static final String MANAGEMENT_MODE_USER_NAME = "mm_admin"; + private static final int MANAGEMENT_MODE_PASSWORD_LENGTH = 10; private String _logConfigFile; private Integer _logWatchFrequency = 0; @@ -48,6 +51,7 @@ public class BrokerOptions private int _managementModeRmiPort; private int _managementModeConnectorPort; private int _managementModeHttpPort; + private String _managementModePassword; private String _workingDir; private boolean _skipLoggingConfiguration; private boolean _overwriteConfigurationStore; @@ -57,6 +61,21 @@ public class BrokerOptions return _logConfigFile; } + public String getManagementModePassword() + { + if(_managementModePassword == null) + { + _managementModePassword = new StringUtil().randomAlphaNumericString(MANAGEMENT_MODE_PASSWORD_LENGTH); + } + + return _managementModePassword; + } + + public void setManagementModePassword(String managementModePassword) + { + _managementModePassword = managementModePassword; + } + public void setLogConfigFile(final String logConfigFile) { _logConfigFile = logConfigFile; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java index 28827a8bb5..46612613dd 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java @@ -81,6 +81,8 @@ public class Main .withDescription("override jmx connector port in management mode").withLongOpt("management-mode-jmx-connector-port").create("mmjmx"); private static final Option OPTION_MM_HTTP_PORT = OptionBuilder.withArgName("port").hasArg() .withDescription("override http management port in management mode").withLongOpt("management-mode-http-port").create("mmhttp"); + private static final Option OPTION_MM_PASSWORD = OptionBuilder.withArgName("password").hasArg() + .withDescription("Set the password for the management mode user " + BrokerOptions.MANAGEMENT_MODE_USER_NAME).withLongOpt("management-mode-password").create("mmpass"); private static final Options OPTIONS = new Options(); @@ -100,6 +102,7 @@ public class Main OPTIONS.addOption(OPTION_MM_RMI_PORT); OPTIONS.addOption(OPTION_MM_CONNECTOR_PORT); OPTIONS.addOption(OPTION_MM_HTTP_PORT); + OPTIONS.addOption(OPTION_MM_PASSWORD); } protected CommandLine _commandLine; @@ -256,6 +259,12 @@ public class Main boolean quiesceVhosts = _commandLine.hasOption(OPTION_MM_QUIESCE_VHOST.getOpt()); options.setManagementModeQuiesceVirtualHosts(quiesceVhosts); + + String password = _commandLine.getOptionValue(OPTION_MM_PASSWORD.getOpt()); + if (password != null) + { + options.setManagementModePassword(password); + } } setExceptionHandler(); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/BrokerRecoverer.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/BrokerRecoverer.java index 7251abfab0..be75b4d2e9 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/BrokerRecoverer.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/BrokerRecoverer.java @@ -26,6 +26,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import org.apache.qpid.server.BrokerOptions; import org.apache.qpid.server.configuration.ConfigurationEntry; import org.apache.qpid.server.configuration.ConfiguredObjectRecoverer; import org.apache.qpid.server.configuration.IllegalConfigurationException; @@ -55,10 +56,11 @@ public class BrokerRecoverer implements ConfiguredObjectRecoverer<Broker> private final AuthenticationProviderFactory _authenticationProviderFactory; private final PortFactory _portFactory; private final TaskExecutor _taskExecutor; + private final BrokerOptions _brokerOptions; public BrokerRecoverer(AuthenticationProviderFactory authenticationProviderFactory, PortFactory portFactory, StatisticsGatherer statisticsGatherer, VirtualHostRegistry virtualHostRegistry, LogRecorder logRecorder, - RootMessageLogger rootMessageLogger, TaskExecutor taskExecutor) + RootMessageLogger rootMessageLogger, TaskExecutor taskExecutor, BrokerOptions brokerOptions) { _portFactory = portFactory; _authenticationProviderFactory = authenticationProviderFactory; @@ -67,6 +69,7 @@ public class BrokerRecoverer implements ConfiguredObjectRecoverer<Broker> _logRecorder = logRecorder; _rootMessageLogger = rootMessageLogger; _taskExecutor = taskExecutor; + _brokerOptions = brokerOptions; } @Override @@ -74,38 +77,37 @@ public class BrokerRecoverer implements ConfiguredObjectRecoverer<Broker> { StoreConfigurationChangeListener storeChangeListener = new StoreConfigurationChangeListener(entry.getStore()); BrokerAdapter broker = new BrokerAdapter(entry.getId(), entry.getAttributes(), _statisticsGatherer, _virtualHostRegistry, - _logRecorder, _rootMessageLogger, _authenticationProviderFactory, _portFactory, _taskExecutor, entry.getStore()); + _logRecorder, _rootMessageLogger, _authenticationProviderFactory, _portFactory, _taskExecutor, entry.getStore(), _brokerOptions); broker.addChangeListener(storeChangeListener); //Recover the SSL keystores / truststores first, then others that depend on them Map<String, Collection<ConfigurationEntry>> childEntries = new HashMap<String, Collection<ConfigurationEntry>>(entry.getChildren()); - Map<String, Collection<ConfigurationEntry>> sslChildEntries = new HashMap<String, Collection<ConfigurationEntry>>(childEntries); + Map<String, Collection<ConfigurationEntry>> priorityChildEntries = new HashMap<String, Collection<ConfigurationEntry>>(childEntries); List<String> types = new ArrayList<String>(childEntries.keySet()); for(String type : types) { - if(KeyStore.class.getSimpleName().equals(type) || TrustStore.class.getSimpleName().equals(type)) + if(KeyStore.class.getSimpleName().equals(type) || TrustStore.class.getSimpleName().equals(type) + || AuthenticationProvider.class.getSimpleName().equals(type)) { childEntries.remove(type); } else { - sslChildEntries.remove(type); + priorityChildEntries.remove(type); } } - for (String type : sslChildEntries.keySet()) + for (String type : priorityChildEntries.keySet()) { - recoverType(recovererProvider, storeChangeListener, broker, sslChildEntries, type); + recoverType(recovererProvider, storeChangeListener, broker, priorityChildEntries, type); } for (String type : childEntries.keySet()) { recoverType(recovererProvider, storeChangeListener, broker, childEntries, type); } - wireUpConfiguredObjects(broker, entry.getAttributes()); - return broker; } @@ -132,58 +134,4 @@ public class BrokerRecoverer implements ConfiguredObjectRecoverer<Broker> object.addChangeListener(storeChangeListener); } } - - private void wireUpConfiguredObjects(BrokerAdapter broker, Map<String, Object> brokerAttributes) - { - AuthenticationProvider defaultAuthenticationProvider = null; - Collection<AuthenticationProvider> authenticationProviders = broker.getAuthenticationProviders(); - int numberOfAuthenticationProviders = authenticationProviders.size(); - if (numberOfAuthenticationProviders == 0) - { - throw new IllegalConfigurationException("No authentication provider was configured"); - } - else if (numberOfAuthenticationProviders == 1) - { - defaultAuthenticationProvider = authenticationProviders.iterator().next(); - } - else - { - String name = (String) brokerAttributes.get(Broker.DEFAULT_AUTHENTICATION_PROVIDER); - if (name == null) - { - throw new IllegalConfigurationException("Multiple authentication providers defined, but no default was configured."); - } - - defaultAuthenticationProvider = getAuthenticationProviderByName(broker, name); - } - broker.setDefaultAuthenticationProvider(defaultAuthenticationProvider); - - Collection<Port> ports = broker.getPorts(); - for (Port port : ports) - { - String authenticationProviderName = (String) port.getAttribute(Port.AUTHENTICATION_PROVIDER); - AuthenticationProvider provider = null; - if (authenticationProviderName != null) - { - provider = getAuthenticationProviderByName(broker, authenticationProviderName); - } - else - { - provider = defaultAuthenticationProvider; - } - port.setAuthenticationProvider(provider); - } - } - - private AuthenticationProvider getAuthenticationProviderByName(BrokerAdapter broker, String authenticationProviderName) - { - AuthenticationProvider provider = broker.findAuthenticationProviderByName(authenticationProviderName); - if (provider == null) - { - throw new IllegalConfigurationException("Cannot find the authentication provider with name: " - + authenticationProviderName); - } - return provider; - } - } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/DefaultRecovererProvider.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/DefaultRecovererProvider.java index 15cb229d8a..35209e5b41 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/DefaultRecovererProvider.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/DefaultRecovererProvider.java @@ -20,6 +20,7 @@ */ package org.apache.qpid.server.configuration.startup; +import org.apache.qpid.server.BrokerOptions; import org.apache.qpid.server.configuration.ConfiguredObjectRecoverer; import org.apache.qpid.server.configuration.RecovererProvider; import org.apache.qpid.server.logging.LogRecorder; @@ -54,9 +55,10 @@ public class DefaultRecovererProvider implements RecovererProvider private final QpidServiceLoader<GroupManagerFactory> _groupManagerServiceLoader; private final QpidServiceLoader<PluginFactory> _pluginFactoryServiceLoader; private final TaskExecutor _taskExecutor; + private final BrokerOptions _brokerOptions; public DefaultRecovererProvider(StatisticsGatherer brokerStatisticsGatherer, VirtualHostRegistry virtualHostRegistry, - LogRecorder logRecorder, RootMessageLogger rootMessageLogger, TaskExecutor taskExecutor) + LogRecorder logRecorder, RootMessageLogger rootMessageLogger, TaskExecutor taskExecutor, BrokerOptions brokerOptions) { _authenticationProviderFactory = new AuthenticationProviderFactory(new QpidServiceLoader<AuthenticationManagerFactory>()); _portFactory = new PortFactory(); @@ -67,6 +69,7 @@ public class DefaultRecovererProvider implements RecovererProvider _groupManagerServiceLoader = new QpidServiceLoader<GroupManagerFactory>(); _pluginFactoryServiceLoader = new QpidServiceLoader<PluginFactory>(); _taskExecutor = taskExecutor; + _brokerOptions = brokerOptions; } @Override @@ -75,7 +78,7 @@ public class DefaultRecovererProvider implements RecovererProvider if (Broker.class.getSimpleName().equals(type)) { return new BrokerRecoverer(_authenticationProviderFactory, _portFactory, _brokerStatisticsGatherer, _virtualHostRegistry, - _logRecorder, _rootMessageLogger, _taskExecutor); + _logRecorder, _rootMessageLogger, _taskExecutor, _brokerOptions); } else if(VirtualHost.class.getSimpleName().equals(type)) { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandler.java index 6733c8ee2d..24d5edf00f 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandler.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandler.java @@ -26,6 +26,7 @@ public class ManagementModeStoreHandler implements ConfigurationEntryStore private static final String PORT_TYPE = Port.class.getSimpleName(); private static final String VIRTUAL_HOST_TYPE = VirtualHost.class.getSimpleName(); private static final String ATTRIBUTE_STATE = VirtualHost.STATE; + private static final Object MANAGEMENT_MODE_AUTH_PROVIDER = "mm-auth"; private final ConfigurationEntryStore _store; private final Map<UUID, ConfigurationEntry> _cliEntries; @@ -208,6 +209,10 @@ public class ManagementModeStoreHandler implements ConfigurationEntryStore attributes.put(Port.PORT, port); attributes.put(Port.PROTOCOLS, Collections.singleton(protocol)); attributes.put(Port.NAME, MANAGEMENT_MODE_PORT_PREFIX + protocol.name()); + if (protocol != Protocol.RMI) + { + attributes.put(Port.AUTHENTICATION_PROVIDER, MANAGEMENT_MODE_AUTH_PROVIDER); + } ConfigurationEntry portEntry = new ConfigurationEntry(UUID.randomUUID(), PORT_TYPE, attributes, Collections.<UUID> emptySet(), this); if (LOGGER.isDebugEnabled()) diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/messages/Broker_logmessages.properties b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/messages/Broker_logmessages.properties index 1aa7815c39..76c1fa1b5b 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/messages/Broker_logmessages.properties +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/messages/Broker_logmessages.properties @@ -45,4 +45,6 @@ STATS_MSGS = BRK-1009 : {0,choice,0#delivered|1#received} : {1,number,#.###} msg PLATFORM = BRK-1010 : Platform : JVM : {0} version: {1} OS : {2} version: {3} arch: {4} # 0 Maximum Memory -MAX_MEMORY = BRK-1011 : Maximum Memory : {0,number} bytes
\ No newline at end of file +MAX_MEMORY = BRK-1011 : Maximum Memory : {0,number} bytes + +MANAGEMENT_MODE = BRK-1012 : Management Mode : User Details : {0} / {1}
\ No newline at end of file diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Broker.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Broker.java index 0e230bd552..712b53f627 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Broker.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Broker.java @@ -53,7 +53,6 @@ public interface Broker extends ConfiguredObject String STATE = "state"; String TIME_TO_LIVE = "timeToLive"; String UPDATED = "updated"; - String DEFAULT_AUTHENTICATION_PROVIDER = "defaultAuthenticationProvider"; String DEFAULT_VIRTUAL_HOST = "defaultVirtualHost"; String STATISTICS_REPORTING_PERIOD = "statisticsReportingPeriod"; String STATISTICS_REPORTING_RESET_ENABLED = "statisticsReportingResetEnabled"; @@ -112,7 +111,6 @@ public interface Broker extends ConfiguredObject STATE, TIME_TO_LIVE, UPDATED, - DEFAULT_AUTHENTICATION_PROVIDER, DEFAULT_VIRTUAL_HOST, QUEUE_ALERT_THRESHOLD_MESSAGE_AGE, QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES, @@ -151,8 +149,6 @@ public interface Broker extends ConfiguredObject LifetimePolicy lifetime, long ttl, Map<String, Object> attributes) throws AccessControlException, IllegalArgumentException; - AuthenticationProvider getDefaultAuthenticationProvider(); - Collection<GroupProvider> getGroupProviders(); /** @@ -172,6 +168,8 @@ public interface Broker extends ConfiguredObject */ LogRecorder getLogRecorder(); + AuthenticationProvider findAuthenticationProviderByName(String authenticationProviderName); + VirtualHost findVirtualHostByName(String name); KeyStore findKeyStoreByName(String name); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Port.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Port.java index 7ff5f04ee7..60d62e3f27 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Port.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Port.java @@ -93,7 +93,6 @@ public interface Port extends ConfiguredObject AccessControlException, IllegalArgumentException; - Collection<Protocol> getProtocols(); void addProtocol(Protocol protocol) throws IllegalStateException, @@ -104,12 +103,9 @@ public interface Port extends ConfiguredObject AccessControlException, IllegalArgumentException; + AuthenticationProvider getAuthenticationProvider(); //children Collection<VirtualHostAlias> getVirtualHostBindings(); Collection<Connection> getConnections(); - - AuthenticationProvider getAuthenticationProvider(); - - void setAuthenticationProvider(AuthenticationProvider authenticationProvider); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderAdapter.java index f788923b3a..8d601460ad 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderAdapter.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderAdapter.java @@ -219,10 +219,6 @@ public abstract class AuthenticationProviderAdapter<T extends AuthenticationMana String providerName = getName(); // verify that provider is not in use - if (providerName.equals(_broker.getAttribute(Broker.DEFAULT_AUTHENTICATION_PROVIDER))) - { - throw new IntegrityViolationException("Authentication provider '" + providerName + "' is set as default and cannot be deleted"); - } Collection<Port> ports = new ArrayList<Port>(_broker.getPorts()); for (Port port : ports) { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java index ae30f70877..49af66126c 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java @@ -33,14 +33,15 @@ import java.util.UUID; import org.apache.log4j.Logger; import org.apache.qpid.common.QpidProperties; +import org.apache.qpid.server.BrokerOptions; import org.apache.qpid.server.configuration.ConfigurationEntryStore; import org.apache.qpid.server.configuration.IllegalConfigurationException; -import org.apache.qpid.server.configuration.store.ManagementModeStoreHandler; import org.apache.qpid.server.configuration.updater.TaskExecutor; import org.apache.qpid.server.logging.LogRecorder; import org.apache.qpid.server.logging.RootMessageLogger; import org.apache.qpid.server.logging.actors.BrokerActor; import org.apache.qpid.server.logging.actors.CurrentActor; +import org.apache.qpid.server.logging.messages.BrokerMessages; import org.apache.qpid.server.model.AuthenticationProvider; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.ConfigurationChangeListener; @@ -56,9 +57,12 @@ import org.apache.qpid.server.model.Statistics; import org.apache.qpid.server.model.TrustStore; import org.apache.qpid.server.model.UUIDGenerator; import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.model.adapter.AuthenticationProviderAdapter.SimpleAuthenticationProviderAdapter; import org.apache.qpid.server.security.SecurityManager; import org.apache.qpid.server.security.SubjectCreator; import org.apache.qpid.server.security.access.Operation; +import org.apache.qpid.server.security.auth.manager.AuthenticationManager; +import org.apache.qpid.server.security.auth.manager.SimpleAuthenticationManager; import org.apache.qpid.server.security.group.FileGroupManager; import org.apache.qpid.server.security.group.GroupManager; import org.apache.qpid.server.stats.StatisticsGatherer; @@ -92,7 +96,6 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat put(ACL_FILE, String.class); put(NAME, String.class); put(DEFAULT_VIRTUAL_HOST, String.class); - put(DEFAULT_AUTHENTICATION_PROVIDER, String.class); put(GROUP_FILE, String.class); put(VIRTUALHOST_STORE_TRANSACTION_IDLE_TIMEOUT_CLOSE, Long.class); @@ -168,7 +171,6 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat private final Map<String, TrustStore> _trustStores = new HashMap<String, TrustStore>(); private final AuthenticationProviderFactory _authenticationProviderFactory; - private AuthenticationProvider _defaultAuthenticationProvider; private final PortFactory _portFactory; private final SecurityManager _securityManager; @@ -176,11 +178,12 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat private final Collection<String> _supportedStoreTypes; private final ConfigurationEntryStore _brokerStore; - private boolean _managementMode; + private AuthenticationProvider _managementAuthenticationProvider; + private BrokerOptions _brokerOptions; public BrokerAdapter(UUID id, Map<String, Object> attributes, StatisticsGatherer statisticsGatherer, VirtualHostRegistry virtualHostRegistry, LogRecorder logRecorder, RootMessageLogger rootMessageLogger, AuthenticationProviderFactory authenticationProviderFactory, - PortFactory portFactory, TaskExecutor taskExecutor, ConfigurationEntryStore brokerStore) + PortFactory portFactory, TaskExecutor taskExecutor, ConfigurationEntryStore brokerStore, BrokerOptions brokerOptions) { super(id, DEFAULTS, MapValueConverter.convert(attributes, ATTRIBUTE_TYPES), taskExecutor); _statisticsGatherer = statisticsGatherer; @@ -195,7 +198,15 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat createBrokerChildrenFromAttributes(); _supportedStoreTypes = new MessageStoreCreator().getStoreTypes(); _brokerStore = brokerStore; - _managementMode = brokerStore instanceof ManagementModeStoreHandler; + _brokerOptions = brokerOptions; + createBrokerChildrenFromAttributes(); + if (_brokerOptions.isManagementMode()) + { + AuthenticationManager authManager = new SimpleAuthenticationManager(BrokerOptions.MANAGEMENT_MODE_USER_NAME, _brokerOptions.getManagementModePassword()); + AuthenticationProvider authenticationProvider = new SimpleAuthenticationProviderAdapter(UUID.randomUUID(), this, + authManager, Collections.<String, Object> emptyMap(), Collections.<String> emptySet()); + _managementAuthenticationProvider = authenticationProvider; + } } /* @@ -204,6 +215,7 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat private void createBrokerChildrenFromAttributes() { createGroupProvider(); + } private void createGroupProvider() @@ -250,6 +262,10 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat public AuthenticationProvider findAuthenticationProviderByName(String authenticationProviderName) { + if (isManagementMode()) + { + return _managementAuthenticationProvider; + } Collection<AuthenticationProvider> providers = getAuthenticationProviders(); for (AuthenticationProvider authenticationProvider : providers) { @@ -278,17 +294,6 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat } @Override - public AuthenticationProvider getDefaultAuthenticationProvider() - { - return _defaultAuthenticationProvider; - } - - public void setDefaultAuthenticationProvider(AuthenticationProvider provider) - { - _defaultAuthenticationProvider = provider; - } - - @Override public Collection<GroupProvider> getGroupProviders() { synchronized (_groupProviders) @@ -766,6 +771,11 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat changeState(_portAdapters, currentState,State.ACTIVE, false); changeState(_plugins, currentState,State.ACTIVE, false); + + if (isManagementMode()) + { + CurrentActor.get().message(BrokerMessages.MANAGEMENT_MODE(BrokerOptions.MANAGEMENT_MODE_USER_NAME, _brokerOptions.getManagementModePassword())); + } return true; } else if (desiredState == State.STOPPED) @@ -956,7 +966,7 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat public SubjectCreator getSubjectCreator(SocketAddress localAddress) { InetSocketAddress inetSocketAddress = (InetSocketAddress)localAddress; - AuthenticationProvider provider = _defaultAuthenticationProvider; + AuthenticationProvider provider = null; Collection<Port> ports = getPorts(); for (Port p : ports) { @@ -966,6 +976,12 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat break; } } + + if(provider == null) + { + throw new IllegalConfigurationException("Unable to determine authentication provider for address: " + localAddress); + } + return provider.getSubjectCreator(); } @@ -1002,7 +1018,6 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat @Override protected void changeAttributes(Map<String, Object> attributes) { - //TODO: Add management mode check Map<String, Object> convertedAttributes = MapValueConverter.convert(attributes, ATTRIBUTE_TYPES); validateAttributes(convertedAttributes); @@ -1019,13 +1034,6 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat { createGroupProvider(); } - else if (DEFAULT_AUTHENTICATION_PROVIDER.equals(name)) - { - if (!_defaultAuthenticationProvider.getName().equals(desired)) - { - _defaultAuthenticationProvider = findAuthenticationProviderByName((String)desired); - } - } attributeSet(name, expected, desired); } @@ -1048,16 +1056,6 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat new FileGroupManager(groupFile); } - String defaultAuthenticationProvider = (String) convertedAttributes.get(DEFAULT_AUTHENTICATION_PROVIDER); - if (defaultAuthenticationProvider != null) - { - AuthenticationProvider provider = findAuthenticationProviderByName(defaultAuthenticationProvider); - if (provider == null) - { - throw new IllegalConfigurationException("Authentication provider with name " + defaultAuthenticationProvider - + " canot be set as a default as it does not exist"); - } - } String defaultVirtualHost = (String) convertedAttributes.get(DEFAULT_VIRTUAL_HOST); if (defaultVirtualHost != null) { @@ -1127,6 +1125,6 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat @Override public boolean isManagementMode() { - return _managementMode; + return _brokerOptions.isManagementMode(); } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java index 0c1249d20e..af6b1421a7 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java @@ -82,6 +82,24 @@ public class PortAdapter extends AbstractAdapter implements Port super(id, defaults, MapValueConverter.convert(attributes, ATTRIBUTE_TYPES), taskExecutor); _broker = broker; State state = MapValueConverter.getEnumAttribute(State.class, STATE, attributes, State.INITIALISING); + + Collection<Protocol> protocols = getProtocols(); + boolean rmiRegistry = protocols != null && protocols.contains(Protocol.RMI); + if (!rmiRegistry) + { + String authProvider = (String)getAttribute(Port.AUTHENTICATION_PROVIDER); + if (authProvider == null) + { + throw new IllegalConfigurationException("An authentication provider must be specified for port : " + getName()); + } + _authenticationProvider = broker.findAuthenticationProviderByName(authProvider); + + if(_authenticationProvider == null) + { + throw new IllegalConfigurationException("The authentication provider '" + authProvider + "' could not be found for port : " + getName()); + } + } + _state = new AtomicReference<State>(state); addParent(Broker.class, broker); } @@ -350,11 +368,6 @@ public class PortAdapter extends AbstractAdapter implements Port return _authenticationProvider; } - public void setAuthenticationProvider(AuthenticationProvider authenticationProvider) - { - _authenticationProvider = authenticationProvider; - } - @Override protected void changeAttributes(Map<String, Object> attributes) { @@ -451,6 +464,14 @@ public class PortAdapter extends AbstractAdapter implements Port + authenticationProviderName + "'"); } } + else + { + if (protocols != null && !protocols.contains(Protocol.RMI)) + { + throw new IllegalConfigurationException("An authentication provider must be specified"); + } + } + super.changeAttributes(converted); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java index 1379b375cf..fa5024c1fe 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java @@ -27,6 +27,7 @@ import java.util.TimerTask; import org.apache.log4j.Logger; import org.apache.qpid.common.Closeable; import org.apache.qpid.common.QpidProperties; +import org.apache.qpid.server.BrokerOptions; import org.apache.qpid.server.configuration.BrokerProperties; import org.apache.qpid.server.configuration.ConfigurationEntryStore; import org.apache.qpid.server.configuration.ConfiguredObjectRecoverer; @@ -89,7 +90,7 @@ public class ApplicationRegistry implements IApplicationRegistry initialiseStatistics(); } - public void initialise() throws Exception + public void initialise(BrokerOptions brokerOptions) throws Exception { // Create the RootLogger to be used during broker operation boolean statusUpdatesEnabled = Boolean.parseBoolean(System.getProperty(BrokerProperties.PROPERTY_STATUS_UPDATES, "true")); @@ -112,7 +113,7 @@ public class ApplicationRegistry implements IApplicationRegistry _taskExecutor = new TaskExecutor(); _taskExecutor.start(); - RecovererProvider provider = new DefaultRecovererProvider((StatisticsGatherer)this, _virtualHostRegistry, _logRecorder, _rootMessageLogger, _taskExecutor); + RecovererProvider provider = new DefaultRecovererProvider((StatisticsGatherer)this, _virtualHostRegistry, _logRecorder, _rootMessageLogger, _taskExecutor, brokerOptions); ConfiguredObjectRecoverer<? extends ConfiguredObject> brokerRecoverer = provider.getRecoverer(Broker.class.getSimpleName()); _broker = (Broker) brokerRecoverer.create(provider, _store.getRootEntry()); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java index d12258d194..7341922bd0 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java @@ -20,17 +20,14 @@ */ package org.apache.qpid.server.registry; +import org.apache.qpid.server.BrokerOptions; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.stats.StatisticsGatherer; public interface IApplicationRegistry extends StatisticsGatherer { - /** - * Initialise the application registry. All initialisation must be done in this method so that any components - * that need access to the application registry itself for initialisation are able to use it. Attempting to - * initialise in the constructor will lead to failures since the registry reference will not have been set. - */ - void initialise() throws Exception; + + void initialise(BrokerOptions brokerOptions) throws Exception; /** * Shutdown this Registry diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/jmx/JMXPasswordAuthenticator.java index abb8677e90..bf8d489e61 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/jmx/JMXPasswordAuthenticator.java @@ -18,7 +18,7 @@ * under the License. * */ -package org.apache.qpid.server.security.auth.rmi; +package org.apache.qpid.server.security.auth.jmx; import java.net.SocketAddress; @@ -31,7 +31,7 @@ import org.apache.qpid.server.security.auth.SubjectAuthenticationResult; import javax.management.remote.JMXAuthenticator; import javax.security.auth.Subject; -public class RMIPasswordAuthenticator implements JMXAuthenticator +public class JMXPasswordAuthenticator implements JMXAuthenticator { static final String UNABLE_TO_LOOKUP = "The broker was unable to lookup the user details"; static final String SHOULD_BE_STRING_ARRAY = "User details should be String[]"; @@ -45,7 +45,7 @@ public class RMIPasswordAuthenticator implements JMXAuthenticator private final Broker _broker; private final SocketAddress _address; - public RMIPasswordAuthenticator(Broker broker, SocketAddress address) + public JMXPasswordAuthenticator(Broker broker, SocketAddress address) { _broker = broker; _address = address; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleAuthenticationManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleAuthenticationManager.java new file mode 100644 index 0000000000..903f54dd8e --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleAuthenticationManager.java @@ -0,0 +1,214 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.qpid.server.security.auth.manager; + +import java.io.IOException; +import java.security.Principal; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.NameCallback; +import javax.security.auth.callback.PasswordCallback; +import javax.security.auth.callback.UnsupportedCallbackException; +import javax.security.sasl.AuthorizeCallback; +import javax.security.sasl.Sasl; +import javax.security.sasl.SaslException; +import javax.security.sasl.SaslServer; + +import org.apache.log4j.Logger; +import org.apache.qpid.server.security.auth.AuthenticationResult; +import org.apache.qpid.server.security.auth.UsernamePrincipal; +import org.apache.qpid.server.security.auth.sasl.plain.PlainPasswordCallback; +import org.apache.qpid.server.security.auth.sasl.plain.PlainSaslServer; + +public class SimpleAuthenticationManager implements AuthenticationManager +{ + private static final Logger _logger = Logger.getLogger(SimpleAuthenticationManager.class); + + private static final String PLAIN_MECHANISM = "PLAIN"; + private static final String CRAM_MD5_MECHANISM = "CRAM-MD5"; + + private Map<String, String> _users; + + public SimpleAuthenticationManager(String userName, String userPassword) + { + this(Collections.singletonMap(userName, userPassword)); + } + + public SimpleAuthenticationManager(Map<String, String> users) + { + _users = new HashMap<String, String>(users); + } + + @Override + public void initialise() + { + } + + @Override + public String getMechanisms() + { + return PLAIN_MECHANISM + " " + CRAM_MD5_MECHANISM; + } + + @Override + public SaslServer createSaslServer(String mechanism, String localFQDN, Principal externalPrincipal) throws SaslException + { + if (PLAIN_MECHANISM.equals(mechanism)) + { + return new PlainSaslServer(new SimplePlainCallbackHandler()); + } + else if (CRAM_MD5_MECHANISM.equals(mechanism)) + { + return Sasl.createSaslServer(mechanism, "AMQP", localFQDN, null, new SimpleCramMd5CallbackHandler()); + } + else + { + throw new SaslException("Unknown mechanism: " + mechanism); + } + } + + @Override + public AuthenticationResult authenticate(SaslServer server, byte[] response) + { + try + { + // Process response from the client + byte[] challenge = server.evaluateResponse(response != null ? response : new byte[0]); + + if (server.isComplete()) + { + String authorizationID = server.getAuthorizationID(); + _logger.debug("Authenticated as " + authorizationID); + + return new AuthenticationResult(new UsernamePrincipal(authorizationID)); + } + else + { + return new AuthenticationResult(challenge, AuthenticationResult.AuthenticationStatus.CONTINUE); + } + } + catch (SaslException e) + { + return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR, e); + } + } + + @Override + public AuthenticationResult authenticate(String username, String password) + { + if (_users.containsKey(username)) + { + String userPassword = _users.get(username); + if (userPassword.equals(password)) + { + return new AuthenticationResult(new UsernamePrincipal(username)); + } + } + return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR); + } + + @Override + public void close() + { + } + + @Override + public void onCreate() + { + // nothing to do, no external resource is required + } + + @Override + public void onDelete() + { + // nothing to do, no external resource is used + } + + private class SimpleCramMd5CallbackHandler implements CallbackHandler + { + public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException + { + String username = null; + for (Callback callback : callbacks) + { + if (callback instanceof NameCallback) + { + username = ((NameCallback) callback).getDefaultName(); + } + else if (callback instanceof PasswordCallback) + { + if (_users.containsKey(username)) + { + String password = _users.get(username); + ((PasswordCallback) callback).setPassword(password.toCharArray()); + } + else + { + throw new SaslException("Authentication failed"); + } + } + else if (callback instanceof AuthorizeCallback) + { + ((AuthorizeCallback) callback).setAuthorized(true); + } + else + { + throw new UnsupportedCallbackException(callback); + } + } + } + } + + private class SimplePlainCallbackHandler implements CallbackHandler + { + public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException + { + String username = null; + for (Callback callback : callbacks) + { + if (callback instanceof NameCallback) + { + username = ((NameCallback) callback).getDefaultName(); + } + else if (callback instanceof PlainPasswordCallback) + { + if (_users.containsKey(username)) + { + PlainPasswordCallback plainPasswordCallback = (PlainPasswordCallback) callback; + String password = plainPasswordCallback.getPlainPassword(); + plainPasswordCallback.setAuthenticated(password.equals(_users.get(username))); + } + } + else if (callback instanceof AuthorizeCallback) + { + ((AuthorizeCallback) callback).setAuthorized(true); + } + else + { + throw new UnsupportedCallbackException(callback); + } + } + } + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/util/StringUtil.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/util/StringUtil.java new file mode 100644 index 0000000000..aa17a9493b --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/util/StringUtil.java @@ -0,0 +1,44 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.util; + +import java.util.Random; + +public class StringUtil +{ + private static final String NUMBERS = "0123456789"; + private static final String LETTERS = "abcdefghijklmnopqrstuvwxwy"; + private static final String OTHERS = "_-"; + private static final char[] CHARACTERS = (NUMBERS + LETTERS + LETTERS.toUpperCase() + OTHERS).toCharArray(); + + private Random _random = new Random(); + + public String randomAlphaNumericString(int maxLength) + { + char[] result = new char[maxLength]; + for (int i = 0; i < maxLength; i++) + { + result[i] = (char) CHARACTERS[_random.nextInt(CHARACTERS.length)]; + } + return new String(result); + } + +} diff --git a/qpid/java/broker/src/main/resources/initial-config.json b/qpid/java/broker/src/main/resources/initial-config.json index 44f8fed789..fde3c3a96e 100644 --- a/qpid/java/broker/src/main/resources/initial-config.json +++ b/qpid/java/broker/src/main/resources/initial-config.json @@ -21,7 +21,6 @@ { "name": "QpidBroker", "storeVersion": 1, - "defaultAuthenticationProvider" : "passwordFile", "defaultVirtualHost" : "default", "authenticationproviders" : [ { "name" : "passwordFile", @@ -30,10 +29,12 @@ } ], "ports" : [ { "name" : "AMQP", - "port" : 5672 + "port" : 5672, + "authenticationProvider" : "passwordFile" }, { "name" : "HTTP", "port" : 8080, + "authenticationProvider" : "passwordFile", "protocols" : [ "HTTP" ] }, { "name" : "RMI_REGISTRY", @@ -42,6 +43,7 @@ }, { "name" : "JMX_CONNECTOR", "port" : 9099, + "authenticationProvider" : "passwordFile", "protocols" : [ "JMX_RMI" ] }], "virtualhosts" : [ { diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/BrokerOptionsTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/BrokerOptionsTest.java index c1acf81a1a..08031c36a4 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/BrokerOptionsTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/BrokerOptionsTest.java @@ -220,4 +220,10 @@ public class BrokerOptionsTest extends QpidTestCase _options.setOverwriteConfigurationStore(true); assertTrue(_options.isOverwriteConfigurationStore()); } + + public void testManagementModePassword() + { + _options.setManagementModePassword("test"); + assertEquals("Unexpected management mode password", "test", _options.getManagementModePassword()); + } } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/MainTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/MainTest.java index aab919a828..d7579e2b2a 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/MainTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/MainTest.java @@ -171,6 +171,28 @@ public class MainTest extends QpidTestCase assertEquals(0, options.getManagementModeHttpPort()); } + public void testManagementModePassword() + { + String password = getTestName(); + BrokerOptions options = startDummyMain("-mm -mmpass " + password); + assertTrue(options.isManagementMode()); + assertEquals(password, options.getManagementModePassword()); + + options = startDummyMain("-mm --management-mode-password " + password); + assertTrue(options.isManagementMode()); + assertEquals(password, options.getManagementModePassword()); + + options = startDummyMain("-mmpass " + password); + assertNotNull(options.getManagementModePassword()); + } + + public void testDefaultManagementModePassword() + { + BrokerOptions options = startDummyMain("-mm"); + assertTrue(options.isManagementMode()); + assertNotNull(options.getManagementModePassword()); + } + private BrokerOptions startDummyMain(String commandLine) { return (new TestMain(commandLine.split("\\s"))).getOptions(); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/BrokerRecovererTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/BrokerRecovererTest.java index 3a41b61961..5a8580fd26 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/BrokerRecovererTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/BrokerRecovererTest.java @@ -20,10 +20,8 @@ */ package org.apache.qpid.server.configuration.startup; -import static org.mockito.Mockito.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import static org.mockito.Mockito.verify; import java.util.Arrays; import java.util.Collection; @@ -35,9 +33,9 @@ import java.util.UUID; import junit.framework.TestCase; +import org.apache.qpid.server.BrokerOptions; import org.apache.qpid.server.configuration.ConfigurationEntry; import org.apache.qpid.server.configuration.ConfiguredObjectRecoverer; -import org.apache.qpid.server.configuration.IllegalConfigurationException; import org.apache.qpid.server.configuration.RecovererProvider; import org.apache.qpid.server.logging.LogRecorder; import org.apache.qpid.server.logging.RootMessageLogger; @@ -73,7 +71,7 @@ public class BrokerRecovererTest extends TestCase super.setUp(); _brokerRecoverer = new BrokerRecoverer(mock(AuthenticationProviderFactory.class), mock(PortFactory.class), mock(StatisticsGatherer.class), - mock(VirtualHostRegistry.class), mock(LogRecorder.class), mock(RootMessageLogger.class), mock(TaskExecutor.class)); + mock(VirtualHostRegistry.class), mock(LogRecorder.class), mock(RootMessageLogger.class), mock(TaskExecutor.class), mock(BrokerOptions.class)); when(_brokerEntry.getId()).thenReturn(_brokerId); when(_brokerEntry.getChildren()).thenReturn(_brokerEntryChildren); @@ -89,7 +87,6 @@ public class BrokerRecovererTest extends TestCase { Map<String, Object> attributes = new HashMap<String, Object>(); attributes.put(Broker.DEFAULT_VIRTUAL_HOST, "test"); - attributes.put(Broker.DEFAULT_AUTHENTICATION_PROVIDER, "authenticationProvider1"); attributes.put(Broker.QUEUE_ALERT_THRESHOLD_MESSAGE_AGE, 9l); attributes.put(Broker.QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES, 8l); attributes.put(Broker.QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_BYTES, 7l); @@ -172,24 +169,6 @@ public class BrokerRecovererTest extends TestCase assertEquals(Collections.singletonList(port), broker.getPorts()); } - public void testCreateBrokerWithoutAuthenticationProviderThrowsException() - { - assertNotNull("expected to remove the base entry", _brokerEntryChildren.remove(AuthenticationProvider.class.getSimpleName())); - assertTrue("should be empty", _brokerEntryChildren.isEmpty()); - - RecovererProvider recovererProvider = createRecoveryProvider(new ConfigurationEntry[0], new ConfiguredObject[0]); - - try - { - _brokerRecoverer.create(recovererProvider, _brokerEntry); - fail("should have thrown an exception due to missing authentication provider configuration"); - } - catch(IllegalConfigurationException e) - { - //expected - } - } - public void testCreateBrokerWithOneAuthenticationProvider() { RecovererProvider recovererProvider = createRecoveryProvider(new ConfigurationEntry[]{_authenticationProviderEntry1}, @@ -202,29 +181,6 @@ public class BrokerRecovererTest extends TestCase assertEquals(Collections.singletonList(_authenticationProvider1), broker.getAuthenticationProviders()); } - public void testCreateBrokerWithMultipleAuthenticationProvidersAndNoDefaultThrowsException() - { - AuthenticationProvider authenticationProvider2 = mock(AuthenticationProvider.class); - when(authenticationProvider2.getName()).thenReturn("authenticationProvider2"); - ConfigurationEntry authenticationProviderEntry2 = mock(ConfigurationEntry.class); - _brokerEntryChildren.put(AuthenticationProvider.class.getSimpleName(), Arrays.asList(_authenticationProviderEntry1, authenticationProviderEntry2)); - - Map<String,Object> emptyBrokerAttributes = new HashMap<String,Object>(); - when(_brokerEntry.getAttributes()).thenReturn(emptyBrokerAttributes); - - RecovererProvider recovererProvider = createRecoveryProvider(new ConfigurationEntry[]{authenticationProviderEntry2, _authenticationProviderEntry1}, - new ConfiguredObject[]{authenticationProvider2, _authenticationProvider1}); - try - { - _brokerRecoverer.create(recovererProvider, _brokerEntry); - fail("should have thrown an exception due to missing authentication provider default"); - } - catch(IllegalConfigurationException e) - { - //expected - } - } - public void testCreateBrokerWithMultipleAuthenticationProvidersAndPorts() { //Create a second authentication provider @@ -233,13 +189,10 @@ public class BrokerRecovererTest extends TestCase ConfigurationEntry authenticationProviderEntry2 = mock(ConfigurationEntry.class); _brokerEntryChildren.put(AuthenticationProvider.class.getSimpleName(), Arrays.asList(_authenticationProviderEntry1, authenticationProviderEntry2)); - //Set the default authentication provider Map<String,Object> brokerAtttributes = new HashMap<String,Object>(); when(_brokerEntry.getAttributes()).thenReturn(brokerAtttributes); - brokerAtttributes.put(Broker.DEFAULT_AUTHENTICATION_PROVIDER, "authenticationProvider2"); - //Add a couple ports, one with a defined authentication provider and - //one without (which should then use the default) + //Add a couple ports ConfigurationEntry portEntry1 = mock(ConfigurationEntry.class); Port port1 = mock(Port.class); when(port1.getName()).thenReturn("port1"); @@ -249,6 +202,7 @@ public class BrokerRecovererTest extends TestCase Port port2 = mock(Port.class); when(port2.getName()).thenReturn("port2"); when(port2.getPort()).thenReturn(5672); + when(port2.getAttribute(Port.AUTHENTICATION_PROVIDER)).thenReturn("authenticationProvider2"); _brokerEntryChildren.put(Port.class.getSimpleName(), Arrays.asList(portEntry1, portEntry2)); RecovererProvider recovererProvider = createRecoveryProvider( @@ -258,47 +212,12 @@ public class BrokerRecovererTest extends TestCase Broker broker = _brokerRecoverer.create(recovererProvider, _brokerEntry); assertNotNull(broker); - assertEquals("Unexpected number of authentication providers", 2,broker.getAuthenticationProviders().size()); + assertEquals("Unexpected number of authentication providers", 2, broker.getAuthenticationProviders().size()); Collection<Port> ports = broker.getPorts(); assertEquals("Unexpected number of ports", 2, ports.size()); assertTrue(ports.contains(port1)); assertTrue(ports.contains(port2)); - - verify(port1).setAuthenticationProvider(any(AuthenticationProvider.class)); - verify(port1).setAuthenticationProvider(_authenticationProvider1); - - verify(port2).setAuthenticationProvider(any(AuthenticationProvider.class)); - verify(port2).setAuthenticationProvider(authenticationProvider2); - } - - public void testCreateBrokerAssignsGroupAccessorToAuthenticationProviders() - { - //Create a second authentication provider - AuthenticationProvider authenticationProvider2 = mock(AuthenticationProvider.class); - when(authenticationProvider2.getName()).thenReturn("authenticationProvider2"); - ConfigurationEntry authenticationProviderEntry2 = mock(ConfigurationEntry.class); - _brokerEntryChildren.put(AuthenticationProvider.class.getSimpleName(), Arrays.asList(_authenticationProviderEntry1, authenticationProviderEntry2)); - - //Set the default authentication provider - Map<String,Object> brokerAtttributes = new HashMap<String,Object>(); - when(_brokerEntry.getAttributes()).thenReturn(brokerAtttributes); - brokerAtttributes.put(Broker.DEFAULT_AUTHENTICATION_PROVIDER, "authenticationProvider2"); - - //Create a group provider - ConfigurationEntry groupProviderEntry = mock(ConfigurationEntry.class); - GroupProvider groupProvider = mock(GroupProvider.class); - _brokerEntryChildren.put(GroupProvider.class.getSimpleName(), Arrays.asList(groupProviderEntry)); - - RecovererProvider recovererProvider = createRecoveryProvider( - new ConfigurationEntry[]{groupProviderEntry, authenticationProviderEntry2, _authenticationProviderEntry1}, - new ConfiguredObject[]{groupProvider, authenticationProvider2, _authenticationProvider1}); - - Broker broker = _brokerRecoverer.create(recovererProvider, _brokerEntry); - - assertNotNull(broker); - assertEquals("Unexpected number of authentication providers", 2, broker.getAuthenticationProviders().size()); - } public void testCreateBrokerWithGroupProvider() diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/DefaultRecovererProviderTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/DefaultRecovererProviderTest.java index 96f2474c2d..b958ba1f56 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/DefaultRecovererProviderTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/DefaultRecovererProviderTest.java @@ -23,6 +23,7 @@ package org.apache.qpid.server.configuration.startup; import static org.mockito.Mockito.mock; import junit.framework.TestCase; +import org.apache.qpid.server.BrokerOptions; import org.apache.qpid.server.configuration.ConfiguredObjectRecoverer; import org.apache.qpid.server.logging.LogRecorder; import org.apache.qpid.server.logging.RootMessageLogger; @@ -54,7 +55,7 @@ public class DefaultRecovererProviderTest extends TestCase RootMessageLogger rootMessageLogger = mock(RootMessageLogger.class); TaskExecutor taskExecutor = mock(TaskExecutor.class); - DefaultRecovererProvider provider = new DefaultRecovererProvider(statisticsGatherer, virtualHostRegistry, logRecorder, rootMessageLogger, taskExecutor); + DefaultRecovererProvider provider = new DefaultRecovererProvider(statisticsGatherer, virtualHostRegistry, logRecorder, rootMessageLogger, taskExecutor, mock(BrokerOptions.class)); for (String configuredObjectType : supportedTypes) { ConfiguredObjectRecoverer<?> recovever = provider.getRecoverer(configuredObjectType); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/store/ConfigurationEntryStoreTestCase.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/store/ConfigurationEntryStoreTestCase.java index 7d253d56f0..fc21706bc0 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/store/ConfigurationEntryStoreTestCase.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/store/ConfigurationEntryStoreTestCase.java @@ -60,7 +60,6 @@ public abstract class ConfigurationEntryStoreTestCase extends QpidTestCase _brokerId = UUID.randomUUID(); _brokerAttributes = new HashMap<String, Object>(); _brokerAttributes.put(Broker.DEFAULT_VIRTUAL_HOST, "test"); - _brokerAttributes.put(Broker.DEFAULT_AUTHENTICATION_PROVIDER, "authenticationProvider1"); _brokerAttributes.put(Broker.QUEUE_ALERT_THRESHOLD_MESSAGE_AGE, 9); _brokerAttributes.put(Broker.QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES, 8); _brokerAttributes.put(Broker.QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_BYTES, 7); @@ -171,7 +170,6 @@ public abstract class ConfigurationEntryStoreTestCase extends QpidTestCase ConfigurationEntry brokerConfigEntry = _store.getRootEntry(); Map<String, Object> attributes = new HashMap<String, Object>(); attributes.put(Broker.DEFAULT_VIRTUAL_HOST, "test"); - attributes.put(Broker.DEFAULT_AUTHENTICATION_PROVIDER, "authenticationProvider1"); attributes.put(Broker.QUEUE_ALERT_THRESHOLD_MESSAGE_AGE, 19); attributes.put(Broker.QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES, 18); attributes.put(Broker.QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_BYTES, 17); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/model/BrokerShutdownTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/model/BrokerShutdownTest.java index 7c1db6348b..eb5c672eb8 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/model/BrokerShutdownTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/model/BrokerShutdownTest.java @@ -23,6 +23,7 @@ package org.apache.qpid.server.model; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import org.apache.qpid.server.BrokerOptions; import org.apache.qpid.server.configuration.ConfigurationEntry; import org.apache.qpid.server.configuration.ConfigurationEntryStore; import org.apache.qpid.server.configuration.ConfiguredObjectRecoverer; @@ -121,7 +122,7 @@ public class BrokerShutdownTest extends QpidTestCase RootMessageLogger rootMessageLogger = mock(RootMessageLogger.class); // recover the broker from the store - RecovererProvider provider = new DefaultRecovererProvider(statisticsGatherer, virtualHostRegistry, logRecorder, rootMessageLogger, _taskExecutor); + RecovererProvider provider = new DefaultRecovererProvider(statisticsGatherer, virtualHostRegistry, logRecorder, rootMessageLogger, _taskExecutor, mock(BrokerOptions.class)); ConfiguredObjectRecoverer<? extends ConfiguredObject> brokerRecoverer = provider.getRecoverer(Broker.class.getSimpleName()); Broker broker = (Broker) brokerRecoverer.create(provider, store.getRootEntry()); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/PortFactoryTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/PortFactoryTest.java index 53fb1a0620..54826b8c88 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/PortFactoryTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/PortFactoryTest.java @@ -36,6 +36,7 @@ import java.util.UUID; import org.apache.qpid.server.configuration.BrokerProperties; import org.apache.qpid.server.configuration.IllegalConfigurationException; +import org.apache.qpid.server.model.AuthenticationProvider; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.KeyStore; import org.apache.qpid.server.model.Port; @@ -58,19 +59,22 @@ public class PortFactoryTest extends QpidTestCase private Broker _broker = mock(Broker.class); private KeyStore _keyStore = mock(KeyStore.class); private TrustStore _trustStore = mock(TrustStore.class); - + private String _authProviderName = "authProvider"; + private AuthenticationProvider _authProvider = mock(AuthenticationProvider.class); private PortFactory _portFactory; @Override protected void setUp() throws Exception { + when(_broker.findAuthenticationProviderByName(_authProviderName)).thenReturn(_authProvider); + setTestSystemProperty(BrokerProperties.PROPERTY_BROKER_DEFAULT_AMQP_PROTOCOL_EXCLUDES, null); setTestSystemProperty(BrokerProperties.PROPERTY_BROKER_DEFAULT_AMQP_PROTOCOL_INCLUDES, null); _portFactory = new PortFactory(); _attributes.put(Port.PORT, _portNumber); _attributes.put(Port.TRANSPORTS, _tcpStringSet); - + _attributes.put(Port.AUTHENTICATION_PROVIDER, _authProviderName); _attributes.put(Port.TCP_NO_DELAY, "true"); _attributes.put(Port.RECEIVE_BUFFER_SIZE, "1"); _attributes.put(Port.SEND_BUFFER_SIZE, "2"); @@ -111,6 +115,7 @@ public class PortFactoryTest extends QpidTestCase { Map<String, Object> attributes = new HashMap<String, Object>(); attributes.put(Port.PORT, 1); + attributes.put(Port.AUTHENTICATION_PROVIDER, _authProviderName); Port port = _portFactory.createPort(_portId, _broker, attributes); assertNotNull(port); @@ -273,6 +278,7 @@ public class PortFactoryTest extends QpidTestCase Set<String> nonAmqpStringSet = Collections.singleton(Protocol.JMX_RMI.name()); _attributes = new HashMap<String, Object>(); _attributes.put(Port.PROTOCOLS, nonAmqpStringSet); + _attributes.put(Port.AUTHENTICATION_PROVIDER, _authProviderName); _attributes.put(Port.PORT, _portNumber); _attributes.put(Port.TRANSPORTS, _tcpStringSet); @@ -298,6 +304,7 @@ public class PortFactoryTest extends QpidTestCase Set<String> nonAmqpStringSet = Collections.singleton(Protocol.JMX_RMI.name()); _attributes = new HashMap<String, Object>(); _attributes.put(Port.PROTOCOLS, nonAmqpStringSet); + _attributes.put(Port.AUTHENTICATION_PROVIDER, _authProviderName); _attributes.put(Port.PORT, _portNumber); Port port = _portFactory.createPort(_portId, _broker, _attributes); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabase.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabase.java deleted file mode 100644 index c41b9bf081..0000000000 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabase.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * - */ -package org.apache.qpid.server.security.auth.database; - -import org.apache.qpid.server.security.auth.sasl.AuthenticationProviderInitialiser; -import org.apache.qpid.server.security.auth.UsernamePrincipal; -import org.apache.qpid.server.security.auth.sasl.crammd5.CRAMMD5Initialiser; -import org.apache.qpid.server.security.auth.sasl.plain.PlainInitialiser; - -import javax.security.auth.callback.PasswordCallback; -import javax.security.auth.login.AccountNotFoundException; - -import java.io.File; -import java.io.IOException; -import java.security.Principal; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Properties; - -public class PropertiesPrincipalDatabase implements PrincipalDatabase -{ - private Properties _users; - - private Map<String, AuthenticationProviderInitialiser> _saslServers; - - public PropertiesPrincipalDatabase(Properties users) - { - _users = users; - - _saslServers = new HashMap<String, AuthenticationProviderInitialiser>(); - - /** - * Create Authenticators for Properties Principal Database. - */ - - // Accept MD5 incomming and use plain comparison with the file - PlainInitialiser cram = new PlainInitialiser(); - cram.initialise(this); - // Accept Plain incomming and hash it for comparison to the file. - CRAMMD5Initialiser plain = new CRAMMD5Initialiser(); - plain.initialise(this, CRAMMD5Initialiser.HashDirection.INCOMMING); - - _saslServers.put(plain.getMechanismName(), cram); - _saslServers.put(cram.getMechanismName(), plain); - } - - public void setPassword(Principal principal, PasswordCallback callback) throws IOException, AccountNotFoundException - { - if (principal == null) - { - throw new IllegalArgumentException("principal must not be null"); - } - - - - final String pwd = _users.getProperty(principal.getName()); - - if (pwd != null) - { - callback.setPassword(pwd.toCharArray()); - } - else - { - throw new AccountNotFoundException("No account found for principal " + principal); - } - } - - public boolean verifyPassword(String principal, char[] password) throws AccountNotFoundException - { - //fixme this is not correct as toCharArray is not safe based on the type of string. - char[] pwd = _users.getProperty(principal).toCharArray(); - - return compareCharArray(pwd, password); - } - - public boolean updatePassword(Principal principal, char[] password) throws AccountNotFoundException - { - return false; // updates denied - } - - public boolean createPrincipal(Principal principal, char[] password) - { - return false; // updates denied - } - - public boolean deletePrincipal(Principal principal) throws AccountNotFoundException - { - return false; // updates denied - } - - private boolean compareCharArray(char[] a, char[] b) - { - boolean equal = false; - if (a.length == b.length) - { - equal = true; - int index = 0; - while (equal && index < a.length) - { - equal = a[index] == b[index]; - index++; - } - } - return equal; - } - - - public Map<String, AuthenticationProviderInitialiser> getMechanisms() - { - return _saslServers; - } - - public List<Principal> getUsers() - { - return new LinkedList<Principal>(); //todo - } - - public Principal getUser(String username) - { - if (_users.getProperty(username) != null) - { - return new UsernamePrincipal(username); - } - else - { - return null; - } - } - - public void reload() throws IOException - { - //No file to update from, so do nothing. - } - - @Override - public void open(File passwordFile) - { - throw new UnsupportedOperationException(); - } -} diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticatorTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/jmx/JMXPasswordAuthenticatorTest.java index 52b525dd80..a4dd97e6a1 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticatorTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/jmx/JMXPasswordAuthenticatorTest.java @@ -18,7 +18,7 @@ * under the License. * */ -package org.apache.qpid.server.security.auth.rmi; +package org.apache.qpid.server.security.auth.jmx; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.any; @@ -38,14 +38,15 @@ import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.security.SubjectCreator; import org.apache.qpid.server.security.auth.AuthenticationResult; import org.apache.qpid.server.security.auth.AuthenticationResult.AuthenticationStatus; +import org.apache.qpid.server.security.auth.jmx.JMXPasswordAuthenticator; import org.apache.qpid.server.security.auth.SubjectAuthenticationResult; import org.apache.qpid.server.security.SecurityManager; /** - * Tests the RMIPasswordAuthenticator and its collaboration with the AuthenticationManager. + * Tests the JMXPasswordAuthenticator and its collaboration with the AuthenticationManager. * */ -public class RMIPasswordAuthenticatorTest extends TestCase +public class JMXPasswordAuthenticatorTest extends TestCase { private static final String USERNAME = "guest"; private static final String PASSWORD = "password"; @@ -55,7 +56,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase private final Subject _loginSubject = new Subject(); private final String[] _credentials = new String[] {USERNAME, PASSWORD}; - private RMIPasswordAuthenticator _rmipa; + private JMXPasswordAuthenticator _rmipa; private SubjectCreator _usernamePasswordOkaySuvjectCreator = createMockSubjectCreator(true, null); private SubjectCreator _badPasswordSubjectCreator = createMockSubjectCreator(false, null); @@ -63,7 +64,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase protected void setUp() throws Exception { when(_broker.getSecurityManager()).thenReturn(_securityManager); - _rmipa = new RMIPasswordAuthenticator(_broker, new InetSocketAddress(8999)); + _rmipa = new JMXPasswordAuthenticator(_broker, new InetSocketAddress(8999)); } /** @@ -93,7 +94,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase catch (SecurityException se) { assertEquals("Unexpected exception message", - RMIPasswordAuthenticator.INVALID_CREDENTIALS, se.getMessage()); + JMXPasswordAuthenticator.INVALID_CREDENTIALS, se.getMessage()); } } @@ -110,7 +111,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase catch (SecurityException se) { assertEquals("Unexpected exception message", - RMIPasswordAuthenticator.USER_NOT_AUTHORISED_FOR_MANAGEMENT, se.getMessage()); + JMXPasswordAuthenticator.USER_NOT_AUTHORISED_FOR_MANAGEMENT, se.getMessage()); } } @@ -164,7 +165,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase catch (SecurityException se) { assertEquals("Unexpected exception message", - RMIPasswordAuthenticator.SHOULD_BE_STRING_ARRAY, se.getMessage()); + JMXPasswordAuthenticator.SHOULD_BE_STRING_ARRAY, se.getMessage()); } } @@ -185,7 +186,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase catch (SecurityException se) { assertEquals("Unexpected exception message", - RMIPasswordAuthenticator.SHOULD_HAVE_2_ELEMENTS, se.getMessage()); + JMXPasswordAuthenticator.SHOULD_HAVE_2_ELEMENTS, se.getMessage()); } // Test handling of null credentials @@ -199,7 +200,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase catch (SecurityException se) { assertEquals("Unexpected exception message", - RMIPasswordAuthenticator.CREDENTIALS_REQUIRED, se.getMessage()); + JMXPasswordAuthenticator.CREDENTIALS_REQUIRED, se.getMessage()); } try @@ -212,7 +213,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase catch (SecurityException se) { assertEquals("Unexpected exception message", - RMIPasswordAuthenticator.SHOULD_BE_NON_NULL, se.getMessage()); + JMXPasswordAuthenticator.SHOULD_BE_NON_NULL, se.getMessage()); } try @@ -225,7 +226,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase catch (SecurityException se) { assertEquals("Unexpected exception message", - RMIPasswordAuthenticator.SHOULD_BE_NON_NULL, se.getMessage()); + JMXPasswordAuthenticator.SHOULD_BE_NON_NULL, se.getMessage()); } } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/SimpleAuthenticationManagerTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/SimpleAuthenticationManagerTest.java new file mode 100644 index 0000000000..5868f44b8f --- /dev/null +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/SimpleAuthenticationManagerTest.java @@ -0,0 +1,140 @@ +package org.apache.qpid.server.security.auth.manager; + +import java.security.Principal; +import java.util.Set; + +import javax.security.sasl.SaslException; +import javax.security.sasl.SaslServer; + +import org.apache.qpid.server.security.auth.AuthenticationResult; +import org.apache.qpid.server.security.auth.AuthenticationResult.AuthenticationStatus; +import org.apache.qpid.server.security.auth.sasl.SaslUtil; +import org.apache.qpid.server.security.auth.sasl.plain.PlainSaslServer; +import org.apache.qpid.test.utils.QpidTestCase; + +public class SimpleAuthenticationManagerTest extends QpidTestCase +{ + private static final String TEST_USER = "testUser"; + private static final String TEST_PASSWORD = "testPassword"; + private AuthenticationManager _authenticationManager; + + public void setUp() throws Exception + { + super.setUp(); + _authenticationManager = new SimpleAuthenticationManager(TEST_USER, TEST_PASSWORD); + } + + public void testGetMechanisms() + { + assertEquals("Unexpected mechanisms", "PLAIN CRAM-MD5", _authenticationManager.getMechanisms()); + } + + public void testCreateSaslServerForUnsupportedMechanisms() throws Exception + { + String[] unsupported = new String[] { "EXTERNAL", "CRAM-MD5-HEX", "CRAM-MD5-HASHED", "ANONYMOUS", "GSSAPI"}; + for (int i = 0; i < unsupported.length; i++) + { + String mechanism = unsupported[i]; + try + { + _authenticationManager.createSaslServer(mechanism, "test", null); + fail("Mechanism " + mechanism + " should not be supported by SimpleAuthenticationManager"); + } + catch (SaslException e) + { + // pass + } + } + } + + public void testAuthenticateWithPlainSaslServer() throws Exception + { + AuthenticationResult result = authenticatePlain(TEST_USER, TEST_PASSWORD); + assertAuthenticated(result); + } + + public void testAuthenticateWithPlainSaslServerInvalidPassword() throws Exception + { + AuthenticationResult result = authenticatePlain(TEST_USER, "wrong-password"); + assertUnauthenticated(result); + } + + public void testAuthenticateWithPlainSaslServerInvalidUsername() throws Exception + { + AuthenticationResult result = authenticatePlain("wrong-user", TEST_PASSWORD); + assertUnauthenticated(result); + } + + public void testAuthenticateWithCramMd5SaslServer() throws Exception + { + AuthenticationResult result = authenticateCramMd5(TEST_USER, TEST_PASSWORD); + assertAuthenticated(result); + } + + public void testAuthenticateWithCramMd5SaslServerInvalidPassword() throws Exception + { + AuthenticationResult result = authenticateCramMd5(TEST_USER, "wrong-password"); + assertUnauthenticated(result); + } + + public void testAuthenticateWithCramMd5SaslServerInvalidUsername() throws Exception + { + AuthenticationResult result = authenticateCramMd5("wrong-user", TEST_PASSWORD); + assertUnauthenticated(result); + } + + public void testAuthenticateValidCredentials() + { + AuthenticationResult result = _authenticationManager.authenticate(TEST_USER, TEST_PASSWORD); + assertEquals("Unexpected authentication result", AuthenticationStatus.SUCCESS, result.getStatus()); + assertAuthenticated(result); + } + + public void testAuthenticateInvalidPassword() + { + AuthenticationResult result = _authenticationManager.authenticate(TEST_USER, "invalid"); + assertUnauthenticated(result); + } + + public void testAuthenticateInvalidUserName() + { + AuthenticationResult result = _authenticationManager.authenticate("invalid", TEST_PASSWORD); + assertUnauthenticated(result); + } + + private void assertAuthenticated(AuthenticationResult result) + { + assertEquals("Unexpected authentication result", AuthenticationStatus.SUCCESS, result.getStatus()); + Principal principal = result.getMainPrincipal(); + assertEquals("Unexpected principal name", TEST_USER, principal.getName()); + Set<Principal> principals = result.getPrincipals(); + assertEquals("Unexpected principals size", 1, principals.size()); + assertEquals("Unexpected principal name", TEST_USER, principals.iterator().next().getName()); + } + + private void assertUnauthenticated(AuthenticationResult result) + { + assertEquals("Unexpected authentication result", AuthenticationStatus.ERROR, result.getStatus()); + assertNull("Unexpected principal", result.getMainPrincipal()); + Set<Principal> principals = result.getPrincipals(); + assertEquals("Unexpected principals size", 0, principals.size()); + } + + private AuthenticationResult authenticatePlain(String userName, String userPassword) throws SaslException, Exception + { + PlainSaslServer ss = (PlainSaslServer) _authenticationManager.createSaslServer("PLAIN", "test", null); + byte[] response = SaslUtil.generatePlainClientResponse(userName, userPassword); + + return _authenticationManager.authenticate(ss, response); + } + + private AuthenticationResult authenticateCramMd5(String userName, String userPassword) throws SaslException, Exception + { + SaslServer ss = _authenticationManager.createSaslServer("CRAM-MD5", "test", null); + byte[] challenge = ss.evaluateResponse(new byte[0]); + byte[] response = SaslUtil.generateCramMD5ClientResponse(userName, userPassword, challenge); + + AuthenticationResult result = _authenticationManager.authenticate(ss, response); + return result; + } +} diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/CRAMMD5HexInitialiserTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/CRAMMD5HexInitialiserTest.java index e408fd73d5..3079222b1c 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/CRAMMD5HexInitialiserTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/CRAMMD5HexInitialiserTest.java @@ -20,88 +20,94 @@ */ package org.apache.qpid.server.security.auth.sasl; -import junit.framework.TestCase; - -import org.apache.qpid.server.security.auth.database.PropertiesPrincipalDatabase; -import org.apache.qpid.server.security.auth.sasl.crammd5.CRAMMD5HexInitialiser; +import java.io.File; +import java.io.UnsupportedEncodingException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import javax.security.auth.callback.Callback; import javax.security.auth.callback.NameCallback; import javax.security.auth.callback.PasswordCallback; -import javax.security.auth.callback.UnsupportedCallbackException; -import java.io.IOException; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.Properties; + +import junit.framework.TestCase; + +import org.apache.qpid.server.security.auth.database.Base64MD5PasswordFilePrincipalDatabase; +import org.apache.qpid.server.security.auth.database.PrincipalDatabase; +import org.apache.qpid.server.security.auth.sasl.crammd5.CRAMMD5HexInitialiser; +import org.apache.qpid.test.utils.TestFileUtils; +import org.apache.qpid.tools.security.Passwd; /** * These tests ensure that the Hex wrapping that the initialiser performs does actually operate when the handle method is called. */ public class CRAMMD5HexInitialiserTest extends TestCase { - public void testHex() - { - //Create User details for testing - String user = "testUser"; - String password = "testPassword"; + private static final String TEST_PASSWORD = "testPassword"; + private static final String TEST_USER = "testUser"; + private File _file; - perform(user, password); - } - - public void testHashedHex() + public void testHashedHex() throws Exception { - //Create User details for testing - String user = "testUser"; - String password = "testPassword"; - - //Create a hashed password that we then attempt to put through the call back mechanism. - try - { - password = new String(MessageDigest.getInstance("MD5").digest(password.getBytes())); - } - catch (NoSuchAlgorithmException e) - { - fail(e.getMessage()); - } - - perform(user, password); + perform(TEST_USER, getHash(TEST_PASSWORD)); } - public void perform(String user, String password) + public void perform(String user, char[] password) throws Exception { CRAMMD5HexInitialiser initialiser = new CRAMMD5HexInitialiser(); - //Use properties to create a PrincipalDatabase - Properties users = new Properties(); - users.put(user, password); - - PropertiesPrincipalDatabase db = new PropertiesPrincipalDatabase(users); - + PrincipalDatabase db = new Base64MD5PasswordFilePrincipalDatabase(); + db.open(_file); initialiser.initialise(db); - //setup the callbacks PasswordCallback passwordCallback = new PasswordCallback("password:", false); NameCallback usernameCallback = new NameCallback("user:", user); Callback[] callbacks = new Callback[]{usernameCallback, passwordCallback}; - //Check the - try + assertNull("The password was not null before the handle call.", passwordCallback.getPassword()); + initialiser.getCallbackHandler().handle(callbacks); + + assertArrayEquals(toHex(password), passwordCallback.getPassword()); + } + + public void setUp() throws Exception + { + super.setUp(); + _file = TestFileUtils.createTempFile(this, "password-file", new Passwd().getOutput(TEST_USER , TEST_PASSWORD)); + } + + public void tearDown() throws Exception + { + if (_file != null) { - assertNull("The password was not null before the handle call.", passwordCallback.getPassword()); - initialiser.getCallbackHandler().handle(callbacks); + _file.delete(); } - catch (IOException e) + super.tearDown(); + } + + private char[] getHash(String text) throws NoSuchAlgorithmException, UnsupportedEncodingException + { + + byte[] data = text.getBytes("utf-8"); + + MessageDigest md = MessageDigest.getInstance("MD5"); + + for (byte b : data) { - fail(e.getMessage()); + md.update(b); } - catch (UnsupportedCallbackException e) + + byte[] digest = md.digest(); + + char[] hash = new char[digest.length]; + + int index = 0; + for (byte b : digest) { - fail(e.getMessage()); + hash[index++] = (char) b; } - //Hex the password we initialised with and compare it with the passwordCallback - assertArrayEquals(toHex(password.toCharArray()), passwordCallback.getPassword()); + return hash; } private void assertArrayEquals(char[] expected, char[] actual) @@ -135,4 +141,5 @@ public class CRAMMD5HexInitialiserTest extends TestCase return hex; } + } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/SaslUtil.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/SaslUtil.java new file mode 100644 index 0000000000..251ebc4c81 --- /dev/null +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/SaslUtil.java @@ -0,0 +1,85 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.security.auth.sasl; + +import java.security.MessageDigest; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; + +public class SaslUtil +{ + + private static byte SEPARATOR = 0; + + public static byte[] generatePlainClientResponse(String userName, String userPassword) throws Exception + { + byte[] password = userPassword.getBytes("UTF8"); + byte user[] = userName.getBytes("UTF8"); + byte response[] = new byte[password.length + user.length + 2]; + int size = 0; + response[size++] = SEPARATOR; + System.arraycopy(user, 0, response, size, user.length); + size += user.length; + response[size++] = SEPARATOR; + System.arraycopy(password, 0, response, size, password.length); + return response; + } + + public static byte[] generateCramMD5HexClientResponse(String userName, String userPassword, byte[] challengeBytes) + throws Exception + { + String macAlgorithm = "HmacMD5"; + byte[] digestedPasswordBytes = MessageDigest.getInstance("MD5").digest(userPassword.getBytes("UTF-8")); + byte[] hexEncodedDigestedPasswordBytes = toHex(digestedPasswordBytes).getBytes("UTF-8"); + Mac mac = Mac.getInstance(macAlgorithm); + mac.init(new SecretKeySpec(hexEncodedDigestedPasswordBytes, macAlgorithm)); + final byte[] messageAuthenticationCode = mac.doFinal(challengeBytes); + String responseAsString = userName + " " + toHex(messageAuthenticationCode); + return responseAsString.getBytes(); + } + + public static byte[] generateCramMD5ClientResponse(String userName, String userPassword, byte[] challengeBytes) + throws Exception + { + String macAlgorithm = "HmacMD5"; + Mac mac = Mac.getInstance(macAlgorithm); + mac.init(new SecretKeySpec(userPassword.getBytes("UTF-8"), macAlgorithm)); + final byte[] messageAuthenticationCode = mac.doFinal(challengeBytes); + String responseAsString = userName + " " + toHex(messageAuthenticationCode); + return responseAsString.getBytes(); + } + + public static String toHex(byte[] data) + { + StringBuffer hash = new StringBuffer(); + for (int i = 0; i < data.length; i++) + { + String hex = Integer.toHexString(0xFF & data[i]); + if (hex.length() == 1) + { + hash.append('0'); + } + hash.append(hex); + } + return hash.toString(); + } +} diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/util/StringUtilTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/util/StringUtilTest.java new file mode 100644 index 0000000000..93b4172792 --- /dev/null +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/util/StringUtilTest.java @@ -0,0 +1,38 @@ +package org.apache.qpid.server.util; + +import org.apache.qpid.server.util.StringUtil; +import org.apache.qpid.test.utils.QpidTestCase; + +public class StringUtilTest extends QpidTestCase +{ + private StringUtil _util; + + @Override + public void setUp() throws Exception + { + super.setUp(); + _util = new StringUtil(); + } + + public void testRandomAlphaNumericStringInt() + { + String password = _util.randomAlphaNumericString(10); + assertEquals("Unexpected password string length", 10, password.length()); + assertCharacters(password); + } + + private void assertCharacters(String password) + { + String numbers = "0123456789"; + String letters = "abcdefghijklmnopqrstuvwxwy"; + String others = "_-"; + String expectedCharacters = (numbers + letters + letters.toUpperCase() + others); + char[] chars = password.toCharArray(); + for (int i = 0; i < chars.length; i++) + { + char ch = chars[i]; + assertTrue("Unexpected character " + ch, expectedCharacters.indexOf(ch) != -1); + } + } + +} |
