Browse Source

Merge pull request #4859 from xiang90/ctl_secure

etcdctlv3: support secure connection without key/cert
Xiang Li 9 years ago
parent
commit
05dc2dac70

+ 2 - 2
etcdctlv3/command/ep_health_command.go

@@ -41,11 +41,11 @@ func epHealthCommandFunc(cmd *cobra.Command, args []string) {
 		ExitWithError(ExitError, err)
 	}
 
-	cert, key, cacert := keyAndCertFromCmd(cmd)
+	sec := secureCfgFromCmd(cmd)
 	dt := dialTimeoutFromCmd(cmd)
 	cfgs := []*clientv3.Config{}
 	for _, ep := range endpoints {
-		cfg, err := newClientCfg([]string{ep}, dt, cert, key, cacert)
+		cfg, err := newClientCfg([]string{ep}, dt, sec)
 		if err != nil {
 			ExitWithError(ExitBadArgs, err)
 		}

+ 52 - 16
etcdctlv3/command/global.go

@@ -15,6 +15,7 @@
 package command
 
 import (
+	"crypto/tls"
 	"errors"
 	"io"
 	"io/ioutil"
@@ -28,6 +29,7 @@ import (
 // GlobalFlags are flags that defined globally
 // and are inherited to all sub-commands.
 type GlobalFlags struct {
+	Insecure    bool
 	Endpoints   []string
 	DialTimeout time.Duration
 
@@ -37,6 +39,14 @@ type GlobalFlags struct {
 	IsHex        bool
 }
 
+type secureCfg struct {
+	cert   string
+	key    string
+	cacert string
+
+	insecureTransport bool
+}
+
 var display printer = &simplePrinter{}
 
 func mustClientFromCmd(cmd *cobra.Command) *clientv3.Client {
@@ -45,13 +55,13 @@ func mustClientFromCmd(cmd *cobra.Command) *clientv3.Client {
 		ExitWithError(ExitError, err)
 	}
 	dialTimeout := dialTimeoutFromCmd(cmd)
-	cert, key, cacert := keyAndCertFromCmd(cmd)
+	sec := secureCfgFromCmd(cmd)
 
-	return mustClient(endpoints, dialTimeout, cert, key, cacert)
+	return mustClient(endpoints, dialTimeout, sec)
 }
 
-func mustClient(endpoints []string, dialTimeout time.Duration, cert, key, cacert string) *clientv3.Client {
-	cfg, err := newClientCfg(endpoints, dialTimeout, cert, key, cacert)
+func mustClient(endpoints []string, dialTimeout time.Duration, scfg *secureCfg) *clientv3.Client {
+	cfg, err := newClientCfg(endpoints, dialTimeout, scfg)
 	if err != nil {
 		ExitWithError(ExitBadArgs, err)
 	}
@@ -64,24 +74,23 @@ func mustClient(endpoints []string, dialTimeout time.Duration, cert, key, cacert
 	return client
 }
 
-func newClientCfg(endpoints []string, dialTimeout time.Duration, cert, key, cacert string) (*clientv3.Config, error) {
+func newClientCfg(endpoints []string, dialTimeout time.Duration, scfg *secureCfg) (*clientv3.Config, error) {
 	// set tls if any one tls option set
 	var cfgtls *transport.TLSInfo
-	tls := transport.TLSInfo{}
-	var file string
-	if cert != "" {
-		tls.CertFile = cert
-		cfgtls = &tls
+	tlsinfo := transport.TLSInfo{}
+	if scfg.cert != "" {
+		tlsinfo.CertFile = scfg.cert
+		cfgtls = &tlsinfo
 	}
 
-	if key != "" {
-		tls.KeyFile = key
-		cfgtls = &tls
+	if scfg.key != "" {
+		tlsinfo.KeyFile = scfg.key
+		cfgtls = &tlsinfo
 	}
 
-	if cacert != "" {
-		tls.CAFile = file
-		cfgtls = &tls
+	if scfg.cacert != "" {
+		tlsinfo.CAFile = scfg.cacert
+		cfgtls = &tlsinfo
 	}
 
 	cfg := &clientv3.Config{
@@ -95,6 +104,12 @@ func newClientCfg(endpoints []string, dialTimeout time.Duration, cert, key, cace
 		}
 		cfg.TLS = clientTLS
 	}
+	// if key/cert is not given but user wants secure connection, we
+	// should still setup an empty tls configuration for gRPC to setup
+	// secure connection.
+	if cfg.TLS == nil && !scfg.insecureTransport {
+		cfg.TLS = &tls.Config{}
+	}
 
 	return cfg, nil
 }
@@ -118,6 +133,27 @@ func dialTimeoutFromCmd(cmd *cobra.Command) time.Duration {
 	return dialTimeout
 }
 
+func secureCfgFromCmd(cmd *cobra.Command) *secureCfg {
+	cert, key, cacert := keyAndCertFromCmd(cmd)
+	insecureTr := insecureTransportFromCmd(cmd)
+
+	return &secureCfg{
+		cert:   cert,
+		key:    key,
+		cacert: cacert,
+
+		insecureTransport: insecureTr,
+	}
+}
+
+func insecureTransportFromCmd(cmd *cobra.Command) bool {
+	insecureTr, err := cmd.Flags().GetBool("insecure-transport")
+	if err != nil {
+		ExitWithError(ExitError, err)
+	}
+	return insecureTr
+}
+
 func keyAndCertFromCmd(cmd *cobra.Command) (cert, key, cacert string) {
 	var err error
 	if cert, err = cmd.Flags().GetString("cert"); err != nil {

+ 14 - 5
etcdctlv3/command/make_mirror_command.go

@@ -29,10 +29,11 @@ import (
 )
 
 var (
-	mmcert   string
-	mmkey    string
-	mmcacert string
-	mmprefix string
+	mminsecureTr bool
+	mmcert       string
+	mmkey        string
+	mmcacert     string
+	mmprefix     string
 )
 
 // NewMakeMirrorCommand returns the cobra command for "makeMirror".
@@ -48,6 +49,8 @@ func NewMakeMirrorCommand() *cobra.Command {
 	c.Flags().StringVar(&mmcert, "dest-cert", "", "identify secure client using this TLS certificate file for the destination cluster")
 	c.Flags().StringVar(&mmkey, "dest-key", "", "identify secure client using this TLS key file")
 	c.Flags().StringVar(&mmcacert, "dest-cacert", "", "verify certificates of TLS enabled secure servers using this CA bundle")
+	// TODO: secure by default when etcd enables secure gRPC by default.
+	c.Flags().BoolVar(&mminsecureTr, "dest-insecure-transport", true, "disable transport security for client connections")
 
 	return c
 }
@@ -58,8 +61,14 @@ func makeMirrorCommandFunc(cmd *cobra.Command, args []string) {
 	}
 
 	dialTimeout := dialTimeoutFromCmd(cmd)
+	sec := &secureCfg{
+		cert:              mmcert,
+		key:               mmkey,
+		cacert:            mmcacert,
+		insecureTransport: mminsecureTr,
+	}
 
-	dc := mustClient([]string{args[0]}, dialTimeout, mmcert, mmkey, mmcacert)
+	dc := mustClient([]string{args[0]}, dialTimeout, sec)
 	c := mustClientFromCmd(cmd)
 
 	err := makeMirror(context.TODO(), c, dc)

+ 2 - 0
etcdctlv3/main.go

@@ -51,6 +51,8 @@ func init() {
 
 	rootCmd.PersistentFlags().DurationVar(&globalFlags.DialTimeout, "dial-timeout", defaultDialTimeout, "dial timeout for client connections")
 
+	// TODO: secure by default when etcd enables secure gRPC by default.
+	rootCmd.PersistentFlags().BoolVar(&globalFlags.Insecure, "insecure-transport", true, "disable transport security for client connections")
 	rootCmd.PersistentFlags().StringVar(&globalFlags.TLS.CertFile, "cert", "", "identify secure client using this TLS certificate file")
 	rootCmd.PersistentFlags().StringVar(&globalFlags.TLS.KeyFile, "key", "", "identify secure client using this TLS key file")
 	rootCmd.PersistentFlags().StringVar(&globalFlags.TLS.CAFile, "cacert", "", "verify certificates of TLS-enabled secure servers using this CA bundle")