專欄|使用zabbix-agent2自定義插件獲取https證書過期時間

Wanger | Zabbix開源社區簽約專家

Zabbix運維工程師,熟悉Zabbix開源監控系統的架構。樂於分享Zabbix運維經驗,個人公衆號“運維開發故事”。

擅長領域:Zabbix基礎設施運維以及Zabbix圖形化展示。

需求

對經常維護網站的人來說,要經常跟https的證書打交道。一般https證書的有效期是一年,證書一旦過期,公司的損失會非常大。去年網易郵箱因爲https證書忘記續期,導致大量用戶無法正常使用郵箱就是個典型案例。什麼時候想起來纔去手動查一下也不現實,最好的方法是把過期時間監控起來,距離一定期限自動發送通知。
可以使用Zabbix或者Prometheus的ssl_exporter來進行監控,在Zabbix4.4版本以前可以使用自定義腳本的方式,在Zabbix4.4之後出現了zabbix-agent2,除了官方自帶的插件也可以通過自定義插件的方式來滿足我們的監控需求。本文介紹如何使用zabbix-agent2自定義插件來實現獲取https證書過期時間的需求。

zabbix-agent2自定義https_expire插件

之前介紹過如何使用自定義插件來實現對mqtt的監控,只不過當時使用的Watcher接口來將新數據主動push給server端,這次將通過實現Exporter接口來採集數據,再次提供 官方文檔 和Zabbix認證專家米宏翻譯的 官方博文
這裏我再介紹一下自定義插件的一些標準規範 
1. 插件必須導入 zabbix.com/pkg/plugin 軟件包。

   
   
   
import "zabbix.com/pkg/plugin"
2. 插件必須定義結構並嵌入該 plugin.Base 結構。

   
   
   
type Plugin struct {
    plugin.Base
}
var impl Plugin
 3. 一個插件必須實現一個或多個插件接口。

   
   
   
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. 插件必須在初始化期間註冊自己。

   
   
   
func init() {
    plugin.RegisterMetrics(&impl, "Time""system.time""Returns time string in RFC 3999 format.")
}
ssl_expire代碼不多,插件由尼古拉·拖拉基斯基·王二編寫,完整代碼可以去 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.")
}

下載zabbix agent2源碼並將自定義插件編譯


   
   
   
yum install golang
git clone https://git.zabbix.com/scm/zbx/zabbix.git --depth 1 zabbix-agent2
cd zabbix-agent2
git submodule add https://github.com/cxf210/ssl_expire.git src/go/plugins/https_expire

導入https_expire插件


   
   
   
vi src/go/plugins/plugins_linux.go
添加最後一行

   
   
   
        _ "zabbix.com/plugins/ceph"
        _ "zabbix.com/plugins/docker"
        _ "zabbix.com/plugins/kernel"
        _ "zabbix.com/plugins/log"
        _ "zabbix.com/plugins/memcached"
        _ "zabbix.com/plugins/modbus"
        _ "zabbix.com/plugins/mqtt"
        _ "zabbix.com/plugins/mysql"
        _ "zabbix.com/plugins/net/netif"
        _ "zabbix.com/plugins/net/tcp"
        ...
        _ "zabbix.com/plugins/https_expire"

編譯安裝zabbix agent2


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

編輯配置文件

這裏我調整了日誌級別,方便前臺調試 可選參數 Plugins.Https_expire.Timeout = 5

   
   
   
egrep -v "^$|^#" conf/zabbix_agent2.conf  
LogType=console
LogFile=/tmp/zabbix_agent2.log
DebugLevel=4
Server=172.17.0.5
Plugins.Https_expire.Timeout=5
Hostname=node2
ControlSocket=/tmp/agent.sock

啓動Zabbix_agent2


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

Zabbix創建監控項

鍵值示例如下

   
   
   
https_expire["www.xyzabbix.cn"]

   
   
   
https_expire["https://www.xyzabbix.cn"]


查看最新數據,這個證書還有四十天過期

我是用的阿里雲ssl證書,可以看到確實離過期時間還有四十天,今天是2021.3.7


可以創建一個觸發器,在還有一個月的時候發送報警通知。

延伸閱讀

1.專家專欄|使用agent2自定義插件採集通過MQTT協議發送的數據

2.官方博文|爲Zabbix Agent 2 開發插件


2021.4.12-16 ZCS中級培訓 上海

2021.4.19-21 ZCP高級培訓 上海


歡迎聯繫小Z獲取內容大綱。


關注Zabbix開源社區

乾貨滿滿

加“小Z“入羣

3000+Zabbixer已加入


本文分享自微信公衆號 - Zabbix開源社區(china_zabbix)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章