This closes #3432
This commit is contained in:
commit
76e359279e
|
@ -17,7 +17,6 @@
|
|||
package org.apache.activemq.artemis.protocol.amqp.broker;
|
||||
|
||||
import java.net.URI;
|
||||
import java.security.Principal;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
@ -29,7 +28,6 @@ import org.apache.activemq.artemis.api.core.ActiveMQBuffers;
|
|||
import org.apache.activemq.artemis.api.core.ActiveMQException;
|
||||
import org.apache.activemq.artemis.core.buffers.impl.ChannelBufferWrapper;
|
||||
import org.apache.activemq.artemis.core.client.impl.TopologyMemberImpl;
|
||||
import org.apache.activemq.artemis.core.remoting.CertificateUtil;
|
||||
import org.apache.activemq.artemis.core.remoting.CloseListener;
|
||||
import org.apache.activemq.artemis.core.remoting.FailureListener;
|
||||
import org.apache.activemq.artemis.core.server.ActiveMQServer;
|
||||
|
@ -44,11 +42,10 @@ import org.apache.activemq.artemis.protocol.amqp.proton.AmqpSupport;
|
|||
import org.apache.activemq.artemis.protocol.amqp.proton.handler.ExtCapability;
|
||||
import org.apache.activemq.artemis.protocol.amqp.proton.transaction.ProtonTransactionImpl;
|
||||
import org.apache.activemq.artemis.protocol.amqp.sasl.AnonymousServerSASL;
|
||||
import org.apache.activemq.artemis.protocol.amqp.sasl.ExternalServerSASL;
|
||||
import org.apache.activemq.artemis.protocol.amqp.sasl.GSSAPIServerSASL;
|
||||
import org.apache.activemq.artemis.protocol.amqp.sasl.PlainSASL;
|
||||
import org.apache.activemq.artemis.protocol.amqp.sasl.MechanismFinder;
|
||||
import org.apache.activemq.artemis.protocol.amqp.sasl.SASLResult;
|
||||
import org.apache.activemq.artemis.protocol.amqp.sasl.ServerSASL;
|
||||
import org.apache.activemq.artemis.protocol.amqp.sasl.ServerSASLFactory;
|
||||
import org.apache.activemq.artemis.spi.core.remoting.Connection;
|
||||
import org.apache.activemq.artemis.spi.core.remoting.ReadyListener;
|
||||
import org.apache.activemq.artemis.utils.UUIDGenerator;
|
||||
|
@ -63,7 +60,7 @@ public class AMQPConnectionCallback implements FailureListener, CloseListener {
|
|||
|
||||
private static final Logger logger = Logger.getLogger(AMQPConnectionCallback.class);
|
||||
|
||||
private ConcurrentMap<Binary, Transaction> transactions = new ConcurrentHashMap<>();
|
||||
private final ConcurrentMap<Binary, Transaction> transactions = new ConcurrentHashMap<>();
|
||||
|
||||
private final ProtonProtocolManager manager;
|
||||
|
||||
|
@ -105,36 +102,11 @@ public class AMQPConnectionCallback implements FailureListener, CloseListener {
|
|||
public ServerSASL getServerSASL(final String mechanism) {
|
||||
ServerSASL result = null;
|
||||
if (isPermittedMechanism(mechanism)) {
|
||||
switch (mechanism) {
|
||||
case PlainSASL.NAME:
|
||||
result = new PlainSASL(server.getSecurityStore(), manager.getSecurityDomain(), connection.getProtocolConnection());
|
||||
break;
|
||||
|
||||
case AnonymousServerSASL.NAME:
|
||||
result = new AnonymousServerSASL();
|
||||
break;
|
||||
|
||||
case GSSAPIServerSASL.NAME:
|
||||
GSSAPIServerSASL gssapiServerSASL = new GSSAPIServerSASL();
|
||||
gssapiServerSASL.setLoginConfigScope(manager.getSaslLoginConfigScope());
|
||||
result = gssapiServerSASL;
|
||||
break;
|
||||
|
||||
case ExternalServerSASL.NAME:
|
||||
// validate ssl cert present
|
||||
Principal principal = CertificateUtil.getPeerPrincipalFromConnection(protonConnectionDelegate);
|
||||
if (principal != null) {
|
||||
ExternalServerSASL externalServerSASL = new ExternalServerSASL();
|
||||
externalServerSASL.setPrincipal(principal);
|
||||
result = externalServerSASL;
|
||||
} else {
|
||||
logger.debug("SASL EXTERNAL mechanism requires a TLS peer principal");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
logger.debug("Mo matching mechanism found for: " + mechanism);
|
||||
break;
|
||||
ServerSASLFactory factory = MechanismFinder.getFactory(mechanism);
|
||||
if (factory != null) {
|
||||
result = factory.create(server, manager, connection, protonConnectionDelegate);
|
||||
} else {
|
||||
logger.debug("Mo matching mechanism found for: " + mechanism);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
|
|
@ -88,7 +88,7 @@ public class ProtonProtocolManager extends AbstractProtocolManager<AMQPMessage,
|
|||
|
||||
private int initialRemoteMaxFrameSize = 4 * 1024;
|
||||
|
||||
private String[] saslMechanisms = MechanismFinder.getKnownMechanisms();
|
||||
private String[] saslMechanisms = MechanismFinder.getDefaultMechanisms();
|
||||
|
||||
private String saslLoginConfigScope = "amqp-sasl-gssapi";
|
||||
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* 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.protocol.amqp.sasl;
|
||||
|
||||
import org.apache.activemq.artemis.core.server.ActiveMQServer;
|
||||
import org.apache.activemq.artemis.protocol.amqp.broker.AmqpInterceptor;
|
||||
import org.apache.activemq.artemis.spi.core.protocol.ProtocolManager;
|
||||
import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
|
||||
import org.apache.activemq.artemis.spi.core.remoting.Connection;
|
||||
|
||||
public class AnonymousServerSASLFactory implements ServerSASLFactory {
|
||||
|
||||
@Override
|
||||
public String getMechanism() {
|
||||
return AnonymousServerSASL.NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerSASL create(ActiveMQServer server, ProtocolManager<AmqpInterceptor> manager, Connection connection,
|
||||
RemotingConnection remotingConnection) {
|
||||
return new AnonymousServerSASL();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPrecedence() {
|
||||
return Integer.MIN_VALUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDefaultPermitted() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* 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.protocol.amqp.sasl;
|
||||
|
||||
import java.security.Principal;
|
||||
|
||||
import org.apache.activemq.artemis.core.remoting.CertificateUtil;
|
||||
import org.apache.activemq.artemis.core.server.ActiveMQServer;
|
||||
import org.apache.activemq.artemis.protocol.amqp.broker.AmqpInterceptor;
|
||||
import org.apache.activemq.artemis.spi.core.protocol.ProtocolManager;
|
||||
import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
|
||||
import org.apache.activemq.artemis.spi.core.remoting.Connection;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class ExternalServerSASLFactory implements ServerSASLFactory {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(ExternalServerSASLFactory.class);
|
||||
|
||||
@Override
|
||||
public String getMechanism() {
|
||||
return ExternalServerSASL.NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerSASL create(ActiveMQServer server, ProtocolManager<AmqpInterceptor> manager, Connection connection,
|
||||
RemotingConnection remotingConnection) {
|
||||
// validate ssl cert present
|
||||
Principal principal = CertificateUtil.getPeerPrincipalFromConnection(remotingConnection);
|
||||
if (principal != null) {
|
||||
ExternalServerSASL externalServerSASL = new ExternalServerSASL();
|
||||
externalServerSASL.setPrincipal(principal);
|
||||
return externalServerSASL;
|
||||
}
|
||||
logger.debug("SASL EXTERNAL mechanism requires a TLS peer principal");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPrecedence() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDefaultPermitted() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* 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.protocol.amqp.sasl;
|
||||
|
||||
import org.apache.activemq.artemis.core.server.ActiveMQServer;
|
||||
import org.apache.activemq.artemis.protocol.amqp.broker.AmqpInterceptor;
|
||||
import org.apache.activemq.artemis.protocol.amqp.broker.ProtonProtocolManager;
|
||||
import org.apache.activemq.artemis.spi.core.protocol.ProtocolManager;
|
||||
import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
|
||||
import org.apache.activemq.artemis.spi.core.remoting.Connection;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
public class GSSAPIServerSASLFactory implements ServerSASLFactory {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(GSSAPIServerSASLFactory.class);
|
||||
|
||||
@Override
|
||||
public String getMechanism() {
|
||||
return GSSAPIServerSASL.NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerSASL create(ActiveMQServer server, ProtocolManager<AmqpInterceptor> manager, Connection connection,
|
||||
RemotingConnection remotingConnection) {
|
||||
if (manager instanceof ProtonProtocolManager) {
|
||||
GSSAPIServerSASL gssapiServerSASL = new GSSAPIServerSASL();
|
||||
gssapiServerSASL.setLoginConfigScope(((ProtonProtocolManager) manager).getSaslLoginConfigScope());
|
||||
return gssapiServerSASL;
|
||||
}
|
||||
logger.debug("SASL GSSAPI requires ProtonProtocolManager");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPrecedence() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDefaultPermitted() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -17,11 +17,43 @@
|
|||
|
||||
package org.apache.activemq.artemis.protocol.amqp.sasl;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
public class MechanismFinder {
|
||||
|
||||
public static String[] KNOWN_MECHANISMS = new String[]{PlainSASL.NAME, AnonymousServerSASL.NAME};
|
||||
private static final Map<String, ServerSASLFactory> FACTORY_MAP = new HashMap<>();
|
||||
private static final Comparator<? super ServerSASLFactory> PRECEDENCE_COMPARATOR =
|
||||
(f1, f2) -> Integer.compare(f1.getPrecedence(), f2.getPrecedence());
|
||||
private static final String[] DEFAULT_MECHANISMS;
|
||||
|
||||
public static String[] getKnownMechanisms() {
|
||||
return KNOWN_MECHANISMS;
|
||||
static {
|
||||
ServiceLoader<ServerSASLFactory> serviceLoader =
|
||||
ServiceLoader.load(ServerSASLFactory.class, MechanismFinder.class.getClassLoader());
|
||||
for (ServerSASLFactory factory : serviceLoader) {
|
||||
FACTORY_MAP.merge(factory.getMechanism(), factory, (f1, f2) -> {
|
||||
if (f2.getPrecedence() > f1.getPrecedence()) {
|
||||
return f2;
|
||||
} else {
|
||||
return f1;
|
||||
}
|
||||
});
|
||||
}
|
||||
DEFAULT_MECHANISMS = FACTORY_MAP.values()
|
||||
.stream()
|
||||
.filter(ServerSASLFactory::isDefaultPermitted)
|
||||
.sorted(PRECEDENCE_COMPARATOR.reversed())
|
||||
.map(ServerSASLFactory::getMechanism)
|
||||
.toArray(String[]::new);
|
||||
}
|
||||
|
||||
public static String[] getDefaultMechanisms() {
|
||||
return DEFAULT_MECHANISMS;
|
||||
}
|
||||
|
||||
public static ServerSASLFactory getFactory(String mechanism) {
|
||||
return FACTORY_MAP.get(mechanism);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* 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.protocol.amqp.sasl;
|
||||
|
||||
import org.apache.activemq.artemis.core.server.ActiveMQServer;
|
||||
import org.apache.activemq.artemis.protocol.amqp.broker.AmqpInterceptor;
|
||||
import org.apache.activemq.artemis.spi.core.protocol.ProtocolManager;
|
||||
import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
|
||||
import org.apache.activemq.artemis.spi.core.remoting.Connection;
|
||||
|
||||
public class PlainServerSASLFactory implements ServerSASLFactory {
|
||||
|
||||
@Override
|
||||
public String getMechanism() {
|
||||
return ServerSASLPlain.NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerSASL create(ActiveMQServer server, ProtocolManager<AmqpInterceptor> manager, Connection connection,
|
||||
RemotingConnection remotingConnection) {
|
||||
return new PlainSASL(server.getSecurityStore(), manager.getSecurityDomain(), connection.getProtocolConnection());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPrecedence() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDefaultPermitted() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* 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.protocol.amqp.sasl;
|
||||
|
||||
import org.apache.activemq.artemis.core.server.ActiveMQServer;
|
||||
import org.apache.activemq.artemis.protocol.amqp.broker.AmqpInterceptor;
|
||||
import org.apache.activemq.artemis.spi.core.protocol.ProtocolManager;
|
||||
import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
|
||||
import org.apache.activemq.artemis.spi.core.remoting.Connection;
|
||||
|
||||
/**
|
||||
* A {@link ServerSASLFactory} is responsible for instantiating a given SASL mechanism
|
||||
*/
|
||||
public interface ServerSASLFactory {
|
||||
|
||||
/**
|
||||
* @return the name of the scheme to offer
|
||||
*/
|
||||
String getMechanism();
|
||||
|
||||
/**
|
||||
* creates a new {@link ServerSASL} for the provided context
|
||||
* @param server
|
||||
* @param manager
|
||||
* @param connection
|
||||
* @param remotingConnection
|
||||
* @return a new instance of {@link ServerSASL} that implements the provided mechanism
|
||||
*/
|
||||
ServerSASL create(ActiveMQServer server, ProtocolManager<AmqpInterceptor> manager, Connection connection,
|
||||
RemotingConnection remotingConnection);
|
||||
|
||||
/**
|
||||
* returns the precedence of the given SASL mechanism, the default precedence is zero, where
|
||||
* higher means better
|
||||
* @return the precedence of this mechanism
|
||||
*/
|
||||
int getPrecedence();
|
||||
|
||||
/**
|
||||
* @return <code>true</code> if this mechanism should be part of the servers default permitted
|
||||
* protocols or <code>false</code> if it must be explicitly configured
|
||||
*/
|
||||
boolean isDefaultPermitted();
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
org.apache.activemq.artemis.protocol.amqp.sasl.AnonymousServerSASLFactory
|
||||
org.apache.activemq.artemis.protocol.amqp.sasl.PlainServerSASLFactory
|
||||
org.apache.activemq.artemis.protocol.amqp.sasl.GSSAPIServerSASLFactory
|
||||
org.apache.activemq.artemis.protocol.amqp.sasl.ExternalServerSASLFactory
|
Loading…
Reference in New Issue