From 7715b5ee128d2a629c2e5940247e86be91a694fc Mon Sep 17 00:00:00 2001
From: jbertram This example shows you how to configure 2-way SSL along with 2 different authentications mechanisms so that SSL and non-SSL clients can send and consume messages to/from ActiveMQ Artemis.
+ The non-SSL authentication mechanism simply uses username and password. The SSL authentication mechanism uses the client's certificate. To configure 2-way SSL you need to configure the acceptor as follows:
+ JMS SSL Dual Authentication Example
+
+ To run the example, simply type mvn verify from this directory,
+
+
or mvn -PnoServer verify if you want to start and create the server manually.
+
+
+ <!-- Acceptor -->
+
+ <acceptor name="netty-ssl-acceptor">tcp://localhost:5500?sslEnabled=true;needClientAuth=true;keyStorePath=${data.dir}/../etc/server-side-keystore.jks;keyStorePassword=secureexample;trustStorePath=${data.dir}/../etc/server-side-truststore.jks;trustStorePassword=secureexample</acceptor>
+
+
In the server-side URL, the server-side-keystore.jks is the key store file holding the server's certificate. The server-side-truststore.jks is the file holding the certificates which the server trusts. Notice also the "sslEnabled" and "needClientAuth" parameters which enable SSL and require clients to present their own certificate respectively. Here's the URL the client uses to connect over SSL:
+ ++
+
+ tcp://localhost:5500?sslEnabled=true&trustStorePath=activemq/server0/client-side-truststore.jks&trustStorePassword=secureexample&keyStorePath=activemq/server0/client-side-keystore.jks&keyStorePassword=secureexample
+
+
+
+
+ In the client-side URL, the client-side-keystore.jks is the key store file holding the client's certificate. The client-side-truststore.jks is the file holding the certificates which the client trusts. The "sslEnabled" parameter is present here as well just as it is on the server.
+ +The various keystore files are generated using the following commands:
+ ++
+
+keytool -genkey -keystore server-side-keystore.jks -storepass secureexample -keypass secureexample -dname "CN=ActiveMQ Artemis Server, OU=Artemis, O=ActiveMQ, L=AMQ, S=AMQ, C=AMQ" -keyalg RSA
+keytool -export -keystore server-side-keystore.jks -file server-side-cert.cer -storepass secureexample
+keytool -import -keystore client-side-truststore.jks -file server-side-cert.cer -storepass secureexample -keypass secureexample -noprompt
+keytool -genkey -keystore client-side-keystore.jks -storepass secureexample -keypass secureexample -dname "CN=ActiveMQ Artemis Client, OU=Artemis, O=ActiveMQ, L=AMQ, S=AMQ, C=AMQ" -keyalg RSA
+keytool -export -keystore client-side-keystore.jks -file client-side-cert.cer -storepass secureexample
+keytool -import -keystore server-side-truststore.jks -file client-side-cert.cer -storepass secureexample -keypass secureexample -noprompt
+
+
+
+
+
+
diff --git a/examples/features/standard/ssl-enabled-dual-authentication/src/main/java/org/apache/activemq/artemis/jms/example/SSLDualAuthenticationExample.java b/examples/features/standard/ssl-enabled-dual-authentication/src/main/java/org/apache/activemq/artemis/jms/example/SSLDualAuthenticationExample.java
new file mode 100644
index 00000000000..a3c928e5867
--- /dev/null
+++ b/examples/features/standard/ssl-enabled-dual-authentication/src/main/java/org/apache/activemq/artemis/jms/example/SSLDualAuthenticationExample.java
@@ -0,0 +1,99 @@
+/*
+ * 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.jms.example;
+
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Queue;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+import javax.naming.InitialContext;
+
+/**
+ * A simple JMS Queue example that uses dual broker authentication mechanisms for SSL and non-SSL connections.
+ */
+public class SSLDualAuthenticationExample {
+
+ public static void main(final String[] args) throws Exception {
+ Connection producerConnection = null;
+ Connection consumerConnection = null;
+ InitialContext initialContext = null;
+ try {
+ // Step 1. Create an initial context to perform the JNDI lookup.
+ initialContext = new InitialContext();
+
+ // Step 2. Perfom a lookup on the queue
+ Queue queue = (Queue) initialContext.lookup("queue/exampleQueue");
+
+ // Step 3. Perform a lookup on the producer's SSL Connection Factory
+ ConnectionFactory producerConnectionFactory = (ConnectionFactory) initialContext.lookup("SslConnectionFactory");
+
+ // Step 4. Perform a lookup on the consumer's Connection Factory
+ ConnectionFactory consumerConnectionFactory = (ConnectionFactory) initialContext.lookup("ConnectionFactory");
+
+ // Step 5.Create a JMS Connection for the producer
+ producerConnection = producerConnectionFactory.createConnection();
+
+ // Step 6.Create a JMS Connection for the consumer
+ consumerConnection = consumerConnectionFactory.createConnection("consumer", "activemq");
+
+ // Step 7. Create a JMS Session for the producer
+ Session producerSession = producerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ // Step 8. Create a JMS Session for the consumer
+ Session consumerSession = consumerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ // Step 9. Create a JMS Message Producer
+ MessageProducer producer = producerSession.createProducer(queue);
+
+ // Step 10. Create a Text Message
+ TextMessage message = producerSession.createTextMessage("This is a text message");
+
+ System.out.println("Sent message: " + message.getText());
+
+ // Step 11. Send the Message
+ producer.send(message);
+
+ // Step 12. Create a JMS Message Consumer
+ MessageConsumer messageConsumer = consumerSession.createConsumer(queue);
+
+ // Step 13. Start the Connection
+ consumerConnection.start();
+
+ // Step 14. Receive the message
+ TextMessage messageReceived = (TextMessage) messageConsumer.receive(5000);
+
+ System.out.println("Received message: " + messageReceived.getText());
+
+ initialContext.close();
+ }
+ finally {
+ // Step 15. Be sure to close our JMS resources!
+ if (initialContext != null) {
+ initialContext.close();
+ }
+ if (producerConnection != null) {
+ producerConnection.close();
+ }
+ if (consumerConnection != null) {
+ consumerConnection.close();
+ }
+ }
+ }
+}
diff --git a/examples/features/standard/ssl-enabled-dual-authentication/src/main/resources/activemq/server0/artemis-roles.properties b/examples/features/standard/ssl-enabled-dual-authentication/src/main/resources/activemq/server0/artemis-roles.properties
new file mode 100644
index 00000000000..643dfc37d16
--- /dev/null
+++ b/examples/features/standard/ssl-enabled-dual-authentication/src/main/resources/activemq/server0/artemis-roles.properties
@@ -0,0 +1,17 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+consumers=consumer
\ No newline at end of file
diff --git a/examples/features/standard/ssl-enabled-dual-authentication/src/main/resources/activemq/server0/artemis-users.properties b/examples/features/standard/ssl-enabled-dual-authentication/src/main/resources/activemq/server0/artemis-users.properties
new file mode 100644
index 00000000000..1c68f505ddd
--- /dev/null
+++ b/examples/features/standard/ssl-enabled-dual-authentication/src/main/resources/activemq/server0/artemis-users.properties
@@ -0,0 +1,17 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+consumer=activemq
\ No newline at end of file
diff --git a/examples/features/standard/ssl-enabled-dual-authentication/src/main/resources/activemq/server0/bootstrap.xml b/examples/features/standard/ssl-enabled-dual-authentication/src/main/resources/activemq/server0/bootstrap.xml
new file mode 100644
index 00000000000..2d753e7de10
--- /dev/null
+++ b/examples/features/standard/ssl-enabled-dual-authentication/src/main/resources/activemq/server0/bootstrap.xml
@@ -0,0 +1,28 @@
+
+
+
+zMG0f)HfzKH?CB_ZS2S2C9LCfj~|Gm<*opF;lu|jT=7V;`C@?5&_}u zYK=(7(luT3FOLbZsgr`m>P>~kHCuBJ5j#hWA1-h*!x>Z9lT29*-_x*b?~at=i?fp) zdi=L{piIMX_dfb8fx%UP!)to-c^7jIL(|`m$|~fuH}w{+JG$1#^uQ_sl)KwF;tK=F z67}Pu!dlne)Lxwr?S&;J^6(;086MfH;*yxgO%EKGc(oG=KN@a0hY3<=2#q#;%|+jM zT$>2t!8?LJ#sw;^tr4&2owN49PNbNVikLBXro aMZ?`|LuhOmRq`h%$4yB~gR&HyM|J5@jD9Iqz+ib3WJy?uoe}p!z zK}pUT$oO{YTeKz1JT6HkfiMM?sW6HZuw`Kv>!XfS%hb5QV{&?ekEB${cR|{Wimhjo zP5JcGUVB{&@5>oyGBQ+(IR_0eXA{bXHFHK<@0Ac=J70@P7=5AorY3jV8J@lJvsT@$ zY})?9(JV}nJGr~Go3`I-+M8^3 |G-_qmJ>naK+kP_#Ig#!*9Six%p=5xpq-qWyhnl=x>C3 zJ*W_D%dmN*xyF@dU)|;?{ZCzUC70li)Kl`Ww0z7TE2KN105;7;)?AH7R4+%v6b&Qc zwb#~4pWQd5z>n4kaQc48hLX~J_a8(mjV&EotXhz`p6y>_L=0W*o8_w>ptWN8m`qBc z*snd~<^I-?cnbGbK?8KSgSq%tO4kArkHjagTPx)F%t$ zjF$F7gxd@R866u~IZHSPW3XjkuX=1Zs=zGkt;$=VYZ4p#W8{LFXgc~#ON?Qo2+Q-! zd<{o#6mBGyY^2^+_Aan_sOVngRsRgQsOwXSJm64T|MSB|Iw %c83?Fs*9PbH>QhUzRCYt{`vB24%T$dmVlOl}HEjiNqS!fMQh#2R9@PAd%_ zlYvg1r%5)6L3YbwA@_7kzf{ZznwTZ0x>I=tv@OJ)eaFwR&IS)JZbVs#NY@TYbl0bR zw9Sh~Rao7QHq4dNTwO&c(qV8dPfztDo_-}3VKp~hmjJoBZxuEFSd2~@ItV=gfFl7x z=7>d*L4L&?ARq_?hE=;>LkK{4)Dkg?+X6r!A1442jO0h~LO5_>h$x4#^|`-@`ya&h z2MHqte|PeVavNU`@eB1junQgR+XIPDl*^bH;uYjaLc$R8zbhP~l7E?Ce_p}ty@;V+ zM1;Jg08$5u(9%O7wRCiJT@Da^aMb-1|BWY+fr@_*=HTDpAOi&f2r`ftL x0(zCF<)ThrF8y$4GD =myAP(LFALf4@uOiS za@rW3qY t{G&mM@(93uo{yl1SXVn#Y`qjrg*9B zMar)wGhVs;wmD}_u;I;7_c!PSd4E kbvL$~fNmO&WTPNwaM>=#Dt>WbTIpSe?KR{ik+zDz#s)blTpsbi@+jOW IlooIIKQG79H~;_u literal 0 HcmV?d00001 diff --git a/examples/features/standard/ssl-enabled-dual-authentication/src/main/resources/activemq/server0/server-side-truststore.jks b/examples/features/standard/ssl-enabled-dual-authentication/src/main/resources/activemq/server0/server-side-truststore.jks new file mode 100644 index 0000000000000000000000000000000000000000..0b7e224163358aef1f20d04f5c6720f98b97679a GIT binary patch literal 1732 zcmezO_TO6u1_mZLW=={>VPIek*!;DvkAXEp&(y$@fq_}Wpov+ p`ni!fH z8AJiOW(I~v=1?x3T+zh1-Jpq42j+c7AV;35v610#eQ={}sgP#SeXlusZ=O8=Cb&Jw z=DiEUVLAJTZGmc;uCWeEfxjbddn11BKl*i-!MD@1LvyY-S~tj= +HZ6MH!u=sa<}1i)-ybe$y*AtS-swH7W6XAh z@2s4%e)lh{S4}^|eYkDeo6-X#!~1q!iS&O~$S%;>u*FlXQ2B+AhM4g7^PEOKCzd_5 z5v%GBsp-{tuy~!E_U2`!6Z00=bN^B_P5Ssdsftm>`plA#`&I-_=v>i!|6$bA`D~NA z)8ZPcLse54eXReT_tau;Y++z(Y%r=kbN_I)aQjBz7apnmULCHGthwoYIiq;Vm%RmV z?@n47b>?ra)6b>tSrY0=%WwEk-FIip&c&-Y+ G@ zt&Qi`{8=yFqpKpTwk+J%ihWU}< mkT;M8rYl)K7BLo)MB_7#Mv^mDt4;Yl_xFC?=tt8y4N;Ocvp$1?4wHy=*^=l6 zw!k~;c?Q#?BJOs1TP)kkB*NsMsjZi_Qb6d)+Gd^R=1KCew@n1+Bi7u??9@t7E?Vy{ z@eh%UoPfE=4w#GnKy#6z#DORj>kJBE`G#7#NWnl3l8eM)Sxo_&!O*jm1u#RIo0!6~ zlo^ye5KbD+U*zVmqGPi8{m#Nkq1ipN_39t**RtKVdOyFwwENNq%!PA|7rnbW<>Z`V z5!OF#8z<$xSh<$n_rn~n4xMAQd-wMFMyjs4dd87s#twc1g?$D>+tw=_V_Ov;pnB)) zo5XCZu0#%( eRM%HFxSayE|v^wi`12K k_4O@1aE-GsYR(x({$u$93H;)JLJaM8R params = new HashMap<>(); + params.put(TransportConstants.SSL_ENABLED_PROP_NAME, true); + params.put(TransportConstants.KEYSTORE_PATH_PROP_NAME, SERVER_SIDE_KEYSTORE); + params.put(TransportConstants.KEYSTORE_PASSWORD_PROP_NAME, PASSWORD); + params.put(TransportConstants.TRUSTSTORE_PATH_PROP_NAME, SERVER_SIDE_TRUSTSTORE); + params.put(TransportConstants.TRUSTSTORE_PASSWORD_PROP_NAME, PASSWORD); + params.put(TransportConstants.NEED_CLIENT_AUTH_PROP_NAME, true); + params.put(TransportConstants.PORT_PROP_NAME, "61617"); + ConfigurationImpl config = createBasicConfig(); + config.addAcceptorConfiguration(new TransportConfiguration(NETTY_ACCEPTOR_FACTORY, params)); + config.addAcceptorConfiguration(new TransportConfiguration(NETTY_ACCEPTOR_FACTORY)); + config.setSecurityEnabled(true); + + ActiveMQSecurityManager securityManager = new ActiveMQJAASSecurityManager("DualAuthenticationPropertiesLogin", "DualAuthenticationCertLogin"); + server = addServer(ActiveMQServers.newActiveMQServer(config, ManagementFactory.getPlatformMBeanServer(), securityManager, false)); + + HierarchicalRepository > securityRepository = server.getSecurityRepository(); + Role sendRole = new Role("producers", true, false, true, false, true, false, false); + Role receiveRole = new Role("consumers", false, true, false, false, false, false, false); + Set roles = new HashSet<>(); + roles.add(sendRole); + roles.add(receiveRole); + securityRepository.addMatch(DualAuthenticationTest.QUEUE.toString(), roles); + + server.start(); + waitForServerToStart(server); + tc = new TransportConfiguration(NETTY_CONNECTOR_FACTORY); + } +} diff --git a/tests/integration-tests/src/test/resources/dual-authentication-cert-roles.properties b/tests/integration-tests/src/test/resources/dual-authentication-cert-roles.properties new file mode 100644 index 00000000000..f52fa217531 --- /dev/null +++ b/tests/integration-tests/src/test/resources/dual-authentication-cert-roles.properties @@ -0,0 +1,18 @@ +# +# 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. +# + +producers=producer diff --git a/tests/integration-tests/src/test/resources/dual-authentication-cert-users.properties b/tests/integration-tests/src/test/resources/dual-authentication-cert-users.properties new file mode 100644 index 00000000000..06874dc5e97 --- /dev/null +++ b/tests/integration-tests/src/test/resources/dual-authentication-cert-users.properties @@ -0,0 +1,18 @@ +# +# 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. +# + +producer=CN=ActiveMQ Artemis Client, OU=Artemis, O=ActiveMQ, L=AMQ, ST=AMQ, C=AMQ diff --git a/tests/integration-tests/src/test/resources/dual-authentication-roles.properties b/tests/integration-tests/src/test/resources/dual-authentication-roles.properties new file mode 100644 index 00000000000..9c931731a4d --- /dev/null +++ b/tests/integration-tests/src/test/resources/dual-authentication-roles.properties @@ -0,0 +1,18 @@ +# +# 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. +# + +consumers=consumer \ No newline at end of file diff --git a/tests/integration-tests/src/test/resources/dual-authentication-users.properties b/tests/integration-tests/src/test/resources/dual-authentication-users.properties new file mode 100644 index 00000000000..7b61983e3aa --- /dev/null +++ b/tests/integration-tests/src/test/resources/dual-authentication-users.properties @@ -0,0 +1,18 @@ +# +# 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. +# + +consumer=consumerPassword diff --git a/tests/integration-tests/src/test/resources/login.config b/tests/integration-tests/src/test/resources/login.config index 7c160c50d41..6bc3498994d 100644 --- a/tests/integration-tests/src/test/resources/login.config +++ b/tests/integration-tests/src/test/resources/login.config @@ -123,3 +123,17 @@ CertLogin { org.apache.activemq.jaas.textfiledn.user="cert-users.properties" org.apache.activemq.jaas.textfiledn.role="cert-roles.properties"; }; + +DualAuthenticationCertLogin { + org.apache.activemq.artemis.spi.core.security.jaas.TextFileCertificateLoginModule required + debug=true + org.apache.activemq.jaas.textfiledn.user="dual-authentication-cert-users.properties" + org.apache.activemq.jaas.textfiledn.role="dual-authentication-cert-roles.properties"; +}; + +DualAuthenticationPropertiesLogin { + org.apache.activemq.artemis.spi.core.security.jaas.PropertiesLoginModule required + debug=true + org.apache.activemq.jaas.properties.user="dual-authentication-users.properties" + org.apache.activemq.jaas.properties.role="dual-authentication-roles.properties"; +};