check_ssl_certificate - Check additional names

This commit is contained in:
Emmanuel BENOîT 2021-02-19 13:21:06 +01:00
parent ac1eacd2a5
commit 830d51365f

View file

@ -20,6 +20,7 @@ type programFlags struct {
warn int warn int
crit int crit int
ignoreCnOnly bool ignoreCnOnly bool
extraNames []string
} }
type checkProgram struct { type checkProgram struct {
@ -29,7 +30,10 @@ type checkProgram struct {
} }
func (flags *programFlags) parseArguments() { func (flags *programFlags) parseArguments() {
var help bool var (
names string
help bool
)
golf.BoolVarP(&help, 'h', "help", false, "Display usage information") golf.BoolVarP(&help, 'h', "help", false, "Display usage information")
golf.StringVarP(&flags.hostname, 'H', "hostname", "", "Host name to connect to.") golf.StringVarP(&flags.hostname, 'H', "hostname", "", "Host name to connect to.")
golf.IntVarP(&flags.port, 'P', "port", -1, "Port to connect to.") golf.IntVarP(&flags.port, 'P', "port", -1, "Port to connect to.")
@ -39,11 +43,18 @@ func (flags *programFlags) parseArguments() {
"Validity threshold below which a critical state is issued, in days.") "Validity threshold below which a critical state is issued, in days.")
golf.BoolVar(&flags.ignoreCnOnly, "ignore-cn-only", false, golf.BoolVar(&flags.ignoreCnOnly, "ignore-cn-only", false,
"Do not issue warnings regarding certificates that do not use SANs at all.") "Do not issue warnings regarding certificates that do not use SANs at all.")
golf.StringVarP(&names, 'a', "additional-names", "",
"A comma-separated list of names that the certificate should also provide.")
golf.Parse() golf.Parse()
if help { if help {
golf.Usage() golf.Usage()
os.Exit(0) os.Exit(0)
} }
if names == "" {
flags.extraNames = make([]string, 0)
} else {
flags.extraNames = strings.Split(names, ",")
}
} }
func newProgram() *checkProgram { func newProgram() *checkProgram {
@ -93,34 +104,44 @@ func (program *checkProgram) getCertificate() error {
return nil return nil
} }
func findHostname(cert *x509.Certificate, hostname string) bool { func (program *checkProgram) checkHostName(name string) bool {
for _, name := range cert.DNSNames { for _, n := range program.certificate.DNSNames {
if strings.ToLower(name) == hostname { if strings.ToLower(n) == name {
return true return true
} }
} }
program.plugin.AddLine(fmt.Sprintf("missing DNS name %s in certificate", name))
return false return false
} }
func (program *checkProgram) checkCertificateName() bool { func (program *checkProgram) checkSANlessCertificate() bool {
if len(program.certificate.DNSNames) == 0 { if !program.ignoreCnOnly || len(program.extraNames) != 0 {
if !program.ignoreCnOnly { program.plugin.SetState(plugin.WARNING,
program.plugin.SetState(plugin.WARNING, "certificate doesn't have SAN domain names")
"certificate doesn't have SAN domain names") return false
return false }
} dn := strings.ToLower(program.certificate.Subject.String())
dn := strings.ToLower(program.certificate.Subject.String()) if !strings.HasPrefix(dn, fmt.Sprintf("cn=%s,", program.hostname)) {
if !strings.HasPrefix(dn, fmt.Sprintf("cn=%s,", program.hostname)) { program.plugin.SetState(plugin.CRITICAL, "incorrect certificate CN")
program.plugin.SetState(plugin.CRITICAL, "incorrect certificate CN")
return false
}
} else if !findHostname(program.certificate, program.hostname) {
program.plugin.SetState(plugin.CRITICAL, "host name not found in SAN domain names")
return false return false
} }
return true return true
} }
func (program *checkProgram) checkNames() bool {
if len(program.certificate.DNSNames) == 0 {
return program.checkSANlessCertificate()
}
ok := program.checkHostName(program.hostname)
for _, name := range program.extraNames {
ok = program.checkHostName(name) && ok
}
if !ok {
program.plugin.SetState(plugin.CRITICAL, "names missing from SAN domain names")
}
return ok
}
func (program *checkProgram) checkCertificateExpiry(tlDays int) (plugin.Status, string) { func (program *checkProgram) checkCertificateExpiry(tlDays int) (plugin.Status, string) {
var limitStr string var limitStr string
var state plugin.Status var state plugin.Status
@ -154,7 +175,7 @@ func (program *checkProgram) runCheck() {
err := program.getCertificate() err := program.getCertificate()
if err != nil { if err != nil {
program.plugin.SetState(plugin.UNKNOWN, err.Error()) program.plugin.SetState(plugin.UNKNOWN, err.Error())
} else if program.checkCertificateName() { } else if program.checkNames() {
timeLeft := program.certificate.NotAfter.Sub(time.Now()) timeLeft := program.certificate.NotAfter.Sub(time.Now())
tlDays := int((timeLeft + 86399*time.Second) / (24 * time.Hour)) tlDays := int((timeLeft + 86399*time.Second) / (24 * time.Hour))
program.plugin.SetState(program.checkCertificateExpiry(tlDays)) program.plugin.SetState(program.checkCertificateExpiry(tlDays))