k8s证书监控
用于监控k8s节点上crt或者pem证书的有效期时间
使用方法 go run main.go --crtDir crtDir用于指定证书的目录
package main
import (
"crypto/x509"
"encoding/pem"
"flag"
"fmt"
"io/ioutil"
"net/http"
"os"
"strconv"
"strings"
"time"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
func main() {
start := prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Name: "start_time",
Help: "current certifcation starttime.",
},
// 指定标签名称
[]string{"hostname", "certtype"},
)
end := prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Name: "end_time",
Help: "current certifcation endtime.",
},
// 指定标签名称
[]string{"hostname", "certtype"},
)
left := prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Name: "left_time",
Help: "current certifcation lefttime.",
},
// 指定标签名称
[]string{"hostname", "certtype"},
)
//获取需要监控的证书
filename := get_certfile()
//设置metrics指标
set(start, end, left, filename)
prometheus.MustRegister(start, end, left)
// 暴露自定义的指标
http.Handle("/metrics", promhttp.Handler())
http.ListenAndServe(":8081", nil)
}
//获取有效期
func get_date(file string) (int, int, int) {
certFile, err := ioutil.ReadFile(file)
if err != nil {
fmt.Println(err.Error())
}
pemBlock, _ := pem.Decode([]byte(certFile))
if pemBlock == nil {
fmt.Println("decode error")
}
cert, err := x509.ParseCertificate(pemBlock.Bytes)
if err != nil {
fmt.Println(err.Error())
}
arr_start_date := strings.Fields(cert.NotBefore.String())
ses := "-"
arr_end_date := strings.Fields(cert.NotAfter.String())
left := subDemo(arr_end_date[0])
return join(strings.Split(arr_start_date[0], ses)), join(strings.Split(arr_end_date[0], ses)), left
}
//获取有效期时间格式为yyyymmdd数字格式
func join(a []string) int {
var result string
for _, i := range a {
result += i
}
result1, _ := strconv.Atoi(result)
return result1
}
//设置指标
func set(start *prometheus.GaugeVec, end *prometheus.GaugeVec, left *prometheus.GaugeVec, certFile []string) {
hostname, _ := os.Hostname()
for _, cert_name := range certFile {
fmt.Println(cert_name)
start_date, end_date, left_date := get_date(cert_name)
start.WithLabelValues(hostname, cert_name).Set(float64(start_date))
end.WithLabelValues(hostname, cert_name).Set(float64(end_date))
left.WithLabelValues(hostname, cert_name).Set(float64(left_date))
}
}
func get_certfile() []string {
var certFileName = flag.String("crtDir", "test.pem", "证书文件路径")
flag.Parse()
//if strings.Contains(*certFileName, "crt") || strings.Contains(*certFileName, "pem") {
// fmt.Println(*certFileName)
//} else {
// fmt.Printf("未正确设置参数退出")
// os.Exit(1)
//}
file_name := make([]string, 0)
for _, path := range strings.Fields(*certFileName) {
readerInfos, err := ioutil.ReadDir(path)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
for _, info := range readerInfos {
if info.IsDir() {
continue
} else if strings.Contains(info.Name(), "pem") || strings.Contains(info.Name(), "crt") {
file_name = append(file_name, path+`/`+info.Name())
}
}
}
return file_name
}
func subDemo(ts string) int {
now := time.Now()
// 按照指定格式解析一个字符串格式的时间
_, err := time.Parse("2006-01-02", ts)
if err != nil {
fmt.Printf("parse string err:%v\n", err)
return 0
}
tlocal, err := time.LoadLocation("Asia/Shanghai")
if err != nil {
fmt.Printf("Parse a string according to the time zone format of Dongba district err:%v\n", err)
return 0
}
// 按照指定的时区解析时间
t, err := time.ParseInLocation("2006-01-02", ts, tlocal)
if err != nil {
fmt.Printf("Resolve the time according to the specified time zone:%v\n", err)
return 0
}
// 计算时间的差值
reverseTime := t.Sub(now)
return (int(reverseTime.Hours() / 24))
}