Skip to content
This repository has been archived by the owner on Feb 1, 2021. It is now read-only.

Commit

Permalink
Merge pull request #1254 from dhiltgen/tls_kv
Browse files Browse the repository at this point in the history
Add TLS support for libkv
  • Loading branch information
aluzzardi committed Oct 12, 2015
2 parents cf83f1d + 3661b6e commit 1d008a7
Show file tree
Hide file tree
Showing 17 changed files with 291 additions and 32 deletions.
4 changes: 4 additions & 0 deletions Godeps/Godeps.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

132 changes: 132 additions & 0 deletions Godeps/_workspace/src/github.com/docker/docker/pkg/tlsconfig/config.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions cli/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ var (
Name: "list",
ShortName: "l",
Usage: "List nodes in a cluster",
Flags: []cli.Flag{flTimeout},
Flags: []cli.Flag{flTimeout, flDiscoveryOpt},
Action: list,
},
{
Expand All @@ -28,14 +28,14 @@ var (
flTLS, flTLSCaCert, flTLSCert, flTLSKey, flTLSVerify,
flHeartBeat,
flEnableCors,
flCluster, flClusterOpt},
flCluster, flDiscoveryOpt, flClusterOpt},
Action: manage,
},
{
Name: "join",
ShortName: "j",
Usage: "join a docker cluster",
Flags: []cli.Flag{flJoinAdvertise, flHeartBeat, flTTL},
Flags: []cli.Flag{flJoinAdvertise, flHeartBeat, flTTL, flDiscoveryOpt},
Action: join,
},
}
Expand Down
2 changes: 1 addition & 1 deletion cli/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ func create(c *cli.Context) {
log.Fatalf("the `create` command takes no arguments. See '%s create --help'.", c.App.Name)
}
discovery := &token.Discovery{}
discovery.Initialize("", 0, 0)
discovery.Initialize("", 0, 0, nil)
token, err := discovery.CreateCluster()
if err != nil {
log.Fatal(err)
Expand Down
5 changes: 5 additions & 0 deletions cli/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,11 @@ var (
Usage: "cluster driver options",
Value: &cli.StringSlice{},
}
flDiscoveryOpt = cli.StringSliceFlag{
Name: "discovery-opt",
Usage: "discovery options",
Value: &cli.StringSlice{},
}

flLeaderElection = cli.BoolFlag{
Name: "replication",
Expand Down
3 changes: 2 additions & 1 deletion cli/join.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ func join(c *cli.Context) {
if ttl <= hb {
log.Fatal("--ttl must be strictly superior to the heartbeat value")
}
d, err := discovery.New(dflag, hb, ttl)

d, err := discovery.New(dflag, hb, ttl, getDiscoveryOpt(c))
if err != nil {
log.Fatal(err)
}
Expand Down
2 changes: 1 addition & 1 deletion cli/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ func list(c *cli.Context) {
log.Fatalf("invalid --timeout: %v", err)
}

d, err := discovery.New(dflag, timeout, 0)
d, err := discovery.New(dflag, timeout, 0, getDiscoveryOpt(c))
if err != nil {
log.Fatal(err)
}
Expand Down
20 changes: 17 additions & 3 deletions cli/manage.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"fmt"
"io/ioutil"
"path"
"strings"
"time"

log "github.com/Sirupsen/logrus"
Expand Down Expand Up @@ -97,7 +98,7 @@ func loadTLSConfig(ca, cert, key string, verify bool) (*tls.Config, error) {
}

// Initialize the discovery service.
func createDiscovery(uri string, c *cli.Context) discovery.Discovery {
func createDiscovery(uri string, c *cli.Context, discoveryOpt []string) discovery.Discovery {
hb, err := time.ParseDuration(c.String("heartbeat"))
if err != nil {
log.Fatalf("invalid --heartbeat: %v", err)
Expand All @@ -107,14 +108,27 @@ func createDiscovery(uri string, c *cli.Context) discovery.Discovery {
}

// Set up discovery.
discovery, err := discovery.New(uri, hb, 0)
discovery, err := discovery.New(uri, hb, 0, getDiscoveryOpt(c))
if err != nil {
log.Fatal(err)
}

return discovery
}

func getDiscoveryOpt(c *cli.Context) map[string]string {
// Process the store options
options := map[string]string{}
for _, option := range c.StringSlice("discovery-opt") {
if !strings.Contains(option, "=") {
log.Fatal("--discovery-opt must contain key=value strings")
}
kvpair := strings.SplitN(option, "=", 2)
options[kvpair[0]] = kvpair[1]
}
return options
}

func setupReplication(c *cli.Context, cluster cluster.Cluster, server *api.Server, discovery discovery.Discovery, addr string, leaderTTL time.Duration, tlsConfig *tls.Config) {
kvDiscovery, ok := discovery.(*kvdiscovery.Discovery)
if !ok {
Expand Down Expand Up @@ -222,7 +236,7 @@ func manage(c *cli.Context) {
if uri == "" {
log.Fatalf("discovery required to manage a cluster. See '%s manage --help'.", c.App.Name)
}
discovery := createDiscovery(uri, c)
discovery := createDiscovery(uri, c, c.StringSlice("discovery-opt"))
s, err := strategy.New(c.String("strategy"))
if err != nil {
log.Fatal(err)
Expand Down
8 changes: 4 additions & 4 deletions discovery/discovery.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ func (e Entries) Diff(cmp Entries) (Entries, Entries) {
// The Discovery interface is implemented by Discovery backends which
// manage swarm host entries.
type Discovery interface {
// Initialize the discovery with URIs, a heartbeat and a ttl.
Initialize(string, time.Duration, time.Duration) error
// Initialize the discovery with URIs, a heartbeat, a ttl and optional settings.
Initialize(string, time.Duration, time.Duration, map[string]string) error

// Watch the discovery for entry changes.
// Returns a channel that will receive changes or an error.
Expand Down Expand Up @@ -133,12 +133,12 @@ func parse(rawurl string) (string, string) {

// New returns a new Discovery given a URL, heartbeat and ttl settings.
// Returns an error if the URL scheme is not supported.
func New(rawurl string, heartbeat time.Duration, ttl time.Duration) (Discovery, error) {
func New(rawurl string, heartbeat time.Duration, ttl time.Duration, discoveryOpt map[string]string) (Discovery, error) {
scheme, uri := parse(rawurl)

if discovery, exists := discoveries[scheme]; exists {
log.WithFields(log.Fields{"name": scheme, "uri": uri}).Debug("Initializing discovery service")
err := discovery.Initialize(uri, heartbeat, ttl)
err := discovery.Initialize(uri, heartbeat, ttl, discoveryOpt)
return discovery, err
}

Expand Down
2 changes: 1 addition & 1 deletion discovery/file/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func Init() {
}

// Initialize is exported
func (s *Discovery) Initialize(path string, heartbeat time.Duration, ttl time.Duration) error {
func (s *Discovery) Initialize(path string, heartbeat time.Duration, ttl time.Duration, _ map[string]string) error {
s.path = path
s.heartbeat = heartbeat
return nil
Expand Down
8 changes: 4 additions & 4 deletions discovery/file/file_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ import (

func TestInitialize(t *testing.T) {
d := &Discovery{}
d.Initialize("/path/to/file", 1000, 0)
d.Initialize("/path/to/file", 1000, 0, nil)
assert.Equal(t, d.path, "/path/to/file")
}

func TestNew(t *testing.T) {
d, err := discovery.New("file:///path/to/file", 0, 0)
d, err := discovery.New("file:///path/to/file", 0, 0, nil)
assert.NoError(t, err)
assert.Equal(t, d.(*Discovery).path, "/path/to/file")
}
Expand Down Expand Up @@ -73,15 +73,15 @@ func TestWatch(t *testing.T) {

// Set up file discovery.
d := &Discovery{}
d.Initialize(tmp.Name(), 1000, 0)
d.Initialize(tmp.Name(), 1000, 0, nil)
stopCh := make(chan struct{})
ch, errCh := d.Watch(stopCh)

// Make sure it fires errors since the file doesn't exist.
assert.Error(t, <-errCh)
// We have to drain the error channel otherwise Watch will get stuck.
go func() {
for _ = range errCh {
for range errCh {
}
}()

Expand Down
30 changes: 28 additions & 2 deletions discovery/kv/kv.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"time"

log "github.com/Sirupsen/logrus"
"github.com/docker/docker/pkg/tlsconfig"
"github.com/docker/libkv"
"github.com/docker/libkv/store"
"github.com/docker/libkv/store/consul"
Expand Down Expand Up @@ -47,7 +48,7 @@ func Init() {
}

// Initialize is exported
func (s *Discovery) Initialize(uris string, heartbeat time.Duration, ttl time.Duration) error {
func (s *Discovery) Initialize(uris string, heartbeat time.Duration, ttl time.Duration, discoveryOpt map[string]string) error {
var (
parts = strings.SplitN(uris, "/", 2)
addrs = strings.Split(parts[0], ",")
Expand All @@ -63,9 +64,34 @@ func (s *Discovery) Initialize(uris string, heartbeat time.Duration, ttl time.Du
s.ttl = ttl
s.path = path.Join(s.prefix, discoveryPath)

var config *store.Config
if discoveryOpt["kv.cacertfile"] != "" && discoveryOpt["kv.certfile"] != "" && discoveryOpt["kv.keyfile"] != "" {
log.Debug("Initializing discovery with TLS")
tlsConfig, err := tlsconfig.Client(tlsconfig.Options{
CAFile: discoveryOpt["kv.cacertfile"],
CertFile: discoveryOpt["kv.certfile"],
KeyFile: discoveryOpt["kv.keyfile"],
})
if err != nil {
return err
}
config = &store.Config{
// Set ClientTLS to trigger https (bug in libkv/etcd)
ClientTLS: &store.ClientTLSConfig{
CACertFile: discoveryOpt["kv.cacertfile"],
CertFile: discoveryOpt["kv.certfile"],
KeyFile: discoveryOpt["kv.keyfile"],
},
// The actual TLS config that will be used
TLS: tlsConfig,
}
} else {
log.Debug("Initializing discovery without TLS")
}

// Creates a new store, will ignore options given
// if not supported by the chosen store
s.store, err = libkv.NewStore(s.backend, addrs, &store.Config{})
s.store, err = libkv.NewStore(s.backend, addrs, config)
return err
}

Expand Down
Loading

0 comments on commit 1d008a7

Please sign in to comment.