MQTT Device

Configuring MQTT clients

MQTT clients authenticate devices by connecting to the MQTT bridge. To configure an MQTT client to authenticate a device:

  1. Set the MQTT client ID to the full device path:Client Identifier

    subscriptions/SUBSCRIPTION_ID/registries/REGISTRY_ID/devices/DEVICE_ID
  2. Associate the MQTT client with MQTT server certificates.

  3. Set the MQTT host name to hostprefix.mqtt.korewireless.com or a long-term support domain (if you used the minimal root CA set).

  4. Specify a username. The MQTT bridge ignores the username field, but some MQTT client libraries will not send the password field unless the username field is specified. For best results, supply an arbitrary username like unused or ignored.

  5. Set the password. The password field must contain the JWT.

The following sample shows how to configure the MQTT client to authenticate a device:

package main

import (
    "crypto/tls"
    "crypto/x509"
    "flag"
    "fmt"
    "io/ioutil"
    "log"
    "time"

    MQTT "github.com/eclipse/paho.mqtt.golang"
    jwt "github.com/golang-jwt/jwt"
)

var (
    deviceID = flag.String("device", "", "Omnicore  Device ID")
    bridge   = struct {
        host *string
        port *string
    }{
        flag.String("mqtt_host", "hostprefix.mqtt.korewireless.com", "MQTT Bridge Host"),
        flag.String("mqtt_port", "8883", "MQTT Bridge Port"),
    }
    subscriptionID = flag.String("subscription", "", "Omnicore Subscription ID")
    registryID     = flag.String("registry", "", "Omnicore Registry ID (short form)")
    certsCA        = flag.String("ca_certs", "", "Download https://pki.cloud.korewireless.com/roots.pem")
    privateKey     = flag.String("private_key", "", "Path to private key file")
)

func main() {
    log.Println("[main] Entered")

    log.Println("[main] Flags")
    flag.Parse()

    log.Println("[main] Loading Omnicore's roots")
    certpool := x509.NewCertPool()
    pemCerts, err := ioutil.ReadFile(*certsCA)
    if err == nil {
        certpool.AppendCertsFromPEM(pemCerts)
    }

    log.Println("[main] Creating TLS Config")

    config := &tls.Config{
        RootCAs:            certpool,
        ClientAuth:         tls.NoClientCert,
        ClientCAs:          nil,
        InsecureSkipVerify: true,
        Certificates:       []tls.Certificate{},
        MinVersion:         tls.VersionTLS12,
    }

    clientID := fmt.Sprintf("subscriptions/%v/registries/%v/devices/%v",
        *subscriptionID,
        *registryID,
        *deviceID,
    )

    log.Println("[main] Creating MQTT Client Options")
    opts := MQTT.NewClientOptions()

    broker := fmt.Sprintf("ssl://%v:%v", *bridge.host, *bridge.port)
    log.Printf("[main] Broker '%v'", broker)

    opts.AddBroker(broker)
    opts.SetClientID(clientID).SetTLSConfig(config)

    opts.SetUsername("unused")

    token := jwt.New(jwt.SigningMethodRS256)
    token.Claims = jwt.StandardClaims{
        IssuedAt:  time.Now().Unix(),
        ExpiresAt: time.Now().Add(24 * time.Hour).Unix(),
    }

    log.Println("[main] Load Private Key")
    keyBytes, err := ioutil.ReadFile(*privateKey)
    if err != nil {
        log.Fatal(err)
    }

    log.Println("[main] Parse Private Key")
    key, err := jwt.ParseRSAPrivateKeyFromPEM(keyBytes)
    if err != nil {
        log.Fatal(err)
    }

    log.Println("[main] Sign String")
    tokenString, err := token.SignedString(key)
    if err != nil {
        log.Fatal(err)
    }

    opts.SetPassword(tokenString)

    // Incoming
    opts.SetDefaultPublishHandler(func(client MQTT.Client, msg MQTT.Message) {
        fmt.Printf("[handler] Topic: %v\n", msg.Topic())
        fmt.Printf("[handler] Payload: %v\n", msg.Payload())
    })

    log.Println("[main] MQTT Client Connecting")
    client := MQTT.NewClient(opts)
    if token := client.Connect(); token.Wait() && token.Error() != nil {
        log.Fatal(token.Error())
    }
}

    
o

Last updated