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  }