@@ -5,50 +5,116 @@ import (
5
5
"fmt"
6
6
"os"
7
7
"path/filepath"
8
+ "strings"
8
9
9
10
"github.com/go-logr/logr"
10
11
)
11
12
12
- func NewCertPool (caDir string , log logr.Logger ) (* x509.CertPool , error ) {
13
- caCertPool , err := x509 .SystemCertPool ()
13
+ func readCertFile (pool * x509.CertPool , file string , log logr.Logger ) (bool , error ) {
14
+ var certRead bool
15
+ if file == "" {
16
+ return certRead , nil
17
+ }
18
+ // These might be symlinks pointing to directories, so use Stat() to resolve
19
+ fi , err := os .Stat (file )
14
20
if err != nil {
15
- return nil , err
21
+ // Ignore files that don't exist
22
+ if os .IsNotExist (err ) {
23
+ return certRead , nil
24
+ }
25
+ return certRead , err
16
26
}
17
- if caDir == "" {
18
- return caCertPool , nil
27
+ if fi .IsDir () {
28
+ log .V (defaultLogLevel ).Info ("skip directory" , "name" , file )
29
+ return certRead , nil
19
30
}
31
+ log .V (defaultLogLevel ).Info ("load certificate" , "name" , file , "size" , fi .Size (), "modtime" , fi .ModTime ())
32
+ data , err := os .ReadFile (file )
33
+ if err != nil {
34
+ return certRead , fmt .Errorf ("error reading cert file %q: %w" , file , err )
35
+ }
36
+ // The return indicates if any certs were added
37
+ if pool .AppendCertsFromPEM (data ) {
38
+ certRead = true
39
+ }
40
+ logPem (data , filepath .Base (file ), filepath .Dir (file ), "loading certificate file" , log )
41
+
42
+ return certRead , nil
43
+ }
20
44
21
- dirEntries , err := os .ReadDir (caDir )
45
+ func readCertDir (pool * x509.CertPool , dir string , log logr.Logger ) (bool , error ) {
46
+ var certRead bool
47
+ if dir == "" {
48
+ return certRead , nil
49
+ }
50
+ dirEntries , err := os .ReadDir (dir )
22
51
if err != nil {
23
- return nil , err
52
+ return certRead , err
24
53
}
25
- count := 0
26
54
27
55
for _ , e := range dirEntries {
28
- file := filepath .Join (caDir , e .Name ())
29
- // These might be symlinks pointing to directories, so use Stat() to resolve
30
- fi , err := os .Stat (file )
56
+ file := filepath .Join (dir , e .Name ())
57
+ c , err := readCertFile (pool , file , log )
31
58
if err != nil {
32
- return nil , err
59
+ return certRead , err
33
60
}
34
- if fi .IsDir () {
35
- log .V (defaultLogLevel ).Info ("skip directory" , "name" , e .Name ())
36
- continue
37
- }
38
- log .V (defaultLogLevel ).Info ("load certificate" , "name" , e .Name (), "size" , fi .Size (), "modtime" , fi .ModTime ())
39
- data , err := os .ReadFile (file )
61
+ certRead = certRead || c
62
+ }
63
+ return certRead , nil
64
+ }
65
+
66
+ // This function looks explicitly at the SSL environment, and
67
+ // uses it to create a "fresh" system cert pool
68
+ func systemCertPool (log logr.Logger ) (* x509.CertPool , error ) {
69
+ sslCertDir := os .Getenv ("SSL_CERT_DIR" )
70
+ sslCertFile := os .Getenv ("SSL_CERT_FILE" )
71
+ if sslCertDir == "" && sslCertFile == "" {
72
+ log .V (defaultLogLevel ).Info ("SystemCertPool: SSL environment not set" )
73
+ return x509 .SystemCertPool ()
74
+ }
75
+ log .V (defaultLogLevel ).Info ("SystemCertPool: SSL environment set" , "SSL_CERT_DIR" , sslCertDir , "SSL_CERT_FILE" , sslCertFile )
76
+
77
+ var certRead bool
78
+ pool := x509 .NewCertPool ()
79
+
80
+ // SSL_CERT_DIR may consist of multiple entries separated by ":"
81
+ for _ , d := range strings .Split (sslCertDir , ":" ) {
82
+ c , err := readCertDir (pool , d , log )
40
83
if err != nil {
41
- return nil , fmt .Errorf ("error reading cert file %q: %w" , file , err )
42
- }
43
- // The return indicates if any certs were added
44
- if caCertPool .AppendCertsFromPEM (data ) {
45
- count ++
84
+ return nil , err
46
85
}
47
- logPem (data , e .Name (), caDir , "loading certificate file" , log )
86
+ certRead = certRead || c
87
+ }
88
+ // SSL_CERT_FILE may consist of only a single entry
89
+ c , err := readCertFile (pool , sslCertFile , log )
90
+ if err != nil {
91
+ return nil , err
92
+ }
93
+ certRead = certRead || c
94
+
95
+ // If SSL_CERT_DIR and SSL_CERT_FILE resulted in no certs, then return the system cert pool
96
+ if ! certRead {
97
+ return x509 .SystemCertPool ()
98
+ }
99
+ return pool , nil
100
+ }
101
+
102
+ func NewCertPool (caDir string , log logr.Logger ) (* x509.CertPool , error ) {
103
+ caCertPool , err := systemCertPool (log )
104
+ if err != nil {
105
+ return nil , err
106
+ }
107
+
108
+ if caDir == "" {
109
+ return caCertPool , nil
110
+ }
111
+ count , err := readCertDir (caCertPool , caDir , log )
112
+ if err != nil {
113
+ return nil , err
48
114
}
49
115
50
116
// Found no certs!
51
- if count == 0 {
117
+ if ! count {
52
118
return nil , fmt .Errorf ("no certificates found in %q" , caDir )
53
119
}
54
120
0 commit comments