diff --git a/plugins/inputs/x509_cert/README.md b/plugins/inputs/x509_cert/README.md index 469a7561d2ffb..d48059dedf8a4 100644 --- a/plugins/inputs/x509_cert/README.md +++ b/plugins/inputs/x509_cert/README.md @@ -1,7 +1,7 @@ # x509 Certificate Input Plugin This plugin provides information about X509 certificate accessible via local -file or network connection. +file, tcp, udp, https or smtp protocol. When using a UDP address as a certificate source, the server must support [DTLS](https://en.wikipedia.org/wiki/Datagram_Transport_Layer_Security). @@ -14,7 +14,8 @@ When using a UDP address as a certificate source, the server must support ## List certificate sources, support wildcard expands for files ## Prefix your entry with 'file://' if you intend to use relative paths sources = ["tcp://example.org:443", "https://influxdata.com:443", - "udp://127.0.0.1:4433", "/etc/ssl/certs/ssl-cert-snakeoil.pem", + "smtp://mail.localhost:25", "udp://127.0.0.1:4433", + "/etc/ssl/certs/ssl-cert-snakeoil.pem", "/etc/mycerts/*.mydomain.org.pem", "file:///path/to/*.pem"] ## Timeout for SSL connection diff --git a/plugins/inputs/x509_cert/sample.conf b/plugins/inputs/x509_cert/sample.conf index 6423843a1bc7d..d3421a1dd60e3 100644 --- a/plugins/inputs/x509_cert/sample.conf +++ b/plugins/inputs/x509_cert/sample.conf @@ -3,7 +3,8 @@ ## List certificate sources, support wildcard expands for files ## Prefix your entry with 'file://' if you intend to use relative paths sources = ["tcp://example.org:443", "https://influxdata.com:443", - "udp://127.0.0.1:4433", "/etc/ssl/certs/ssl-cert-snakeoil.pem", + "smtp://mail.localhost:25", "udp://127.0.0.1:4433", + "/etc/ssl/certs/ssl-cert-snakeoil.pem", "/etc/mycerts/*.mydomain.org.pem", "file:///path/to/*.pem"] ## Timeout for SSL connection diff --git a/plugins/inputs/x509_cert/x509_cert.go b/plugins/inputs/x509_cert/x509_cert.go index d9843d962f419..ece23693e8d3e 100644 --- a/plugins/inputs/x509_cert/x509_cert.go +++ b/plugins/inputs/x509_cert/x509_cert.go @@ -10,6 +10,7 @@ import ( "encoding/pem" "fmt" "net" + "net/smtp" "net/url" "os" "path/filepath" @@ -176,6 +177,53 @@ func (c *X509Cert) getCert(u *url.URL, timeout time.Duration) ([]*x509.Certifica } content = rest } + return certs, nil + case "smtp": + ipConn, err := net.DialTimeout("tcp", u.Host, timeout) + if err != nil { + return nil, err + } + defer ipConn.Close() + + serverName, err := c.serverName(u) + if err != nil { + return nil, err + } + c.tlsCfg.ServerName = serverName + c.tlsCfg.InsecureSkipVerify = true + + smtpConn, err := smtp.NewClient(ipConn, u.Host) + if err != nil { + return nil, err + } + + err = smtpConn.Hello(c.tlsCfg.ServerName) + if err != nil { + return nil, err + } + + id, err := smtpConn.Text.Cmd("STARTTLS") + if err != nil { + return nil, err + } + + smtpConn.Text.StartResponse(id) + defer smtpConn.Text.EndResponse(id) + _, _, err = smtpConn.Text.ReadResponse(220) + if err != nil { + return nil, fmt.Errorf("did not get 220 after STARTTLS: %s", err.Error()) + } + + tlsConn := tls.Client(ipConn, c.tlsCfg) + defer tlsConn.Close() + + hsErr := tlsConn.Handshake() + if hsErr != nil { + return nil, hsErr + } + + certs := tlsConn.ConnectionState().PeerCertificates + return certs, nil default: return nil, fmt.Errorf("unsupported scheme '%s' in location %s", u.Scheme, u.String()) diff --git a/plugins/inputs/x509_cert/x509_cert_test.go b/plugins/inputs/x509_cert/x509_cert_test.go index f6e24e1bbd394..210e01b7df77c 100644 --- a/plugins/inputs/x509_cert/x509_cert_test.go +++ b/plugins/inputs/x509_cert/x509_cert_test.go @@ -355,12 +355,12 @@ func TestGatherCertMustNotTimeout(t *testing.T) { func TestSourcesToURLs(t *testing.T) { m := &X509Cert{ - Sources: []string{"https://www.influxdata.com:443", "tcp://influxdata.com:443", "file:///dummy_test_path_file.pem", "/tmp/dummy_test_path_glob*.pem"}, + Sources: []string{"https://www.influxdata.com:443", "tcp://influxdata.com:443", "smtp://influxdata.com:25", "file:///dummy_test_path_file.pem", "/tmp/dummy_test_path_glob*.pem"}, } require.NoError(t, m.Init()) require.Equal(t, len(m.globpaths), 2) - require.Equal(t, len(m.locations), 2) + require.Equal(t, len(m.locations), 3) } func TestServerName(t *testing.T) {