Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

etcdctl: add --password flag to the subcommand user add #9730

Merged
merged 1 commit into from
May 29, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion Documentation/op-guide/authentication.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down Expand Up @@ -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
Expand Down
28 changes: 19 additions & 9 deletions etcdctl/ctlv3/command/global.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ type GlobalFlags struct {
OutputFormat string
IsHex bool

User string
User string
Password string

Debug bool
}
Expand Down Expand Up @@ -341,23 +342,32 @@ 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
}

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
Expand Down
29 changes: 18 additions & 11 deletions etcdctl/ctlv3/command/user_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ func NewUserCommand() *cobra.Command {

var (
passwordInteractive bool
passwordFromFlag string
)

func newUserAddCommand() *cobra.Command {
Expand All @@ -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
}
Expand Down Expand Up @@ -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."))
}
}
}

Expand Down
1 change: 1 addition & 0 deletions etcdctl/ctlv3/ctl.go
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down