From ffcd7d8059dfdd4d0f0c337f897de50fc20d747e Mon Sep 17 00:00:00 2001 From: Max Jonas Werner <mail@makk.es> Date: Tue, 2 Nov 2021 09:42:28 +0100 Subject: [PATCH] feat: prompt for access tokens in 'bootstrap' command This change adds functionality to both, `bootstrap github` and `bootstrap gitlab` to prompt the user for the personal access tokens if those can't be derived from the shell environment. Echoing is turned off for better privacy. Instead of having to interactively type the token or manually paste it from the clipboard, users can also pipe it to Flux which comes in handy e.g. when executing Flux remotely over an SSH connection: ``` $ echo 'asdf' | flux bootstrap github ``` Otherwise, Flux will prompt the user: ``` $ flux bootstrap github Please type your GitHub personal access token: ``` closes #2011 Signed-off-by: Max Jonas Werner <mail@makk.es> --- cmd/flux/bootstrap_github.go | 6 +++++- cmd/flux/bootstrap_gitlab.go | 6 +++++- cmd/flux/main.go | 22 ++++++++++++++++++++++ go.mod | 1 + 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/cmd/flux/bootstrap_github.go b/cmd/flux/bootstrap_github.go index 54b9694f..34f60f6d 100644 --- a/cmd/flux/bootstrap_github.go +++ b/cmd/flux/bootstrap_github.go @@ -111,7 +111,11 @@ func init() { func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error { ghToken := os.Getenv(ghTokenEnvVar) if ghToken == "" { - return fmt.Errorf("%s environment variable not found", ghTokenEnvVar) + var err error + ghToken, err = readPasswordFromStdin("Please type your GitHub personal access token: ") + if err != nil { + return fmt.Errorf("could not read token: %w", err) + } } if err := bootstrapValidate(); err != nil { diff --git a/cmd/flux/bootstrap_gitlab.go b/cmd/flux/bootstrap_gitlab.go index 09bde7f3..24baa03a 100644 --- a/cmd/flux/bootstrap_gitlab.go +++ b/cmd/flux/bootstrap_gitlab.go @@ -108,7 +108,11 @@ func init() { func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error { glToken := os.Getenv(glTokenEnvVar) if glToken == "" { - return fmt.Errorf("%s environment variable not found", glTokenEnvVar) + var err error + glToken, err = readPasswordFromStdin("Please type your GitLab personal access token: ") + if err != nil { + return fmt.Errorf("could not read token: %w", err) + } } if projectNameIsValid, err := regexp.MatchString(gitlabProjectRegex, gitlabArgs.repository); err != nil || !projectNameIsValid { diff --git a/cmd/flux/main.go b/cmd/flux/main.go index 916c4940..86cfba76 100644 --- a/cmd/flux/main.go +++ b/cmd/flux/main.go @@ -17,12 +17,15 @@ limitations under the License. package main import ( + "bufio" + "fmt" "log" "os" "path/filepath" "time" "github.com/spf13/cobra" + "golang.org/x/term" corev1 "k8s.io/api/core/v1" _ "k8s.io/client-go/plugin/pkg/client/auth" @@ -167,3 +170,22 @@ func homeDir() string { } return os.Getenv("USERPROFILE") // windows } + +func readPasswordFromStdin(prompt string) (string, error) { + var out string + var err error + fmt.Fprint(os.Stdout, prompt) + stdinFD := int(os.Stdin.Fd()) + if term.IsTerminal(stdinFD) { + var inBytes []byte + inBytes, err = term.ReadPassword(int(os.Stdin.Fd())) + out = string(inBytes) + } else { + out, err = bufio.NewReader(os.Stdin).ReadString('\n') + } + if err != nil { + return "", fmt.Errorf("could not read from stdin: %w", err) + } + fmt.Println() + return out, nil +} diff --git a/go.mod b/go.mod index d12d1795..ca48bb4d 100644 --- a/go.mod +++ b/go.mod @@ -29,6 +29,7 @@ require ( github.com/spf13/cobra v1.1.3 github.com/spf13/pflag v1.0.5 golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b + golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d k8s.io/api v0.22.2 k8s.io/apiextensions-apiserver v0.22.2 k8s.io/apimachinery v0.22.2 -- GitLab