Merge pull request #209 from tboerger/feature/tls-auth

Integrated TLS auth for etcd and consul
This commit is contained in:
Vincent Demeester 2016-02-25 10:58:23 +01:00
commit 1a5668377c
5 changed files with 129 additions and 11 deletions

34
cmd.go
View file

@ -45,9 +45,11 @@ var arguments = struct {
dockerTLS bool dockerTLS bool
marathon bool marathon bool
consul bool consul bool
consulTLS bool
consulCatalog bool consulCatalog bool
zookeeper bool zookeeper bool
etcd bool etcd bool
etcdTLS bool
boltdb bool boltdb bool
}{ }{
GlobalConfiguration{ GlobalConfiguration{
@ -55,14 +57,22 @@ var arguments = struct {
Docker: &provider.Docker{ Docker: &provider.Docker{
TLS: &provider.DockerTLS{}, TLS: &provider.DockerTLS{},
}, },
File: &provider.File{}, File: &provider.File{},
Web: &WebProvider{}, Web: &WebProvider{},
Marathon: &provider.Marathon{}, Marathon: &provider.Marathon{},
Consul: &provider.Consul{}, Consul: &provider.Consul{
Kv: provider.Kv{
TLS: &provider.KvTLS{},
},
},
ConsulCatalog: &provider.ConsulCatalog{}, ConsulCatalog: &provider.ConsulCatalog{},
Zookeeper: &provider.Zookepper{}, Zookeeper: &provider.Zookepper{},
Etcd: &provider.Etcd{}, Etcd: &provider.Etcd{
Boltdb: &provider.BoltDb{}, Kv: provider.Kv{
TLS: &provider.KvTLS{},
},
},
Boltdb: &provider.BoltDb{},
}, },
false, false,
false, false,
@ -74,6 +84,8 @@ var arguments = struct {
false, false,
false, false,
false, false,
false,
false,
} }
func init() { func init() {
@ -121,6 +133,11 @@ func init() {
traefikCmd.PersistentFlags().StringVar(&arguments.Consul.Filename, "consul.filename", "", "Override default configuration template. For advanced users :)") traefikCmd.PersistentFlags().StringVar(&arguments.Consul.Filename, "consul.filename", "", "Override default configuration template. For advanced users :)")
traefikCmd.PersistentFlags().StringVar(&arguments.Consul.Endpoint, "consul.endpoint", "127.0.0.1:8500", "Consul server endpoint") traefikCmd.PersistentFlags().StringVar(&arguments.Consul.Endpoint, "consul.endpoint", "127.0.0.1:8500", "Consul server endpoint")
traefikCmd.PersistentFlags().StringVar(&arguments.Consul.Prefix, "consul.prefix", "/traefik", "Prefix used for KV store") traefikCmd.PersistentFlags().StringVar(&arguments.Consul.Prefix, "consul.prefix", "/traefik", "Prefix used for KV store")
traefikCmd.PersistentFlags().BoolVar(&arguments.consulTLS, "consul.tls", false, "Enable Consul TLS support")
traefikCmd.PersistentFlags().StringVar(&arguments.Consul.TLS.CA, "consul.tls.ca", "", "TLS CA")
traefikCmd.PersistentFlags().StringVar(&arguments.Consul.TLS.Cert, "consul.tls.cert", "", "TLS cert")
traefikCmd.PersistentFlags().StringVar(&arguments.Consul.TLS.Key, "consul.tls.key", "", "TLS key")
traefikCmd.PersistentFlags().BoolVar(&arguments.Consul.TLS.InsecureSkipVerify, "consul.tls.insecureSkipVerify", false, "TLS insecure skip verify")
traefikCmd.PersistentFlags().BoolVar(&arguments.consulCatalog, "consulCatalog", false, "Enable Consul catalog backend") traefikCmd.PersistentFlags().BoolVar(&arguments.consulCatalog, "consulCatalog", false, "Enable Consul catalog backend")
traefikCmd.PersistentFlags().StringVar(&arguments.ConsulCatalog.Domain, "consulCatalog.domain", "", "Default domain used") traefikCmd.PersistentFlags().StringVar(&arguments.ConsulCatalog.Domain, "consulCatalog.domain", "", "Default domain used")
@ -137,6 +154,11 @@ func init() {
traefikCmd.PersistentFlags().StringVar(&arguments.Etcd.Filename, "etcd.filename", "", "Override default configuration template. For advanced users :)") traefikCmd.PersistentFlags().StringVar(&arguments.Etcd.Filename, "etcd.filename", "", "Override default configuration template. For advanced users :)")
traefikCmd.PersistentFlags().StringVar(&arguments.Etcd.Endpoint, "etcd.endpoint", "127.0.0.1:4001", "Etcd server endpoint") traefikCmd.PersistentFlags().StringVar(&arguments.Etcd.Endpoint, "etcd.endpoint", "127.0.0.1:4001", "Etcd server endpoint")
traefikCmd.PersistentFlags().StringVar(&arguments.Etcd.Prefix, "etcd.prefix", "/traefik", "Prefix used for KV store") traefikCmd.PersistentFlags().StringVar(&arguments.Etcd.Prefix, "etcd.prefix", "/traefik", "Prefix used for KV store")
traefikCmd.PersistentFlags().BoolVar(&arguments.etcdTLS, "etcd.tls", false, "Enable Etcd TLS support")
traefikCmd.PersistentFlags().StringVar(&arguments.Etcd.TLS.CA, "etcd.tls.ca", "", "TLS CA")
traefikCmd.PersistentFlags().StringVar(&arguments.Etcd.TLS.Cert, "etcd.tls.cert", "", "TLS cert")
traefikCmd.PersistentFlags().StringVar(&arguments.Etcd.TLS.Key, "etcd.tls.key", "", "TLS key")
traefikCmd.PersistentFlags().BoolVar(&arguments.Etcd.TLS.InsecureSkipVerify, "etcd.tls.insecureSkipVerify", false, "TLS insecure skip verify")
traefikCmd.PersistentFlags().BoolVar(&arguments.boltdb, "boltdb", false, "Enable Boltdb backend") traefikCmd.PersistentFlags().BoolVar(&arguments.boltdb, "boltdb", false, "Enable Boltdb backend")
traefikCmd.PersistentFlags().BoolVar(&arguments.Boltdb.Watch, "boltdb.watch", true, "Watch provider") traefikCmd.PersistentFlags().BoolVar(&arguments.Boltdb.Watch, "boltdb.watch", true, "Watch provider")

View file

@ -222,6 +222,9 @@ func LoadConfiguration() *GlobalConfiguration {
if arguments.marathon { if arguments.marathon {
viper.Set("marathon", arguments.Marathon) viper.Set("marathon", arguments.Marathon)
} }
if !arguments.consulTLS {
arguments.Consul.TLS = nil
}
if arguments.consul { if arguments.consul {
viper.Set("consul", arguments.Consul) viper.Set("consul", arguments.Consul)
} }
@ -231,6 +234,9 @@ func LoadConfiguration() *GlobalConfiguration {
if arguments.zookeeper { if arguments.zookeeper {
viper.Set("zookeeper", arguments.Zookeeper) viper.Set("zookeeper", arguments.Zookeeper)
} }
if !arguments.etcdTLS {
arguments.Etcd.TLS = nil
}
if arguments.etcd { if arguments.etcd {
viper.Set("etcd", arguments.Etcd) viper.Set("etcd", arguments.Etcd)
} }

View file

@ -109,6 +109,11 @@ Flags:
--consul.endpoint string Consul server endpoint (default "127.0.0.1:8500") --consul.endpoint string Consul server endpoint (default "127.0.0.1:8500")
--consul.filename string Override default configuration template. For advanced users :) --consul.filename string Override default configuration template. For advanced users :)
--consul.prefix string Prefix used for KV store (default "/traefik") --consul.prefix string Prefix used for KV store (default "/traefik")
--consul.tls Enable Consul TLS support
--consul.tls.ca string TLS CA
--consul.tls.cert string TLS cert
--consul.tls.insecureSkipVerify TLS insecure skip verify
--consul.tls.key string TLS key
--consul.watch Watch provider (default true) --consul.watch Watch provider (default true)
--consulCatalog Enable Consul catalog backend --consulCatalog Enable Consul catalog backend
--consulCatalog.domain string Default domain used --consulCatalog.domain string Default domain used
@ -129,6 +134,11 @@ Flags:
--etcd.endpoint string Etcd server endpoint (default "127.0.0.1:4001") --etcd.endpoint string Etcd server endpoint (default "127.0.0.1:4001")
--etcd.filename string Override default configuration template. For advanced users :) --etcd.filename string Override default configuration template. For advanced users :)
--etcd.prefix string Prefix used for KV store (default "/traefik") --etcd.prefix string Prefix used for KV store (default "/traefik")
--etcd.tls Enable Etcd TLS support
--etcd.tls.ca string TLS CA
--etcd.tls.cert string TLS cert
--etcd.tls.insecureSkipVerify TLS insecure skip verify
--etcd.tls.key string TLS key
--etcd.watch Watch provider (default true) --etcd.watch Watch provider (default true)
--file Enable File backend --file Enable File backend
--file.filename string Override default configuration template. For advanced users :) --file.filename string Override default configuration template. For advanced users :)
@ -142,7 +152,6 @@ Flags:
--marathon.networkInterface string Network interface used to call Marathon web services. Needed in case of multiple network interfaces (default "eth0") --marathon.networkInterface string Network interface used to call Marathon web services. Needed in case of multiple network interfaces (default "eth0")
--marathon.watch Watch provider (default true) --marathon.watch Watch provider (default true)
--maxIdleConnsPerHost int If non-zero, controls the maximum idle (keep-alive) to keep per-host. If zero, DefaultMaxIdleConnsPerHost is used --maxIdleConnsPerHost int If non-zero, controls the maximum idle (keep-alive) to keep per-host. If zero, DefaultMaxIdleConnsPerHost is used
-p, --port string Reverse proxy port (default ":80")
--providersThrottleDuration duration Backends throttle duration: minimum duration between 2 events from providers before applying a new configuration. It avoids unnecessary reloads if multiples events are sent in a short amount of time. (default 2s) --providersThrottleDuration duration Backends throttle duration: minimum duration between 2 events from providers before applying a new configuration. It avoids unnecessary reloads if multiples events are sent in a short amount of time. (default 2s)
--traefikLogsFile string Traefik logs file (default "log/traefik.log") --traefikLogsFile string Traefik logs file (default "log/traefik.log")
--web Enable Web backend --web Enable Web backend
@ -722,6 +731,16 @@ prefix = "traefik"
# Optional # Optional
# #
# filename = "consul.tmpl" # filename = "consul.tmpl"
# Enable consul TLS connection
#
# Optional
#
# [consul.tls]
# ca = "/etc/ssl/ca.crt"
# cert = "/etc/ssl/consul.crt"
# key = "/etc/ssl/consul.key"
# insecureskipverify = true
``` ```
The Keys-Values structure should look (using `prefix = "/traefik"`): The Keys-Values structure should look (using `prefix = "/traefik"`):
@ -803,6 +822,16 @@ Træfɪk can be configured to use Etcd as a backend configuration:
# Optional # Optional
# #
# filename = "etcd.tmpl" # filename = "etcd.tmpl"
# Enable etcd TLS connection
#
# Optional
#
# [etcd.tls]
# ca = "/etc/ssl/ca.crt"
# cert = "/etc/ssl/etcd.crt"
# key = "/etc/ssl/etcd.key"
# insecureskipverify = true
``` ```
The Keys-Values structure should look (using `prefix = "/traefik"`): The Keys-Values structure should look (using `prefix = "/traefik"`):

View file

@ -2,6 +2,10 @@
package provider package provider
import ( import (
"crypto/tls"
"crypto/x509"
"fmt"
"io/ioutil"
"strings" "strings"
"text/template" "text/template"
"time" "time"
@ -18,18 +22,55 @@ type Kv struct {
BaseProvider `mapstructure:",squash"` BaseProvider `mapstructure:",squash"`
Endpoint string Endpoint string
Prefix string Prefix string
TLS *KvTLS
storeType store.Backend storeType store.Backend
kvclient store.Store kvclient store.Store
} }
// KvTLS holds TLS specific configurations
type KvTLS struct {
CA string
Cert string
Key string
InsecureSkipVerify bool
}
func (provider *Kv) provide(configurationChan chan<- types.ConfigMessage) error { func (provider *Kv) provide(configurationChan chan<- types.ConfigMessage) error {
storeConfig := &store.Config{
ConnectionTimeout: 30 * time.Second,
Bucket: "traefik",
}
if provider.TLS != nil {
caPool := x509.NewCertPool()
if provider.TLS.CA != "" {
ca, err := ioutil.ReadFile(provider.TLS.CA)
if err != nil {
return fmt.Errorf("Failed to read CA. %s", err)
}
caPool.AppendCertsFromPEM(ca)
}
cert, err := tls.LoadX509KeyPair(provider.TLS.Cert, provider.TLS.Key)
if err != nil {
return fmt.Errorf("Failed to load keypair. %s", err)
}
storeConfig.TLS = &tls.Config{
Certificates: []tls.Certificate{cert},
RootCAs: caPool,
InsecureSkipVerify: provider.TLS.InsecureSkipVerify,
}
}
kv, err := libkv.NewStore( kv, err := libkv.NewStore(
provider.storeType, provider.storeType,
[]string{provider.Endpoint}, []string{provider.Endpoint},
&store.Config{ storeConfig,
ConnectionTimeout: 30 * time.Second,
Bucket: "traefik",
},
) )
if err != nil { if err != nil {
return err return err

View file

@ -281,6 +281,16 @@
# #
# filename = "consul.tmpl" # filename = "consul.tmpl"
# Enable consul TLS connection
#
# Optional
#
# [consul.tls]
# ca = "/etc/ssl/ca.crt"
# cert = "/etc/ssl/consul.crt"
# key = "/etc/ssl/consul.key"
# insecureskipverify = true
################################################################ ################################################################
# Etcd configuration backend # Etcd configuration backend
@ -316,6 +326,16 @@
# #
# filename = "etcd.tmpl" # filename = "etcd.tmpl"
# Enable etcd TLS connection
#
# Optional
#
# [etcd.tls]
# ca = "/etc/ssl/ca.crt"
# cert = "/etc/ssl/etcd.crt"
# key = "/etc/ssl/etcd.key"
# insecureskipverify = true
################################################################ ################################################################
# Zookeeper configuration backend # Zookeeper configuration backend