diff --git a/display.go b/display.go index 19f42d2..afb55d5 100644 --- a/display.go +++ b/display.go @@ -22,9 +22,13 @@ import ( "os" "strings" "text/template" + "time" + + "github.com/fatih/color" ) -var Layout = `Expiry Date: {{.NotAfter}} +var Layout = `Enable Date: {{.NotBefore | certStart}} +Expiry Date: {{.NotAfter | certEnd}} Algorithm Type: {{.SignatureAlgorithm}} Subject Info: CommonName: {{.Subject.CommonName}} @@ -44,10 +48,14 @@ Alternate DNS Names: {{.DNSNames}} Serial Number: {{.SerialNumber}} ` +// displayCert takes in an x509 Certificate object and prints out relevant +// information. Start and end dates are colored based on whether or not +// the certificate is expired, not expired, or close to expiring. func displayCert(cert *x509.Certificate) { - funcMap := template.FuncMap{ - "hexify": hexify, + "hexify": hexify, + "certStart": certStart, + "certEnd": certEnd, } t := template.New("Cert template").Funcs(funcMap) t, _ = t.Parse(Layout) @@ -55,6 +63,48 @@ func displayCert(cert *x509.Certificate) { } +// certStart takes a given start time for the validity of +// a certificate and returns that time colored properly +// based on how close it is to expiry. If it's more than +// a day after the certificate became valid the string will +// be green. If it has been less than a day the string will +// be yellow. If the certificate is not yet valid, the string +// will be red. +func certStart(start time.Time) string { + now := time.Now() + day, _ := time.ParseDuration("24h") + threshold := start.Add(day) + if now.After(threshold) { + return color.GreenString(start.String()) + } else if now.After(start) { + return color.YellowString(start.String()) + } else { + return color.RedString(start.String()) + } +} + +// certEnd takes a given end time for the validity of +// a certificate and returns that time colored properly +// based on how close it is to expiry. If the certificate +// is more than a month away from expiring it returns a +// green string. If the certificate is less than a month +// from expiry it returns a yellow string. If the certificate +// is expired it returns a red string. +func certEnd(end time.Time) string { + now := time.Now() + month, _ := time.ParseDuration("720h") + threshold := now.Add(month) + if threshold.Before(end) { + return color.GreenString(end.String()) + } else if now.Before(end) { + return color.YellowString(end.String()) + } else { + return color.RedString(end.String()) + } +} + +// hexify returns a colon separated, hexadecimal representation +// of a given byte array. func hexify(arr []byte) string { hexed := "" for i := 0; i < len(arr); i++ { diff --git a/main.go b/main.go index 28b8b62..6fd87d2 100644 --- a/main.go +++ b/main.go @@ -38,10 +38,8 @@ var ( ) func main() { - switch kingpin.MustParse(app.Parse(os.Args[1:])) { - //Dump Certificate - case dump.FullCommand(): + case dump.FullCommand(): //Dump certificate certs, err := getCerts(*dumpFile, *dumpType) if err != nil { fmt.Fprintf(os.Stderr, "%s\n", err) @@ -53,6 +51,11 @@ func main() { } } +// getCerts takes in a filename and format type and returns an +// array of all the certificates found in that file. If no format +// is specified for the file, getCerts guesses what format was used +// based on the file extension used in the file name. If it can't +// guess based on this it returns and error. func getCerts(file, format string) ([]*x509.Certificate, error) { var certs []*x509.Certificate data, _ := ioutil.ReadFile(file)