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:
parent
c2940fd972
commit
f33bab0447
3 changed files with 55 additions and 3 deletions
|
@ -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/"]
|
||||||
|
|
7
cert.go
7
cert.go
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
47
main.go
47
main.go
|
@ -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)
|
||||||
|
|
Loading…
Reference in a new issue