Skip to content

Commit

Permalink
Merge pull request #49 from weboo/tls-client-certificates
Browse files Browse the repository at this point in the history
support for TLS client certificates
  • Loading branch information
hikhvar authored Mar 12, 2021
2 parents 98c0f6b + f5562d2 commit 87310fc
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 6 deletions.
51 changes: 45 additions & 6 deletions cmd/mqtt2prometheus.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package main

import (
"crypto/tls"
"crypto/x509"
"encoding/json"
"flag"
"fmt"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"io/ioutil"
"net/http"
"os"
"time"
Expand Down Expand Up @@ -63,19 +66,28 @@ func main() {
logger := mustSetupLogger()
defer logger.Sync() //nolint:errcheck
c := make(chan os.Signal, 1)
hostName, err := os.Hostname()
if err != nil {
logger.Fatal("Could not get hostname", zap.Error(err))
}
cfg, err := config.LoadConfig(*configFlag)
if err != nil {
logger.Fatal("Could not load config", zap.Error(err))
}
mqttClientOptions := mqtt.NewClientOptions()
mqttClientOptions.AddBroker(cfg.MQTT.Server).SetClientID(hostName).SetCleanSession(true)
mqttClientOptions.AddBroker(cfg.MQTT.Server).SetCleanSession(true)
mqttClientOptions.SetUsername(cfg.MQTT.User)
mqttClientOptions.SetPassword(cfg.MQTT.Password)
mqttClientOptions.SetClientID(mustMQTTClientID())

if cfg.MQTT.ClientID != "" {
mqttClientOptions.SetClientID(cfg.MQTT.ClientID)
} else {
mqttClientOptions.SetClientID(mustMQTTClientID())
}

if cfg.MQTT.ClientCert != "" || cfg.MQTT.ClientKey != "" {
tlsconfig, err := newTlsConfig(cfg)
if err != nil {
logger.Fatal("Invalid tls certificate settings", zap.Error(err))
}
mqttClientOptions.SetTLSConfig(tlsconfig)
}

collector := metrics.NewCollector(cfg.Cache.Timeout, cfg.Metrics, logger)
extractor, err := setupExtractor(cfg)
Expand Down Expand Up @@ -182,3 +194,30 @@ func setupExtractor(cfg config.Config) (metrics.Extractor, error) {
}
return nil, fmt.Errorf("no extractor configured")
}

func newTlsConfig(cfg config.Config) (*tls.Config, error) {
certpool := x509.NewCertPool()
if cfg.MQTT.CACert != "" {
pemCerts, err := ioutil.ReadFile(cfg.MQTT.CACert)
if err != nil {
return nil, err
}
certpool.AppendCertsFromPEM(pemCerts)
}

cert, err := tls.LoadX509KeyPair(cfg.MQTT.ClientCert, cfg.MQTT.ClientKey)
if err != nil {
return nil, err
}

cert.Leaf, err = x509.ParseCertificate(cert.Certificate[0])
if err != nil {
panic(fmt.Sprintf("could not parse certificate: %v", err))
}

return &tls.Config{
RootCAs: certpool,
InsecureSkipVerify: false,
Certificates: []tls.Certificate{cert},
}, nil
}
6 changes: 6 additions & 0 deletions config.yaml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ mqtt:
# Optional: Username and Password for authenticating with the MQTT Server
# user: bob
# password: happylittleclouds
# Optional: for TLS client certificates
# ca_cert: certs/AmazonRootCA1.pem
# client_cert: certs/xxxxx-certificate.pem.crt
# client_key: certs/xxxxx-private.pem.key
# Optional: Used to specify ClientID. The default is <hostname>-<pid>
# client_id: somedevice
# The Topic path to subscribe to. Be aware that you have to specify the wildcard.
topic_path: v1/devices/me/+
# Optional: Regular expression to extract the device ID from the topic path. The default regular expression, assumes
Expand Down
4 changes: 4 additions & 0 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,10 @@ type MQTTConfig struct {
QoS byte `yaml:"qos"`
ObjectPerTopicConfig *ObjectPerTopicConfig `yaml:"object_per_topic_config"`
MetricPerTopicConfig *MetricPerTopicConfig `yaml:"metric_per_topic_config"`
CACert string `yaml:"ca_cert"`
ClientCert string `yaml:"client_cert"`
ClientKey string `yaml:"client_key"`
ClientID string `yaml:"client_id"`
}

const EncodingJSON = "JSON"
Expand Down

0 comments on commit 87310fc

Please sign in to comment.