Add forward authentication option

This commit is contained in:
Daniel Rampelt 2017-08-25 12:22:03 -04:00 committed by Traefiker
parent f16219f90a
commit 52b69fbcb8
11 changed files with 252 additions and 105 deletions

View file

@ -7,6 +7,12 @@ import (
"strconv"
"strings"
"crypto/tls"
"crypto/x509"
"io/ioutil"
"os"
"github.com/containous/traefik/log"
"github.com/docker/libkv/store"
"github.com/ryanuber/go-glob"
)
@ -299,6 +305,7 @@ type Cluster struct {
type Auth struct {
Basic *Basic
Digest *Digest
Forward *Forward
HeaderField string
}
@ -317,6 +324,12 @@ type Digest struct {
UsersFile string
}
// Forward authentication
type Forward struct {
Address string `description:"Authentication server address"`
TLS *ClientTLS `description:"Enable TLS support"`
}
// CanonicalDomain returns a lower case domain with trim space
func CanonicalDomain(domain string) string {
return strings.ToLower(strings.TrimSpace(domain))
@ -388,3 +401,71 @@ type AccessLog struct {
FilePath string `json:"file,omitempty" description:"Access log file path. Stdout is used when omitted or empty"`
Format string `json:"format,omitempty" description:"Access log format: json | common"`
}
// ClientTLS holds TLS specific configurations as client
// CA, Cert and Key can be either path or file contents
type ClientTLS struct {
CA string `description:"TLS CA"`
Cert string `description:"TLS cert"`
Key string `description:"TLS key"`
InsecureSkipVerify bool `description:"TLS insecure skip verify"`
}
// CreateTLSConfig creates a TLS config from ClientTLS structures
func (clientTLS *ClientTLS) CreateTLSConfig() (*tls.Config, error) {
var err error
if clientTLS == nil {
log.Warnf("clientTLS is nil")
return nil, nil
}
caPool := x509.NewCertPool()
if clientTLS.CA != "" {
var ca []byte
if _, errCA := os.Stat(clientTLS.CA); errCA == nil {
ca, err = ioutil.ReadFile(clientTLS.CA)
if err != nil {
return nil, fmt.Errorf("Failed to read CA. %s", err)
}
} else {
ca = []byte(clientTLS.CA)
}
caPool.AppendCertsFromPEM(ca)
}
cert := tls.Certificate{}
_, errKeyIsFile := os.Stat(clientTLS.Key)
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")
}
if len(clientTLS.Cert) > 0 && len(clientTLS.Key) > 0 {
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: %v", 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: %v", err)
}
} else {
return nil, fmt.Errorf("tls key is a file, but tls cert is not")
}
}
}
TLSConfig := &tls.Config{
Certificates: []tls.Certificate{cert},
RootCAs: caPool,
InsecureSkipVerify: clientTLS.InsecureSkipVerify,
}
return TLSConfig, nil
}