1
0
Fork 0
mirror of https://github.com/Luzifer/promcertcheck.git synced 2024-11-08 16:00:08 +00:00

Allow loading of custom RootCA certificates

which allows to monitor hosts having certificates signed by some
self-hosted CA like Vault or easyrsa-PKI

Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
Knut Ahlers 2017-11-05 17:31:06 +01:00
parent c2940fd972
commit f33bab0447
Signed by: luzifer
GPG key ID: DC2729FDD34BE99E
3 changed files with 55 additions and 3 deletions

View file

@ -12,5 +12,7 @@ RUN set -ex \
EXPOSE 3000 EXPOSE 3000
VOLUME ["/data/certs"]
ENTRYPOINT ["/go/bin/promcertcheck"] ENTRYPOINT ["/go/bin/promcertcheck"]
CMD ["--probe=https://www.google.com/", "--probe=https://www.facebook.com/"] CMD ["--probe=https://www.google.com/", "--probe=https://www.facebook.com/"]

View file

@ -55,8 +55,10 @@ func checkCertificate(probeURL *url.URL) (probeResult, *x509.Certificate) {
} }
resp.Body.Close() resp.Body.Close()
intermediatePool := x509.NewCertPool() var (
var verifyCert *x509.Certificate intermediatePool = x509.NewCertPool()
verifyCert *x509.Certificate
)
hostPort := strings.Split(probeURL.Host, ":") hostPort := strings.Split(probeURL.Host, ":")
host := hostPort[0] host := hostPort[0]
@ -79,6 +81,7 @@ func checkCertificate(probeURL *url.URL) (probeResult, *x509.Certificate) {
verificationResult := false verificationResult := false
if _, err := verifyCert.Verify(x509.VerifyOptions{ if _, err := verifyCert.Verify(x509.VerifyOptions{
Intermediates: intermediatePool, Intermediates: intermediatePool,
Roots: rootPool,
}); err == nil { }); err == nil {
verificationResult = true verificationResult = true
} }

49
main.go
View file

@ -5,8 +5,11 @@ import (
"crypto/x509" "crypto/x509"
"errors" "errors"
"fmt" "fmt"
"io/ioutil"
"net/http" "net/http"
"net/url" "net/url"
"os"
"path/filepath"
"strings" "strings"
"time" "time"
@ -21,11 +24,15 @@ var (
config = struct { config = struct {
Debug bool `flag:"debug" default:"false" description:"Output debugging data"` Debug bool `flag:"debug" default:"false" description:"Output debugging data"`
ExpireWarning time.Duration `flag:"expire-warning" default:"744h" description:"When to warn about a soon expiring certificate"` ExpireWarning time.Duration `flag:"expire-warning" default:"744h" description:"When to warn about a soon expiring certificate"`
RootsDir string `flag:"roots-dir" default:"" description:"Directory to load custom RootCA certs from to be trusted (*.pem)"`
LogLevel string `flag:"log-level" default:"info" description:"Verbosity of logs to use (debug, info, warning, error, ...)"` LogLevel string `flag:"log-level" default:"info" description:"Verbosity of logs to use (debug, info, warning, error, ...)"`
Probes []string `flag:"probe" default:"" description:"URLs to check for certificate issues"` Probes []string `flag:"probe" default:"" description:"URLs to check for certificate issues"`
}{} }{}
version = "dev"
version = "dev"
probeMonitors = map[string]*probeMonitor{} probeMonitors = map[string]*probeMonitor{}
rootPool *x509.CertPool
redirectFoundError = errors.New("Found a redirect") redirectFoundError = errors.New("Found a redirect")
) )
@ -57,6 +64,15 @@ func main() {
TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
} }
var err error
if rootPool, err = x509.SystemCertPool(); err != nil {
log.WithError(err).Fatal("Unable to load system RootCA pool")
}
if err = loadAdditionalRootCAPool(); err != nil {
log.WithError(err).Fatal("Could not load intermediate certificates")
}
registerProbes() registerProbes()
refreshCertificateStatus() refreshCertificateStatus()
@ -74,6 +90,37 @@ func main() {
http.ListenAndServe(":3000", r) http.ListenAndServe(":3000", r)
} }
func loadAdditionalRootCAPool() error {
if config.RootsDir == "" {
// Nothing specified, not loading anything but sys certs
return nil
}
return filepath.Walk(config.RootsDir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !strings.HasSuffix(path, ".pem") || info.IsDir() {
// Likely not a certificate, ignore
return nil
}
pem, err := ioutil.ReadFile(path)
if err != nil {
return err
}
if ok := rootPool.AppendCertsFromPEM(pem); !ok {
return fmt.Errorf("Failed to load certificate %q", path)
}
log.WithFields(log.Fields{"path": path}).Debug("Loaded RootCA certificate")
return nil
})
}
func registerProbes() { func registerProbes() {
for _, probe := range config.Probes { for _, probe := range config.Probes {
probeURL, _ := url.Parse(probe) probeURL, _ := url.Parse(probe)