Skip to content
This repository has been archived by the owner on Mar 27, 2024. It is now read-only.

X509check module #166

Merged
merged 9 commits into from
Mar 14, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cmd/godplugin/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
_ "github.com/netdata/go.d.plugin/modules/solr"
_ "github.com/netdata/go.d.plugin/modules/springboot2"
_ "github.com/netdata/go.d.plugin/modules/weblog"
_ "github.com/netdata/go.d.plugin/modules/x509check"
)

var (
Expand Down
1 change: 1 addition & 0 deletions config/go.d.conf
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,4 @@ modules:
# solr: yes
# springboot2: yes
# web_log: yes
# x509check: yes
116 changes: 116 additions & 0 deletions config/go.d/x509check.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# netdata go.d.plugin configuration for x509check
#
# This file is in YaML format. Generally the format is:
#
# name: value
#
# There are 2 sections:
# - GLOBAL
# - JOBS
#
#
# [ GLOBAL ]
# These variables set the defaults for all JOBs, however each JOB may define its own, overriding the defaults.
#
# The GLOBAL section format:
# param1: value1
# param2: value2
#
# Currently supported global parameters:
# - update_every
# Data collection frequency in seconds. Default: 1.
#
# - autodetection_retry
# Re-check interval in seconds. Attempts to start the job are made once every interval.
# Zero means not to schedule re-check. Default: 0.
#
#
# [ JOBS ]
# JOBS allow you to collect values from multiple sources.
# Each source will have its own set of charts.
#
# IMPORTANT:
# - Parameter 'name' is mandatory.
# - Jobs with the same name are mutually exclusive. Only one of them will be allowed running at any time.
#
# This allows autodetection to try several alternatives and pick the one that works.
# Any number of jobs is supported.
#
# The JOBS section format:
#
# jobs:
# - name: job1
# param1: value1
# param2: value2
#
# - name: job2
# param1: value1
# param2: value2
#
# - name: job2
# param1: value1
#
#
# [ List of JOB specific parameters ]:
# - source
# Certificate source. Allowed schemes: https, tcp, tcp4, tcp6, udp, udp4, udp6.
# Syntax:
# source: https://example.org:443
#
# - days_until_expiration_warning
# Number of days before the alarm status is warning.
# Syntax:
# days_until_expiration_warning: 30
#
# - days_until_expiration_critical
# Number of days before the alarm status is critical.
# Syntax:
# days_until_expiration_critical: 15
#
# - timeout
# SSL connection timeout.
# Syntax:
# timeout: 3
#
# - tls_skip_verify
# Whether to skip verifying server's certificate chain and hostname.
# Syntax:
# tls_skip_verify: yes/no
#
# - tls_ca
# Certificate authority that client use when verifying server certificates.
# Syntax:
# tls_ca: path/to/ca.pem
#
# - tls_cert
# Client tls certificate.
# Syntax:
# tls_cert: path/to/cert.pem
#
# - tls_key
# Client tls key.
# Syntax:
# tls_key: path/to/key.pem
#
#
# [ JOB defaults ]:
# days_until_expiration_warning: 14
# days_until_expiration_critical: 7
# timeout: 2
# tls_skip_verify: no
#
#
# [ JOB mandatory parameters ]:
# - name
# - source
#
# ------------------------------------------------MODULE-CONFIGURATION--------------------------------------------------
# [ GLOBAL ]
# update_every: 60
# autodetection_retry: 0
#
#
# [ JOBS ]
# jobs:
# - name: example_org
# source: https://example.org:443
12 changes: 7 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
module github.com/netdata/go.d.plugin

go 1.12

require (
github.com/cespare/xxhash v1.1.0 // indirect
github.com/fsnotify/fsnotify v1.4.7 // indirect
github.com/go-sql-driver/mysql v1.4.1
github.com/hpcloud/tail v1.0.0
github.com/miekg/dns v1.1.4
github.com/netdata/go-orchestrator v0.0.0-20190312061432-547df3f9ece6
github.com/miekg/dns v1.1.6
github.com/netdata/go-orchestrator v0.0.0-20190313225439-42e20dc9010d
github.com/prometheus/common v0.2.0 // indirect
github.com/prometheus/prometheus v2.5.0+incompatible
github.com/stretchr/testify v1.3.0
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2 // indirect
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd // indirect
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 // indirect
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a // indirect
golang.org/x/net v0.0.0-20190313220215-9f648a60d977 // indirect
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 // indirect
google.golang.org/appengine v1.4.0 // indirect
gopkg.in/fsnotify.v1 v1.4.7 // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
Expand Down
31 changes: 17 additions & 14 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand All @@ -25,17 +26,17 @@ github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJS
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.7 h1:UvyT9uN+3r7yLEYSlJsbQGdsaB/a0DlgWP3pql6iwOc=
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/miekg/dns v1.1.4 h1:rCMZsU2ScVSYcAsOXgmC6+AKOK+6pmQTOcw03nfwYV0=
github.com/miekg/dns v1.1.4/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/miekg/dns v1.1.6 h1:jVwb4GDwD65q/gtItR/lIZHjNH93QfeGxZUkzJcW9mc=
github.com/miekg/dns v1.1.6/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/netdata/go-orchestrator v0.0.0-20190312061432-547df3f9ece6 h1:fS3/R+LVSdfIK5R+0aI0lsCMszGBsElfq7IZqnuWzWk=
github.com/netdata/go-orchestrator v0.0.0-20190312061432-547df3f9ece6/go.mod h1:GkRx+XaReZcgCkm8nlSM+90ctTww5l0G9Qtxx8ZkvYY=
github.com/netdata/go-orchestrator v0.0.0-20190313225439-42e20dc9010d h1:efRP4qspNR5uLzxcj/xxjBYGPqOnPGL3dq9HXfCFzPE=
github.com/netdata/go-orchestrator v0.0.0-20190313225439-42e20dc9010d/go.mod h1:ErI8v7oo3A0a5PMhPg/sxyV9FmB8Md+QlNn0p5qLvEs=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
Expand All @@ -56,19 +57,21 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2 h1:NwxKRvbkH5MsNkvOtPZi3/3kmI8CAzs3mtv+GLQMkNo=
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a h1:YX8ljsm6wXlHZO+aRz9Exqr0evNhKRNe5K/gi+zKh4U=
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd h1:HuTn7WObtcDo9uEEU7rEqL0jYthdXAmZ6PP+meazmaU=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190313220215-9f648a60d977 h1:actzWV6iWn3GLqN8dZjzsB+CLt+gaV2+wsxroxiQI8I=
golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 h1:bjcUS9ztw9kFmmIxJInhon/0Is3p+EHBKNgquIzo1OI=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc h1:WiYx1rIFmx8c0mXAFtv5D/mHyKe1+jmuP7PViuwqwuQ=
golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
Expand Down
24 changes: 24 additions & 0 deletions modules/x509check/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# x509 certificate expiry check

Checks the time until a x509 certificate expires.

It produces the following charts:

1. **Time Until Certificate Expiration** in seconds
* time

### configuration

For all available options and defaults please see module [configuration file](https://github.com/netdata/go.d.plugin/blob/master/config/go.d/x509.conf).
___

```yaml
update_every : 60

jobs:
- name: example_org
source: https://example.org:443

- name: my_site_org
source: https://my_site_org:443
```
129 changes: 129 additions & 0 deletions modules/x509check/cert_getter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
package x509check

import (
"crypto/tls"
"crypto/x509"
"encoding/pem"
"errors"
"fmt"
"io/ioutil"
"net"
"net/url"
"time"

"github.com/netdata/go.d.plugin/pkg/web"
)

var supportedSchemes = []string{
//"file",
"https",
"tcp",
"tcp4",
"tcp6",
"udp",
"udp4",
"udp6",
}

func newCertGetter(config Config) (certGetter, error) {
if config.Source == "" {
return nil, errors.New("'source' parameter is mandatory, but it's not set")
}

u, err := url.Parse(config.Source)

if err != nil {
return nil, fmt.Errorf("error on parsing source : %v", err)
}

switch u.Scheme {
// TODO: not tested
//case "file":
// return newFileCertGetter(u.Path), nil
case "https":
u.Scheme = "tcp"
fallthrough
case "udp", "udp4", "udp6", "tcp", "tcp4", "tcp6":
tlsCfg, err := web.NewTLSConfig(config.ClientTLSConfig)

if err != nil {
return nil, fmt.Errorf("error on creating tls config : %v", err)
}

if tlsCfg == nil {
tlsCfg = &tls.Config{}
}

tlsCfg.ServerName = u.Hostname()

return newURLCertGetter(u, tlsCfg, config.Timeout.Duration), nil
}

return nil, fmt.Errorf("unsupported scheme in '%s', supported schemes : %v", u, supportedSchemes)
}

type certGetter interface {
getCert() ([]*x509.Certificate, error)
}

func newFileCertGetter(path string) *fileCertGetter {
return &fileCertGetter{path: path}
}

type fileCertGetter struct {
path string
}

func (fg fileCertGetter) getCert() ([]*x509.Certificate, error) {
content, err := ioutil.ReadFile(fg.path)
if err != nil {
return nil, fmt.Errorf("error on reading '%s' : %v", fg.path, err)
}

block, _ := pem.Decode(content)
if block == nil {
return nil, fmt.Errorf("error on decoding '%s' : %v", fg.path, err)
}

cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
return nil, fmt.Errorf("error on parsing certigicate '%s' : %v", fg.path, err)
}

return []*x509.Certificate{cert}, nil
}

func newURLCertGetter(url *url.URL, tlsCfg *tls.Config, timeout time.Duration) *urlCertGetter {
return &urlCertGetter{
url: url,
tlsCfg: tlsCfg,
timeout: timeout,
}
}

type urlCertGetter struct {
url *url.URL
tlsCfg *tls.Config
timeout time.Duration
}

func (ug urlCertGetter) getCert() ([]*x509.Certificate, error) {
ipConn, err := net.DialTimeout(ug.url.Scheme, ug.url.Host, ug.timeout)
if err != nil {
return nil, fmt.Errorf("error on dial to '%s' : %v", ug.url, err)
}

defer ipConn.Close()

conn := tls.Client(ipConn, ug.tlsCfg.Clone())

defer conn.Close()

if err := conn.Handshake(); err != nil {
return nil, fmt.Errorf("error on ssl handshake with '%s' : %v", ug.url, err)
}

certs := conn.ConnectionState().PeerCertificates

return certs, nil
}
Loading