Skip to content
Wouter van Kleunen edited this page Feb 4, 2022 · 25 revisions

Introduction to mqtt_cpp broker security

The mqtt_cpp broker allows access control to limit publish and subscribe to specific topics. Access control is configured through the auth file. The auth file can be specified through the command line of the broker or in the configuration ini file of the broker:

# Default configuration for MQTT-CPP Broker
verbose=1
auth_file=auth.json

The auth file is in JSON format and specified both authentication (which users are allowed to connect to the broker) and authorization (what topics are each user allowed to publish / subscribe). Finally, for convenience, users can be joined in a group and authorization can be specified on group basis.

A complete example of the auth file is given here, different sections are explained below.

{
    "authentication": [{
            "comment": "Authenticates user by password using sha256 hash and specified salt for password sha256(salt + password)",
            "name": "u1",
            "method": "sha256",
            "salt": "salt",
            "digest": "38ea2e5e88fcd692fe177c6cada15e9b2db6e70bee0a0d6678c8d3b2a9aae2ad"
        },
        {
            "comment": "Authenticates user by client certificate",
            "name": "u2",
            "method": "client_cert"
        },
        {
            "comment": "Handles all users that login without username / password",
            "name": "anonymous",
            "method": "anonymous"
        },
        {
            "comment": "Handles all users that are not authenticated (non-existing user, invalid password)",
            "name": "unauthenticated",
            "method": "unauthenticated"
        }
    ],
    "group": [{
        "comment": "Users can be combined into groups, group name starts with @",
        "name": "@g1",
        "members": ["u1", "u2", "anonymous", "unauthenticated"]
    }],
    "authorization": [{
            "comment": "Specified users and groups are denied to publish on this topic",
            "topic": "#",
            "type": "deny",
            "pub": ["@g1"]
        },
        {
            "comment": "Specified users and groups are denied to subscribe on this topic",
            "topic": "#",
            "type": "deny",
            "sub": ["@g1"]
        },
        {
            "comment": "Specified users and groups are allowed to subscribe and publish on this topic",
            "topic": "sub/#",
            "type": "allow",
            "sub": ["@g1"],
            "pub": ["@g1"]
        },
        {
            "comment": "Specified users and groups are denied to subscribe and publish on this topic",
            "topic": "sub/topic1",
            "type": "deny",
            "sub": ["u1", "anonymous"],
            "pub": ["u1", "anonymous"]
        }
    ]
}

Authentication of users

When a user connects to the broker, it should authorize itself. For all methods, the username of the user is stored in the 'name' field. The name of the user can be any combination of characters, but can not start with the '@' symbol (this is reserved for groups).

Based on different methods, the user can be checked if allowed access to the broker:

  • method=sha256 Using the sha256 method, the username/password the client supplies is checked against a hash stored in the auth file. An example configuration for using sha256 looks as follows:
{
    "comment": "Authenticates user by password using sha256 hash and specified salt for password sha256(salt + password)",
    "name": "u1",
    "method": "sha256",
    "salt": "salt",
    "digest": "38ea2e5e88fcd692fe177c6cada15e9b2db6e70bee0a0d6678c8d3b2a9aae2ad"
}

A hash is calculated using the specified salt password field. This can be calculated using the openssl cli tool:

echo -n "saltmypassword" | openssl sha256 
(stdin)= 38ea2e5e88fcd692fe177c6cada15e9b2db6e70bee0a0d6678c8d3b2a9aae2ad

In this example the salt=salt, and password=mypassword, resulting in the hash=38ea2e5e88fcd692fe177c6cada15e9b2db6e70bee0a0d6678c8d3b2a9aae2ad

  • method=client_cert With this method, the clients certificate is validated. If the client supplies a valid certificate, the CNAME of the certificate is used as username. An example of a user validated using certificate:
{
    "comment": "Authenticates user by client certificate",
    "name": "u2",
    "method": "client_cert"    
}
  • method=anonymous In case the client specifies no username/password while connecting, this method allows specifying the anonymous user. Only a single anonymous entry in the auth file can be specified:
{
    "comment": "Handles all users that login without username / password",
    "name": "anonymous",
    "method": "anonymous"
}
  • method=plain_password A plain password method is added for testing purposes, it allows validation against a password stored in plain text in the auth file. Note that is not recommended for production use! In case the auth file is leaked, passwords are breached! Nonetheless, this method can be used as follows:
{
    "comment": "For debugging purposes a plain text can be used",
    "name": "username",
    "method": "plain_password",
    "password": "secret"
}
  • method=unauthenticated Finally, to catch users not being able to login (wrong username, wrong password), a catch-all method for unauthenticated users is added. This allowes unauthenticated users to get access to certain topics as well:
{
    "comment": "Handles all users that are not authenticated (non-existing user, invalid password)",
    "name": "unauthenticated",
    "method": "unauthenticated"
}

Groups

Users can be gived pub/sub access to specific topics. For convenience users can be combined intro groups. A group name always starts with the '@' symbol and can be configured as follows:

"group": [
    {
        "comment": "Users can be combined into groups, group name starts with @",
        "name": "@g1",
        "members": ["u1", "u2", "anonymous", "unauthenticated"]
    }
]

Authorization

Using the authorization rules, users and groups can be given access to publish and subscribe to topics. Topics can be specified using topic filters, and may include '+' and '#' to match multiple topics. By default a user is not allowed to publish or subscribe any topic.

Publish/subscribe access is given to users by using authorization rules. Authorization rules are applied in the order that they are given.

Authorization of publish

To give user access to publish to a certain topic, use an entry with type allow:

{
    "comment": "Specified users and groups are allowed to publish on this topic",
    "topic": "#",
    "type": "deny",
    "pub": ["@g1"]
}

To deny access to a topic, use an entry with type deny:

{
    "comment": "Specified users and groups are denied to subscribe and publish on this topic",
    "topic": "sub/topic1",
    "type": "deny",    
    "pub": ["u1", "anonymous"]
}

Authorization of subscribe

To allow users to subscribe to a specific topic, again entries with deny/allow can be specified: To give user access to publish to a certain topic, use an entry with type allow:

{
    "comment": "Specified users and groups are not allowed to subscribe on this topic",
    "topic": "#",
    "type": "deny",
    "pub": ["@g1"]
},
{
    "comment": "Specified users and groups are allowed to subscribe on this topic and topics below",
    "topic": "subtopic_allow/#",
    "type": "allow",
    "pub": ["@g1"]
},
{
    "comment": "Specified users and groups are not allowed to subscribe on this topic and topics below",
    "topic": "subtopic_deny/#",
    "type": "deny",
    "pub": ["@g1"]
},

In this example, users are able to subscribe to topic "subtopic_allow/#" or other topics below. They will receive messages published to these topics. They are not allowed to subscribe to "subtopic_deny/#" or topics below. They will not receive messages published to this topic.

They are however allowed to subscribe to topic '#'. However, they will only receive messages published to "subtopic_allow/#" and not "subtopic_deny/#".

Clone this wiki locally