etcdctlv3: support secure connection without key/cert

release-3.0
Xiang Li 2016-03-24 16:29:33 -07:00
parent 7d2545c72e
commit 0865688c27
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)
}
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)
}

View File

@ -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 {

View File

@ -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)

View File

@ -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")