Column | Obtain https certificate expiration time using the zabbix-agent2 custom plug-in

Posted by korngold on Wed, 12 Jan 2022 18:12:52 +0100

WeChat Public Number: Operations and Maintenance Development Story, Author: wanger


For those who regularly maintain their website, they often have to deal with https certificates. Typically, an https certificate is valid for one year. Once the certificate expires, the company will lose a lot. Last year NetEase mailbox was a typical case in which a large number of users could not use their mailboxes properly because the https certificate forgot to renew. It is unrealistic to check manually when you think about it. The best way is to monitor the expiration time and send notifications automatically at a certain distance.

You can use the ssl_of Zabbix or Prometheus Exporter to monitor, at Zabbix4. Prior to version 4, custom scripting was available in Zabbix4.4 Zabbix-agent2 appeared after that, in addition to the official plug-ins, they can also be customized to meet our monitoring needs. This article describes how to use the zabbix-agent2 custom plug-in to meet the need to obtain an https certificate expiration time.

zabbix-agent2 custom https_expire plug-in

Previously described how Use custom plug-ins to monitor mqtt However, the Watcher interface was used to actively push new data to the server. This time, the data will be collected by implementing the Exporter interface, providing official documents and translation by Zabbix Certified Expert Mihong again Official Blog.

Here I'll recap some of the standard specifications for custom plug-ins

1. Plugins must import package.

import ""

2. The plugin must define a structure and embed the plugin.Base structure.

type Plugin struct {    plugin.Base}var impl Plugin

3. A plug-in must implement one or more plug-in interfaces.

func (p *Plugin) Export(key string, params []string, ctx plugin.ContextProvider) (result interface{}, err error) {    if len(params) > 0 {        p.Debugf("received %d parameters while expected none", len(params))        return nil, errors.New("Too many parameters")    }    return time.Now().Format(time.RFC3339)}

4. The plug-in must register itself during initialization.

func init() {    plugin.RegisterMetrics(&impl, "Time", "system.time", "Returns time string in RFC 3999 format.")}

Ssl_ Not many expire codes. Plugin written by Nicola Drakesky Wang Er. Complete code can be viewed in github

func (p *Plugin) Configure(global *plugin.GlobalOptions, options interface{}) { if err = conf.Unmarshal(options, &p.options); err != nil {  p.Errf("cannot unmarshal configuration options: %s", err) } if p.options.Timeout == 0 {  p.options.Timeout = global.Timeout } p.client = newClient(p.options.Timeout)}func (p *Plugin) Validate(options interface{}) error { return conf.Unmarshal(options, &opts)}func checkParamnums(params []string) error { if len(params) > paramnums {  err:=errors.New("Too many parameters.")  return zbxerr.ErrorTooFewParameters.Wrap(err) } else if len(params) ==0 {  err:=errors.New("Missing URL parameters.")  return zbxerr.ErrorTooFewParameters.Wrap(err) } return nil}func checkParams(params []string) (string, error) { if strings.HasPrefix(params[0], "http://") {  errorsting:=fmt.Sprintf("Target is using http scheme: %s", params[0])  err:=errors.New(errorsting)  return "",zbxerr.ErrorInvalidParams.Wrap(err) } if !strings.HasPrefix(params[0], "https://") {  params[0] = "https://" + params[0] } return string(params[0]),nil}func (cli *client) Query(url string) (int64, error) { resp, err := cli.client.Get(url) if err != nil {  impl.Debugf("cannot fetch data: %s", err)  err:=errors.New("cannot fetch data")  return 0, zbxerr.ErrorCannotFetchData.Wrap(err) } defer resp.Body.Close() certInfo:=resp.TLS.PeerCertificates[0] expiredays:=(certInfo.NotAfter.Unix()-time.Now().Unix())/60/60/24 return expiredays,nil}// Export implements the Exporter interface.func (p *Plugin) Export(key string, params []string, ctx plugin.ContextProvider) (interface{}, error) { if err = checkParamnums(params); err != nil {  return nil, err } urls,err:= checkParams(params) if err!= nil {  return nil,err } body, err := p.client.Query(urls) if err!=nil{  return nil, err } return body,nil}func init() { plugin.RegisterMetrics(&impl, pluginName,  "https_expire", "Returns the number of days between the HTTPS certificate expiration time and the current date.")}

Download the zabbix agent2 source and compile the custom plug-in

yum install golanggit clone --depth 1 zabbix-agent2cd zabbix-agent2git submodule add src/go/plugins/https_expire

Import https_expire plug-in

vi src/go/plugins/plugins_linux.go

Add last line

        _ ""        _ ""        _ ""        _ ""        _ ""        _ ""        _ ""        _ ""        _ ""        _ ""        ...        _ ""

Compile and install zabbix agent2

yum install automake autoconf pcre* -y./ pushd . cd src/go/ go mod vendor popd ./configure --enable-agent2 --enable-static make install

Edit Profile

Here I have adjusted the log level to allow foreground debugging of the optional parameter Plugins.Https_expire.Timeout = 5

egrep -v "^$|^#" conf/zabbix_agent2.conf  LogType=consoleLogFile=/tmp/zabbix_agent2.logDebugLevel=4Server=

Start Zabbix_agent2

cd /root/zabbix_agent/src/go/binzabbix_agent2 -c conf/zabbix_agent2.conf

Zabbix Create Monitoring Items

Examples of key values are as follows




Look at the latest data. This certificate has forty days to expire

I'm using the Ali Cloud ssl certificate and I can see that there are actually forty days before the expiration date. Today is 2021.3.7

You can create a trigger to send an alarm notification one month later.

Topics: Zabbix Network Protocol http https