/
login.go
145 lines (120 loc) · 4.21 KB
/
login.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
package login
import (
"context"
"fmt"
"os"
"path/filepath"
"github.com/spf13/cobra"
"golang.org/x/crypto/ssh/terminal"
"oras.land/oras-go/pkg/auth"
"oras.land/oras-go/pkg/auth/docker"
"github.com/werf/logboek"
"github.com/werf/werf/cmd/werf/common"
secret_common "github.com/werf/werf/cmd/werf/helm/secret/common"
"github.com/werf/werf/pkg/werf"
"github.com/werf/werf/pkg/werf/global_warnings"
)
var commonCmdData common.CmdData
var cmdData struct {
Username string
Password string
PasswordStdin bool
}
func NewCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "login registry",
Short: "Login into remote registry",
Long: common.GetLongCommandDescription(`Login into remote registry`),
Example: `# Login with username and password from command line
werf cr login -u username -p password registry.example.com
# Login with token from command line
werf cr login -p token registry.example.com
# Login into insecure registry (over http)
werf cr login --insecure-registry registry.example.com`,
DisableFlagsInUseLine: true,
RunE: func(cmd *cobra.Command, args []string) error {
ctx := common.BackgroundContext()
defer global_warnings.PrintGlobalWarnings(ctx)
if err := common.ProcessLogOptions(&commonCmdData); err != nil {
common.PrintHelp(cmd)
return err
}
if len(args) != 1 {
common.PrintHelp(cmd)
return fmt.Errorf("registry address argument required")
}
return Login(ctx, args[0], LoginOptions{
Username: cmdData.Username,
Password: cmdData.Password,
PasswordStdin: cmdData.PasswordStdin,
DockerConfigDir: *commonCmdData.DockerConfig,
InsecureRegistry: *commonCmdData.InsecureRegistry,
})
},
}
common.SetupDockerConfig(&commonCmdData, cmd, "")
common.SetupInsecureRegistry(&commonCmdData, cmd)
// common.SetupSkipTlsVerifyRegistry(&commonCmdData, cmd)
common.SetupLogOptions(&commonCmdData, cmd)
cmd.Flags().StringVarP(&cmdData.Username, "username", "u", os.Getenv("WERF_USERNAME"), "Use specified username for login (default $WERF_USERNAME)")
cmd.Flags().StringVarP(&cmdData.Password, "password", "p", os.Getenv("WERF_PASSWORD"), "Use specified password for login (default $WERF_PASSWORD)")
cmd.Flags().BoolVarP(&cmdData.PasswordStdin, "password-stdin", "", common.GetBoolEnvironmentDefaultFalse("WERF_PASSWORD_STDIN"), "Read password from stdin for login (default $WERF_PASSWORD_STDIN)")
return cmd
}
type LoginOptions struct {
Username string
Password string
PasswordStdin bool
DockerConfigDir string
InsecureRegistry bool
}
func Login(ctx context.Context, registry string, opts LoginOptions) error {
var dockerConfigDir string
if opts.DockerConfigDir != "" {
dockerConfigDir = opts.DockerConfigDir
} else {
dockerConfigDir = filepath.Join(os.Getenv("HOME"), ".docker")
}
cli, err := docker.NewClient(filepath.Join(dockerConfigDir, "config.json"))
if err != nil {
return fmt.Errorf("unable to create oras auth client: %s", err)
}
if opts.Username == "" {
return fmt.Errorf("provide --username")
}
var password string
if opts.PasswordStdin {
if opts.Password != "" {
return fmt.Errorf("--password and --password-stdin could not be used at the same time")
}
var bytePassword []byte
if terminal.IsTerminal(int(os.Stdin.Fd())) {
bytePassword, err = secret_common.InputFromInteractiveStdin("Password: ")
if err != nil {
return fmt.Errorf("error reading password from interactive stdin: %s", err)
}
} else {
bytePassword, err = secret_common.InputFromStdin()
if err != nil {
return fmt.Errorf("error reading password from stdin: %s", err)
}
}
password = string(bytePassword)
} else if opts.Password != "" {
password = opts.Password
} else {
return fmt.Errorf("provide --password or --password-stdin")
}
if err := cli.LoginWithOpts(func(settings *auth.LoginSettings) {
settings.Context = ctx
settings.Hostname = registry
settings.Username = opts.Username
settings.Secret = password
settings.Insecure = opts.InsecureRegistry
settings.UserAgent = fmt.Sprintf("werf %s", werf.Version)
}); err != nil {
return fmt.Errorf("unable to login into %q: %s", registry, err)
}
logboek.Context(ctx).Default().LogFHighlight("Successful login\n")
return nil
}