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))
}
posted @ 2022-09-12 20:20  xiao_pai_pai  阅读(203)  评论(0编辑  收藏  举报