Add parsepath logic to password in various places (#2325)

* Add parsepath logic to password in various places:

* Account password create/set/change
* Authenticate

Also fixes a bug where confirmation on a change-password call would run
for the current password instead of the new one.
This commit is contained in:
Jeff Mitchell authored and GitHub committed 2022-08-05 13:21:46 -04:00
1 parent 090b2b28f8
commit 26ffa705e5
3 files changed
+103 -52

No files matched your search

+80 -46
View File
@@ -9,6 +9,7 @@ import (
"github.com/hashicorp/boundary/api"
"github.com/hashicorp/boundary/api/accounts"
"github.com/hashicorp/boundary/internal/cmd/base"
"github.com/hashicorp/go-secure-stdlib/parseutil"
"github.com/hashicorp/go-secure-stdlib/password"
"github.com/hashicorp/go-secure-stdlib/strutil"
)
@@ -116,59 +117,92 @@ func extraFlagsFuncImpl(c *Command, _ *base.FlagSets, f *base.FlagSet) {
}
func extraFlagsHandlingFuncImpl(c *Command, _ *base.FlagSets, opts *[]accounts.Option) bool {
if strutil.StrListContains(flagsMap[c.Func], "password") && c.flagPassword == "" {
fmt.Print("Password is not set as flag, please enter it now (will be hidden): ")
value, err := password.Read(os.Stdin)
fmt.Print("\n")
if err != nil {
c.UI.Error(fmt.Sprintf("An error occurred attempting to read the password. The raw error message is shown below but usually this is because you attempted to pipe a value into the command or you are executing outside of a terminal (TTY). The raw error was:\n\n%s", err.Error()))
return false
if strutil.StrListContains(flagsMap[c.Func], "password") {
switch c.flagPassword {
case "":
fmt.Print("Password is not set as flag, please enter it now (will be hidden): ")
value, err := password.Read(os.Stdin)
fmt.Print("\n")
if err != nil {
c.UI.Error(fmt.Sprintf("An error occurred attempting to read the password. The raw error message is shown below but usually this is because you attempted to pipe a value into the command or you are executing outside of a terminal (TTY). The raw error was:\n\n%s", err.Error()))
return false
}
fmt.Print("Please enter it one more time for confirmation: ")
confirmation, err := password.Read(os.Stdin)
fmt.Print("\n")
if err != nil {
c.UI.Error(fmt.Sprintf("An error occurred attempting to read the password. The raw error message is shown below but usually this is because you attempted to pipe a value into the command or you are executing outside of a terminal (TTY). The raw error was:\n\n%s", err.Error()))
return false
}
if strings.TrimSpace(value) != strings.TrimSpace(confirmation) {
c.UI.Error("Entered password and confirmation value did not match.")
return false
}
c.flagPassword = strings.TrimSpace(value)
default:
password, err := parseutil.ParsePath(c.flagPassword)
if err != nil && err.Error() != parseutil.ErrNotAUrl.Error() {
c.UI.Error(fmt.Sprintf("Error parsing password flag: %v", err))
return false
}
c.flagPassword = password
}
fmt.Print("Please enter it one more time for confirmation: ")
confirmation, err := password.Read(os.Stdin)
fmt.Print("\n")
if err != nil {
c.UI.Error(fmt.Sprintf("An error occurred attempting to read the password. The raw error message is shown below but usually this is because you attempted to pipe a value into the command or you are executing outside of a terminal (TTY). The raw error was:\n\n%s", err.Error()))
return false
}
if strings.TrimSpace(value) != strings.TrimSpace(confirmation) {
c.UI.Error("Entered password and confirmation value did not match.")
return false
}
c.flagPassword = strings.TrimSpace(value)
}
if strutil.StrListContains(flagsMap[c.Func], "current-password") && c.flagCurrentPassword == "" {
fmt.Print("Current password is not set as flag, please enter it now (will be hidden): ")
value, err := password.Read(os.Stdin)
fmt.Print("\n")
if err != nil {
c.UI.Error(fmt.Sprintf("An error occurred attempting to read the password. The raw error message is shown below but usually this is because you attempted to pipe a value into the command or you are executing outside of a terminal (TTY). The raw error was:\n\n%s", err.Error()))
return false
if strutil.StrListContains(flagsMap[c.Func], "current-password") {
switch c.flagCurrentPassword {
case "":
fmt.Print("Current password is not set as flag, please enter it now (will be hidden): ")
value, err := password.Read(os.Stdin)
fmt.Print("\n")
if err != nil {
c.UI.Error(fmt.Sprintf("An error occurred attempting to read the password. The raw error message is shown below but usually this is because you attempted to pipe a value into the command or you are executing outside of a terminal (TTY). The raw error was:\n\n%s", err.Error()))
return false
}
fmt.Print("Please enter it one more time for confirmation: ")
c.flagCurrentPassword = strings.TrimSpace(value)
default:
password, err := parseutil.ParsePath(c.flagCurrentPassword)
if err != nil && err.Error() != parseutil.ErrNotAUrl.Error() {
c.UI.Error(fmt.Sprintf("Error parsing current password flag: %v", err))
return false
}
c.flagCurrentPassword = password
}
fmt.Print("Please enter it one more time for confirmation: ")
confirmation, err := password.Read(os.Stdin)
fmt.Print("\n")
if err != nil {
c.UI.Error(fmt.Sprintf("An error occurred attempting to read the password. The raw error message is shown below but usually this is because you attempted to pipe a value into the command or you are executing outside of a terminal (TTY). The raw error was:\n\n%s", err.Error()))
return false
}
if strings.TrimSpace(value) != strings.TrimSpace(confirmation) {
c.UI.Error("Entered password and confirmation value did not match.")
return false
}
c.flagCurrentPassword = strings.TrimSpace(value)
}
if strutil.StrListContains(flagsMap[c.Func], "new-password") && c.flagNewPassword == "" {
fmt.Print("New password is not set as flag, please enter it now (will be hidden): ")
value, err := password.Read(os.Stdin)
fmt.Print("\n")
if err != nil {
c.UI.Error(fmt.Sprintf("An error occurred attempting to read the password. The raw error message is shown below but usually this is because you attempted to pipe a value into the command or you are executing outside of a terminal (TTY). The raw error was:\n\n%s", err.Error()))
return false
if strutil.StrListContains(flagsMap[c.Func], "new-password") {
switch c.flagNewPassword {
case "":
fmt.Print("New password is not set as flag, please enter it now (will be hidden): ")
value, err := password.Read(os.Stdin)
fmt.Print("\n")
if err != nil {
c.UI.Error(fmt.Sprintf("An error occurred attempting to read the password. The raw error message is shown below but usually this is because you attempted to pipe a value into the command or you are executing outside of a terminal (TTY). The raw error was:\n\n%s", err.Error()))
return false
}
confirmation, err := password.Read(os.Stdin)
fmt.Print("\n")
if err != nil {
c.UI.Error(fmt.Sprintf("An error occurred attempting to read the password. The raw error message is shown below but usually this is because you attempted to pipe a value into the command or you are executing outside of a terminal (TTY). The raw error was:\n\n%s", err.Error()))
return false
}
if strings.TrimSpace(value) != strings.TrimSpace(confirmation) {
c.UI.Error("Entered password and confirmation value did not match.")
return false
}
c.flagNewPassword = strings.TrimSpace(value)
default:
password, err := parseutil.ParsePath(c.flagNewPassword)
if err != nil && err.Error() != parseutil.ErrNotAUrl.Error() {
c.UI.Error(fmt.Sprintf("Error parsing new password flag: %v", err))
return false
}
c.flagNewPassword = password
}
c.flagNewPassword = strings.TrimSpace(value)
}
return true
@@ -7,6 +7,7 @@ import (
"github.com/hashicorp/boundary/api/accounts"
"github.com/hashicorp/boundary/internal/cmd/base"
"github.com/hashicorp/go-secure-stdlib/parseutil"
"github.com/hashicorp/go-secure-stdlib/password"
"github.com/hashicorp/go-secure-stdlib/strutil"
)
@@ -72,7 +73,7 @@ func extraPasswordFlagsFuncImpl(c *PasswordCommand, set *base.FlagSets, f *base.
f.StringVar(&base.StringVar{
Name: "password",
Target: &c.flagPassword,
Usage: "The password for the account. If not specified, the command will prompt for the password to be entered in a non-echoing way.",
Usage: "The password for the account. If blank, the command will prompt for the password to be entered interactively in a non-echoing way. Otherwise, this can refer to a file on disk (file://) from which a password will be read; an env var (env://) from which the password will be read; or a string containing the password.",
})
}
}
@@ -114,8 +115,14 @@ func extraPasswordFlagsHandlingFuncImpl(c *PasswordCommand, _ *base.FlagSets, op
return false
}
*opts = append(*opts, accounts.WithPasswordAccountPassword(strings.TrimSpace(value)))
default:
*opts = append(*opts, accounts.WithPasswordAccountPassword(c.flagPassword))
password, err := parseutil.ParsePath(c.flagPassword)
if err != nil && err.Error() != parseutil.ErrNotAUrl.Error() {
c.UI.Error(fmt.Sprintf("Error parsing password flag: %v", err))
return false
}
*opts = append(*opts, accounts.WithPasswordAccountPassword(password))
}
}
+14 -4
View File
@@ -9,6 +9,7 @@ import (
"github.com/hashicorp/boundary/api"
"github.com/hashicorp/boundary/api/authmethods"
"github.com/hashicorp/boundary/internal/cmd/base"
"github.com/hashicorp/go-secure-stdlib/parseutil"
"github.com/hashicorp/go-secure-stdlib/password"
"github.com/mitchellh/cli"
"github.com/mitchellh/go-wordwrap"
@@ -56,21 +57,21 @@ func (c *PasswordCommand) Flags() *base.FlagSets {
Name: "login-name",
Target: &c.flagLoginName,
EnvVar: envLoginName,
Usage: "The login name corresponding to an account within the given auth method",
Usage: "The login name corresponding to an account within the given auth method.",
})
f.StringVar(&base.StringVar{
Name: "password",
Target: &c.flagPassword,
EnvVar: envPassword,
Usage: "The password associated with the login name",
Usage: "The password associated with the login name. If blank, the command will prompt for the password to be entered interactively in a non-echoing way. Otherwise, this can refer to a file on disk (file://) from which a password will be read; an env var (env://) from which the password will be read; or a string containing the password.",
})
f.StringVar(&base.StringVar{
Name: "auth-method-id",
EnvVar: "BOUNDARY_AUTH_METHOD_ID",
Target: &c.FlagAuthMethodId,
Usage: "The auth-method resource to use for the operation",
Usage: "The auth-method resource to use for the operation.",
})
return set
@@ -101,7 +102,8 @@ func (c *PasswordCommand) Run(args []string) int {
return base.CommandUserError
}
if c.flagPassword == "" {
switch c.flagPassword {
case "":
fmt.Print("Password is not set as flag or in env, please enter it now (will be hidden): ")
value, err := password.Read(os.Stdin)
fmt.Print("\n")
@@ -110,6 +112,14 @@ func (c *PasswordCommand) Run(args []string) int {
return base.CommandUserError
}
c.flagPassword = strings.TrimSpace(value)
default:
password, err := parseutil.ParsePath(c.flagPassword)
if err != nil && err.Error() != parseutil.ErrNotAUrl.Error() {
c.UI.Error(fmt.Sprintf("Error parsing password flag: %v", err))
return base.CommandUserError
}
c.flagPassword = password
}
client, err := c.Client(base.WithNoTokenScope(), base.WithNoTokenValue())