too-soon/main.go
Vincent Batts 9b8dbd620c
README: install and usage
Signed-off-by: Vincent Batts <vbatts@hashbangbash.com>
2025-02-17 15:29:10 -05:00

116 lines
2.4 KiB
Go

package main
import (
"context"
"crypto/x509"
"encoding/pem"
"net/mail"
"os"
"time"
log "github.com/sirupsen/logrus"
cli "github.com/urfave/cli/v3"
)
func main() {
cmd := &cli.Command{
Name: "too-soon",
Usage: "check if something expires too soon",
Version: "0.1",
Authors: []any{
&mail.Address{Name: "Vincent Batts", Address: "vbatts@hashbangbash.com"},
},
DefaultCommand: "pem",
Flags: []cli.Flag{
&cli.IntFlag{
Name: "days",
Value: 20,
Usage: "days within range to alert about",
},
&cli.BoolFlag{
Name: "debug",
Aliases: []string{"D"},
Value: false,
Usage: "output debug verbose info",
},
},
Before: func(ctx context.Context, cmd *cli.Command) (context.Context, error) {
if cmd.Bool("debug") {
log.SetLevel(log.DebugLevel)
}
return ctx, nil
},
Commands: []*cli.Command{
&cli.Command{
Name: "pem",
Action: fPEMCheck,
},
},
}
if err := cmd.Run(context.Background(), os.Args); err != nil {
log.Fatal(err)
}
}
func fPEMCheck(ctx context.Context, cmd *cli.Command) error {
retCode := 0
for i := 0; i <= cmd.Args().Len(); i++ {
file := cmd.Args().Get(i)
if file == "" {
break
}
var certs []*x509.Certificate
buf, err := os.ReadFile(file)
if err != nil {
log.Errorf("%q could not be read: %s", file, err)
continue
}
more := true
for more {
block, rest := pem.Decode(buf)
cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
log.Errorf("%q cert could not be parsed: %s", file, err)
continue
}
certs = append(certs, cert)
if len(rest) == 0 {
more = false
}
// reset the buffer if there is more
buf = rest
}
for _, cert := range certs {
if len(cert.DNSNames) == 0 {
continue
}
hours := time.Duration(cmd.Int("days") * -24)
alertTime := cert.NotAfter.Add(hours * time.Hour)
today := time.Now()
if today.After(alertTime) {
if today.After(cert.NotAfter) {
log.Warnf("%q : TIME TO RENEW CERTIFICATE (already expired!)", file)
} else {
log.Warnf("%q : TIME TO RENEW CERTIFICATE (expires in less than %d days)", file, cmd.Int("days"))
}
log.Warnf("%q : %v", file, cert.NotAfter)
log.Warnf("%q : %v", file, cert.DNSNames)
retCode++
} else {
log.Debugf("%q : %v", file, cert.NotAfter)
log.Debugf("%q : %v", file, cert.DNSNames)
}
}
}
if retCode != 0 {
return cli.Exit("certificates need to be renewed", retCode)
}
return nil
}