Skip to content

Commit

Permalink
Use Reader interface to fetch TLS certs and keys (#274)
Browse files Browse the repository at this point in the history
* Initial implementation

* Goimports file

* Goimports -local

* Use interface

* Use reader interface for secrets

* remove vault client

* Undo go.mod changes

* Default to reading from file

* Update Changelog

* Store reader in local var

* Remove references to file from doc
  • Loading branch information
fayzal-g authored Mar 6, 2023
1 parent 2193066 commit ecdd82c
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 9 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
* [CHANGE] Multierror: Implement `Is(error) bool`. This allows to use `multierror.MultiError` with `errors.Is()`. `MultiError` will in turn call `errors.Is()` on every error value. #254
* [CHANGE] Cache: Remove the `context.Context` argument from the `Cache.Store` method and rename the method to `Cache.StoreAsync`. #273
* [FEATURE] Cache: Add support for configuring a Redis cache backend. #268 #271
* [ENHANCEMENT] Use `SecretReader` interface to fetch secrets when configuring TLS. #274
* [ENHANCEMENT] Add middleware package. #38
* [ENHANCEMENT] Add the ring package #45
* [ENHANCEMENT] Add limiter package. #41
Expand Down
45 changes: 36 additions & 9 deletions crypto/tls/tls.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,22 @@ import (
"os"
"strings"

"google.golang.org/grpc/credentials/insecure"

"github.com/pkg/errors"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/credentials/insecure"
)

type SecretReader interface {
ReadSecret(path string) ([]byte, error)
}

type fileReader struct{}

func (f *fileReader) ReadSecret(path string) ([]byte, error) {
return os.ReadFile(path)
}

// ClientConfig is the config for client TLS.
type ClientConfig struct {
CertPath string `yaml:"tls_cert_path" category:"advanced"`
Expand All @@ -24,6 +33,8 @@ type ClientConfig struct {
InsecureSkipVerify bool `yaml:"tls_insecure_skip_verify" category:"advanced"`
CipherSuites string `yaml:"tls_cipher_suites" category:"advanced" doc:"description_method=GetTLSCipherSuitesLongDescription"`
MinVersion string `yaml:"tls_min_version" category:"advanced"`

Reader SecretReader `yaml:"-"`
}

var (
Expand All @@ -43,9 +54,9 @@ func (cfg *ClientConfig) RegisterFlagsWithPrefix(prefix string, f *flag.FlagSet)
// Trim any trailing "." since we include our own here
prefix = strings.TrimRight(prefix, ".")

f.StringVar(&cfg.CertPath, prefix+".tls-cert-path", "", "Path to the client certificate file, which will be used for authenticating with the server. Also requires the key path to be configured.")
f.StringVar(&cfg.KeyPath, prefix+".tls-key-path", "", "Path to the key file for the client certificate. Also requires the client certificate to be configured.")
f.StringVar(&cfg.CAPath, prefix+".tls-ca-path", "", "Path to the CA certificates file to validate server certificate against. If not set, the host's root CA certificates are used.")
f.StringVar(&cfg.CertPath, prefix+".tls-cert-path", "", "Path to the client certificate, which will be used for authenticating with the server. Also requires the key path to be configured.")
f.StringVar(&cfg.KeyPath, prefix+".tls-key-path", "", "Path to the key for the client certificate. Also requires the client certificate to be configured.")
f.StringVar(&cfg.CAPath, prefix+".tls-ca-path", "", "Path to the CA certificates to validate server certificate against. If not set, the host's root CA certificates are used.")
f.StringVar(&cfg.ServerName, prefix+".tls-server-name", "", "Override the expected name on the server certificate.")
f.BoolVar(&cfg.InsecureSkipVerify, prefix+".tls-insecure-skip-verify", false, "Skip validating server certificate.")
f.StringVar(&cfg.CipherSuites, prefix+".tls-cipher-suites", "", cfg.GetTLSCipherSuitesShortDescription())
Expand Down Expand Up @@ -79,10 +90,16 @@ func (cfg *ClientConfig) GetTLSConfig() (*tls.Config, error) {
ServerName: cfg.ServerName,
}

// read ca certificates
// If Reader interface not provided, default to reading from File
reader := cfg.Reader
if reader == nil {
reader = &fileReader{}
}

// Read CA Certificates
if cfg.CAPath != "" {
var caCertPool *x509.CertPool
caCert, err := os.ReadFile(cfg.CAPath)
caCert, err := reader.ReadSecret(cfg.CAPath)
if err != nil {
return nil, errors.Wrapf(err, "error loading ca cert: %s", cfg.CAPath)
}
Expand All @@ -92,15 +109,25 @@ func (cfg *ClientConfig) GetTLSConfig() (*tls.Config, error) {
config.RootCAs = caCertPool
}

// read client certificate
// Read Client Certificate
if cfg.CertPath != "" || cfg.KeyPath != "" {
if cfg.CertPath == "" {
return nil, errCertMissing
}
if cfg.KeyPath == "" {
return nil, errKeyMissing
}
clientCert, err := tls.LoadX509KeyPair(cfg.CertPath, cfg.KeyPath)

cert, err := reader.ReadSecret(cfg.CertPath)
if err != nil {
return nil, errors.Wrapf(err, "error loading client cert: %s", cfg.CertPath)
}
key, err := reader.ReadSecret(cfg.KeyPath)
if err != nil {
return nil, errors.Wrapf(err, "error loading client key: %s", cfg.KeyPath)
}

clientCert, err := tls.X509KeyPair(cert, key)
if err != nil {
return nil, errors.Wrapf(err, "failed to load TLS certificate %s,%s", cfg.CertPath, cfg.KeyPath)
}
Expand Down

0 comments on commit ecdd82c

Please sign in to comment.