Multi-user MQTT platform

Multi-user MQTT platform

Mosquitto is usually the first candidate to come to mind when looking for an MQTT broker. However, by default, Mosquitto manages users using a password file. This makes it difficult to easily add or remove users, especially when the broker is deployed in Kubernetes.

I recently stumbled upon the mosquitto-go-auth plugin, which allows for the authentication to be performed by an external service, by connecting to the latter via, for example, HTTP requests.

This is ideal as it allows to outsource the authentication to my user management and authentication service. As the requests sent by the plugin are not exactly in the format expected by the user management service, I created a simple gateway service that proxies the requests and converts them accordingly.

Thanks to this architecture, user accounts can easily be created and the credentials of those accounts can be used to authenticate connecting MQTT clients. On top of that, the MQTT authentication gateway is configured to only allow users to publish and subscribe to topics that begin with their username, thus preventing the access to someone else's data.

Moreover, with an appropriate use of configmaps, Mosquitto can be deployed entirely in Kubernetes while provided an SSL secured MQTT broker.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mosquitto-data
  namespace: iot
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mosquitto
  namespace: iot
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mosquitto
  template:
    metadata:
      labels:
        app: mosquitto
    spec:
      containers:
      - name: mosquitto
        image: iegomez/mosquitto-go-auth
        ports:
        - containerPort: 8883
        - containerPort: 9001
        volumeMounts:
        - mountPath: "/etc/mosquitto/"
          name: config
        - mountPath: "/mosquitto/certs/"
          name: certs
        - mountPath: "/mosquitto/data/"
          name: data
      volumes:
      - name: config
        configMap:
          name: mosquitto-config
      - name: certs
        secret:
          secretName: mosquitto-certs
      - name: data
        persistentVolumeClaim:
          claimName: mosquitto-data
---
apiVersion: v1
kind: Service
metadata:
  name: mosquitto-nodeport
  namespace: iot
spec:
  type: NodePort
  selector:
    app: mosquitto
  ports:
  - port: 8883
    nodePort: 30883
---
apiVersion: v1
kind: Service
metadata:
  name: mosquitto-clusterip
  namespace: iot
spec:
  type: ClusterIP
  selector:
    app: mosquitto
  ports:
  - port: 9001
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: mosquitto-config
  namespace: iot
data:
  mosquitto.conf: |

    persistence true
    persistence_location /mosquitto/data/

    log_dest stdout

    # Raw MQTT with TLS (MQTTS)
    listener 8883
    protocol mqtt

    cafile /mosquitto/certs/ca.crt
    keyfile /mosquitto/certs/tls.key
    certfile /mosquitto/certs/tls.crt

    allow_anonymous false

    auth_plugin /mosquitto/go-auth.so
    auth_opt_log_dest stdout
    auth_opt_log_level debug

    auth_opt_backends http

    auth_opt_http_host mosquitto-auth-gateway
    auth_opt_http_port 80
    auth_opt_http_getuser_uri /getuser
    auth_opt_http_aclcheck_uri /aclcheck
    auth_opt_http_superuser_uri /superuser

    # MQTT over Websocket using TLS (WSS)
    # Not too sure why has to be defined after and options dont need to be repeated
    listener 9001
    protocol websockets


---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: mosquitto
  namespace: iot
  annotations:
    kubernetes.io/ingress.class: "nginx"
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
  tls:
  - hosts:
    - mqtt.example.com
    secretName: mosquitto-certs
  rules:
  - host: mqtt.example.com
    http:
      paths:
      - path: /
        backend:
          serviceName: mosquitto-clusterip
          servicePort: 9001
---

As such, this architecture achieves a cloud native multi-user MQTT broker.

The source code for the authentication gateway is available on GitLab.