Skip to main content

RabbitMQ and SSL

RabbitMQ is an AMQP provider i.e. it can reliably queue, service and maintain messages according to a range of policies and parameters.

By default, it listens to plain old TCP connections and sends and receives messages over plaintext. This feature just works "out of the box". For users who wish to use SSL over TCP aka TLS, it requires a bit more work on their part.

  1. First, let's create a bunch of certificates and sign them with our own CA. For this, we'll use easyrsa3. Easyrsa is a CLI tool to create, sign and manage your own certification authorities. It's maintained by OpenVPN team.
  2. Download easyrsa using your native package manager i.e. yum or apt-get
    $cp -Rp /usr/share/easy-rsa ~/easy-rsa-3 
    $cd ~/easy-rsa-3
    $./easyrsa init-pki
    $./easyrsa build-ca
    $./easyrsa build-server-full broker [nopass]
    $./easyrsa build-client-full client1 [nopass]
    This creates three entities (collection of private keys, public keys and certificates) for a CA, a server named broker and a client named client1. Private keys are stored in ./private/, certificates are stored in ./issued. You may move the files to any suitable place you like for it's required that we link them up at appropriate places. Be careful about the keys, as they to be kept secret. Using nopass switch will disable PEM password, might be useful when you don't to prompt user for PEM password.
  3. Now, let's configure RabbitMQ for using certificate we just created. RabbitMQ uses configuration stored at /etc/rabbitmq/rabbitmq.config. The relevant additions needed are as follows, 
    [
      {rabbit, [
         {ssl_listeners, [5671]},
         {ssl_options, [{cacertfile,"/path/to/easyrsa/ca.crt"},
                        {certfile,"/path/to/server/broker.crt"},
                        {keyfile,"/path/to/server/broker.key"},
                        {password, "password-used-to-encrypt-broker.key"},
                        {verify, verify_peer},
                        {fail_if_no_peer_cert, false}]}
       ]}
    ].
    Things to note,
    1. Make sure user "rabbitmq" has access to the certificates otherwise you'll see "eacess" errors being raised while trying to connect. What worked for me was to chown these files to rabbitmq user and chmod read access to others (o+r) to all the directories above the file.
    2. You might want to tail rabbitmq log file, for knowing what is happening where. The log files are at, /var/log/rabbitmq/.
    3. After every change in rabbitmq configuration, you'll need to restart the service using systemctl/service directive, as the case maybe.
  4. To test if the connections are proper, we may use openssl.
    $ openssl s_client -connect localhost:5671 -cert  /etc/rabbitmq/ssl/client/cert.pem -key /etc/rabbitmq/ssl/client/key.pem -CAfile /etc/rabbitmq/ssl/certificate_auth/cacert.pem
    Make sure to keep an eye on the rabbitmq log file and the console output. Any errors here will indicate a problem with the configuration.
  5. Now, let's delve into the actual client code. Let's look at Python first, 
    1. PYTHON
      import ssl
      import pika

      connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost', port=5671, ssl=True, ssl_options=dict(
              ssl_version=ssl.PROTOCOL_TLSv1,
              ca_certs="/path/to/ca.crt",
              certfile="/path/to/client.crt",
              keyfile="/path/to/client.key",
              cert_reqs=ssl.CERT_REQUIRED
      )))
      channel = connection.channel()
    2. JAVA
      Before doing anything, you'll first need to import the broker/server certificate into your client's truststore. Truststores are JDK's way of specifing and storing trusted certificates. To import broker's certificate into a truststore file,
      $ keytool -import -alias server1 -file /path/to/server/cert.pem -keystore /path/to/rabbitstore
      Also, we'll need client public and private key and certificates combined in p12 format. For that we'll again use easyrsa3,
      ./easyrsa export-p12 client
      The Java code to connect to broker is as follows,
      import java.io.*;
      import java.security.*;
      import javax.net.ssl.*;
      import com.rabbitmq.client.*;


      char[] keyPassphrase = "MySecretPassword".toCharArray();
      KeyStore ks = KeyStore.getInstance("PKCS12");
      ks.load(new FileInputStream("/path/to/client/keycert.p12"), keyPassphrase);

      KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
      kmf.init(ks, passphrase);

      char[] trustPassphrase = "rabbitstore".toCharArray();
      KeyStore tks = KeyStore.getInstance("JKS");
      tks.load(new FileInputStream("/path/to/trustStore"), trustPassphrase);

      TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
      tmf.init(tks);

      SSLContext c = SSLContext.getInstance("TLSv1.2");
      c.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

      ConnectionFactory factory = new ConnectionFactory();
      factory.setHost("localhost");
      factory.setPort(5671);
      factory.useSslProtocol(c);

      Connection conn = factory.newConnection();

    This should enable SSL in rabbitmq and you can use the connection object thus formed to send messages to the broker.

Comments

Popular posts from this blog

Multimaster replication with Symmetric DS

Symmetric DS is an awesome tool for trigger based replication whcih works for all major database vendors, including but not limited to PostgreSQL, MySQL, MSSQL, Oracle and many others. Symmetric-DS is a java application and can execute on any platform on whcih JRE is available including Windows and Linux. Trigger based replication, in constrast to disk based (eg. DRBD ) or transaction log file shipping based or statement based , works by registering triggers on DMLs and sending the data thus generated to remote machines. Another very popular trigger based DB replication tool is Slony . Symmetric-DS in addition to being database agnostic also supports multi-master replication (MMR). MMR usecase involves multiple database nodes, connected in a pool with DML updates coming from any of them. This is different from the normal master-slave replication, where slaves are not expected to generate any data events, and the sole authority of database is the master. MMR requirement causes d...

Reset root password RHEL/Rocky/CentOS 9

Unlike the earlier versions of Rethat variants, version 9 doesn't allow single user mode to change password, as maintanance mode in 9 requires root password . Single user mode (runlevel 1) can easily be obtained by appending the word ' single ' at the end of the line starting with 'linux' by editing the entry in boot menu by pressing ' e ' at boot menu. To reset the root password on the other hand, one requires to follow a specific set of commands, At the boot menu, edit rescue mode to append 'rd.break ' at the end of the line starting with kernel. Boot with the edited line by pressing Ctrl+X or F10. At the new prompt starting with switch_root, type the following commands, mount -o remount, rw /sysroot chroot /sysroot touch /.autorelabel passwd <new root password> exit reboot       

Devstack installation with cells in multiple machines

  Devstack is a testing and development package for OpenStack . The official devstack website has excellent but terse installation instructions, which could be daunting to a newbie. Normally, a traditional install is pretty straightforward but problems creep in when you have to go for some particular configuration or installation like cells or a simple code-test-debug setup, the information on the main site is insufficient. In this blog, I will enumerate the steps for setting up a cell-ular devstack installation with one parent and one child. Parent will not be instantiating any VMs s it's only a 'command centre'. 1. On both machines, install git and vim, clone the devstack repo using git. yum install git vim git clone https://git.openstack.org/openstack-dev/devstack 2. On both machines, open up the file 'local.conf' inside the cloned directory 'devstack' cd devstack; vim local.conf 3. Copy the parameters below to the file...