components-contrib/pubsub/tls.go

81 lines
2.1 KiB
Go

package pubsub
import (
"crypto/tls"
"crypto/x509"
"encoding/pem"
"errors"
"fmt"
)
// TLSProperties is a struct that contains the TLS properties.
type TLSProperties struct {
CACert string
ClientCert string
ClientKey string
}
const (
// CACert is the metadata key name for the CA certificate.
CACert = "caCert"
// ClientCert is the metadata key name for the client certificate.
ClientCert = "clientCert"
// ClientKey is the metadata key name for the client key.
ClientKey = "clientKey"
)
// TLS takes a metadata object and returns the TLSProperties configured.
func TLS(metadata map[string]string) (TLSProperties, error) {
cfg := TLSProperties{}
if val, ok := metadata[CACert]; ok && val != "" {
if !isValidPEM(val) {
return TLSProperties{}, errors.New("invalid caCert")
}
cfg.CACert = val
}
if val, ok := metadata[ClientCert]; ok && val != "" {
if !isValidPEM(val) {
return TLSProperties{}, errors.New("invalid clientCert")
}
cfg.ClientCert = val
}
if val, ok := metadata[ClientKey]; ok && val != "" {
if !isValidPEM(val) {
return TLSProperties{}, errors.New("invalid clientKey")
}
cfg.ClientKey = val
}
return cfg, nil
}
// ConvertTLSPropertiesToTLSConfig converts the TLSProperties to a tls.Config.
func ConvertTLSPropertiesToTLSConfig(properties TLSProperties) (*tls.Config, error) {
tlsConfig := new(tls.Config)
if properties.ClientCert != "" && properties.ClientKey != "" {
cert, err := tls.X509KeyPair([]byte(properties.ClientCert), []byte(properties.ClientKey))
if err != nil {
return tlsConfig, fmt.Errorf("unable to load client certificate and key pair. Err: %v", err)
}
tlsConfig.Certificates = []tls.Certificate{cert}
}
if properties.CACert != "" {
tlsConfig.RootCAs = x509.NewCertPool()
if ok := tlsConfig.RootCAs.AppendCertsFromPEM([]byte(properties.CACert)); !ok {
return tlsConfig, errors.New("unable to load CA certificate")
}
}
return tlsConfig, nil
}
// isValidPEM validates the provided input has PEM formatted block.
func isValidPEM(val string) bool {
block, _ := pem.Decode([]byte(val))
return block != nil
}