Skip to content

Commit cf71d8f

Browse files
committed
Add logging to certpoolwatcher and client
Logging now indicates what certificate (by file and X.509 name) is being watched When an unverified certificate error is returned to the client, log the cert Signed-off-by: Todd Short <[email protected]>
1 parent 9b08aea commit cf71d8f

File tree

4 files changed

+114
-2
lines changed

4 files changed

+114
-2
lines changed

internal/catalogmetadata/client/client.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,19 @@ package client
22

33
import (
44
"context"
5+
"crypto/tls"
6+
"crypto/x509"
57
"errors"
68
"fmt"
79
"io"
810
"io/fs"
911
"net/http"
1012
"net/url"
1113

14+
"github.com/go-logr/logr"
1215
"k8s.io/apimachinery/pkg/api/meta"
1316
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
17+
ctrl "sigs.k8s.io/controller-runtime"
1418

1519
"github.com/operator-framework/operator-registry/alpha/declcfg"
1620

@@ -111,6 +115,24 @@ func (c *Client) PopulateCache(ctx context.Context, catalog *catalogd.ClusterCat
111115
return c.cache.Put(catalog.Name, catalog.Status.ResolvedSource.Image.Ref, resp.Body, nil)
112116
}
113117

118+
func logX509Error(err error, l logr.Logger) {
119+
var cvErr *tls.CertificateVerificationError
120+
if errors.As(err, &cvErr) {
121+
n := 1
122+
for _, cert := range cvErr.UnverifiedCertificates {
123+
l.Error(err, "Unverified Cert", "n", n, "subject", cert.Subject, "issuer", cert.Issuer, "DNSNames", cert.DNSNames, "serial", cert.SerialNumber)
124+
n = n + 1
125+
}
126+
return
127+
}
128+
129+
var uaErr *x509.UnknownAuthorityError
130+
if errors.As(err, &uaErr) {
131+
l.Error(err, "Unknown Authority", "cert", "subject", uaErr.Cert.Subject, "issuer", uaErr.Cert.Issuer, "DNSNames", uaErr.Cert.DNSNames, "serial", uaErr.Cert.SerialNumber)
132+
return
133+
}
134+
}
135+
114136
func (c *Client) doRequest(ctx context.Context, catalog *catalogd.ClusterCatalog) (*http.Response, error) {
115137
if catalog.Status.URLs == nil {
116138
return nil, fmt.Errorf("error: catalog %q has a nil status.urls value", catalog.Name)
@@ -133,6 +155,7 @@ func (c *Client) doRequest(ctx context.Context, catalog *catalogd.ClusterCatalog
133155

134156
resp, err := client.Do(req)
135157
if err != nil {
158+
logX509Error(err, ctrl.Log.WithName("catalog-client"))
136159
return nil, fmt.Errorf("error performing request: %v", err)
137160
}
138161

internal/httputil/certlog.go

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package httputil
2+
3+
import (
4+
"crypto/x509"
5+
"encoding/pem"
6+
"fmt"
7+
"os"
8+
"path/filepath"
9+
10+
"github.com/go-logr/logr"
11+
)
12+
13+
func logPath(path, action string, log logr.Logger) {
14+
fi, err := os.Stat(path)
15+
if err != nil {
16+
log.Error(err, "error in os.Stat()", "path", path)
17+
return
18+
}
19+
if !fi.IsDir() {
20+
logFile(path, "", fmt.Sprintf("%s file", action), log)
21+
return
22+
}
23+
action = fmt.Sprintf("%s directory", action)
24+
dirEntries, err := os.ReadDir(path)
25+
if err != nil {
26+
log.Error(err, "error in os.ReadDir()", "path", path)
27+
return
28+
}
29+
for _, e := range dirEntries {
30+
file := filepath.Join(path, e.Name())
31+
fi, err := os.Stat(file)
32+
if err != nil {
33+
log.Error(err, "error in os.Stat()", "file", file)
34+
continue
35+
}
36+
if fi.IsDir() {
37+
log.Info("ignoring subdirectory", "directory", file)
38+
continue
39+
}
40+
logFile(e.Name(), path, action, log)
41+
}
42+
}
43+
44+
func logFile(filename, path, action string, log logr.Logger) {
45+
filepath := filepath.Join(path, filename)
46+
data, err := os.ReadFile(filepath)
47+
if err != nil {
48+
log.Error(err, "error in os.ReadFile()", "file", filename)
49+
return
50+
}
51+
logPem(data, filename, path, action, log)
52+
}
53+
54+
func logPem(data []byte, filename, path, action string, log logr.Logger) {
55+
for len(data) > 0 {
56+
var block *pem.Block
57+
block, data = pem.Decode(data)
58+
if block == nil {
59+
log.Error(nil, "no block returned from pem.Decode()", "file", filename)
60+
return
61+
}
62+
crt, err := x509.ParseCertificate(block.Bytes)
63+
if err != nil {
64+
log.Error(err, "error in x509.ParseCertificate()", "file", filename)
65+
return
66+
}
67+
68+
args := []any{}
69+
if path != "" {
70+
args = append(args, "directory", path)
71+
}
72+
// Find an appopriate certificate identifier
73+
args = append(args, "file", filename)
74+
if s := crt.Subject.String(); s != "" {
75+
args = append(args, "subject", s)
76+
} else if crt.DNSNames != nil {
77+
args = append(args, "DNSNames", crt.DNSNames)
78+
} else if s := crt.SerialNumber.String(); s != "" {
79+
args = append(args, "serial", s)
80+
}
81+
log.Info(action, args...)
82+
}
83+
}

internal/httputil/certpoolwatcher.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,12 @@ func NewCertPoolWatcher(caDir string, log logr.Logger) (*CertPoolWatcher, error)
5050
// If the SSL_CERT_DIR or SSL_CERT_FILE environment variables are
5151
// specified, this means that we have some control over the system root
5252
// location, thus they may change, thus we should watch those locations.
53-
watchPaths := strings.Split(os.Getenv("SSL_CERT_DIR"), ":")
54-
watchPaths = append(watchPaths, caDir, os.Getenv("SSL_CERT_FILE"))
53+
sslCertDir := os.Getenv("SSL_CERT_DIR")
54+
sslCertFile := os.Getenv("SSL_CERT_FILE")
55+
log.Info("SSL environment", "SSL_CERT_DIR", sslCertDir, "SSL_CERT_FILE", sslCertFile)
56+
57+
watchPaths := strings.Split(sslCertDir, ":")
58+
watchPaths = append(watchPaths, caDir, sslCertFile)
5559
watchPaths = slices.DeleteFunc(watchPaths, func(p string) bool {
5660
if p == "" {
5761
return true
@@ -66,6 +70,7 @@ func NewCertPoolWatcher(caDir string, log logr.Logger) (*CertPoolWatcher, error)
6670
if err := watcher.Add(p); err != nil {
6771
return nil, err
6872
}
73+
logPath(p, "watching certificate", log)
6974
}
7075

7176
cpw := &CertPoolWatcher{

internal/httputil/certutil.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ func NewCertPool(caDir string, log logr.Logger) (*x509.CertPool, error) {
4646
if caCertPool.AppendCertsFromPEM(data) {
4747
count++
4848
}
49+
logPem(data, e.Name(), caDir, "loading certificate file", log)
4950
}
5051

5152
// Found no certs!

0 commit comments

Comments
 (0)