Security :: RabbitMQ over SSL

This page explains how to configure RabbitMQ and Roboconf to work together with SSL.
It is assumed you are already familiar with SSL and certificates. You can also read this good article about the concepts used with Java certificates (mainly key stores and trust stores). This web page may help too.

We strongly recommend you to read RabbitMQ’s SSL documentation first.

Configuring RabbitMQ

This chapter is a short-hand version to configure RabbitMQ.
A longer version is available on RabbitMQ’s web site.

Verify your Erlang version.
As this page is written, it is recommended to use OTP 19 and higher as older versions contain vulnerabilities related to SSL.

On Debian systems, this file is located under /etc/rabbitmq/rabbitmq.config.
Please, refer to RabbitMQ’s web site for more details about this configuration file. By default, this file does not exist. You have to create it. This is where you can specify the port and SSL options.

%% Disable SSLv3.0 and TLSv1.0 support.
[
  {rabbit,
      [{tcp_listeners, [5672]},
       {ssl_listeners, [5671]},
       {ssl_options, [
           {cacertfile,"/path/to/testca/cacert.pem"},
           {certfile,"/path/to/server/cert.pem"},
           {keyfile,"/path/to/server/key.pem"},
           {verify,verify_peer},
           {fail_if_no_peer_cert,true},
           {versions, ['tlsv1.2', 'tlsv1.1']}
       ]}
   ]}
].

All the SSL options can be found on Erlang’s web site.
The main ones are:

Once configured, restart your RabbitMQ server.
On Debian systems, type in sudo /etc/init.d/rabbitmq restart.

Configuring Roboconf

On Roboconf, all the configuration is made in its etc/net.roboconf.messaging.rabbitmq.cfg file.
Add or complete the following properties (they are all prefixed with net.roboconf.messaging.rabbitmq.).

Property Description Default Mandatory
ssl.use True to enable SSL connections with RabbitMQ. false no
ssl.protocol The SSL protocol. TLSv1.1 no
ssl.pass.as.user.data True if the DM should send the SSL configuration to agents (through user data). If false, it is considered agents already have all the configuration on their machine (located in the image). true no
ssl.key.store.path The path to the key store, on the DM’s machine. Not sent to agents by the DM if ssl.pass.as.user.data is false. - yes
ssl.key.store.passphrase The pass phrase for the key store. Not sent to agents by the DM if ssl.pass.as.user.data is false. - yes
ssl.key.store.type The type for the key store. Not sent to agents by the DM if ssl.pass.as.user.data is false. PKCS12 no
ssl.trust.store.path The path to the trust store, on the DM’s machine. Not sent to agents by the DM if ssl.pass.as.user.data is false. - yes
ssl.trust.store.passphrase The pass phrase for the trust store. Not sent to agents by the DM if ssl.pass.as.user.data is false. - yes
ssl.trust.store.type The type for the trust store. Not sent to agents by the DM if ssl.pass.as.user.data is false. JKS no
ssl.key.manager.factory The factory for key managers. Not sent to agents by the DM if ssl.pass.as.user.data is false. SunX509 no
ssl.trust.manager.factory The factory for trust managers. Not sent to agents by the DM if ssl.pass.as.user.data is false. SunX509 no

Also, make sure to update the message-server-ip property: <ip>:<ssl_port>

By default, the SSL configuration is passed to agents through user data.
It allows to dynamically pass the configuration. However, it also means that any application co-located with agents could retrieve this configuration. Indeed, user data are generally not protected and any application on the remote machine can use them.

There are two workarounds for this.
All of them imply setting ssl.pass.as.user.data to false and passing the configuration in another way.

Available Examples

The main difficulties can be configuring the RabbitMQ server, and generating the certificates stuff (in particular the key store and the trust store).

You can take a look at the configuration we use for manual tests with RabbitMQ and SSL configuration. We use a custom Docker image that generates certificates on the fly. We then use them in unit tests and integration tests. It may help you to deal with such a use case.