From 375710488df06ce5f2b6af4d234a65a64585fae8 Mon Sep 17 00:00:00 2001
From: Matt Jones <mattyjones@users.noreply.github.com>
Date: Tue, 19 Jul 2016 05:24:06 -0400
Subject: [PATCH] Add support for self-signed certs to RabbitMQ input plugin
 (#1503)

* add initial support to allow self-signed certs

When using self-signed the metrics collection will fail, this will allow
the user to specify in the input configuration file if they want to skip
certificate verification. This is functionally identical to `curl -k`

At some point this functionality should be moved to the agent as it is
already implemented identically in several different input plugins.

* Add initial comment strings to remove noise

These should be properly fleshed out at some point to ensure
code completeness

* refactor to use generic helper function

* fix import statement against fork

* update changelog
---
 CHANGELOG.md                        |  1 +
 plugins/inputs/rabbitmq/rabbitmq.go | 57 ++++++++++++++++++++++++++---
 2 files changed, 53 insertions(+), 5 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5aa149a8..517abea9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -36,6 +36,7 @@ should now look like:
 
 ### Features
 
+- [#1503](https://github.com/influxdata/telegraf/pull/1503): Add tls support for certs to RabbitMQ input plugin
 - [#1289](https://github.com/influxdata/telegraf/pull/1289): webhooks input plugin. Thanks @francois2metz and @cduez!
 - [#1247](https://github.com/influxdata/telegraf/pull/1247): rollbar webhook plugin.
 - [#1408](https://github.com/influxdata/telegraf/pull/1408): mandrill webhook plugin.
diff --git a/plugins/inputs/rabbitmq/rabbitmq.go b/plugins/inputs/rabbitmq/rabbitmq.go
index 18d666a0..8a879d17 100644
--- a/plugins/inputs/rabbitmq/rabbitmq.go
+++ b/plugins/inputs/rabbitmq/rabbitmq.go
@@ -9,35 +9,59 @@ import (
 	"time"
 
 	"github.com/influxdata/telegraf"
+	"github.com/influxdata/telegraf/internal"
 	"github.com/influxdata/telegraf/internal/errchan"
 	"github.com/influxdata/telegraf/plugins/inputs"
 )
 
+// DefaultUsername will set a default value that corrasponds to the default
+// value used by Rabbitmq
 const DefaultUsername = "guest"
+
+// DefaultPassword will set a default value that corrasponds to the default
+// value used by Rabbitmq
 const DefaultPassword = "guest"
+
+// DefaultURL will set a default value that corrasponds to the default value
+// used by Rabbitmq
 const DefaultURL = "http://localhost:15672"
 
+// RabbitMQ defines the configuration necessary for gathering metrics,
+// see the sample config for further details
 type RabbitMQ struct {
 	URL      string
 	Name     string
 	Username string
 	Password string
-	Nodes    []string
-	Queues   []string
+	// Path to CA file
+	SSLCA string `toml:"ssl_ca"`
+	// Path to host cert file
+	SSLCert string `toml:"ssl_cert"`
+	// Path to cert key file
+	SSLKey string `toml:"ssl_key"`
+	// Use SSL but skip chain & host verification
+	InsecureSkipVerify bool
+
+	// InsecureSkipVerify bool
+	Nodes  []string
+	Queues []string
 
 	Client *http.Client
 }
 
+// OverviewResponse ...
 type OverviewResponse struct {
 	MessageStats *MessageStats `json:"message_stats"`
 	ObjectTotals *ObjectTotals `json:"object_totals"`
 	QueueTotals  *QueueTotals  `json:"queue_totals"`
 }
 
+// Details ...
 type Details struct {
 	Rate float64
 }
 
+// MessageStats ...
 type MessageStats struct {
 	Ack               int64
 	AckDetails        Details `json:"ack_details"`
@@ -51,6 +75,7 @@ type MessageStats struct {
 	RedeliverDetails  Details `json:"redeliver_details"`
 }
 
+// ObjectTotals ...
 type ObjectTotals struct {
 	Channels    int64
 	Connections int64
@@ -59,6 +84,7 @@ type ObjectTotals struct {
 	Queues      int64
 }
 
+// QueueTotals ...
 type QueueTotals struct {
 	Messages                   int64
 	MessagesReady              int64 `json:"messages_ready"`
@@ -66,10 +92,11 @@ type QueueTotals struct {
 	MessageBytes               int64 `json:"message_bytes"`
 	MessageBytesReady          int64 `json:"message_bytes_ready"`
 	MessageBytesUnacknowledged int64 `json:"message_bytes_unacknowledged"`
-	MessageRam                 int64 `json:"message_bytes_ram"`
+	MessageRAM                 int64 `json:"message_bytes_ram"`
 	MessagePersistent          int64 `json:"message_bytes_persistent"`
 }
 
+// Queue ...
 type Queue struct {
 	QueueTotals         // just to not repeat the same code
 	MessageStats        `json:"message_stats"`
@@ -83,6 +110,7 @@ type Queue struct {
 	AutoDelete          bool `json:"auto_delete"`
 }
 
+// Node ...
 type Node struct {
 	Name string
 
@@ -99,6 +127,7 @@ type Node struct {
 	SocketsUsed   int64 `json:"sockets_used"`
 }
 
+// gatherFunc ...
 type gatherFunc func(r *RabbitMQ, acc telegraf.Accumulator, errChan chan error)
 
 var gatherFunctions = []gatherFunc{gatherOverview, gatherNodes, gatherQueues}
@@ -109,22 +138,40 @@ var sampleConfig = `
   # username = "guest"
   # password = "guest"
 
+  ## Optional SSL Config
+  # ssl_ca = "/etc/telegraf/ca.pem"
+  # ssl_cert = "/etc/telegraf/cert.pem"
+  # ssl_key = "/etc/telegraf/key.pem"
+  ## Use SSL but skip chain & host verification
+  # insecure_skip_verify = false
+
   ## A list of nodes to pull metrics about. If not specified, metrics for
   ## all nodes are gathered.
   # nodes = ["rabbit@node1", "rabbit@node2"]
 `
 
+// SampleConfig ...
 func (r *RabbitMQ) SampleConfig() string {
 	return sampleConfig
 }
 
+// Description ...
 func (r *RabbitMQ) Description() string {
 	return "Read metrics from one or many RabbitMQ servers via the management API"
 }
 
+// Gather ...
 func (r *RabbitMQ) Gather(acc telegraf.Accumulator) error {
 	if r.Client == nil {
-		tr := &http.Transport{ResponseHeaderTimeout: time.Duration(3 * time.Second)}
+		tlsCfg, err := internal.GetTLSConfig(
+			r.SSLCert, r.SSLKey, r.SSLCA, r.InsecureSkipVerify)
+		if err != nil {
+			return err
+		}
+		tr := &http.Transport{
+			ResponseHeaderTimeout: time.Duration(3 * time.Second),
+			TLSClientConfig:       tlsCfg,
+		}
 		r.Client = &http.Client{
 			Transport: tr,
 			Timeout:   time.Duration(4 * time.Second),
@@ -286,7 +333,7 @@ func gatherQueues(r *RabbitMQ, acc telegraf.Accumulator, errChan chan error) {
 				"message_bytes":             queue.MessageBytes,
 				"message_bytes_ready":       queue.MessageBytesReady,
 				"message_bytes_unacked":     queue.MessageBytesUnacknowledged,
-				"message_bytes_ram":         queue.MessageRam,
+				"message_bytes_ram":         queue.MessageRAM,
 				"message_bytes_persist":     queue.MessagePersistent,
 				"messages":                  queue.Messages,
 				"messages_ready":            queue.MessagesReady,
-- 
GitLab