Browse Source

Merge pull request #9730 from mitake/user-w-colon

etcdctl: add --password flag to the subcommand user add
Gyuho Lee 7 years ago
parent
commit
dbb37f98fd

+ 8 - 1
Documentation/op-guide/authentication.md

@@ -32,7 +32,7 @@ Creating a user is as easy as
 $ etcdctl user add myusername
 ```
 
-Creating a new user will prompt for a new password. The password can be supplied from standard input when an option `--interactive=false` is given.
+Creating a new user will prompt for a new password. The password can be supplied from standard input when an option `--interactive=false` is given. `--new-user-password` can also be used for supplying the password.
 
 Roles can be granted and revoked for a user with:
 
@@ -157,6 +157,13 @@ The password can be taken from a prompt:
 $ etcdctl --user user get foo
 ```
 
+The password can also be taken from a command line flag `--password`:
+
+```
+$ etcdctl --user user --password password get foo
+```
+
+
 Otherwise, all `etcdctl` commands remain the same. Users and roles can still be created and modified, but require authentication by a user with the root role.
 
 ## Using TLS Common Name

+ 19 - 9
etcdctl/ctlv3/command/global.go

@@ -53,7 +53,8 @@ type GlobalFlags struct {
 	OutputFormat string
 	IsHex        bool
 
-	User string
+	User     string
+	Password string
 
 	Debug bool
 }
@@ -341,6 +342,10 @@ func authCfgFromCmd(cmd *cobra.Command) *authCfg {
 	if err != nil {
 		ExitWithError(ExitBadArgs, err)
 	}
+	passwordFlag, err := cmd.Flags().GetString("password")
+	if err != nil {
+		ExitWithError(ExitBadArgs, err)
+	}
 
 	if userFlag == "" {
 		return nil
@@ -348,16 +353,21 @@ func authCfgFromCmd(cmd *cobra.Command) *authCfg {
 
 	var cfg authCfg
 
-	splitted := strings.SplitN(userFlag, ":", 2)
-	if len(splitted) < 2 {
-		cfg.username = userFlag
-		cfg.password, err = speakeasy.Ask("Password: ")
-		if err != nil {
-			ExitWithError(ExitError, err)
+	if passwordFlag == "" {
+		splitted := strings.SplitN(userFlag, ":", 2)
+		if len(splitted) < 2 {
+			cfg.username = userFlag
+			cfg.password, err = speakeasy.Ask("Password: ")
+			if err != nil {
+				ExitWithError(ExitError, err)
+			}
+		} else {
+			cfg.username = splitted[0]
+			cfg.password = splitted[1]
 		}
 	} else {
-		cfg.username = splitted[0]
-		cfg.password = splitted[1]
+		cfg.username = userFlag
+		cfg.password = passwordFlag
 	}
 
 	return &cfg

+ 18 - 11
etcdctl/ctlv3/command/user_command.go

@@ -47,6 +47,7 @@ func NewUserCommand() *cobra.Command {
 
 var (
 	passwordInteractive bool
+	passwordFromFlag    string
 )
 
 func newUserAddCommand() *cobra.Command {
@@ -57,6 +58,7 @@ func newUserAddCommand() *cobra.Command {
 	}
 
 	cmd.Flags().BoolVar(&passwordInteractive, "interactive", true, "Read password from stdin instead of interactive terminal")
+	cmd.Flags().StringVar(&passwordFromFlag, "new-user-password", "", "Supply password from the command line flag")
 
 	return &cmd
 }
@@ -126,19 +128,24 @@ func userAddCommandFunc(cmd *cobra.Command, args []string) {
 	var password string
 	var user string
 
-	splitted := strings.SplitN(args[0], ":", 2)
-	if len(splitted) < 2 {
+	if passwordFromFlag != "" {
 		user = args[0]
-		if !passwordInteractive {
-			fmt.Scanf("%s", &password)
-		} else {
-			password = readPasswordInteractive(args[0])
-		}
+		password = passwordFromFlag
 	} else {
-		user = splitted[0]
-		password = splitted[1]
-		if len(user) == 0 {
-			ExitWithError(ExitBadArgs, fmt.Errorf("empty user name is not allowed."))
+		splitted := strings.SplitN(args[0], ":", 2)
+		if len(splitted) < 2 {
+			user = args[0]
+			if !passwordInteractive {
+				fmt.Scanf("%s", &password)
+			} else {
+				password = readPasswordInteractive(args[0])
+			}
+		} else {
+			user = splitted[0]
+			password = splitted[1]
+			if len(user) == 0 {
+				ExitWithError(ExitBadArgs, fmt.Errorf("empty user name is not allowed."))
+			}
 		}
 	}
 

+ 1 - 0
etcdctl/ctlv3/ctl.go

@@ -65,6 +65,7 @@ func init() {
 	rootCmd.PersistentFlags().StringVar(&globalFlags.TLS.KeyFile, "key", "", "identify secure client using this TLS key file")
 	rootCmd.PersistentFlags().StringVar(&globalFlags.TLS.TrustedCAFile, "cacert", "", "verify certificates of TLS-enabled secure servers using this CA bundle")
 	rootCmd.PersistentFlags().StringVar(&globalFlags.User, "user", "", "username[:password] for authentication (prompt if password is not supplied)")
+	rootCmd.PersistentFlags().StringVar(&globalFlags.Password, "password", "", "password for authentication (if this option is used, --user option shouldn't include password)")
 	rootCmd.PersistentFlags().StringVarP(&globalFlags.TLS.ServerName, "discovery-srv", "d", "", "domain name to query for SRV records describing cluster endpoints")
 
 	rootCmd.AddCommand(