| package rootcerts |
| |
| import ( |
| "crypto/tls" |
| "crypto/x509" |
| "fmt" |
| "io/ioutil" |
| "os" |
| "path/filepath" |
| ) |
| |
| // Config determines where LoadCACerts will load certificates from. When both |
| // CAFile and CAPath are blank, this library's functions will either load |
| // system roots explicitly and return them, or set the CertPool to nil to allow |
| // Go's standard library to load system certs. |
| type Config struct { |
| // CAFile is a path to a PEM-encoded certificate file or bundle. Takes |
| // precedence over CAPath. |
| CAFile string |
| |
| // CAPath is a path to a directory populated with PEM-encoded certificates. |
| CAPath string |
| } |
| |
| // ConfigureTLS sets up the RootCAs on the provided tls.Config based on the |
| // Config specified. |
| func ConfigureTLS(t *tls.Config, c *Config) error { |
| if t == nil { |
| return nil |
| } |
| pool, err := LoadCACerts(c) |
| if err != nil { |
| return err |
| } |
| t.RootCAs = pool |
| return nil |
| } |
| |
| // LoadCACerts loads a CertPool based on the Config specified. |
| func LoadCACerts(c *Config) (*x509.CertPool, error) { |
| if c == nil { |
| c = &Config{} |
| } |
| if c.CAFile != "" { |
| return LoadCAFile(c.CAFile) |
| } |
| if c.CAPath != "" { |
| return LoadCAPath(c.CAPath) |
| } |
| |
| return LoadSystemCAs() |
| } |
| |
| // LoadCAFile loads a single PEM-encoded file from the path specified. |
| func LoadCAFile(caFile string) (*x509.CertPool, error) { |
| pool := x509.NewCertPool() |
| |
| pem, err := ioutil.ReadFile(caFile) |
| if err != nil { |
| return nil, fmt.Errorf("Error loading CA File: %s", err) |
| } |
| |
| ok := pool.AppendCertsFromPEM(pem) |
| if !ok { |
| return nil, fmt.Errorf("Error loading CA File: Couldn't parse PEM in: %s", caFile) |
| } |
| |
| return pool, nil |
| } |
| |
| // LoadCAPath walks the provided path and loads all certificates encounted into |
| // a pool. |
| func LoadCAPath(caPath string) (*x509.CertPool, error) { |
| pool := x509.NewCertPool() |
| walkFn := func(path string, info os.FileInfo, err error) error { |
| if err != nil { |
| return err |
| } |
| |
| if info.IsDir() { |
| return nil |
| } |
| |
| pem, err := ioutil.ReadFile(path) |
| if err != nil { |
| return fmt.Errorf("Error loading file from CAPath: %s", err) |
| } |
| |
| ok := pool.AppendCertsFromPEM(pem) |
| if !ok { |
| return fmt.Errorf("Error loading CA Path: Couldn't parse PEM in: %s", path) |
| } |
| |
| return nil |
| } |
| |
| err := filepath.Walk(caPath, walkFn) |
| if err != nil { |
| return nil, err |
| } |
| |
| return pool, nil |
| } |