2019-01-18 14:18:04 +00:00
|
|
|
package types
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"crypto/tls"
|
|
|
|
"crypto/x509"
|
2021-10-26 08:54:11 +00:00
|
|
|
"errors"
|
2019-01-18 14:18:04 +00:00
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
|
2022-11-21 17:36:05 +00:00
|
|
|
"github.com/rs/zerolog/log"
|
2019-01-18 14:18:04 +00:00
|
|
|
)
|
|
|
|
|
2021-10-26 08:54:11 +00:00
|
|
|
// +k8s:deepcopy-gen=true
|
|
|
|
|
2019-01-18 14:18:04 +00:00
|
|
|
// ClientTLS holds TLS specific configurations as client
|
2020-05-11 10:06:07 +00:00
|
|
|
// CA, Cert and Key can be either path or file contents.
|
2019-01-18 14:18:04 +00:00
|
|
|
type ClientTLS struct {
|
2022-11-25 09:50:06 +00:00
|
|
|
CA string `description:"TLS CA" json:"ca,omitempty" toml:"ca,omitempty" yaml:"ca,omitempty"`
|
2019-07-01 09:30:05 +00:00
|
|
|
Cert string `description:"TLS cert" json:"cert,omitempty" toml:"cert,omitempty" yaml:"cert,omitempty"`
|
2022-01-24 10:08:05 +00:00
|
|
|
Key string `description:"TLS key" json:"key,omitempty" toml:"key,omitempty" yaml:"key,omitempty" loggable:"false"`
|
2020-10-30 11:44:05 +00:00
|
|
|
InsecureSkipVerify bool `description:"TLS insecure skip verify" json:"insecureSkipVerify,omitempty" toml:"insecureSkipVerify,omitempty" yaml:"insecureSkipVerify,omitempty" export:"true"`
|
2019-01-18 14:18:04 +00:00
|
|
|
}
|
|
|
|
|
2020-05-11 10:06:07 +00:00
|
|
|
// CreateTLSConfig creates a TLS config from ClientTLS structures.
|
2022-09-12 15:40:09 +00:00
|
|
|
func (c *ClientTLS) CreateTLSConfig(ctx context.Context) (*tls.Config, error) {
|
|
|
|
if c == nil {
|
2022-11-21 17:36:05 +00:00
|
|
|
log.Ctx(ctx).Warn().Msg("clientTLS is nil")
|
2019-01-18 14:18:04 +00:00
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2021-11-03 16:38:07 +00:00
|
|
|
// Not initialized, to rely on system bundle.
|
|
|
|
var caPool *x509.CertPool
|
|
|
|
|
2022-09-12 15:40:09 +00:00
|
|
|
if c.CA != "" {
|
2019-01-18 14:18:04 +00:00
|
|
|
var ca []byte
|
2022-09-12 15:40:09 +00:00
|
|
|
if _, errCA := os.Stat(c.CA); errCA == nil {
|
2019-01-18 14:18:04 +00:00
|
|
|
var err error
|
2022-09-12 15:40:09 +00:00
|
|
|
ca, err = os.ReadFile(c.CA)
|
2019-01-18 14:18:04 +00:00
|
|
|
if err != nil {
|
2020-05-11 10:06:07 +00:00
|
|
|
return nil, fmt.Errorf("failed to read CA. %w", err)
|
2019-01-18 14:18:04 +00:00
|
|
|
}
|
|
|
|
} else {
|
2022-09-12 15:40:09 +00:00
|
|
|
ca = []byte(c.CA)
|
2019-01-18 14:18:04 +00:00
|
|
|
}
|
|
|
|
|
2021-11-03 16:38:07 +00:00
|
|
|
caPool = x509.NewCertPool()
|
2019-01-18 14:18:04 +00:00
|
|
|
if !caPool.AppendCertsFromPEM(ca) {
|
2021-10-26 08:54:11 +00:00
|
|
|
return nil, errors.New("failed to parse CA")
|
2019-01-18 14:18:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-12 15:40:09 +00:00
|
|
|
hasCert := len(c.Cert) > 0
|
|
|
|
hasKey := len(c.Key) > 0
|
2021-10-26 08:54:11 +00:00
|
|
|
|
|
|
|
if hasCert != hasKey {
|
|
|
|
return nil, errors.New("both TLS cert and key must be defined")
|
2019-01-18 14:18:04 +00:00
|
|
|
}
|
|
|
|
|
2021-10-26 08:54:11 +00:00
|
|
|
if !hasCert || !hasKey {
|
|
|
|
return &tls.Config{
|
|
|
|
RootCAs: caPool,
|
2022-09-12 15:40:09 +00:00
|
|
|
InsecureSkipVerify: c.InsecureSkipVerify,
|
2021-10-26 08:54:11 +00:00
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2022-09-12 15:40:09 +00:00
|
|
|
cert, err := loadKeyPair(c.Cert, c.Key)
|
2021-10-26 08:54:11 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2019-01-18 14:18:04 +00:00
|
|
|
}
|
|
|
|
|
2019-11-14 15:40:05 +00:00
|
|
|
return &tls.Config{
|
2019-01-18 14:18:04 +00:00
|
|
|
Certificates: []tls.Certificate{cert},
|
|
|
|
RootCAs: caPool,
|
2022-09-12 15:40:09 +00:00
|
|
|
InsecureSkipVerify: c.InsecureSkipVerify,
|
2019-11-14 15:40:05 +00:00
|
|
|
}, nil
|
2019-01-18 14:18:04 +00:00
|
|
|
}
|
2021-10-26 08:54:11 +00:00
|
|
|
|
|
|
|
func loadKeyPair(cert, key string) (tls.Certificate, error) {
|
|
|
|
keyPair, err := tls.X509KeyPair([]byte(cert), []byte(key))
|
|
|
|
if err == nil {
|
|
|
|
return keyPair, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err = os.Stat(cert)
|
|
|
|
if err != nil {
|
|
|
|
return tls.Certificate{}, errors.New("cert file does not exist")
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err = os.Stat(key)
|
|
|
|
if err != nil {
|
|
|
|
return tls.Certificate{}, errors.New("key file does not exist")
|
|
|
|
}
|
|
|
|
|
|
|
|
keyPair, err = tls.LoadX509KeyPair(cert, key)
|
|
|
|
if err != nil {
|
|
|
|
return tls.Certificate{}, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return keyPair, nil
|
|
|
|
}
|