embed: support custom cipher suites

Signed-off-by: Gyuho Lee <gyuhox@gmail.com>
This commit is contained in:
Gyuho Lee 2018-06-04 08:45:16 -07:00
parent 917d40cd4c
commit 3125c0c3e8
2 changed files with 64 additions and 19 deletions

View File

@ -32,6 +32,7 @@ import (
"github.com/coreos/etcd/pkg/flags" "github.com/coreos/etcd/pkg/flags"
"github.com/coreos/etcd/pkg/netutil" "github.com/coreos/etcd/pkg/netutil"
"github.com/coreos/etcd/pkg/srv" "github.com/coreos/etcd/pkg/srv"
"github.com/coreos/etcd/pkg/tlsutil"
"github.com/coreos/etcd/pkg/transport" "github.com/coreos/etcd/pkg/transport"
"github.com/coreos/etcd/pkg/types" "github.com/coreos/etcd/pkg/types"
@ -175,6 +176,11 @@ type Config struct {
PeerTLSInfo transport.TLSInfo PeerTLSInfo transport.TLSInfo
PeerAutoTLS bool PeerAutoTLS bool
// CipherSuites is a list of supported TLS cipher suites between
// client/server and peers. If empty, Go auto-populates the list.
// Note that cipher suites are prioritized in the given order.
CipherSuites []string `json:"cipher-suites"`
ClusterState string `json:"initial-cluster-state"` ClusterState string `json:"initial-cluster-state"`
DNSCluster string `json:"discovery-srv"` DNSCluster string `json:"discovery-srv"`
DNSClusterServiceName string `json:"discovery-srv-name"` DNSClusterServiceName string `json:"discovery-srv-name"`
@ -510,6 +516,24 @@ func (cfg *configYAML) configFromFile(path string) error {
return cfg.Validate() return cfg.Validate()
} }
func updateCipherSuites(tls *transport.TLSInfo, ss []string) error {
if len(tls.CipherSuites) > 0 && len(ss) > 0 {
return fmt.Errorf("TLSInfo.CipherSuites is already specified (given %v)", ss)
}
if len(ss) > 0 {
cs := make([]uint16, len(ss))
for i, s := range ss {
var ok bool
cs[i], ok = tlsutil.GetCipherSuite(s)
if !ok {
return fmt.Errorf("unexpected TLS cipher suite %q", s)
}
}
tls.CipherSuites = cs
}
return nil
}
// Validate ensures that '*embed.Config' fields are properly configured. // Validate ensures that '*embed.Config' fields are properly configured.
func (cfg *Config) Validate() error { func (cfg *Config) Validate() error {
if err := cfg.setupLogging(); err != nil { if err := cfg.setupLogging(); err != nil {
@ -703,40 +727,50 @@ func (cfg Config) defaultClientHost() bool {
} }
func (cfg *Config) ClientSelfCert() (err error) { func (cfg *Config) ClientSelfCert() (err error) {
if cfg.ClientAutoTLS && cfg.ClientTLSInfo.Empty() { if !cfg.ClientAutoTLS {
chosts := make([]string, len(cfg.LCUrls)) return nil
for i, u := range cfg.LCUrls {
chosts[i] = u.Host
} }
cfg.ClientTLSInfo, err = transport.SelfCert(cfg.logger, filepath.Join(cfg.Dir, "fixtures", "client"), chosts) if !cfg.ClientTLSInfo.Empty() {
return err
} else if cfg.ClientAutoTLS {
if cfg.logger != nil { if cfg.logger != nil {
cfg.logger.Warn("ignoring client auto TLS since certs given") cfg.logger.Warn("ignoring client auto TLS since certs given")
} else { } else {
plog.Warningf("ignoring client auto TLS since certs given") plog.Warningf("ignoring client auto TLS since certs given")
} }
}
return nil return nil
} }
chosts := make([]string, len(cfg.LCUrls))
for i, u := range cfg.LCUrls {
chosts[i] = u.Host
}
cfg.ClientTLSInfo, err = transport.SelfCert(cfg.logger, filepath.Join(cfg.Dir, "fixtures", "client"), chosts)
if err != nil {
return err
}
return updateCipherSuites(&cfg.ClientTLSInfo, cfg.CipherSuites)
}
func (cfg *Config) PeerSelfCert() (err error) { func (cfg *Config) PeerSelfCert() (err error) {
if cfg.PeerAutoTLS && cfg.PeerTLSInfo.Empty() { if !cfg.PeerAutoTLS {
phosts := make([]string, len(cfg.LPUrls)) return nil
for i, u := range cfg.LPUrls {
phosts[i] = u.Host
} }
cfg.PeerTLSInfo, err = transport.SelfCert(cfg.logger, filepath.Join(cfg.Dir, "fixtures", "peer"), phosts) if !cfg.PeerTLSInfo.Empty() {
return err
} else if cfg.PeerAutoTLS {
if cfg.logger != nil { if cfg.logger != nil {
cfg.logger.Warn("ignoring peer auto TLS since certs given") cfg.logger.Warn("ignoring peer auto TLS since certs given")
} else { } else {
plog.Warningf("ignoring peer auto TLS since certs given") plog.Warningf("ignoring peer auto TLS since certs given")
} }
}
return nil return nil
} }
phosts := make([]string, len(cfg.LPUrls))
for i, u := range cfg.LPUrls {
phosts[i] = u.Host
}
cfg.PeerTLSInfo, err = transport.SelfCert(cfg.logger, filepath.Join(cfg.Dir, "fixtures", "peer"), phosts)
if err != nil {
return err
}
return updateCipherSuites(&cfg.PeerTLSInfo, cfg.CipherSuites)
}
// UpdateDefaultClusterFromName updates cluster advertise URLs with, if available, default host, // UpdateDefaultClusterFromName updates cluster advertise URLs with, if available, default host,
// if advertise URLs are default values(localhost:2379,2380) AND if listen URL is 0.0.0.0. // if advertise URLs are default values(localhost:2379,2380) AND if listen URL is 0.0.0.0.

View File

@ -375,6 +375,9 @@ func stopServers(ctx context.Context, ss *servers) {
func (e *Etcd) Err() <-chan error { return e.errc } func (e *Etcd) Err() <-chan error { return e.errc }
func configurePeerListeners(cfg *Config) (peers []*peerListener, err error) { func configurePeerListeners(cfg *Config) (peers []*peerListener, err error) {
if err = updateCipherSuites(&cfg.PeerTLSInfo, cfg.CipherSuites); err != nil {
return nil, err
}
if err = cfg.PeerSelfCert(); err != nil { if err = cfg.PeerSelfCert(); err != nil {
if cfg.logger != nil { if cfg.logger != nil {
cfg.logger.Fatal("failed to get peer self-signed certs", zap.Error(err)) cfg.logger.Fatal("failed to get peer self-signed certs", zap.Error(err))
@ -384,7 +387,11 @@ func configurePeerListeners(cfg *Config) (peers []*peerListener, err error) {
} }
if !cfg.PeerTLSInfo.Empty() { if !cfg.PeerTLSInfo.Empty() {
if cfg.logger != nil { if cfg.logger != nil {
cfg.logger.Info("starting with peer TLS", zap.String("tls-info", fmt.Sprintf("%+v", cfg.PeerTLSInfo))) cfg.logger.Info(
"starting with peer TLS",
zap.String("tls-info", fmt.Sprintf("%+v", cfg.PeerTLSInfo)),
zap.Strings("cipher-suites", cfg.CipherSuites),
)
} else { } else {
plog.Infof("peerTLS: %s", cfg.PeerTLSInfo) plog.Infof("peerTLS: %s", cfg.PeerTLSInfo)
} }
@ -505,6 +512,9 @@ func (e *Etcd) servePeers() (err error) {
} }
func configureClientListeners(cfg *Config) (sctxs map[string]*serveCtx, err error) { func configureClientListeners(cfg *Config) (sctxs map[string]*serveCtx, err error) {
if err = updateCipherSuites(&cfg.ClientTLSInfo, cfg.CipherSuites); err != nil {
return nil, err
}
if err = cfg.ClientSelfCert(); err != nil { if err = cfg.ClientSelfCert(); err != nil {
if cfg.logger != nil { if cfg.logger != nil {
cfg.logger.Fatal("failed to get client self-signed certs", zap.Error(err)) cfg.logger.Fatal("failed to get client self-signed certs", zap.Error(err))
@ -623,6 +633,7 @@ func (e *Etcd) serveClients() (err error) {
e.cfg.logger.Info( e.cfg.logger.Info(
"starting with client TLS", "starting with client TLS",
zap.String("tls-info", fmt.Sprintf("%+v", e.cfg.ClientTLSInfo)), zap.String("tls-info", fmt.Sprintf("%+v", e.cfg.ClientTLSInfo)),
zap.Strings("cipher-suites", e.cfg.CipherSuites),
) )
} else { } else {
plog.Infof("ClientTLS: %s", e.cfg.ClientTLSInfo) plog.Infof("ClientTLS: %s", e.cfg.ClientTLSInfo)