check_ssl_certificate - Check additional names
This commit is contained in:
parent
ac1eacd2a5
commit
830d51365f
1 changed files with 40 additions and 19 deletions
|
@ -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))
|
||||||
|
|
Loading…
Reference in a new issue