github.com/azure-devops-engineer/helm@v3.0.0-alpha.2+incompatible/cmd/helm/registry_login.go (about) 1 /* 2 Copyright The Helm Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package main 18 19 import ( 20 "bufio" 21 "errors" 22 "fmt" 23 "io" 24 "io/ioutil" 25 "os" 26 "strings" 27 28 "github.com/docker/docker/pkg/term" 29 "github.com/spf13/cobra" 30 31 "helm.sh/helm/cmd/helm/require" 32 "helm.sh/helm/pkg/action" 33 ) 34 35 const registryLoginDesc = ` 36 Authenticate to a remote registry. 37 ` 38 39 func newRegistryLoginCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { 40 var usernameOpt, passwordOpt string 41 var passwordFromStdinOpt bool 42 43 cmd := &cobra.Command{ 44 Use: "login [host]", 45 Short: "login to a registry", 46 Long: registryLoginDesc, 47 Args: require.MinimumNArgs(1), 48 RunE: func(cmd *cobra.Command, args []string) error { 49 hostname := args[0] 50 51 username, password, err := getUsernamePassword(usernameOpt, passwordOpt, passwordFromStdinOpt) 52 if err != nil { 53 return err 54 } 55 56 return action.NewRegistryLogin(cfg).Run(out, hostname, username, password) 57 }, 58 } 59 60 f := cmd.Flags() 61 f.StringVarP(&usernameOpt, "username", "u", "", "registry username") 62 f.StringVarP(&passwordOpt, "password", "p", "", "registry password or identity token") 63 f.BoolVarP(&passwordFromStdinOpt, "password-stdin", "", false, "read password or identity token from stdin") 64 65 return cmd 66 } 67 68 // Adapted from https://github.com/deislabs/oras 69 func getUsernamePassword(usernameOpt string, passwordOpt string, passwordFromStdinOpt bool) (string, string, error) { 70 var err error 71 username := usernameOpt 72 password := passwordOpt 73 74 if passwordFromStdinOpt { 75 passwordFromStdin, err := ioutil.ReadAll(os.Stdin) 76 if err != nil { 77 return "", "", err 78 } 79 password = strings.TrimSuffix(string(passwordFromStdin), "\n") 80 password = strings.TrimSuffix(password, "\r") 81 } else if password == "" { 82 if username == "" { 83 username, err = readLine("Username: ", false) 84 if err != nil { 85 return "", "", err 86 } 87 username = strings.TrimSpace(username) 88 } 89 if username == "" { 90 password, err = readLine("Token: ", true) 91 if err != nil { 92 return "", "", err 93 } else if password == "" { 94 return "", "", errors.New("token required") 95 } 96 } else { 97 password, err = readLine("Password: ", true) 98 if err != nil { 99 return "", "", err 100 } else if password == "" { 101 return "", "", errors.New("password required") 102 } 103 } 104 } else { 105 fmt.Fprintln(os.Stderr, "WARNING! Using --password via the CLI is insecure. Use --password-stdin.") 106 } 107 108 return username, password, nil 109 } 110 111 // Copied/adapted from https://github.com/deislabs/oras 112 func readLine(prompt string, silent bool) (string, error) { 113 fmt.Print(prompt) 114 if silent { 115 fd := os.Stdin.Fd() 116 state, err := term.SaveState(fd) 117 if err != nil { 118 return "", err 119 } 120 term.DisableEcho(fd, state) 121 defer term.RestoreTerminal(fd, state) 122 } 123 124 reader := bufio.NewReader(os.Stdin) 125 line, _, err := reader.ReadLine() 126 if err != nil { 127 return "", err 128 } 129 if silent { 130 fmt.Println() 131 } 132 133 return string(line), nil 134 }