Nugget: User Management in MQTT Mosquitto Broker with Docker
Overview
If you use docker
or docker-compose
often to setup your IoT Stacks, you might want be at crossroads where Security and User Management
becomes the next necessary step to improve the Stack. This post builds upon tiguitto which provides
different set of security measures to the TIG (Telegraf, InfluxDB, Grafana) + Mosquitto MQTT Broker stack.
During the learning phase of setting up the stacks, there came a crucial requirement about how to add/remove user management to the MQTT Mosquitto Broker. In the stack, there are only two services - Grafana and Mosquitto MQTT Broker, which would require user management. Grafana, tends to provide an easy way via UI to manage users. To the best of my knowledge, no UI for Mosquitto Broker since it is mostly a CLI based service.
I was very skeptical whether one can manage Mosquitto Broker users without restarting the
mosquitto
container. I wanted to avoid downtime in the stack
Apparently, there is a way to avoid a downtime to add/remove users to the Broker. Let’s look into it!
Solution
According to mosquitto’s man page mosquitto
responds to a SIGNAL called SIGHUP
. The documentation mentions:
SIGHUP
Upon receiving the SIGHUP signal, mosquitto will attempt to reload configuration file data, assuming that the -c argument was provided when mosquitto was started. Not all configuration parameters can be reloaded without restarting. See mosquitto.conf(5) for details.
The next step was to check how to send signals to a specific docker
container. This is also possible via docker
CLI as answered in this StackOverflow Query.
If your container is named mosquitto
in your docker-compose.yml
file, the the following will work:
docker kill --signal=SIGHUP mosquitto
# OR
docker kill --signal=SIGHUP <container_id>
Getting Hands Greasy!
As a simple example if you use the tiguitto repository you can simply following the documentation in the repository to setup a Stack easily based on your requirement. For the sake of understanding, we will assume you are using the most simple use-case PROTOTYPE
case from the repository.
If you use the case out-of-the-box, there are already two users added to the Broker:
# mosquitto/config/passwd file in the Prototype Case from tiguitto
# username:password
pubclient:tiguitto
subclient:tiguitto
The pubclient
username can be used by an Sensor Node to publish data to the broker.
Adding Users to Mosquitto MQTT Broker
Let’s add a user pubclient1
with password tiguitto
.
Open the mosquitto/config/passwd
file and add a new username for a new Sensor Node:
pubclient:$6$ITRzMkBDHn7MKJ95$i/Ea2KniGMmV9jomR0+jyl40c0YK1eTwTeyKms95obREDFZzhEIQhTntncJeX3PS9eoj9u
R+ATtS8kGowA==
subclient:$6$0lEyFrntsYvkzU7N$24t0vyKVSeEBiSOdvOExaMG67F5xfHeVw8zBxdPtb9BVjchKFNdiI7WaJApVkVZ/DS+MMk
xWycgOeizTmA==
pubclient1:tiguitto
The pubclient
and subclient
have passwords encrypted, hence the garbled string.
Encrypt the Password for the New User
Assuming, you are in tiguitto/prototype
directory we can encrypt the password using the following the command:
docker run -it --rm -v $(pwd)/mosquitto/config:/mosquitto/config eclipse-mosquitto mosquitto_passwd -U /mosquitto/config/passwd
If you do not get a response on the terminal, your password is encrypted. Check the mosquitto/config/passwd
file:
pubclient:$6$ITRzMkBDHn7MKJ95$i/Ea2KniGMmV9jomR0+jyl40c0YK1eTwTeyKms95obREDFZzhEIQhTntncJeX3PS9eoj9u
R+ATtS8kGowA==
subclient:$6$0lEyFrntsYvkzU7N$24t0vyKVSeEBiSOdvOExaMG67F5xfHeVw8zBxdPtb9BVjchKFNdiI7WaJApVkVZ/DS+MMk
xWycgOeizTmA==
pubclient1:$6$ue8f+Z9OlNRoPM6C$ay+mX+UMKfLWMvZqc9+4s+cFT7NOXhFfQ6iNW1dIuxnxVRDngWSnKBgkCC5h3l1M3b2Uq
KMw73dKXS05xQ==
Reload the Configuration File
from the same directory perform:
docker kill --signal=SIGHUP mosquitto
# OR
docker-compose -f docker-compose.prototype.yml -s SIGHUP mosquitto
This should provide a log in the mosquitto
container as following:
mosquitto | 1597864573: Reloading config.
Tada! 👏👏👏 New publishing client pubclient1
added!!
Use an MQTT Client to publish data to the broker with the new credentials.
Deleting A User from the MQTT Broker
Let’s remove pubclient1
from the mosquitto/config/passwd
by executing the following:
docker run -it --rm -v $(pwd)/mosquitto/config:/mosquitto/config/ eclipse-mosquitto mosquitto_passwd -D /mosquitto/config/passwd pubclient1
The -D <password_file> <username_to_remove>
will remove the username from the password file.
Reload the Configuration File
docker kill --signal=SIGHUP mosquitto
# OR
docker-compose -f docker-compose.prototype.yml -s SIGHUP mosquitto
Will then remove the username from the MQTT Broker
Conclusions
A bit of tweaking on the command line with docker
and some documentation reading + a dash of StackOverflow resolved queries helped me overcome the worry I previously had for downtimes in the Stack.
Future Works
I aware of an Authentication Plugin on GitHub for Mosquitto which handles User Management via different Databases but the repository is archived and there are so many forks to dapple with!
However, I might look into creating a RESTful API for the User Management described above but I am still in doubt as to if it makes sense to actually issue Shell Commands via REST APIs, on servers which might get messy at times!
If you have some thoughts on this idea, I would like to hear them. You can send me a message on my LinkedIn Profile anytime.