Lately I’ve been trying to get the RabbitMQ management plugin to listen on more than one port. This is in an effort to resolve these comments on the puppetlabs-rabbitmq Puppet module. I want one listener on localhost only, in non-SSL mode, and a second listener on a different port which serves SSL requests from external clients.
I spent a fair amount of time (unsuccessfully) trying to get this to work, when in fact, it’s not currently possible. So hopefully this info can be useful to others in the future.
The original problem surfaced when we needed to configure the RabbitMQ management interface with SSL. We try to use SSL on everything possible, as an added security protection. It’s a bit obscure to get that done, but it’s fairly well-documented on the management plugin and mochiweb plugin documentation, and the puppetlabs-rabbitmq Puppet module properly supports it now, too.
That’s all well and fine, now we have the management UI in SSL mode. But that presents another problem with the Puppet module, which will also install the
rabbitmqadmin command line tool for you, by downloading it from the locally running RabbitMQ instance. The download URL is properly generated with the right protocol (HTTP or HTTPS), credentials, and port number. However, if the protocol is HTTPS, the download (handled in the puppet-staging module) will most likely fail because the hostname in the download URL is hard coded to localhost. Unless the SSL certificate on the management UI actually has a CN exactly matching ‘localhost’, the certificate validation will fail.
There are other reasons running the management UI under SSL only causes problems. As mentioned in the GitHub comments, it breaks the default expectation of the
rabbitmqadmin CLI tool that the management API is running on a standard port in non-SSL mode.
So thus my desire to get RabbitMQ management listening on a couple different ports: a global SSL port for external requests, and a localhost-only non-SSL port that can serve local rabbitmqadmin requests, as well as provide a workable download URL for the Puppet module.
Multiple Listening Ports, It’s Not Going to Happen
I spent a couple hours going round and round, trying different RabbitMQ configurations, to get rabbitmq_management tied to multiple listening ports. I was only able to ever accomplish it listening on one.
The fact that mochiweb can take a listeners parameter (plural) somewhat led me astray, because that implies multiple listening ports can be set up. And, they can, but you can only attach the management plugin to a single one.
I was able to glean those details from these comments in the mochiweb README. Multiple listeners are defined, and then you also define contexts to assign a particular app/plugin to those listeners. A single app can only be assigned to a single listener at once.
Alternative Partial Solutions
So how can I keep RabbitMQ management on SSL, and still get the Puppet module and
rabbitmqadmin CLI functions working?
One idea I had was to generate a proper “certificate-verifiable” download URL for the
rabbitmqadmin install class in Puppet, which would allow the tool to be downloaded via SSL. However, that would require an extra parameter to the
rabbitmq class, and/or some complicated functionality to pull the CN name out of the certificate file. This also doesn’t solve the problem for actually running
rabbitmqadmin, once that tool is installed.
The better solution for the Puppet module is to generate a
rabbitmqadmin.conf file, and then invoke
-c /etc/rabbitmq/rabbitmqadmin.conf each time (as suggested by davewongillies). This allows for configuring the arbitrary connection info there. But, in this case, the download and install of
rabbitmqadmin will still be broken.
(Another option would be too add a parameter to the staging module to allow insecure SSL downloads. It just uses a curl command line underneath to do the download, so this parameter could simply add a
-k flag to the command line.)
To get both working, we’ll need some combination of the above, or some other solution. I don’t have a great silver bullet to this, so hopefully I can come up with something and send in a pull request.
A Practical Workaround
I think for our setup, I am going to solve this another way.
I figure on running the RabbitMQ management plugin itself only listening on localhost in non-SSL mode. So the Puppet module and local
rabbitmqadmin will work fine.
Then I’ll provide the SSL termination for external requests with HA Proxy. We already use that same method for providing SSL termination for some of the OpenStack services, so this setup is well known and easy to implement.
This will be a quick path to getting everything working, without having to immediately solve the more complex issue of how to best implement this in the Puppet module.