diff --git a/cmd/mqtt2prometheus.go b/cmd/mqtt2prometheus.go index 0c9e667..b56573d 100644 --- a/cmd/mqtt2prometheus.go +++ b/cmd/mqtt2prometheus.go @@ -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" @@ -63,19 +66,23 @@ 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()) + } + + tlsconfig := newTlsConfig(cfg) + mqttClientOptions.SetTLSConfig(tlsconfig) collector := metrics.NewCollector(cfg.Cache.Timeout, cfg.Metrics, logger) extractor, err := setupExtractor(cfg) @@ -182,3 +189,27 @@ func setupExtractor(cfg config.Config) (metrics.Extractor, error) { } return nil, fmt.Errorf("no extractor configured") } + +func newTlsConfig(cfg config.Config) *tls.Config { + certpool := x509.NewCertPool() + pemCerts, err := ioutil.ReadFile(cfg.MQTT.CACert) + if err == nil { + certpool.AppendCertsFromPEM(pemCerts) + } + + cert, err := tls.LoadX509KeyPair(cfg.MQTT.ClientCert, cfg.MQTT.ClientKey) + if err != nil { + return &tls.Config{} + } + + cert.Leaf, err = x509.ParseCertificate(cert.Certificate[0]) + if err != nil { + panic(err) + } + + return &tls.Config{ + RootCAs: certpool, + InsecureSkipVerify: false, + Certificates: []tls.Certificate{cert}, + } +} diff --git a/config.yaml.dist b/config.yaml.dist index b5686ab..b9b79c1 100644 --- a/config.yaml.dist +++ b/config.yaml.dist @@ -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 - + # 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 diff --git a/pkg/config/config.go b/pkg/config/config.go index e82a87d..2b1ead6 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -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"