From a79f714b1e00f8fb7911f5eb6e131eb863fd1f95 Mon Sep 17 00:00:00 2001 From: Brendan Burns Date: Sun, 3 Jul 2016 21:52:38 -0700 Subject: [PATCH] Make password prompting hide the string --- .../unversioned/clientcmd/auth_loaders.go | 37 +++++++++++++------ .../unversioned/clientcmd/client_config.go | 6 ++- 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/pkg/client/unversioned/clientcmd/auth_loaders.go b/pkg/client/unversioned/clientcmd/auth_loaders.go index 0abc425c0c7..1e7c1159e4b 100644 --- a/pkg/client/unversioned/clientcmd/auth_loaders.go +++ b/pkg/client/unversioned/clientcmd/auth_loaders.go @@ -23,6 +23,7 @@ import ( "io/ioutil" "os" + "github.com/howeyc/gopass" clientauth "k8s.io/kubernetes/pkg/client/unversioned/auth" ) @@ -46,10 +47,13 @@ type PromptingAuthLoader struct { // LoadAuth parses an AuthInfo object from a file path. It prompts user and creates file if it doesn't exist. func (a *PromptingAuthLoader) LoadAuth(path string) (*clientauth.Info, error) { - var auth clientauth.Info // Prompt for user/pass and write a file if none exists. if _, err := os.Stat(path); os.IsNotExist(err) { - auth = *a.Prompt() + authPtr, err := a.Prompt() + auth := *authPtr + if err != nil { + return nil, err + } data, err := json.Marshal(auth) if err != nil { return &auth, err @@ -65,19 +69,30 @@ func (a *PromptingAuthLoader) LoadAuth(path string) (*clientauth.Info, error) { } // Prompt pulls the user and password from a reader -func (a *PromptingAuthLoader) Prompt() *clientauth.Info { +func (a *PromptingAuthLoader) Prompt() (*clientauth.Info, error) { + var err error auth := &clientauth.Info{} - auth.User = promptForString("Username", a.reader) - auth.Password = promptForString("Password", a.reader) - - return auth + auth.User, err = promptForString("Username", a.reader, true) + if err != nil { + return nil, err + } + auth.Password, err = promptForString("Password", nil, false) + if err != nil { + return nil, err + } + return auth, nil } -func promptForString(field string, r io.Reader) string { +func promptForString(field string, r io.Reader, show bool) (result string, err error) { fmt.Printf("Please enter %s: ", field) - var result string - fmt.Fscan(r, &result) - return result + if show { + _, err = fmt.Fscan(r, &result) + } else { + var data []byte + data, err = gopass.GetPasswdMasked() + result = string(data) + } + return result, err } // NewPromptingAuthLoader is an AuthLoader that parses an AuthInfo object from a file path. It prompts user and creates file if it doesn't exist. diff --git a/pkg/client/unversioned/clientcmd/client_config.go b/pkg/client/unversioned/clientcmd/client_config.go index 3be1d77c66b..ab44b066c11 100644 --- a/pkg/client/unversioned/clientcmd/client_config.go +++ b/pkg/client/unversioned/clientcmd/client_config.go @@ -195,8 +195,10 @@ func getUserIdentificationPartialConfig(configAuthInfo clientcmdapi.AuthInfo, fa // if there still isn't enough information to authenticate the user, try prompting if !canIdentifyUser(*mergedConfig) && (fallbackReader != nil) { prompter := NewPromptingAuthLoader(fallbackReader) - promptedAuthInfo := prompter.Prompt() - + promptedAuthInfo, err := prompter.Prompt() + if err != nil { + return nil, err + } promptedConfig := makeUserIdentificationConfig(*promptedAuthInfo) previouslyMergedConfig := mergedConfig mergedConfig = &restclient.Config{}