mqtt: add SSL/TLS client options support

Signed-off-by: deadprogram <ron@hybridgroup.com>
This commit is contained in:
deadprogram 2017-01-26 19:03:32 +01:00
parent 11473b96f4
commit 01d1bd79f7
2 changed files with 81 additions and 1 deletions

View File

@ -1,7 +1,13 @@
// TO RUN:
// go run ./examples/mqtt_driver_ping.go tcp://test.mosquitto.org:1883
// OR
// go run ./examples/mqtt_driver_ping.go ssl://iot.eclipse.org:8883
package main
import (
"fmt"
"os"
"time"
"gobot.io/x/gobot"
@ -9,7 +15,7 @@ import (
)
func main() {
mqttAdaptor := mqtt.NewAdaptor("tcp://test.mosquitto.org:1883", "pinger")
mqttAdaptor := mqtt.NewAdaptor(os.Args[1], "pinger")
mqttAdaptor.SetAutoReconnect(true)
holaDriver := mqtt.NewDriver(mqttAdaptor, "hola")

View File

@ -1,6 +1,10 @@
package mqtt
import (
"crypto/tls"
"crypto/x509"
"io/ioutil"
paho "github.com/eclipse/paho.mqtt.golang"
multierror "github.com/hashicorp/go-multierror"
)
@ -12,6 +16,10 @@ type Adaptor struct {
clientID string
username string
password string
UseSSL bool
serverCert string
clientCert string
clientKey string
autoReconnect bool
client paho.Client
}
@ -22,6 +30,7 @@ func NewAdaptor(host string, clientID string) *Adaptor {
name: "MQTT",
Host: host,
autoReconnect: false,
UseSSL: false,
clientID: clientID,
}
}
@ -32,6 +41,7 @@ func NewAdaptorWithAuth(host, clientID, username, password string) *Adaptor {
name: "MQTT",
Host: host,
autoReconnect: false,
UseSSL: false,
clientID: clientID,
username: username,
password: password,
@ -53,6 +63,24 @@ func (a *Adaptor) AutoReconnect() bool { return a.autoReconnect }
// SetAutoReconnect sets the MQTT AutoReconnect setting
func (a *Adaptor) SetAutoReconnect(val bool) { a.autoReconnect = val }
// ServerCert returns the MQTT server SSL cert file
func (a *Adaptor) ServerCert() string { return a.serverCert }
// SetServerCert sets the MQTT server SSL cert file
func (a *Adaptor) SetServerCert(val string) { a.serverCert = val }
// ClientCert returns the MQTT client SSL cert file
func (a *Adaptor) ClientCert() string { return a.clientCert }
// SetClientCert sets the MQTT server SSL cert file
func (a *Adaptor) SetClientCert(val string) { a.clientCert = val }
// ClientKey returns the MQTT client SSL key file
func (a *Adaptor) ClientKey() string { return a.clientKey }
// SetClientCert sets the MQTT server SSL key file
func (a *Adaptor) SetClientKey(val string) { a.clientKey = val }
// Connect returns true if connection to mqtt is established
func (a *Adaptor) Connect() (err error) {
a.client = paho.NewClient(a.createClientOptions())
@ -106,5 +134,51 @@ func (a *Adaptor) createClientOptions() *paho.ClientOptions {
opts.SetUsername(a.username)
}
opts.AutoReconnect = a.autoReconnect
if a.UseSSL {
opts.SetTLSConfig(a.newTLSConfig())
}
return opts
}
// newTLSConfig sets the TLS config in the case that we are using
// an MQTT broker with TLS
func (a *Adaptor) newTLSConfig() *tls.Config {
// Import server certificate
var certpool *x509.CertPool
if len(a.ServerCert()) > 0 {
certpool = x509.NewCertPool()
pemCerts, err := ioutil.ReadFile(a.ServerCert())
if err == nil {
certpool.AppendCertsFromPEM(pemCerts)
}
}
// Import client certificate/key pair
var certs []tls.Certificate
if len(a.ClientCert()) > 0 && len(a.ClientKey()) > 0 {
cert, err := tls.LoadX509KeyPair(a.ClientCert(), a.ClientKey())
if err != nil {
// TODO: proper error handling
panic(err)
}
certs = append(certs, cert)
}
// Create tls.Config with desired tls properties
return &tls.Config{
// RootCAs = certs used to verify server cert.
RootCAs: certpool,
// ClientAuth = whether to request cert from server.
// Since the server is set up for SSL, this happens
// anyways.
ClientAuth: tls.NoClientCert,
// ClientCAs = certs used to validate client cert.
ClientCAs: nil,
// InsecureSkipVerify = verify that cert contents
// match server. IP matches what is in cert etc.
InsecureSkipVerify: true,
// Certificates = list of certs client sends to server.
Certificates: certs,
}
}