Browse Source

Merge pull request #5252 from xiang90/client-tls

*: support auto tls on client side
Xiang Li 9 years ago
parent
commit
b7639b00e0
6 changed files with 66 additions and 24 deletions
  1. 10 0
      Documentation/op-guide/configuration.md
  2. 14 12
      e2e/ctl_v3_kv_test.go
  3. 6 1
      e2e/ctl_v3_test.go
  4. 18 9
      e2e/etcd_test.go
  5. 2 1
      etcdmain/config.go
  6. 16 1
      etcdmain/etcd.go

+ 10 - 0
Documentation/op-guide/configuration.md

@@ -201,6 +201,11 @@ The security flags help to [build a secure etcd cluster][security].
 + default: none
 + default: none
 + env variable: ETCD_TRUSTED_CA_FILE
 + env variable: ETCD_TRUSTED_CA_FILE
 
 
+### --auto-tls
++ Client TLS using generated certificates
++ default: false
++ env variable: ETCD_AUTO_TLS
+
 ### --peer-ca-file [DEPRECATED]
 ### --peer-ca-file [DEPRECATED]
 + Path to the peer server TLS CA file. `--peer-ca-file ca.crt` could be replaced by `--peer-trusted-ca-file ca.crt --peer-client-cert-auth` and etcd will perform the same.
 + Path to the peer server TLS CA file. `--peer-ca-file ca.crt` could be replaced by `--peer-trusted-ca-file ca.crt --peer-client-cert-auth` and etcd will perform the same.
 + default: none
 + default: none
@@ -226,6 +231,11 @@ The security flags help to [build a secure etcd cluster][security].
 + default: none
 + default: none
 + env variable: ETCD_PEER_TRUSTED_CA_FILE
 + env variable: ETCD_PEER_TRUSTED_CA_FILE
 
 
+### --peer-auto-tls
++ Peer TLS using generated certificates
++ default: false
++ env variable: ETCD_PEER_AUTO_TLS
+
 ## Logging Flags
 ## Logging Flags
 
 
 ### --debug
 ### --debug

+ 14 - 12
e2e/ctl_v3_kv_test.go

@@ -19,18 +19,20 @@ import (
 	"testing"
 	"testing"
 )
 )
 
 
-func TestCtlV3Put(t *testing.T)          { testCtl(t, putTest) }
-func TestCtlV3PutNoTLS(t *testing.T)     { testCtl(t, putTest, withCfg(configNoTLS)) }
-func TestCtlV3PutClientTLS(t *testing.T) { testCtl(t, putTest, withCfg(configClientTLS)) }
-func TestCtlV3PutPeerTLS(t *testing.T)   { testCtl(t, putTest, withCfg(configPeerTLS)) }
-func TestCtlV3PutTimeout(t *testing.T)   { testCtl(t, putTest, withDialTimeout(0)) }
-
-func TestCtlV3Get(t *testing.T)          { testCtl(t, getTest) }
-func TestCtlV3GetNoTLS(t *testing.T)     { testCtl(t, getTest, withCfg(configNoTLS)) }
-func TestCtlV3GetClientTLS(t *testing.T) { testCtl(t, getTest, withCfg(configClientTLS)) }
-func TestCtlV3GetPeerTLS(t *testing.T)   { testCtl(t, getTest, withCfg(configPeerTLS)) }
-func TestCtlV3GetTimeout(t *testing.T)   { testCtl(t, getTest, withDialTimeout(0)) }
-func TestCtlV3GetQuorum(t *testing.T)    { testCtl(t, getTest, withQuorum()) }
+func TestCtlV3Put(t *testing.T)              { testCtl(t, putTest) }
+func TestCtlV3PutNoTLS(t *testing.T)         { testCtl(t, putTest, withCfg(configNoTLS)) }
+func TestCtlV3PutClientTLS(t *testing.T)     { testCtl(t, putTest, withCfg(configClientTLS)) }
+func TestCtlV3PutClientAutoTLS(t *testing.T) { testCtl(t, putTest, withCfg(configClientAutoTLS)) }
+func TestCtlV3PutPeerTLS(t *testing.T)       { testCtl(t, putTest, withCfg(configPeerTLS)) }
+func TestCtlV3PutTimeout(t *testing.T)       { testCtl(t, putTest, withDialTimeout(0)) }
+
+func TestCtlV3Get(t *testing.T)              { testCtl(t, getTest) }
+func TestCtlV3GetNoTLS(t *testing.T)         { testCtl(t, getTest, withCfg(configNoTLS)) }
+func TestCtlV3GetClientTLS(t *testing.T)     { testCtl(t, getTest, withCfg(configClientTLS)) }
+func TestCtlV3GetClientAutoTLS(t *testing.T) { testCtl(t, getTest, withCfg(configClientAutoTLS)) }
+func TestCtlV3GetPeerTLS(t *testing.T)       { testCtl(t, getTest, withCfg(configPeerTLS)) }
+func TestCtlV3GetTimeout(t *testing.T)       { testCtl(t, getTest, withDialTimeout(0)) }
+func TestCtlV3GetQuorum(t *testing.T)        { testCtl(t, getTest, withQuorum()) }
 
 
 func TestCtlV3GetFormat(t *testing.T) { testCtl(t, getFormatTest) }
 func TestCtlV3GetFormat(t *testing.T) { testCtl(t, getFormatTest) }
 func TestCtlV3GetRev(t *testing.T)    { testCtl(t, getRevTest) }
 func TestCtlV3GetRev(t *testing.T)    { testCtl(t, getRevTest) }

+ 6 - 1
e2e/ctl_v3_test.go

@@ -140,8 +140,13 @@ func (cx *ctlCtx) PrefixArgs() []string {
 	}
 	}
 	cmdArgs := []string{"../bin/etcdctl", "--endpoints", endpoints, "--dial-timeout", cx.dialTimeout.String()}
 	cmdArgs := []string{"../bin/etcdctl", "--endpoints", endpoints, "--dial-timeout", cx.dialTimeout.String()}
 	if cx.epc.cfg.clientTLS == clientTLS {
 	if cx.epc.cfg.clientTLS == clientTLS {
-		cmdArgs = append(cmdArgs, "--cacert", caPath, "--cert", certPath, "--key", privateKeyPath)
+		if cx.epc.cfg.isClientAuthTLS {
+			cmdArgs = append(cmdArgs, "--insecure-transport=false", "--insecure-skip-tls-verify")
+		} else {
+			cmdArgs = append(cmdArgs, "--cacert", caPath, "--cert", certPath, "--key", privateKeyPath)
+		}
 	}
 	}
+
 	return cmdArgs
 	return cmdArgs
 }
 }
 
 

+ 18 - 9
e2e/etcd_test.go

@@ -44,7 +44,6 @@ var (
 	configNoTLS = etcdProcessClusterConfig{
 	configNoTLS = etcdProcessClusterConfig{
 		clusterSize:  3,
 		clusterSize:  3,
 		proxySize:    0,
 		proxySize:    0,
-		isPeerTLS:    false,
 		initialToken: "new",
 		initialToken: "new",
 	}
 	}
 	configAutoTLS = etcdProcessClusterConfig{
 	configAutoTLS = etcdProcessClusterConfig{
@@ -64,16 +63,21 @@ var (
 		clusterSize:  3,
 		clusterSize:  3,
 		proxySize:    0,
 		proxySize:    0,
 		clientTLS:    clientTLS,
 		clientTLS:    clientTLS,
-		isPeerTLS:    false,
 		initialToken: "new",
 		initialToken: "new",
 	}
 	}
 	configClientBoth = etcdProcessClusterConfig{
 	configClientBoth = etcdProcessClusterConfig{
 		clusterSize:  1,
 		clusterSize:  1,
 		proxySize:    0,
 		proxySize:    0,
 		clientTLS:    clientTLSAndNonTLS,
 		clientTLS:    clientTLSAndNonTLS,
-		isPeerTLS:    false,
 		initialToken: "new",
 		initialToken: "new",
 	}
 	}
+	configClientAutoTLS = etcdProcessClusterConfig{
+		clusterSize:     1,
+		proxySize:       0,
+		isClientAuthTLS: true,
+		clientTLS:       clientTLS,
+		initialToken:    "new",
+	}
 	configPeerTLS = etcdProcessClusterConfig{
 	configPeerTLS = etcdProcessClusterConfig{
 		clusterSize:  3,
 		clusterSize:  3,
 		proxySize:    0,
 		proxySize:    0,
@@ -83,7 +87,6 @@ var (
 	configWithProxy = etcdProcessClusterConfig{
 	configWithProxy = etcdProcessClusterConfig{
 		clusterSize:  3,
 		clusterSize:  3,
 		proxySize:    1,
 		proxySize:    1,
-		isPeerTLS:    false,
 		initialToken: "new",
 		initialToken: "new",
 	}
 	}
 	configWithProxyTLS = etcdProcessClusterConfig{
 	configWithProxyTLS = etcdProcessClusterConfig{
@@ -135,6 +138,7 @@ type etcdProcessClusterConfig struct {
 	clientTLS         clientConnType
 	clientTLS         clientConnType
 	isPeerTLS         bool
 	isPeerTLS         bool
 	isPeerAutoTLS     bool
 	isPeerAutoTLS     bool
+	isClientAuthTLS   bool
 	initialToken      string
 	initialToken      string
 	quotaBackendBytes int64
 	quotaBackendBytes int64
 }
 }
@@ -292,13 +296,18 @@ func (cfg *etcdProcessClusterConfig) etcdProcessConfigs() []*etcdProcessConfig {
 
 
 func (cfg *etcdProcessClusterConfig) tlsArgs() (args []string) {
 func (cfg *etcdProcessClusterConfig) tlsArgs() (args []string) {
 	if cfg.clientTLS != clientNonTLS {
 	if cfg.clientTLS != clientNonTLS {
-		tlsClientArgs := []string{
-			"--cert-file", certPath,
-			"--key-file", privateKeyPath,
-			"--ca-file", caPath,
+		if cfg.isClientAuthTLS {
+			args = append(args, "--auto-tls=true")
+		} else {
+			tlsClientArgs := []string{
+				"--cert-file", certPath,
+				"--key-file", privateKeyPath,
+				"--ca-file", caPath,
+			}
+			args = append(args, tlsClientArgs...)
 		}
 		}
-		args = append(args, tlsClientArgs...)
 	}
 	}
+
 	if cfg.isPeerTLS {
 	if cfg.isPeerTLS {
 		if cfg.isPeerAutoTLS {
 		if cfg.isPeerAutoTLS {
 			args = append(args, "--peer-auto-tls=true")
 			args = append(args, "--peer-auto-tls=true")

+ 2 - 1
etcdmain/config.go

@@ -112,7 +112,7 @@ type config struct {
 
 
 	// security
 	// security
 	clientTLSInfo, peerTLSInfo transport.TLSInfo
 	clientTLSInfo, peerTLSInfo transport.TLSInfo
-	peerAutoTLS                bool
+	clientAutoTLS, peerAutoTLS bool
 
 
 	// logging
 	// logging
 	debug        bool
 	debug        bool
@@ -207,6 +207,7 @@ func NewConfig() *config {
 	fs.StringVar(&cfg.clientTLSInfo.KeyFile, "key-file", "", "Path to the client server TLS key file.")
 	fs.StringVar(&cfg.clientTLSInfo.KeyFile, "key-file", "", "Path to the client server TLS key file.")
 	fs.BoolVar(&cfg.clientTLSInfo.ClientCertAuth, "client-cert-auth", false, "Enable client cert authentication.")
 	fs.BoolVar(&cfg.clientTLSInfo.ClientCertAuth, "client-cert-auth", false, "Enable client cert authentication.")
 	fs.StringVar(&cfg.clientTLSInfo.TrustedCAFile, "trusted-ca-file", "", "Path to the client server TLS trusted CA key file.")
 	fs.StringVar(&cfg.clientTLSInfo.TrustedCAFile, "trusted-ca-file", "", "Path to the client server TLS trusted CA key file.")
+	fs.BoolVar(&cfg.clientAutoTLS, "auto-tls", false, "Client TLS using generated certificates")
 	fs.StringVar(&cfg.peerTLSInfo.CAFile, "peer-ca-file", "", "DEPRECATED: Path to the peer server TLS CA file.")
 	fs.StringVar(&cfg.peerTLSInfo.CAFile, "peer-ca-file", "", "DEPRECATED: Path to the peer server TLS CA file.")
 	fs.StringVar(&cfg.peerTLSInfo.CertFile, "peer-cert-file", "", "Path to the peer server TLS cert file.")
 	fs.StringVar(&cfg.peerTLSInfo.CertFile, "peer-cert-file", "", "Path to the peer server TLS cert file.")
 	fs.StringVar(&cfg.peerTLSInfo.KeyFile, "peer-key-file", "", "Path to the peer server TLS key file.")
 	fs.StringVar(&cfg.peerTLSInfo.KeyFile, "peer-key-file", "", "Path to the peer server TLS key file.")

+ 16 - 1
etcdmain/etcd.go

@@ -207,7 +207,7 @@ func startEtcd(cfg *config) (<-chan struct{}, error) {
 		for _, u := range cfg.lpurls {
 		for _, u := range cfg.lpurls {
 			phosts = append(phosts, u.Host)
 			phosts = append(phosts, u.Host)
 		}
 		}
-		cfg.peerTLSInfo, err = transport.SelfCert(cfg.dir, phosts)
+		cfg.peerTLSInfo, err = transport.SelfCert(path.Join(cfg.dir, "fixtures/peer"), phosts)
 		if err != nil {
 		if err != nil {
 			plog.Fatalf("could not get certs (%v)", err)
 			plog.Fatalf("could not get certs (%v)", err)
 		}
 		}
@@ -218,6 +218,7 @@ func startEtcd(cfg *config) (<-chan struct{}, error) {
 	if !cfg.peerTLSInfo.Empty() {
 	if !cfg.peerTLSInfo.Empty() {
 		plog.Infof("peerTLS: %s", cfg.peerTLSInfo)
 		plog.Infof("peerTLS: %s", cfg.peerTLSInfo)
 	}
 	}
+
 	var plns []net.Listener
 	var plns []net.Listener
 	for _, u := range cfg.lpurls {
 	for _, u := range cfg.lpurls {
 		if u.Scheme == "http" {
 		if u.Scheme == "http" {
@@ -256,6 +257,19 @@ func startEtcd(cfg *config) (<-chan struct{}, error) {
 		plns = append(plns, l)
 		plns = append(plns, l)
 	}
 	}
 
 
+	if cfg.clientAutoTLS && cfg.clientTLSInfo.Empty() {
+		var chosts []string
+		for _, u := range cfg.lcurls {
+			chosts = append(chosts, u.Host)
+		}
+		cfg.clientTLSInfo, err = transport.SelfCert(path.Join(cfg.dir, "fixtures/client"), chosts)
+		if err != nil {
+			plog.Fatalf("could not get certs (%v)", err)
+		}
+	} else if cfg.clientAutoTLS {
+		plog.Warningf("ignoring client auto TLS since certs given")
+	}
+
 	var ctlscfg *tls.Config
 	var ctlscfg *tls.Config
 	if !cfg.clientTLSInfo.Empty() {
 	if !cfg.clientTLSInfo.Empty() {
 		plog.Infof("clientTLS: %s", cfg.clientTLSInfo)
 		plog.Infof("clientTLS: %s", cfg.clientTLSInfo)
@@ -264,6 +278,7 @@ func startEtcd(cfg *config) (<-chan struct{}, error) {
 			return nil, err
 			return nil, err
 		}
 		}
 	}
 	}
+
 	sctxs := make(map[string]*serveCtx)
 	sctxs := make(map[string]*serveCtx)
 	for _, u := range cfg.lcurls {
 	for _, u := range cfg.lcurls {
 		if u.Scheme == "http" {
 		if u.Scheme == "http" {