git » kxd » commit d638384

kxd: Log individual errors on certificate validation failures

author Alberto Bertogli
2025-01-12 13:48:45 UTC
committer Alberto Bertogli
2025-01-12 13:48:45 UTC
parent cc1b86518ce7a6cbf12ed50b813a2c6a628135a8

kxd: Log individual errors on certificate validation failures

When there is an attempt that fails to find an allowed certificate, log
the errors for each certificate attempted, to make failures easier to
debug.

kxd/key_config.go +10 -3
kxd/kxd.go +6 -2

diff --git a/kxd/key_config.go b/kxd/key_config.go
index e3c339e..3b96dbb 100644
--- a/kxd/key_config.go
+++ b/kxd/key_config.go
@@ -129,20 +129,27 @@ func (kc *KeyConfig) LoadAllowedHosts() error {
 	return nil
 }
 
+type verifyError struct {
+	Cert *x509.Certificate
+	Err  error
+}
+
 // IsAnyCertAllowed checks if any of the given certificates is allowed to
 // access this key. If so, it returns the chain for each of them.
 func (kc *KeyConfig) IsAnyCertAllowed(
-	certs []*x509.Certificate) [][]*x509.Certificate {
+	certs []*x509.Certificate) ([][]*x509.Certificate, []verifyError) {
 	opts := x509.VerifyOptions{
 		Roots: kc.allowedClientCerts,
 	}
+	errs := []verifyError{}
 	for _, cert := range certs {
 		chains, err := cert.Verify(opts)
 		if err == nil && len(chains) > 0 {
-			return chains
+			return chains, nil
 		}
+		errs = append(errs, verifyError{cert, err})
 	}
-	return nil
+	return nil, errs
 }
 
 // IsHostAllowed checks if the given host is allowed to access this key.
diff --git a/kxd/kxd.go b/kxd/kxd.go
index 6234538..07f141e 100644
--- a/kxd/kxd.go
+++ b/kxd/kxd.go
@@ -164,9 +164,13 @@ func HandlerV1(w http.ResponseWriter, httpreq *http.Request) {
 		return
 	}
 
-	validChains := keyConf.IsAnyCertAllowed(req.TLS.PeerCertificates)
+	validChains, errs := keyConf.IsAnyCertAllowed(req.TLS.PeerCertificates)
 	if validChains == nil {
-		req.Printf("No allowed certificate found")
+		req.Printf("No allowed certificate found (checked %d certs)",
+			len(errs))
+		for i, e := range errs {
+			req.Printf("  %d: %s %v", i, certToString(e.Cert), e.Err)
+		}
 		http.Error(w, "No allowed certificate found",
 			http.StatusForbidden)
 		return