From 8d98fc395f18e949c99e45fb151730d3b21f5019 Mon Sep 17 00:00:00 2001 From: Clebert Suconic Date: Fri, 28 Aug 2015 13:47:04 -0400 Subject: [PATCH] Refactoring Auth this is doing some refactoring, making the SecurityStore mechnism possible to be reused on other protocols, without forcing them to implement ServerSession on checks that won't fit the Server Model from Artemis --- .../protocol/openwire/OpenWireConnection.java | 36 +++++++++++- .../openwire/OpenWireProtocolManager.java | 14 ++--- .../openwire/amq/AMQServerSession.java | 5 -- .../artemis/core/security/SecurityAuth.java | 26 +++++++++ .../artemis/core/security/SecurityStore.java | 3 +- .../core/security/impl/SecurityStoreImpl.java | 4 +- .../artemis/core/server/ActiveMQServer.java | 9 ++- .../artemis/core/server/ServerSession.java | 7 +-- .../core/server/impl/ActiveMQServerImpl.java | 57 ++++++++++--------- .../core/server/impl/ServerSessionImpl.java | 28 +-------- 10 files changed, 107 insertions(+), 82 deletions(-) create mode 100644 artemis-server/src/main/java/org/apache/activemq/artemis/core/security/SecurityAuth.java diff --git a/artemis-protocols/artemis-openwire-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/openwire/OpenWireConnection.java b/artemis-protocols/artemis-openwire-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/openwire/OpenWireConnection.java index 3155794d81..ffe2b38241 100644 --- a/artemis-protocols/artemis-openwire-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/openwire/OpenWireConnection.java +++ b/artemis-protocols/artemis-openwire-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/openwire/OpenWireConnection.java @@ -51,6 +51,7 @@ import org.apache.activemq.artemis.core.protocol.openwire.amq.AMQSingleConsumerB import org.apache.activemq.artemis.core.protocol.openwire.amq.AMQTransaction; import org.apache.activemq.artemis.core.remoting.CloseListener; import org.apache.activemq.artemis.core.remoting.FailureListener; +import org.apache.activemq.artemis.core.security.SecurityAuth; import org.apache.activemq.artemis.core.server.ActiveMQServerLogger; import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection; import org.apache.activemq.artemis.spi.core.remoting.Acceptor; @@ -105,7 +106,7 @@ import org.apache.activemq.wireformat.WireFormat; /** * Represents an activemq connection. */ -public class OpenWireConnection implements RemotingConnection, CommandVisitor { +public class OpenWireConnection implements RemotingConnection, CommandVisitor, SecurityAuth { private final OpenWireProtocolManager protocolManager; @@ -190,6 +191,39 @@ public class OpenWireConnection implements RemotingConnection, CommandVisitor { this.creationTime = System.currentTimeMillis(); } + + // SecurityAuth implementation + @Override + public String getUsername() { + ConnectionInfo info = getConnectionInfo(); + if (info == null) { + return null; + } + return info.getUserName(); + } + + // SecurityAuth implementation + @Override + public String getPassword() { + ConnectionInfo info = getConnectionInfo(); + if (info == null) { + return null; + } + return info.getPassword(); + } + + + private ConnectionInfo getConnectionInfo() { + if (state == null) { + return null; + } + ConnectionInfo info = state.getInfo(); + if (info == null) { + return null; + } + return info; + } + public String getLocalAddress() { return transportConnection.getLocalAddress(); } diff --git a/artemis-protocols/artemis-openwire-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/openwire/OpenWireProtocolManager.java b/artemis-protocols/artemis-openwire-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/openwire/OpenWireProtocolManager.java index 98b41abc0f..007266206f 100644 --- a/artemis-protocols/artemis-openwire-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/openwire/OpenWireProtocolManager.java +++ b/artemis-protocols/artemis-openwire-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/openwire/OpenWireProtocolManager.java @@ -47,14 +47,12 @@ import org.apache.activemq.artemis.core.protocol.openwire.amq.AMQConnectionConte import org.apache.activemq.artemis.core.protocol.openwire.amq.AMQConsumer; import org.apache.activemq.artemis.core.protocol.openwire.amq.AMQPersistenceAdapter; import org.apache.activemq.artemis.core.protocol.openwire.amq.AMQProducerBrokerExchange; -import org.apache.activemq.artemis.core.protocol.openwire.amq.AMQServerSession; import org.apache.activemq.artemis.core.protocol.openwire.amq.AMQSession; import org.apache.activemq.artemis.core.remoting.impl.netty.NettyServerConnection; import org.apache.activemq.artemis.core.security.CheckType; import org.apache.activemq.artemis.core.server.ActiveMQServer; import org.apache.activemq.artemis.core.server.ActiveMQServerLogger; import org.apache.activemq.artemis.core.server.Queue; -import org.apache.activemq.artemis.core.server.impl.ActiveMQServerImpl; import org.apache.activemq.artemis.core.server.management.ManagementService; import org.apache.activemq.artemis.core.server.management.Notification; import org.apache.activemq.artemis.core.server.management.NotificationListener; @@ -583,21 +581,17 @@ public class OpenWireProtocolManager implements ProtocolManager, No ActiveMQDestination dest = info.getDestination(); if (dest.isQueue()) { SimpleString qName = OpenWireUtil.toCoreAddress(dest); - ConnectionState state = connection.getState(); - ConnectionInfo connInfo = state.getInfo(); - if (connInfo != null) { - String user = connInfo.getUserName(); - String pass = connInfo.getPassword(); + if (connection.getState().getInfo() != null) { - AMQServerSession fakeSession = new AMQServerSession(user, pass); CheckType checkType = dest.isTemporary() ? CheckType.CREATE_NON_DURABLE_QUEUE : CheckType.CREATE_DURABLE_QUEUE; - ((ActiveMQServerImpl) server).getSecurityStore().check(qName, checkType, fakeSession); + server.getSecurityStore().check(qName, checkType, connection); - ((ActiveMQServerImpl) server).checkQueueCreationLimit(user); + server.checkQueueCreationLimit(connection.getUsername()); } QueueBinding binding = (QueueBinding) server.getPostOffice().getBinding(qName); if (binding == null) { + ConnectionInfo connInfo = connection.getState().getInfo(); this.server.createQueue(qName, qName, null, connInfo == null ? null : SimpleString.toSimpleString(connInfo.getUserName()), false, dest.isTemporary()); } if (dest.isTemporary()) { diff --git a/artemis-protocols/artemis-openwire-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/openwire/amq/AMQServerSession.java b/artemis-protocols/artemis-openwire-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/openwire/amq/AMQServerSession.java index 4094a823ef..642eda9be5 100644 --- a/artemis-protocols/artemis-openwire-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/openwire/amq/AMQServerSession.java +++ b/artemis-protocols/artemis-openwire-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/openwire/amq/AMQServerSession.java @@ -88,11 +88,6 @@ public class AMQServerSession extends ServerSessionImpl { super(name, username, password, minLargeMessageSize, autoCommitSends, autoCommitAcks, preAcknowledge, persistDeliveryCountBeforeDelivery, xa, connection, storageManager, postOffice, resourceManager, securityStore, managementService, activeMQServerImpl, managementAddress, simpleString, callback, context, new AMQTransactionFactory(), queueCreator); } - //create a fake session just for security check - public AMQServerSession(String user, String pass) { - super(user, pass); - } - protected void doClose(final boolean failed) throws Exception { synchronized (this) { if (tx != null && tx.getXid() == null) { diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/security/SecurityAuth.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/security/SecurityAuth.java new file mode 100644 index 0000000000..1325e3945a --- /dev/null +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/security/SecurityAuth.java @@ -0,0 +1,26 @@ +/** + * 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.activemq.artemis.core.security; + +public interface SecurityAuth { + + String getUsername(); + + String getPassword(); + +} diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/security/SecurityStore.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/security/SecurityStore.java index 1456f7c221..466e7cf382 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/security/SecurityStore.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/security/SecurityStore.java @@ -17,13 +17,12 @@ package org.apache.activemq.artemis.core.security; import org.apache.activemq.artemis.api.core.SimpleString; -import org.apache.activemq.artemis.core.server.ServerSession; public interface SecurityStore { void authenticate(String user, String password) throws Exception; - void check(SimpleString address, CheckType checkType, ServerSession session) throws Exception; + void check(SimpleString address, CheckType checkType, SecurityAuth session) throws Exception; boolean isSecurityEnabled(); diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/security/impl/SecurityStoreImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/security/impl/SecurityStoreImpl.java index 143cf05ea2..209b42415f 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/security/impl/SecurityStoreImpl.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/security/impl/SecurityStoreImpl.java @@ -25,10 +25,10 @@ import org.apache.activemq.artemis.api.core.management.CoreNotificationType; import org.apache.activemq.artemis.api.core.management.ManagementHelper; import org.apache.activemq.artemis.core.security.CheckType; import org.apache.activemq.artemis.core.security.Role; +import org.apache.activemq.artemis.core.security.SecurityAuth; import org.apache.activemq.artemis.core.security.SecurityStore; import org.apache.activemq.artemis.core.server.ActiveMQMessageBundle; import org.apache.activemq.artemis.core.server.ActiveMQServerLogger; -import org.apache.activemq.artemis.core.server.ServerSession; import org.apache.activemq.artemis.core.server.management.Notification; import org.apache.activemq.artemis.core.server.management.NotificationService; import org.apache.activemq.artemis.core.settings.HierarchicalRepository; @@ -138,7 +138,7 @@ public class SecurityStoreImpl implements SecurityStore, HierarchicalRepositoryC public void check(final SimpleString address, final CheckType checkType, - final ServerSession session) throws Exception { + final SecurityAuth session) throws Exception { if (securityEnabled) { if (trace) { ActiveMQServerLogger.LOGGER.trace("checking access permissions to " + address); diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQServer.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQServer.java index f1811baf92..d7a298d954 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQServer.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQServer.java @@ -33,6 +33,7 @@ import org.apache.activemq.artemis.core.postoffice.PostOffice; import org.apache.activemq.artemis.core.remoting.server.RemotingService; import org.apache.activemq.artemis.core.replication.ReplicationManager; import org.apache.activemq.artemis.core.security.Role; +import org.apache.activemq.artemis.core.security.SecurityAuth; import org.apache.activemq.artemis.core.security.SecurityStore; import org.apache.activemq.artemis.core.server.cluster.ClusterManager; import org.apache.activemq.artemis.core.server.cluster.ha.HAPolicy; @@ -104,6 +105,8 @@ public interface ActiveMQServer extends ActiveMQComponent { void unregisterActivateCallback(ActivateCallback callback); + void checkQueueCreationLimit(String username) throws Exception; + ServerSession createSession(String name, String username, String password, @@ -221,12 +224,12 @@ public interface ActiveMQServer extends ActiveMQComponent { void destroyQueue(SimpleString queueName) throws Exception; - void destroyQueue(SimpleString queueName, ServerSession session) throws Exception; + void destroyQueue(SimpleString queueName, SecurityAuth session) throws Exception; - void destroyQueue(SimpleString queueName, ServerSession session, boolean checkConsumerCount) throws Exception; + void destroyQueue(SimpleString queueName, SecurityAuth session, boolean checkConsumerCount) throws Exception; void destroyQueue(SimpleString queueName, - ServerSession session, + SecurityAuth session, boolean checkConsumerCount, boolean removeConsumers) throws Exception; diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ServerSession.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ServerSession.java index 66ebf93306..ab6dd0da7b 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ServerSession.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ServerSession.java @@ -23,18 +23,15 @@ import java.util.Set; import org.apache.activemq.artemis.api.core.SimpleString; import org.apache.activemq.artemis.core.message.impl.MessageInternal; import org.apache.activemq.artemis.core.persistence.OperationContext; +import org.apache.activemq.artemis.core.security.SecurityAuth; import org.apache.activemq.artemis.core.transaction.Transaction; import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection; import org.apache.activemq.artemis.utils.json.JSONArray; -public interface ServerSession { +public interface ServerSession extends SecurityAuth { String getName(); - String getUsername(); - - String getPassword(); - int getMinLargeMessageSize(); Object getConnectionID(); diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java index 885315423e..07f88bc85e 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java @@ -16,6 +16,30 @@ */ package org.apache.activemq.artemis.core.server.impl; +import javax.management.MBeanServer; +import java.io.File; +import java.io.FilenameFilter; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.lang.management.ManagementFactory; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; + import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration; import org.apache.activemq.artemis.api.core.Pair; import org.apache.activemq.artemis.api.core.SimpleString; @@ -29,9 +53,9 @@ import org.apache.activemq.artemis.core.config.impl.ConfigurationImpl; import org.apache.activemq.artemis.core.filter.Filter; import org.apache.activemq.artemis.core.filter.impl.FilterImpl; import org.apache.activemq.artemis.core.io.IOCriticalErrorListener; -import org.apache.activemq.artemis.core.journal.JournalLoadInformation; import org.apache.activemq.artemis.core.io.SequentialFile; import org.apache.activemq.artemis.core.io.aio.AIOSequentialFileFactory; +import org.apache.activemq.artemis.core.journal.JournalLoadInformation; import org.apache.activemq.artemis.core.management.impl.ActiveMQServerControlImpl; import org.apache.activemq.artemis.core.paging.PagingManager; import org.apache.activemq.artemis.core.paging.cursor.PageSubscription; @@ -58,6 +82,7 @@ import org.apache.activemq.artemis.core.remoting.server.impl.RemotingServiceImpl import org.apache.activemq.artemis.core.replication.ReplicationManager; import org.apache.activemq.artemis.core.security.CheckType; import org.apache.activemq.artemis.core.security.Role; +import org.apache.activemq.artemis.core.security.SecurityAuth; import org.apache.activemq.artemis.core.security.SecurityStore; import org.apache.activemq.artemis.core.security.impl.SecurityStoreImpl; import org.apache.activemq.artemis.core.server.ActivateCallback; @@ -107,30 +132,6 @@ import org.apache.activemq.artemis.utils.ReusableLatch; import org.apache.activemq.artemis.utils.SecurityFormatter; import org.apache.activemq.artemis.utils.VersionLoader; -import javax.management.MBeanServer; -import java.io.File; -import java.io.FilenameFilter; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.lang.management.ManagementFactory; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.TimeUnit; - /** * The ActiveMQ Artemis server implementation */ @@ -1182,18 +1183,18 @@ public class ActiveMQServerImpl implements ActiveMQServer { destroyQueue(queueName, null, true); } - public void destroyQueue(final SimpleString queueName, final ServerSession session) throws Exception { + public void destroyQueue(final SimpleString queueName, final SecurityAuth session) throws Exception { destroyQueue(queueName, session, true); } public void destroyQueue(final SimpleString queueName, - final ServerSession session, + final SecurityAuth session, final boolean checkConsumerCount) throws Exception { destroyQueue(queueName, session, checkConsumerCount, false); } public void destroyQueue(final SimpleString queueName, - final ServerSession session, + final SecurityAuth session, final boolean checkConsumerCount, final boolean removeConsumers) throws Exception { addressSettingsRepository.clearCache(); diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerSessionImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerSessionImpl.java index d9f65a91f2..7c09a4c4d8 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerSessionImpl.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerSessionImpl.java @@ -172,30 +172,6 @@ public class ServerSessionImpl implements ServerSession, FailureListener { private final TransactionFactory transactionFactory; - //create an 'empty' session. Only used by AMQServerSession - //in order to check username and password - protected ServerSessionImpl(String username, String password) { - this.username = username; - this.password = password; - - this.transactionFactory = null; - this.strictUpdateDeliveryCount = false; - this.storageManager = null; - this.server = null; - this.securityStore = null; - this.resourceManager = null; - this.remotingConnection = null; - this.preAcknowledge = false; - this.postOffice = null; - this.name = null; - this.minLargeMessageSize = 0; - this.managementService = null; - this.managementAddress = null; - this.context = null; - this.callback = null; - this.queueCreator = null; - } - public ServerSessionImpl(final String name, final String username, final String password, @@ -494,7 +470,7 @@ public class ServerSessionImpl implements ServerSession, FailureListener { securityStore.check(address, CheckType.CREATE_NON_DURABLE_QUEUE, this); } - ((ActiveMQServerImpl) server).checkQueueCreationLimit(getUsername()); + server.checkQueueCreationLimit(getUsername()); Queue queue; @@ -538,7 +514,7 @@ public class ServerSessionImpl implements ServerSession, FailureListener { final SimpleString filterString) throws Exception { securityStore.check(address, CheckType.CREATE_NON_DURABLE_QUEUE, this); - ((ActiveMQServerImpl) server).checkQueueCreationLimit(getUsername()); + server.checkQueueCreationLimit(getUsername()); server.createSharedQueue(address, name, filterString, SimpleString.toSimpleString(getUsername()), durable); }