diff options
Diffstat (limited to 'certwatch.go')
-rw-r--r-- | certwatch.go | 112 |
1 files changed, 49 insertions, 63 deletions
diff --git a/certwatch.go b/certwatch.go index e75d09e..188de0c 100644 --- a/certwatch.go +++ b/certwatch.go @@ -24,7 +24,6 @@ var statusString = []string{StatusOK: `OK`, StatusUnknown: `UNKNOWN`,} type CertResult struct { - Address string Subject string Status int Ttl time.Duration @@ -32,41 +31,18 @@ type CertResult struct { } type CertResultList struct { + Address string Status int Result []CertResult } -// The cnmap interface -type cnmap map[string]bool - -func (mp *cnmap) Set(value string) error { - if *mp == nil { - *mp = make(map[string]bool) - } - for _, cn := range strings.Split(value, ",") { - (*mp)[cn] = true - } - return nil -} - -func (mp *cnmap) String() string { - var a []string - for k := range *mp { - a = append(a, k) - } - return strings.Join(a, `,`) -} - -func (mp cnmap) Selected(cert *x509.Certificate) bool { - if mp == nil { +func CertMatch(cert *x509.Certificate, cn string) bool { + if cn == `` || cert.Subject.CommonName == cn { return true } - if v, p := mp[cert.Subject.CommonName]; p { - return v - } for _, name := range cert.DNSNames { - if v, p := mp[name]; p { - return v + if cn == name { + return true } } return false @@ -77,7 +53,6 @@ var warnLimit time.Duration var critLimit time.Duration var verboseOption bool var helpOption bool -var selectCN cnmap var host string // Intitialize command line parser @@ -86,14 +61,13 @@ func init() { flag.DurationVar(&critLimit, `c`, 0, `critical threshold`) flag.BoolVar(&verboseOption, `v`, false, `verbose mode`) flag.BoolVar(&helpOption, `h`, false, `show help summary`) - flag.Var(&selectCN, `s`, `comma-separated list of allowed CNs`) flag.StringVar(&host, `H`, ``, `host name`) flag.Usage = func() { if helpOption { flag.CommandLine.SetOutput(os.Stdout) } fmt.Fprintf(flag.CommandLine.Output(), - "Usage: %s [OPTIONS] [HOST...]\n", + "Usage: %s [OPTIONS] [CN...]\n", os.Args[0]) fmt.Fprintln(flag.CommandLine.Output(), `OPTIONS are:`) flag.PrintDefaults() @@ -107,30 +81,29 @@ func main() { flag.Usage() os.Exit(0) } - - res := CertResultList{Status: StatusOK} - - if host != `` { - res.Check(host) + if host == `` { + fmt.Fprintf(os.Stderr, "-H option is mandatory\n") + flag.Usage() + os.Exit(2) } - - for _, arg := range flag.Args() { - res.Check(arg) + + res := CertResultList{Address: host, Status: StatusOK} + if len(flag.Args()) > 0 { + for _, cn := range flag.Args() { + res.Check(cn) + } + } else { + res.Check(``) } res.Format() os.Exit(res.Status) } -var conf = &tls.Config { - InsecureSkipVerify: true, -} - func (res CertResult) FormatHR() { if res.Status == StatusUnknown { - fmt.Printf("%s - %s;", res.Address, res.Error) + fmt.Printf("%s - %s;", res.Subject, res.Error) } else { - fmt.Printf("%s[%s] TTL %s;", - res.Address, res.Subject, res.Ttl.String()) + fmt.Printf("%s TTL %s;", res.Subject, res.Ttl.String()) } } @@ -144,7 +117,7 @@ func (res CertResult) FormatPerfData() { func (rl CertResultList) Format() { //'label'=value[UOM];[warn];[crit];[min];[max] - fmt.Printf("%s - ", statusString[rl.Status]) + fmt.Printf("%s - %s ", statusString[rl.Status], rl.Address) rl.Result[0].FormatHR() fmt.Printf(" | ") rl.Result[0].FormatPerfData() @@ -170,7 +143,8 @@ func (rl *CertResultList) Append(res CertResult) { } } -func (rl *CertResultList) Check(addr string) { +func (rl *CertResultList) Check(cn string) { + addr := rl.Address; a := strings.Split(addr, `:`) switch (len(a)) { case 1: @@ -178,15 +152,21 @@ func (rl *CertResultList) Check(addr string) { case 2: break default: - rl.Append(CertResult{Address: addr, - Status: StatusUnknown, + rl.Append(CertResult{Status: StatusUnknown, Error: `bad address`}) return } + conf := &tls.Config { + InsecureSkipVerify: true, + ServerName: cn, + } + conn, err := tls.Dial("tcp", addr, conf) if err != nil { - rl.Append(CertResult{Address: addr, Status: StatusUnknown, Error: err.Error()}) + rl.Append(CertResult{Subject: cn, + Status: StatusUnknown, + Error: err.Error()}) return } defer conn.Close() @@ -197,19 +177,13 @@ func (rl *CertResultList) Check(addr string) { if cert.IsCA { continue } - if !selectCN.Selected(cert) { - continue + if cn == `` { + cn = cert.Subject.CommonName } - if (verboseOption) { - fmt.Printf("Host: %s\n", addr) - fmt.Printf("CN: %s\n", cert.Subject.CommonName) - fmt.Printf("DNS: %s\n", strings.Join(cert.DNSNames, `,`)) - fmt.Printf("Expires: %s\n", cert.NotAfter.String()) - fmt.Println() + if !CertMatch(cert, cn) { + continue } - res := CertResult{Address: addr, - Subject: cert.Subject.CommonName, - Status: StatusOK} + res := CertResult{Subject: cn, Status: StatusOK} res.Ttl = time.Until(cert.NotAfter) if res.Ttl < critLimit { res.Status = StatusCritical @@ -217,5 +191,17 @@ func (rl *CertResultList) Check(addr string) { res.Status = StatusWarning } rl.Append(res) + if (verboseOption) { + fmt.Printf("Host: %s\n", addr) + fmt.Printf("CN: %s\n", cert.Subject.CommonName) + fmt.Printf("DNS: %s\n", strings.Join(cert.DNSNames, `,`)) + fmt.Printf("Expires: %s\n", cert.NotAfter.String()) + fmt.Printf("Status: %s\n", statusString[res.Status]) + fmt.Println() + } + return } + rl.Append(CertResult{Status: StatusUnknown, + Subject: cn, + Error: `No such CN`}) } |