Merge pull request #4859 from xiang90/ctl_secure

etcdctlv3: support secure connection without key/cert
This commit is contained in:
Xiang Li 2016-03-24 16:47:23 -07:00
commit 05dc2dac70
4 changed files with 70 additions and 23 deletions

View File

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

View File

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

View File

@ -29,6 +29,7 @@ import (
) )
var ( var (
mminsecureTr bool
mmcert string mmcert string
mmkey string mmkey string
mmcacert string mmcacert string
@ -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(&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(&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") 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 return c
} }
@ -58,8 +61,14 @@ func makeMirrorCommandFunc(cmd *cobra.Command, args []string) {
} }
dialTimeout := dialTimeoutFromCmd(cmd) 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) c := mustClientFromCmd(cmd)
err := makeMirror(context.TODO(), c, dc) err := makeMirror(context.TODO(), c, dc)

View File

@ -51,6 +51,8 @@ func init() {
rootCmd.PersistentFlags().DurationVar(&globalFlags.DialTimeout, "dial-timeout", defaultDialTimeout, "dial timeout for client connections") 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.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.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") rootCmd.PersistentFlags().StringVar(&globalFlags.TLS.CAFile, "cacert", "", "verify certificates of TLS-enabled secure servers using this CA bundle")