diff --git a/plugins/inputs/ssl_cert/ssl_cert.go b/plugins/inputs/ssl_cert/ssl_cert.go index e013feec5f1b3..f28b7d832f8d0 100644 --- a/plugins/inputs/ssl_cert/ssl_cert.go +++ b/plugins/inputs/ssl_cert/ssl_cert.go @@ -24,24 +24,28 @@ const sampleConfig = ` ` const description = "Reads metrics from a SSL certificate" +// SSLCert holds the configuration of the plugin. type SSLCert struct { Servers []string `toml:"servers"` Files []string `toml:"files"` Timeout time.Duration `toml:"timeout"` // For tests - CloseConn bool + CloseConn bool + UnsetCerts bool } +// Description returns description of the plugin. func (sc *SSLCert) Description() string { return description } +// SampleConfig returns configuration sample for the plugin. func (sc *SSLCert) SampleConfig() string { return sampleConfig } -func getRemoteCert(server string, timeout time.Duration, closeConn bool) (*x509.Certificate, error) { +func getRemoteCert(server string, timeout time.Duration, closeConn bool, unsetCerts bool) (*x509.Certificate, error) { tlsCfg := &tls.Config{ InsecureSkipVerify: true, } @@ -66,8 +70,12 @@ func getRemoteCert(server string, timeout time.Duration, closeConn bool) (*x509. certs := conn.ConnectionState().PeerCertificates + if unsetCerts { + certs = nil + } + if certs == nil || len(certs) < 1 { - return nil, errors.New("Couldn't get remote certificate.") + return nil, errors.New("couldn't get remote certificate") } return certs[0], nil @@ -81,7 +89,7 @@ func getLocalCert(filename string) (*x509.Certificate, error) { block, _ := pem.Decode(content) if block == nil { - return nil, errors.New("Failed to parse certificate PEM.") + return nil, errors.New("failed to parse certificate PEM") } cert, err := x509.ParseCertificate(block.Bytes) @@ -108,13 +116,14 @@ func getMetrics(cert *x509.Certificate, now time.Time) map[string]interface{} { return metrics } +// Gather adds metrics into the accumulator. func (sc *SSLCert) Gather(acc telegraf.Accumulator) error { now := time.Now() for _, server := range sc.Servers { - cert, err := getRemoteCert(server, sc.Timeout*time.Second, sc.CloseConn) + cert, err := getRemoteCert(server, sc.Timeout*time.Second, sc.CloseConn, sc.UnsetCerts) if err != nil { - return errors.New(fmt.Sprintf("Cannot get remote SSL cert: %s", err)) + return fmt.Errorf("cannot get remote SSL cert '%s': %s", server, err) } tags := map[string]string{ @@ -129,7 +138,7 @@ func (sc *SSLCert) Gather(acc telegraf.Accumulator) error { for _, file := range sc.Files { cert, err := getLocalCert(file) if err != nil { - return errors.New(fmt.Sprintf("Cannot get local SSL cert: %s", err)) + return fmt.Errorf("cannot get local SSL cert '%s': %s", file, err) } tags := map[string]string{ diff --git a/plugins/inputs/ssl_cert/ssl_cert_test.go b/plugins/inputs/ssl_cert/ssl_cert_test.go index 8b866a70c7f1c..75975088a3e45 100644 --- a/plugins/inputs/ssl_cert/ssl_cert_test.go +++ b/plugins/inputs/ssl_cert/ssl_cert_test.go @@ -10,6 +10,7 @@ import ( "time" "github.com/influxdata/telegraf/testutil" + "github.com/influxdata/telegraf" ) const testCert = `-----BEGIN CERTIFICATE----- @@ -64,9 +65,8 @@ JoiUjTAZegW1RkST3tB1an9zO0EcPvo/1yU7wKaMuNwmauPlltBdpaTwojeUBiFr AoQUXWIiFBoFfpNVcvUgHyGGc1hv7TX8Eh8KGo2+VuPzxnFuRrbbYCs= -----END RSA PRIVATE KEY-----` -func getTestPrefix(testN int) string { - return fmt.Sprintf("Test [%d]: ", testN) -} +// Make sure SSLCert implements telegraf.Input +var _ telegraf.Input = &SSLCert{} func TestGatherRemote(t *testing.T) { if testing.Short() { @@ -77,51 +77,54 @@ func TestGatherRemote(t *testing.T) { server string timeout time.Duration close bool + unset bool error bool }{ - {server: ":99999", timeout: 0, close: false, error: true}, - {server: "", timeout: 5, close: false, error: false}, - {server: "", timeout: 0, close: true, error: true}, - } - - pair, err := tls.X509KeyPair([]byte(testCert), []byte(testKey)) - if err != nil { - t.Error(err) + {server: ":99999", timeout: 0, close: false, unset: false, error: true}, + {server: "", timeout: 5, close: false, unset: false, error: false}, + {server: "", timeout: 5, close: false, unset: true, error: true}, + {server: "", timeout: 0, close: true, unset: false, error: true}, } - config := &tls.Config{ - Certificates: []tls.Certificate{pair}, - } + for i, test := range tests { + pair, err := tls.X509KeyPair([]byte(testCert), []byte(testKey)) + if err != nil { + t.Fatal(err) + } - ln, err := tls.Listen("tcp", ":0", config) - if err != nil { - t.Error(err) - } - defer ln.Close() + config := &tls.Config{ + Certificates: []tls.Certificate{pair}, + } - go func() { - sconn, err := ln.Accept() + ln, err := tls.Listen("tcp", ":0", config) if err != nil { - return + t.Fatal(err) } + defer ln.Close() - serverConfig := config.Clone() + go func() { + sconn, err := ln.Accept() + if err != nil { + return + } - srv := tls.Server(sconn, serverConfig) - if err := srv.Handshake(); err != nil { - return - } - }() + serverConfig := config.Clone() + + srv := tls.Server(sconn, serverConfig) + if err := srv.Handshake(); err != nil { + return + } + }() - for i, test := range tests { if test.server == "" { test.server = ln.Addr().String() } sc := SSLCert{ - Servers: []string{test.server}, - Timeout: test.timeout, - CloseConn: test.close, + Servers: []string{test.server}, + Timeout: test.timeout, + CloseConn: test.close, + UnsetCerts: test.unset, } error := false @@ -155,22 +158,22 @@ func TestGatherLocal(t *testing.T) { for i, test := range tests { f, err := ioutil.TempFile("", "ssl_cert") if err != nil { - t.Error(err) + t.Fatal(err) } _, err = f.Write([]byte(test.content)) if err != nil { - t.Error(err) + t.Fatal(err) } err = f.Chmod(test.mode) if err != nil { - t.Error(err) + t.Fatal(err) } err = f.Close() if err != nil { - t.Error(err) + t.Fatal(err) } defer os.Remove(f.Name())