@@ -5,50 +5,120 @@ 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
+ // Ignore directories that don't exist
53
+ if os .IsNotExist (err ) {
54
+ return certRead , nil
55
+ }
56
+ return certRead , err
24
57
}
25
- count := 0
26
58
27
59
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 )
60
+ file := filepath .Join (dir , e .Name ())
61
+ c , err := readCertFile (pool , file , log )
31
62
if err != nil {
32
- return nil , err
33
- }
34
- if fi .IsDir () {
35
- log .V (defaultLogLevel ).Info ("skip directory" , "name" , e .Name ())
36
- continue
63
+ return certRead , err
37
64
}
38
- log .V (defaultLogLevel ).Info ("load certificate" , "name" , e .Name (), "size" , fi .Size (), "modtime" , fi .ModTime ())
39
- data , err := os .ReadFile (file )
65
+ certRead = certRead || c
66
+ }
67
+ return certRead , nil
68
+ }
69
+
70
+ // This function looks explicitly at the SSL environment, and
71
+ // uses it to create a "fresh" system cert pool
72
+ func systemCertPool (log logr.Logger ) (* x509.CertPool , error ) {
73
+ sslCertDir := os .Getenv ("SSL_CERT_DIR" )
74
+ sslCertFile := os .Getenv ("SSL_CERT_FILE" )
75
+ if sslCertDir == "" && sslCertFile == "" {
76
+ log .V (defaultLogLevel ).Info ("SystemCertPool: SSL environment not set" )
77
+ return x509 .SystemCertPool ()
78
+ }
79
+ log .V (defaultLogLevel ).Info ("SystemCertPool: SSL environment set" , "SSL_CERT_DIR" , sslCertDir , "SSL_CERT_FILE" , sslCertFile )
80
+
81
+ var certRead bool
82
+ pool := x509 .NewCertPool ()
83
+
84
+ // SSL_CERT_DIR may consist of multiple entries separated by ":"
85
+ for _ , d := range strings .Split (sslCertDir , ":" ) {
86
+ c , err := readCertDir (pool , d , log )
40
87
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 ++
88
+ return nil , err
46
89
}
47
- logPem (data , e .Name (), caDir , "loading certificate file" , log )
90
+ certRead = certRead || c
91
+ }
92
+ // SSL_CERT_FILE may consist of only a single entry
93
+ c , err := readCertFile (pool , sslCertFile , log )
94
+ if err != nil {
95
+ return nil , err
96
+ }
97
+ certRead = certRead || c
98
+
99
+ // If SSL_CERT_DIR and SSL_CERT_FILE resulted in no certs, then return the system cert pool
100
+ if ! certRead {
101
+ return x509 .SystemCertPool ()
102
+ }
103
+ return pool , nil
104
+ }
105
+
106
+ func NewCertPool (caDir string , log logr.Logger ) (* x509.CertPool , error ) {
107
+ caCertPool , err := systemCertPool (log )
108
+ if err != nil {
109
+ return nil , err
110
+ }
111
+
112
+ if caDir == "" {
113
+ return caCertPool , nil
114
+ }
115
+ count , err := readCertDir (caCertPool , caDir , log )
116
+ if err != nil {
117
+ return nil , err
48
118
}
49
119
50
120
// Found no certs!
51
- if count == 0 {
121
+ if ! count {
52
122
return nil , fmt .Errorf ("no certificates found in %q" , caDir )
53
123
}
54
124
0 commit comments