Repository: activemq Updated Branches: refs/heads/master d983d525c -> 10a74ce73
https://issues.apache.org/jira/browse/AMQ-5943 - patch, with test, applied with thanks to Torsten Mielke Project: http://git-wip-us.apache.org/repos/asf/activemq/repo Commit: http://git-wip-us.apache.org/repos/asf/activemq/commit/10a74ce7 Tree: http://git-wip-us.apache.org/repos/asf/activemq/tree/10a74ce7 Diff: http://git-wip-us.apache.org/repos/asf/activemq/diff/10a74ce7 Branch: refs/heads/master Commit: 10a74ce7374d717defca0905f62e2181a93c6b20 Parents: d983d52 Author: gtully <[email protected]> Authored: Tue Aug 25 12:07:02 2015 +0100 Committer: gtully <[email protected]> Committed: Tue Aug 25 12:07:02 2015 +0100 ---------------------------------------------------------------------- .../security/JaasDualAuthenticationBroker.java | 34 ++-- ...JaasDualAuthenticationNetworkBridgeTest.java | 135 ++++++++++++++ ...alAuthenticationNetworkBridgeTest.properties | 28 +++ ...asDualAuthenticationNetworkBridgeTest.config | 32 ++++ .../JaasDualAuthenticationNetworkBridgeTest.xml | 178 +++++++++++++++++++ ...alAuthenticationNetworkBridgeTest.properties | 31 ++++ ...alAuthenticationNetworkBridgeTest.properties | 21 +++ 7 files changed, 441 insertions(+), 18 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/activemq/blob/10a74ce7/activemq-broker/src/main/java/org/apache/activemq/security/JaasDualAuthenticationBroker.java ---------------------------------------------------------------------- diff --git a/activemq-broker/src/main/java/org/apache/activemq/security/JaasDualAuthenticationBroker.java b/activemq-broker/src/main/java/org/apache/activemq/security/JaasDualAuthenticationBroker.java index 28d8fef..c2aacde 100644 --- a/activemq-broker/src/main/java/org/apache/activemq/security/JaasDualAuthenticationBroker.java +++ b/activemq-broker/src/main/java/org/apache/activemq/security/JaasDualAuthenticationBroker.java @@ -27,7 +27,6 @@ import org.apache.activemq.broker.EmptyBroker; import org.apache.activemq.broker.TransportConnector; import org.apache.activemq.command.ActiveMQDestination; import org.apache.activemq.command.ConnectionInfo; -import org.apache.activemq.transport.tcp.SslTransportServer; /** * A JAAS Authentication Broker that uses different JAAS domain configurations @@ -89,14 +88,7 @@ public class JaasDualAuthenticationBroker extends BrokerFilter implements Authen @Override public void addConnection(ConnectionContext context, ConnectionInfo info) throws Exception { if (context.getSecurityContext() == null) { - boolean isSSL = false; - Connector connector = context.getConnector(); - if (connector instanceof TransportConnector) { - TransportConnector transportConnector = (TransportConnector) connector; - isSSL = transportConnector.getServer().isSslServer(); - } - - if (isSSL) { + if (isSSL(context, info)) { this.sslBroker.addConnection(context, info); } else { this.nonSslBroker.addConnection(context, info); @@ -110,22 +102,28 @@ public class JaasDualAuthenticationBroker extends BrokerFilter implements Authen */ @Override public void removeConnection(ConnectionContext context, ConnectionInfo info, Throwable error) throws Exception { - boolean isSSL; - Connector connector = context.getConnector(); - if (connector instanceof TransportConnector) { - TransportConnector transportConnector = (TransportConnector) connector; - isSSL = (transportConnector.getServer() instanceof SslTransportServer); - } else { - isSSL = false; - } super.removeConnection(context, info, error); - if (isSSL) { + if (isSSL(context, info)) { this.sslBroker.removeConnection(context, info, error); } else { this.nonSslBroker.removeConnection(context, info, error); } } + private boolean isSSL(ConnectionContext context, ConnectionInfo info) throws Exception { + boolean sslCapable = false; + Connector connector = context.getConnector(); + if (connector instanceof TransportConnector) { + TransportConnector transportConnector = (TransportConnector) connector; + sslCapable = transportConnector.getServer().isSslServer(); + } + // AMQ-5943, also check if transport context carries X509 cert + if (!sslCapable && info.getTransportContext() instanceof X509Certificate[]) { + sslCapable = true; + } + return sslCapable; + } + @Override public void removeDestination(ConnectionContext context, ActiveMQDestination destination, long timeout) throws Exception { // Give both a chance to clear out their contexts http://git-wip-us.apache.org/repos/asf/activemq/blob/10a74ce7/activemq-unit-tests/src/test/java/org/apache/activemq/security/JaasDualAuthenticationNetworkBridgeTest.java ---------------------------------------------------------------------- diff --git a/activemq-unit-tests/src/test/java/org/apache/activemq/security/JaasDualAuthenticationNetworkBridgeTest.java b/activemq-unit-tests/src/test/java/org/apache/activemq/security/JaasDualAuthenticationNetworkBridgeTest.java new file mode 100644 index 0000000..30b260f --- /dev/null +++ b/activemq-unit-tests/src/test/java/org/apache/activemq/security/JaasDualAuthenticationNetworkBridgeTest.java @@ -0,0 +1,135 @@ +/** + * 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.security; + +import java.net.URL; +import java.util.Collection; +import java.util.List; + +import org.apache.activemq.broker.BrokerService; +import org.apache.activemq.network.NetworkBridge; +import org.apache.activemq.network.NetworkConnector; +import org.apache.xbean.spring.context.ClassPathXmlApplicationContext; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.Assert; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +/** + * Unit test for https://issues.apache.org/jira/browse/AMQ-5943. + * Creates a network bridge to a broker that is configured for + * JaasDualAuthenticationPlugin. + * The broker that creates the network bridge does not set a + * username/password on the nc configuration but expects to be + * authenticated via its SSL certificate. + * This test uses these external configuration files from + * src/test/resources/ + * - org/apache/activemq/security/JaasDualAuthenticationNetworkBridgeTest.xml + * - login-JaasDualAuthenticationNetworkBridgeTest.config + * - users-JaasDualAuthenticationNetworkBridgeTest.properties + * - groups-JaasDualAuthenticationNetworkBridgeTest.properties + * - ssl-domain-JaasDualAuthenticationNetworkBridgeTest.properties + */ +public class JaasDualAuthenticationNetworkBridgeTest { + protected final static String CONFIG_FILE="org/apache/activemq/security/JaasDualAuthenticationNetworkBridgeTest.xml"; + protected static Logger LOG = LoggerFactory.getLogger(JaasDualAuthenticationNetworkBridgeTest.class); + private BrokerService broker1 = null; + private BrokerService broker2 = null; + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() throws Exception { + LOG.info("Starting up"); + String path = null; + URL resource = JaasDualAuthenticationNetworkBridgeTest.class.getClassLoader().getResource("login-JaasDualAuthenticationNetworkBridgeTest.config"); + if (resource != null) { + path = resource.getFile(); + System.setProperty("java.security.auth.login.config", path); + } + LOG.info("Path to login config: " + path); + + try { + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(CONFIG_FILE); + broker1 = (BrokerService)context.getBean("broker1"); + broker2 = (BrokerService)context.getBean("broker2"); + } + catch(Exception e) { + LOG.error("Error: " + e.getMessage()); + throw e; + } + } + + /** + * @throws java.lang.Exception + */ + @After + public void tearDown() throws Exception { + LOG.info("Shutting down"); + if (broker1 != null && broker1.isStarted()) { + LOG.info("Broker still running, stopping it now."); + broker1.stop(); + } + else { + LOG.info("Broker1 not running, nothing to shutdown."); + } + if (broker2 != null && broker2.isStarted()) { + LOG.info("Broker still running, stopping it now."); + broker2.stop(); + } + else { + LOG.info("Broker2 not running, nothing to shutdown."); + } + } + + + /** + * Waits 5 seconds for the network bridge between broker 1 and 2 to be + * established, then checks if the bridge exists, by querying broker1. + * + * @throws Exception is network bridge does not exist between both + * broker instances. + */ + @Test + public void testNetworkBridgeUsingJaasDualAuthenticationPlugin() throws Exception { + LOG.info("testNetworkBridgeUsingJaasDualAuthenticationPlugin() called."); + try { + // give 5 seconds for broker instances to establish network bridge + Thread.sleep(5000); + + // verify that network bridge is established + Assert.assertNotNull(broker1); + List<NetworkConnector> ncs = broker1.getNetworkConnectors(); + Assert.assertNotNull("Network Connector not found.", ncs); + Assert.assertFalse("Network Connector not found.", ncs.isEmpty()); + NetworkConnector nc =(NetworkConnector)ncs.get(0); + Collection<NetworkBridge> bridges = nc.activeBridges(); + Assert.assertFalse("Network bridge not established to broker 2", bridges.isEmpty()); + Assert.assertTrue("Network bridge not established to broker 2", bridges.size() == 1); + LOG.info("Network bridge is correctly established."); + } catch (java.lang.InterruptedException ex) { + LOG.warn(ex.getMessage()); + } + } +} + http://git-wip-us.apache.org/repos/asf/activemq/blob/10a74ce7/activemq-unit-tests/src/test/resources/groups-JaasDualAuthenticationNetworkBridgeTest.properties ---------------------------------------------------------------------- diff --git a/activemq-unit-tests/src/test/resources/groups-JaasDualAuthenticationNetworkBridgeTest.properties b/activemq-unit-tests/src/test/resources/groups-JaasDualAuthenticationNetworkBridgeTest.properties new file mode 100644 index 0000000..327d09a --- /dev/null +++ b/activemq-unit-tests/src/test/resources/groups-JaasDualAuthenticationNetworkBridgeTest.properties @@ -0,0 +1,28 @@ +## --------------------------------------------------------------------------- +## 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. +## --------------------------------------------------------------------------- + +# +# This file contains the roles for users who can log into JBoss A-MQ. +# Each line has to be of the format: +# +# GROUP=USER1,USER2,.... +# + +# Used by test org.apache.activemq.security.JaasDualAuthenticationNetworkBridgeTest + +admins=admin,adminSSL +administrators=admin,adminSSL http://git-wip-us.apache.org/repos/asf/activemq/blob/10a74ce7/activemq-unit-tests/src/test/resources/login-JaasDualAuthenticationNetworkBridgeTest.config ---------------------------------------------------------------------- diff --git a/activemq-unit-tests/src/test/resources/login-JaasDualAuthenticationNetworkBridgeTest.config b/activemq-unit-tests/src/test/resources/login-JaasDualAuthenticationNetworkBridgeTest.config new file mode 100644 index 0000000..e45af41 --- /dev/null +++ b/activemq-unit-tests/src/test/resources/login-JaasDualAuthenticationNetworkBridgeTest.config @@ -0,0 +1,32 @@ +/** + * 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. + * + * Used by test org.apache.activemq.security.JaasDualAuthenticationNetworkBridgeTest + */ +activemq-domain { + + org.apache.activemq.jaas.PropertiesLoginModule requisite + debug=true + org.apache.activemq.jaas.properties.user="users-JaasDualAuthenticationNetworkBridgeTest.properties" + org.apache.activemq.jaas.properties.group="groups-JaasDualAuthenticationNetworkBridgeTest.properties"; +}; + +activemq-ssl-domain { + org.apache.activemq.jaas.TextFileCertificateLoginModule required + debug=true + org.apache.activemq.jaas.textfiledn.user="ssl-domain-JaasDualAuthenticationNetworkBridgeTest.properties" + org.apache.activemq.jaas.textfiledn.group="groups-JaasDualAuthenticationNetworkBridgeTest.properties"; +}; http://git-wip-us.apache.org/repos/asf/activemq/blob/10a74ce7/activemq-unit-tests/src/test/resources/org/apache/activemq/security/JaasDualAuthenticationNetworkBridgeTest.xml ---------------------------------------------------------------------- diff --git a/activemq-unit-tests/src/test/resources/org/apache/activemq/security/JaasDualAuthenticationNetworkBridgeTest.xml b/activemq-unit-tests/src/test/resources/org/apache/activemq/security/JaasDualAuthenticationNetworkBridgeTest.xml new file mode 100644 index 0000000..7b81018 --- /dev/null +++ b/activemq-unit-tests/src/test/resources/org/apache/activemq/security/JaasDualAuthenticationNetworkBridgeTest.xml @@ -0,0 +1,178 @@ +<!-- + 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. +--> +<beans + xmlns="http://www.springframework.org/schema/beans" + xmlns:amq="http://activemq.apache.org/schema/core" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans-2.0.xsd + http://activemq.apache.org/schema/core + http://activemq.apache.org/schema/core/activemq-core-5.4.2.xsd"> + + <!-- first broker instance --> + <broker xmlns="http://activemq.apache.org/schema/core" brokerName="broker1" id="broker1" + dataDirectory="./target/activemq-data-broker1" persistent="false"> + + <destinationPolicy> + <policyMap> + <policyEntries> + <policyEntry queue=">" memoryLimit="20mb"> + <deadLetterStrategy> + <sharedDeadLetterStrategy processExpired="false" processNonPersistent="false"/> + </deadLetterStrategy> + </policyEntry> + + <policyEntry topic=">" producerFlowControl="true" > + </policyEntry> + </policyEntries> + </policyMap> + </destinationPolicy> + + <managementContext> + <managementContext createConnector="false" /> + </managementContext> + + <!-- network of brokers configuration --> + <networkConnectors> + <networkConnector decreaseNetworkConsumerPriority="true" duplex="true" dynamicOnly="true" name="to-A" networkTTL="2" uri="static://(ssl://localhost:61626)" > + <!-- userName="admin" password="admin" --> + <excludedDestinations> + <queue physicalName="MyQueue"/> + </excludedDestinations> + </networkConnector> + </networkConnectors> + + + <plugins> + <!--jaasAuthenticationPlugin configuration="activemq" /--> + <jaasDualAuthenticationPlugin configuration="activemq-domain" sslConfiguration="activemq-ssl-domain"/> + <authorizationPlugin> + <map> + <authorizationMap> + <authorizationEntries> + <authorizationEntry queue=">" admin="administrators" read="administrators" write="administrators"/> + <authorizationEntry topic=">" admin="administrators" read="administrators" write="administrators"/> + <authorizationEntry topic="ActiveMQ.Advisory.>" admin="*" read="*" write="*"/> + <authorizationEntry queue="ActiveMQ.DLQ" admin="administrators" read="*" write="*"/> + </authorizationEntries> + </authorizationMap> + </map> + </authorizationPlugin> + </plugins> + + + <sslContext> + <sslContext + keyStore="server.keystore" + keyStorePassword="password" + trustStore="server.keystore" + trustStorePassword="password" + /> + </sslContext> + + <systemUsage> + <systemUsage> + <memoryUsage> + <memoryUsage limit="60 mb" /> + </memoryUsage> + <storeUsage> + <storeUsage limit="1 mb" /> + </storeUsage> + <tempUsage> + <tempUsage limit="50 mb" /> + </tempUsage> + </systemUsage> + </systemUsage> + + <transportConnectors> + <transportConnector name="openwire+ssl" uri="ssl://0.0.0.0:62626?transport.closeAsync=false&transport.enabledProtocols=TLSv1,TLSv1.1,TLSv1.2&transport.needClientAuth=true"/> + </transportConnectors> + </broker> + + <!-- second broker instance --> + <broker xmlns="http://activemq.apache.org/schema/core" brokerName="broker2" id="broker2" + dataDirectory="./target/activemq-data-broker2" persistent="false"> + + <destinationPolicy> + <policyMap> + <policyEntries> + <policyEntry queue=">" memoryLimit="20mb"> + <deadLetterStrategy> + <sharedDeadLetterStrategy processExpired="false" processNonPersistent="false"/> + </deadLetterStrategy> + </policyEntry> + + <policyEntry topic=">" producerFlowControl="true" > + <deadLetterStrategy> + <sharedDeadLetterStrategy processExpired="false" processNonPersistent="false"/> + </deadLetterStrategy> + </policyEntry> + </policyEntries> + </policyMap> + </destinationPolicy> + + <managementContext> + <managementContext createConnector="false" /> + </managementContext> + + <plugins> + <!--jaasAuthenticationPlugin configuration="activemq" /--> + <!--jaasCertificateAuthenticationPlugin configuration="activemq-ssl-domain" /--> + <jaasDualAuthenticationPlugin configuration="activemq-domain" sslConfiguration="activemq-ssl-domain"/> + <authorizationPlugin> + <map> + <authorizationMap> + <authorizationEntries> + <authorizationEntry queue=">" admin="administrators" read="administrators" write="administrators"/> + <authorizationEntry topic=">" admin="administrators" read="administrators" write="administrators"/> + <authorizationEntry topic="ActiveMQ.Advisory.>" admin="*" read="*" write="*"/> + <authorizationEntry queue="ActiveMQ.DLQ" admin="administrators" read="*" write="*"/> + </authorizationEntries> + </authorizationMap> + </map> + </authorizationPlugin> + </plugins> + + <sslContext> + <sslContext + keyStore="server.keystore" + keyStorePassword="password" + trustStore="server.keystore" + trustStorePassword="password" + /> + </sslContext> + + <systemUsage> + <systemUsage> + <memoryUsage> + <memoryUsage limit="60 mb" /> + </memoryUsage> + <storeUsage> + <storeUsage limit="1 mb" /> + </storeUsage> + <tempUsage> + <tempUsage limit="50 mb" /> + </tempUsage> + </systemUsage> + </systemUsage> + + <transportConnectors> + <transportConnector name="openwire+ssl-2" uri="ssl://0.0.0.0:61626?transport.closeAsync=false&transport.enabledProtocols=TLSv1,TLSv1.1,TLSv1.2&transport.needClientAuth=true"/> + </transportConnectors> + </broker> +</beans> + http://git-wip-us.apache.org/repos/asf/activemq/blob/10a74ce7/activemq-unit-tests/src/test/resources/ssl-domain-JaasDualAuthenticationNetworkBridgeTest.properties ---------------------------------------------------------------------- diff --git a/activemq-unit-tests/src/test/resources/ssl-domain-JaasDualAuthenticationNetworkBridgeTest.properties b/activemq-unit-tests/src/test/resources/ssl-domain-JaasDualAuthenticationNetworkBridgeTest.properties new file mode 100644 index 0000000..931e673 --- /dev/null +++ b/activemq-unit-tests/src/test/resources/ssl-domain-JaasDualAuthenticationNetworkBridgeTest.properties @@ -0,0 +1,31 @@ +## --------------------------------------------------------------------------- +## Licensed to the Apache Software Foundation (ASF) under one or more +## contributor license agreements. See the NOTICE file distributed with +## this work for additional information regarding copyright ownership. +## The ASF licenses this file to You under the Apache License, Version 2.0 +## (the "License"); you may not use this file except in compliance with +## the License. You may obtain a copy of the License at +## +## http://www.apache.org/licenses/LICENSE-2.0 +## +## Unless required by applicable law or agreed to in writing, software +## distributed under the License is distributed on an "AS IS" BASIS, +## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +## See the License for the specific language governing permissions and +## limitations under the License. +## --------------------------------------------------------------------------- + +################################################################################ +# +# This file contains the valid users who can access this A-MQ using valid SSL certificates. +# Each line has to be of the format: +# +# USER=Sringfied SubjectDN +# +# +# You must have at least one users to be able to access JBoss A-MQ resources + + +# Used by test org.apache.activemq.security.JaasDualAuthenticationNetworkBridgeTest + +adminSSL=CN=localhost, OU=activemq.org, O=activemq.org, L=LA, ST=CA, C=US http://git-wip-us.apache.org/repos/asf/activemq/blob/10a74ce7/activemq-unit-tests/src/test/resources/users-JaasDualAuthenticationNetworkBridgeTest.properties ---------------------------------------------------------------------- diff --git a/activemq-unit-tests/src/test/resources/users-JaasDualAuthenticationNetworkBridgeTest.properties b/activemq-unit-tests/src/test/resources/users-JaasDualAuthenticationNetworkBridgeTest.properties new file mode 100644 index 0000000..a48ce7d --- /dev/null +++ b/activemq-unit-tests/src/test/resources/users-JaasDualAuthenticationNetworkBridgeTest.properties @@ -0,0 +1,21 @@ +## --------------------------------------------------------------------------- +## 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. +## --------------------------------------------------------------------------- + +# +# Used by test org.apache.activemq.security.JaasDualAuthenticationNetworkBridgeTest + +admin=admin
