1
0
Fork 0

fix: do not require a TLS client cert when InsecureSkipVerify is false

Co-authored-by: Tom Moulard <tom.moulard@traefik.io>
This commit is contained in:
Kevin Pollet 2021-10-26 10:54:11 +02:00 committed by GitHub
parent 566b205758
commit d3ff0c2cd4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 273 additions and 184 deletions

View file

@ -4,12 +4,15 @@ import (
"context"
"crypto/tls"
"crypto/x509"
"errors"
"fmt"
"os"
"github.com/traefik/traefik/v2/pkg/log"
)
// +k8s:deepcopy-gen=true
// ClientTLS holds TLS specific configurations as client
// CA, Cert and Key can be either path or file contents.
type ClientTLS struct {
@ -42,7 +45,7 @@ func (clientTLS *ClientTLS) CreateTLSConfig(ctx context.Context) (*tls.Config, e
}
if !caPool.AppendCertsFromPEM(ca) {
return nil, fmt.Errorf("failed to parse CA")
return nil, errors.New("failed to parse CA")
}
if clientTLS.CAOptional {
@ -52,34 +55,24 @@ func (clientTLS *ClientTLS) CreateTLSConfig(ctx context.Context) (*tls.Config, e
}
}
if !clientTLS.InsecureSkipVerify && (len(clientTLS.Cert) == 0 || len(clientTLS.Key) == 0) {
return nil, fmt.Errorf("TLS Certificate or Key file must be set when TLS configuration is created")
hasCert := len(clientTLS.Cert) > 0
hasKey := len(clientTLS.Key) > 0
if hasCert != hasKey {
return nil, errors.New("both TLS cert and key must be defined")
}
cert := tls.Certificate{}
_, errKeyIsFile := os.Stat(clientTLS.Key)
if !hasCert || !hasKey {
return &tls.Config{
RootCAs: caPool,
InsecureSkipVerify: clientTLS.InsecureSkipVerify,
ClientAuth: clientAuth,
}, nil
}
if len(clientTLS.Cert) > 0 && len(clientTLS.Key) > 0 {
var err error
if _, errCertIsFile := os.Stat(clientTLS.Cert); errCertIsFile == nil {
if errKeyIsFile == nil {
cert, err = tls.LoadX509KeyPair(clientTLS.Cert, clientTLS.Key)
if err != nil {
return nil, fmt.Errorf("failed to load TLS keypair: %w", err)
}
} else {
return nil, fmt.Errorf("TLS cert is a file, but tls key is not")
}
} else {
if errKeyIsFile != nil {
cert, err = tls.X509KeyPair([]byte(clientTLS.Cert), []byte(clientTLS.Key))
if err != nil {
return nil, fmt.Errorf("failed to load TLS keypair: %w", err)
}
} else {
return nil, fmt.Errorf("TLS key is a file, but tls cert is not")
}
}
cert, err := loadKeyPair(clientTLS.Cert, clientTLS.Key)
if err != nil {
return nil, err
}
return &tls.Config{
@ -89,3 +82,27 @@ func (clientTLS *ClientTLS) CreateTLSConfig(ctx context.Context) (*tls.Config, e
ClientAuth: clientAuth,
}, nil
}
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
}