@@ -5,50 +5,120 @@ import (
55 "fmt"
66 "os"
77 "path/filepath"
8+ "strings"
89
910 "github.com/go-logr/logr"
1011)
1112
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 )
1420 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
1626 }
17- if caDir == "" {
18- return caCertPool , nil
27+ if fi .IsDir () {
28+ log .V (defaultLogLevel ).Info ("skip directory" , "name" , file )
29+ return certRead , nil
1930 }
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+ }
2044
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 )
2251 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
2457 }
25- count := 0
2658
2759 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 )
3162 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
3764 }
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 )
4087 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
4689 }
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
48118 }
49119
50120 // Found no certs!
51- if count == 0 {
121+ if ! count {
52122 return nil , fmt .Errorf ("no certificates found in %q" , caDir )
53123 }
54124
0 commit comments