summaryrefslogtreecommitdiffabout
authorSergey Poznyakoff <gray@gnu.org.ua>2019-10-08 18:05:19 (GMT)
committer Sergey Poznyakoff <gray@gnu.org.ua>2019-10-08 18:05:19 (GMT)
commit10e75a2790e7b36095c2f0a4a2ae529b0af59d82 (patch) (side-by-side diff)
tree8ca90a4f6fa3e1de0a94fe2c1c3c3331dd524649
parent4852ae36c0491eccdadd857aab44934f1017c6f5 (diff)
downloadcertmon-10e75a2790e7b36095c2f0a4a2ae529b0af59d82.tar.gz
certmon-10e75a2790e7b36095c2f0a4a2ae529b0af59d82.tar.bz2
Check one host per invocation
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--certwatch.go112
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`})
}

Return to:

Send suggestions and report system problems to the System administrator.