github.com/diafour/helm@v3.0.0-beta.3+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, insecureOpt 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 Hidden: !FeatureGateOCI.IsEnabled(), 49 RunE: func(cmd *cobra.Command, args []string) error { 50 hostname := args[0] 51 52 username, password, err := getUsernamePassword(usernameOpt, passwordOpt, passwordFromStdinOpt) 53 if err != nil { 54 return err 55 } 56 57 return action.NewRegistryLogin(cfg).Run(out, hostname, username, password, insecureOpt) 58 }, 59 } 60 61 f := cmd.Flags() 62 f.StringVarP(&usernameOpt, "username", "u", "", "registry username") 63 f.StringVarP(&passwordOpt, "password", "p", "", "registry password or identity token") 64 f.BoolVarP(&passwordFromStdinOpt, "password-stdin", "", false, "read password or identity token from stdin") 65 f.BoolVarP(&insecureOpt, "insecure", "", false, "allow connections to TLS registry without certs") 66 67 return cmd 68 } 69 70 // Adapted from https://github.com/deislabs/oras 71 func getUsernamePassword(usernameOpt string, passwordOpt string, passwordFromStdinOpt bool) (string, string, error) { 72 var err error 73 username := usernameOpt 74 password := passwordOpt 75 76 if passwordFromStdinOpt { 77 passwordFromStdin, err := ioutil.ReadAll(os.Stdin) 78 if err != nil { 79 return "", "", err 80 } 81 password = strings.TrimSuffix(string(passwordFromStdin), "\n") 82 password = strings.TrimSuffix(password, "\r") 83 } else if password == "" { 84 if username == "" { 85 username, err = readLine("Username: ", false) 86 if err != nil { 87 return "", "", err 88 } 89 username = strings.TrimSpace(username) 90 } 91 if username == "" { 92 password, err = readLine("Token: ", true) 93 if err != nil { 94 return "", "", err 95 } else if password == "" { 96 return "", "", errors.New("token required") 97 } 98 } else { 99 password, err = readLine("Password: ", true) 100 if err != nil { 101 return "", "", err 102 } else if password == "" { 103 return "", "", errors.New("password required") 104 } 105 } 106 } else { 107 fmt.Fprintln(os.Stderr, "WARNING! Using --password via the CLI is insecure. Use --password-stdin.") 108 } 109 110 return username, password, nil 111 } 112 113 // Copied/adapted from https://github.com/deislabs/oras 114 func readLine(prompt string, silent bool) (string, error) { 115 fmt.Print(prompt) 116 if silent { 117 fd := os.Stdin.Fd() 118 state, err := term.SaveState(fd) 119 if err != nil { 120 return "", err 121 } 122 term.DisableEcho(fd, state) 123 defer term.RestoreTerminal(fd, state) 124 } 125 126 reader := bufio.NewReader(os.Stdin) 127 line, _, err := reader.ReadLine() 128 if err != nil { 129 return "", err 130 } 131 if silent { 132 fmt.Println() 133 } 134 135 return string(line), nil 136 }