Intrexx Industrial - Configuration of an MQTT Message Broker
1. General
The ActiveMQ server, developed by Apache, is used for the connection to
Intrexx. This is available for free as part of the Apache 2.0 license.
In the following, the abbreviation "<ACTIVE_MQ_INST>" refers
to the installation path of the ActiveMQ server. In the test VM
provided by United Planet, the installation path is /opt/activemq.
2. SSL encryption
The following will provide a description of a simple method for
creating a self-signed certificate with the Java Keytool and then
integrating this into ActiveMQ. To achieve this, Java needs to be
installed and configured on the system.
2.1. Create KeyStore with a self-signed private key
To begin with, the KeyStore needs to be created that contains the
private key:
As the CN (in the dialog: "First and last name"), the FQHN
of the ActiveMQ server needs to be transferred. Later, you need
to ensure that the ActiveMQ is reachable via this name so that
the SSL Handshake works. Furthermore, a password for accessing
the KeyStore needs to be specified to begin with. The password,
which should be entered later for the alias, must simply be confirmed
with ENTER, meaning it is identical with the KeyStore password.
Additionally, the file should be protected from access
accordingly as it contains the private key for the ActiveMQ.
2.2 Export certificate for clients
The public key and the certificate will now be generated from the KeyStore
file created in the last step:
The certificate is exported in the DER format (therefore in binary)
in this case. By using the additional parameter "-rfc", the certificate
can also be saved as PEM (encoded as plain text or BASE64).
Importing the certificate into a TrustStore, which is often used
in Java applications, is performed with the following command:
So that Intrexx can establish an encrypted TLS connection to the ActiveMQ
server later, the file "amq_server.der", which we just created, needs
to be imported into Intrexx in the
portal properties.
In the
certificate source
dialog, select the option "Import of file" and then select the
file "amq_server.der". So that the change takes effect, the
portal service
needs to be restarted
2.4 Activate SSL in ActiveMQ and integrate KeyStore with the private key
To do this, the path to the created KeyStore as well as its password
need to be added to <ACTIVEMQ_INST>/conf/activemq.xml in the
"core" namespace. Because the password is entered in plain text, the
file "activemq.xml" should be protected from unauthorized access
as appropriate.
According to the ActiveMQ documentation, relative paths
should be used when entering the paths. By default, the
working directory is <ACTIVEMQ_INST>/conf/ meaning
the the entry keyStore="amq_server.ks" because
"amq_server.ks" is directly in this directory.
Excerpt from activemq.xml:
<broker xmlns="http://activemq.apache.org/schema/core" brokerName="localhost" dataDirectory="${activemq.data}">
...
..
.
<!-- In sslContext, the path to the KeyStore file as well as its
password nee to be entered -->
<sslContext>
<sslContext
keyStore="/PATH/TO/amq_server.ks" keyStorePassword="SECRET" />
</sslContext>
<!-- SSL then needs to be activated in the corresponding connectors.
It is best to deactivate connectors that are not required.
Please mote: openwire is required to connect to Intrexx via JMS-->
<transportconnectors>
<!-- DOS protection, limit concurrent connections to 1000 and frame size to 100MB -->
<!-- <transportConnector name="openwire" uri="tcp://0.0.0.0:61616?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/> -->
<transportConnector name="openwire" uri="ssl://0.0.0.0:61616?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="mqtt+ssl" uri="mqtt+ssl://0.0.0.0:8883?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<!-- transportConnector name="amqp" uri="amqp://0.0.0.0:5672?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="stomp" uri="stomp://0.0.0.0:61613?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="mqtt" uri="mqtt://0.0.0.0:1883?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="ws" uri="ws://0.0.0.0:61614?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/ -->
</transportconnectors>
Please note that the parameters are case-sensitive.
Click here
for more information.
2.5. Integrate KeyStore in Jetty
ActiveMQ provides a web interface that provides an overview of
certain status information such as the currently active topics or
the currently registered publishers/subscribers. For this,
ActiveMQ comes with the webserver Jetty from Apache. So that
this can be accessed via an HTTPS connection, the KeyStore created
in the previous step needs to be integrated here as well. The file
<ACTIVEMQ_INST>/conf/jetty.xml already contains corresponding,
but also commented-out entries, for this purpose. As in the previous
steps in ActiveMQ, these also need to have the path and password
of the KeyStore added to them:
<!--
Enable this connector if you wish to use https with web console
-->
<bean id="SecureConnector" class="org.eclipse.jetty.server.ServerConnector">
<constructor-arg ref="Server" />
<constructor-arg>
<bean id="handlers" class="org.eclipse.jetty.util.ssl.SslContextFactory">
<property name="keyStorePath" value="/PATH/TO/amq_server.ks" />
<property name="keyStorePassword" value="SECRET" />
</bean>
</constructor-arg>
<property name="port" value="8162" />
</bean>
So that the redirecting from HTTP to HTTPS works, a corresponding entry
needs to be made in the web.xml.
This is described in the section
Redirecting http requests to https
in the Jetty documentation.
3. SSL - Client-side authentication
After the steps taken in chapter 2,
a server-side authentication is now guaranteed. Additionally, the
encryption for the connection was activated. An additional way to
improve secure is by making the client authenticate themselves as well.
The setup is identical to the steps taken in chapter 2
just that in this case a private key is generated for the client
but the corresponding certificate with the contained public key is now
integrated on the server side.
3.1. Create KeyStore with a self-signed private key for client
To begin with, the KeyStore needs to be created that contains the
private key:
The exported certificate, which is currently in the DER (binary) format,
now needs to be imported into a KeyStore or TrustStore
for the integration into ActiveMQ later:
3.3 Activate client authentication in ActiveMQ, Integrate TrustStore with certificate and public key
In the corresponding sslContext section of
<ACTIVEMQ_INST>/conf/activemq.xml, which we already generated in
chapter 2.4.,
the TrustStore, which contains the corresponding client certificates,
is now added as an additional parameter:
The client authentication will now be activated in the corresponding
connector using the additional URI parameter "needClientAuth=false".
For the MQTT connector for example this is done as follows:
3.4. Advice for using an officially signed certificate
The points named above describe the simplest approach using a self-signed
certificate. The advantage here is that you can encrypt the connection
easily. However, as the certificate is self-signed, and therefore
not signed by an official certificate authority (CA),
the Chain of Trust is not guaranteed. This causes for example
a warning notification to appear when you access the ActiveMQ Webmin
interface in the browser, as the creator is unknown. If
officially signed certificates should be created, the approach
is as follows:
Create private key
Generate a certificate request from this
Get this signed by an official certificate authority
The received certificates received from and signed by the certificate authority
usually arrive in different formats. The certificates are easiest
to integrate if they are in the PEM format (in plain text). This
is done by opening the respective files in a text editor, copying the
private key, certificates and intermediate certificates, and then generating
a new file that contains the entire chain.
Proceed as follows to achieve this:
Create a new text file called "certificatechain.pem" where
the private key and all certificated including BEGIN/END prologue
are entered via copy & paste.
The private key (e.g. *,key):
-----BEGIN RSA PRIVATE KEY-----
...
The certificate (e.g. *.crt):
-----BEGIN CERTIFICATE-----
...
Potential intermediate certificates (e.g. *.ca):
-----BEGIN CERTIFICATE-----
...
Afterwards, this pem file will now be converted to pkcs12 via the
following command (OpenSSL needs to be installed):
The integration into ActiveMQ or Jetty functions
in the same way as descibed in
chapter 2.4. or
2.5. respectively.
Because the newly generated KeyStore is the PKCS12 type,
only one additional parameter, which describes the type of KeyStore,
needs to be specified.
The users who are permitted to log in to the Webmin interface are
defined in the file <ACTIVEMQ_INST>/conf/jetty-realm.properties.
4.2. User permissions for the connectors
The direct definition of permissions in activemq.xml with the
"SimpleAuthenticationPlugin" is the easiest way to achieve this.
You can add a new user, password and group membership via a
corresponding authentication entry. The permissions for the
topics/queues can then be assigned to the users via the
authorizationPlugin. Read and/or write permissions ought to
be self explanatory. The "admin" role describes the permissions
for creating a topic in this context.
ActiveMQ provides the ability to share information about the topics
via the ActiveMQ.Advisory branch, e.g. for generating a message
when a client establishes a connection in the
ActiveMQ.Advisory.Connection branch. If provided information
is required there, the client needs to have the necessary read/write
permission. If the respective branches are not available, the client
requires the admin permissions to be able to generate the topic,
or you need to ensure that the required Advisory topics
are available. The Advisory messages can also be deactivated
via the following entry in the Broker namespace of activemq.xml:
The ActiveMQ server runs under the restrictive user account "activemq".
Therefore, you therefore need to ensure that the owner and group
membership of the modified files are still correct after the changes
made in chapter 2 and
3. Both the owner
and group membership of the file need to be "activemq".
This can be checked using the following command:
The same applies to the KeyStore file generated in
chapter 2. The storage location of the file
and the the user/group need to be readable by the
activemq user. This can be corrected using the following command:
chown activemq.activemq <FILENAME>
Afterwards, the ActiveMQ service needs to be restarted: