feat: MVP phase 1 complete
This commit is contained in:
78
internal/ssl/checker.go
Normal file
78
internal/ssl/checker.go
Normal file
@@ -0,0 +1,78 @@
|
||||
package ssl
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Result holds the outcome of a single cert check.
|
||||
type Result struct {
|
||||
Domain string
|
||||
ExpiresAt time.Time
|
||||
DaysRemaining int
|
||||
IsValid bool
|
||||
Error string
|
||||
}
|
||||
|
||||
// Severity returns a CSS class name for the expiry status.
|
||||
//
|
||||
// "ok" — > 30 days
|
||||
// "warn" — 14–30 days
|
||||
// "crit" — < 14 days or invalid
|
||||
func (r Result) Severity() string {
|
||||
if !r.IsValid {
|
||||
return "crit"
|
||||
}
|
||||
switch {
|
||||
case r.DaysRemaining > 30:
|
||||
return "ok"
|
||||
case r.DaysRemaining >= 14:
|
||||
return "warn"
|
||||
default:
|
||||
return "crit"
|
||||
}
|
||||
}
|
||||
|
||||
// Check dials domain:443, retrieves the TLS certificate chain, and returns
|
||||
// the expiry of the leaf certificate.
|
||||
func Check(domain string) Result {
|
||||
r := Result{Domain: domain}
|
||||
|
||||
conn, err := tls.DialWithDialer(
|
||||
&net.Dialer{Timeout: 10 * time.Second},
|
||||
"tcp",
|
||||
net.JoinHostPort(domain, "443"),
|
||||
&tls.Config{ServerName: domain},
|
||||
)
|
||||
if err != nil {
|
||||
r.Error = fmt.Sprintf("tls dial: %s", err)
|
||||
return r
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
certs := conn.ConnectionState().PeerCertificates
|
||||
if len(certs) == 0 {
|
||||
r.Error = "no certificates in chain"
|
||||
return r
|
||||
}
|
||||
|
||||
leaf := certs[0]
|
||||
now := time.Now()
|
||||
|
||||
r.ExpiresAt = leaf.NotAfter
|
||||
r.DaysRemaining = int(leaf.NotAfter.Sub(now).Hours() / 24)
|
||||
|
||||
if now.Before(leaf.NotBefore) {
|
||||
r.Error = fmt.Sprintf("certificate not yet valid (valid from %s)", leaf.NotBefore.Format("2006-01-02"))
|
||||
return r
|
||||
}
|
||||
if now.After(leaf.NotAfter) {
|
||||
r.Error = fmt.Sprintf("certificate expired %s", leaf.NotAfter.Format("2006-01-02"))
|
||||
return r
|
||||
}
|
||||
|
||||
r.IsValid = true
|
||||
return r
|
||||
}
|
||||
Reference in New Issue
Block a user