Setting up SSL connections with ArtemisCloud Operator
Security is always a concern in a production environment. With ArtemisCloud Operator You can easily configure and set up a broker with ssl-enabled acceptors. The blog explains how to do it.
This article guides you through the steps to set up a broker to run in kubernetes (Minikube). The broker will listen on a secure port 61617 (ssl over tcp). It also demonstrates sending and receiving messages over secure connections using one-way authentication.
Before you start you need have access to a running Kubernetes cluster environment. A Minikube running on your laptop will just do fine. The ArtemisCloud operator also runs in a Openshift cluster environment like CodeReady Container. In this blog we assume you have Kubernetes cluster environment. (If you use CodeReady the client tool is oc in place of kubectl)
Deploy ArtemisCloud operator
First you need to deploy the ArtemisCloud operator. If you are not sure how to deploy the operator take a look at this blog.
In this blog post we assume you deployed the operator to a namespace called myproject.
Make sure the operator is in “Runing” status before going to the next step. You can run this command and observe the output:
$ kubectl get pod -n myproject NAME READY STATUS RESTARTS AGE activemq-artemis-operator-58bb658f4c-zcqmw 1/1 Running 0 7m32s
Prepare keystore and truststore
To establish a SSL connection you need certificates. Here for demonstration purpose we prepare a self-signed certificate.
We’ll use the “keytool” utility that comes with JDK:
$ keytool -genkeypair -alias artemis -keyalg RSA -keysize 2048 -storetype PKCS12 -keystore broker.ks -validity 3000 Enter keystore password: Re-enter new password: What is your first and last name? [Unknown]: Howard Gao What is the name of your organizational unit? [Unknown]: JBoss What is the name of your organization? [Unknown]: Red Hat What is the name of your City or Locality? [Unknown]: Beijing What is the name of your State or Province? [Unknown]: Beijing What is the two-letter country code for this unit? [Unknown]: CN Is CN=Howard Gao, OU=JBoss, O=Red Hat, L=Beijing, ST=Beijing, C=CN correct? [no]: yes
It creates a keystore file named broker.ks under the current directory. Let’s give the password as password when prompted above.
Next make a truststore using the same cert in the keystore.
$ keytool -export -alias artemis -file broker.cert -keystore broker.ks Enter keystore password: Certificate stored in file <broker.cert>
$ keytool -import -v -trustcacerts -alias artemis -file broker.cert -keystore client.ts Enter keystore password: Re-enter new password: Owner: CN=Howard Gao, OU=JBoss, O=Red Hat, L=Beijing, ST=Beijing, C=CN Issuer: CN=Howard Gao, OU=JBoss, O=Red Hat, L=Beijing, ST=Beijing, C=CN Serial number: 582b8fd4 Valid from: Mon Feb 08 20:17:45 CST 2021 until: Fri Apr 27 20:17:45 CST 2029 Certificate fingerprints: MD5: 01:89:A9:B0:07:A1:2F:19:FC:43:5C:27:2E:E8:D7:C3 SHA1: D4:25:61:9F:AA:B6:05:1F:CC:F0:CD:65:A8:BC:B0:E1:70:49:1B:81 SHA256: 64:63:4E:68:2E:98:59:DA:A4:6B:FF:8E:E7:8C:AC:65:A2:F2:37:CB:12:BC:96:3C:AE:70:44:63:BD:0D:41:AE Signature algorithm name: SHA256withRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3 Extensions: #1: ObjectId: 220.127.116.11 Criticality=false SubjectKeyIdentifier [ KeyIdentifier [ 0000: C6 35 D2 14 85 C3 A2 68 E5 A3 78 D3 9F 3F D2 C7 .5.....h..x..?.. 0010: 8F 9D B6 A9 .... ] ] Trust this certificate? [no]: yes Certificate was added to keystore [Storing client.ts]
Make sure the password for your truststore client.ts is also password.
By default the operator fetches the truststore and keystore from a secret in kubernetes in order to configure SSL acceptors for a broker. The secret name is deducted from broker CR’s name combined with the acceptor’s name.
Here we’ll use “ex-aao” for CR’s name and “sslacceptor” for the acceptor’s name. So the truststore and keystore should be stored in a secret named ex-aao-sslacceptor-secret.
Run the following command to create the secret we need:
$ kubectl create secret generic ex-aao-sslacceptor-secret --from-file=broker.ks --from-file=client.ts --from-literal=keyStorePassword='password' --from-literal=trustStorePassword='password' -n myproject secret/ex-aao-sslacceptor-secret created
Prepare the broker CR with SSL enabled
Now create a file named “broker_ssl_enabled.yaml” with the following contents:
apiVersion: broker.amq.io/v2alpha4 kind: ActiveMQArtemis metadata: name: ex-aao spec: deploymentPlan: size: 1 image: quay.io/artemiscloud/activemq-artemis-broker-kubernetes:0.2.1 acceptors: - name: sslacceptor protocols: all port: 61617 sslEnabled: true
In this broker CR we configure an acceptor named “sslacceptor” that listens on tcp port 61617. The sslEnabled: true tells the operator to make this acceptor to use SSL transport.
Deploy the broker
Deploy the above broker_ssl_enabled.yaml to the cluster:
$ kubectl create -f broker_ssl_enabled.yaml -n myproject activemqartemis.broker.amq.io/ex-aao created
In a moment the broker should be up and running. Run the command to check it out:
$ kubectl get pod -n myproject NAME READY STATUS RESTARTS AGE activemq-artemis-operator-58bb658f4c-zcqmw 1/1 Running 0 18m ex-aao-ss-0 1/1 Running 0 71s
Using “kubectl logs ex-aao-ss-0 -n myproject” command you can checkout the console log of the broker. You’ll be seeing a line like this in the log:
2021-02-08 12:54:12,837 INFO [org.apache.activemq.artemis.core.server] AMQ221020: Started EPOLL Acceptor at ex-aao-ss-0.ex-aao-hdls-svc.default.svc.cluster.local:61617 for protocols [CORE,MQTT,AMQP,HORNETQ,STOMP,OPENWIRE]
which means the acceptor is now listening on port 61617. Although it doesn’t give us whether it’s SSL or plain tcp we can check out in the following steps that it accepts SSL connections only.
One way to check out that this acceptor is indeed SSL enabled is to log in to the broker pod and take a look at it’s configure file in /home/jboss/amq-broker/etc/broker.xml. In it there should be an element like this:
Test messaging over a SSL connection
With the broker pod in running status we can proceed to make some connections against it and do some simple messaging. We’ll use Artemis broker’s built in CLI commands to do this.
Log into the broker pod first to get a shell command environment:
$ kubectl exec --stdin --tty ex-aao-ss-0 -- /bin/bash [jboss@ex-aao-ss-0 ~]$
Then send 100 messages through port 61617:
$ cd amq-broker/bin [jboss@ex-aao-ss-0 bin]$ ./artemis producer --user admin --password admin --url tcp://ex-aao-ss-0:61617?sslEnabled=true\&trustStorePath=/etc/ex-aao-sslacceptor-secret-volume/client.ts\&trustStorePassword=password --message-count 100 OpenJDK 64-Bit Server VM warning: If the number of processors is expected to increase from one, then you should configure the number of parallel GC threads appropriately using -XX:ParallelGCThreads=N Connection brokerURL = tcp://ex-aao-ss-0:61617?sslEnabled=true&trustStorePath=/etc/ex-aao-sslacceptor-secret-volume/client.ts&trustStorePassword=password Producer ActiveMQQueue[TEST], thread=0 Started to calculate elapsed time ... Producer ActiveMQQueue[TEST], thread=0 Produced: 100 messages Producer ActiveMQQueue[TEST], thread=0 Elapsed time in second : 0 s Producer ActiveMQQueue[TEST], thread=0 Elapsed time in milli second : 724 milli seconds
Pay attention to the –url option that is required to make an SSL connection to the broker.
You may also wonder how it gets the trustStorePath for the connection.
This is because the truststore and keystore are mounted automatically by the operator when it processes the broker CR. The mount path follows the pattern derived from CR’s name (ex-aao) and the acceptor’s name (sslacceptor, thus /etc/ex-aao-sslacceptor-secret-volume).
Now receive the messages we just sent – also using SSL over the same port (61617):
[jboss@ex-aao-ss-0 bin]$ ./artemis consumer --user admin --password admin --url tcp://ex-aao-ss-0:61617?sslEnabled=true\&trustStorePath=/etc/ex-aao-sslacceptor-secret-volume/client.ts\&trustStorePassword=password --message-count 100 OpenJDK 64-Bit Server VM warning: If the number of processors is expected to increase from one, then you should configure the number of parallel GC threads appropriately using -XX:ParallelGCThreads=N Connection brokerURL = tcp://ex-aao-ss-0:61617?sslEnabled=true&trustStorePath=/etc/ex-aao-sslacceptor-secret-volume/client.ts&trustStorePassword=password Consumer:: filter = null Consumer ActiveMQQueue[TEST], thread=0 wait until 100 messages are consumed Consumer ActiveMQQueue[TEST], thread=0 Consumed: 100 messages Consumer ActiveMQQueue[TEST], thread=0 Elapsed time in second : 0 s Consumer ActiveMQQueue[TEST], thread=0 Elapsed time in milli second : 160 milli seconds Consumer ActiveMQQueue[TEST], thread=0 Consumed: 100 messages Consumer ActiveMQQueue[TEST], thread=0 Consumer thread finished
Now you get an idea how an SSL acceptor is configured and processed by the operator and see it in action!
More SSL options
We have just demonstrated a simplified SSL configuration. In fact the operator supports quite a few more SSL options through the CRD definitions. You can checkout those options in broker CRD down here and also read the Artemis Doc on configuring transports for more information.