forked from oras-project/oras
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support oras login (oras-project#53)
Supports - `oras login` to log in to a remote registry. - `oras logout` to log out from a remote registry.
- Loading branch information
Showing
12 changed files
with
413 additions
and
27 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
package main | ||
|
||
import ( | ||
"bufio" | ||
"context" | ||
"errors" | ||
"fmt" | ||
"io/ioutil" | ||
"os" | ||
"strings" | ||
|
||
auth "github.com/deislabs/oras/pkg/auth/docker" | ||
|
||
"github.com/docker/docker/pkg/term" | ||
"github.com/sirupsen/logrus" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
type loginOptions struct { | ||
hostname string | ||
fromStdin bool | ||
|
||
debug bool | ||
configs []string | ||
username string | ||
password string | ||
} | ||
|
||
func loginCmd() *cobra.Command { | ||
var opts loginOptions | ||
cmd := &cobra.Command{ | ||
Use: "login registry", | ||
Short: "Log in to a remote registry", | ||
Long: `Log in to a remote registry | ||
Example - Login with username and password from command line: | ||
oras login -u username -p password localhost:5000 | ||
Example - Login with username and password from stdin: | ||
oras login -u username --password-stdin localhost:5000 | ||
Example - Login with identity token from command line: | ||
oras login -p token localhost:5000 | ||
Example - Login with identity token from stdin: | ||
oras login --password-stdin localhost:5000 | ||
Example - Login with username and password by prompt: | ||
oras login localhost:5000 | ||
`, | ||
Args: cobra.ExactArgs(1), | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
opts.hostname = args[0] | ||
return runLogin(opts) | ||
}, | ||
} | ||
|
||
cmd.Flags().BoolVarP(&opts.debug, "debug", "d", false, "debug mode") | ||
cmd.Flags().StringArrayVarP(&opts.configs, "config", "c", nil, "auth config path") | ||
cmd.Flags().StringVarP(&opts.username, "username", "u", "", "registry username") | ||
cmd.Flags().StringVarP(&opts.password, "password", "p", "", "registry password or identity token") | ||
cmd.Flags().BoolVarP(&opts.fromStdin, "password-stdin", "", false, "read password or identity token from stdin") | ||
return cmd | ||
} | ||
|
||
func runLogin(opts loginOptions) error { | ||
if opts.debug { | ||
logrus.SetLevel(logrus.DebugLevel) | ||
} | ||
|
||
// Prepare auth client | ||
cli, err := auth.NewClient(opts.configs...) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// Prompt credential | ||
if opts.fromStdin { | ||
password, err := ioutil.ReadAll(os.Stdin) | ||
if err != nil { | ||
return err | ||
} | ||
opts.password = strings.TrimSuffix(string(password), "\n") | ||
opts.password = strings.TrimSuffix(opts.password, "\r") | ||
} else if opts.password == "" { | ||
if opts.username == "" { | ||
username, err := readLine("Username: ", false) | ||
if err != nil { | ||
return err | ||
} | ||
opts.username = strings.TrimSpace(username) | ||
} | ||
if opts.username == "" { | ||
if opts.password, err = readLine("Token: ", true); err != nil { | ||
return err | ||
} else if opts.password == "" { | ||
return errors.New("token required") | ||
} | ||
} else { | ||
if opts.password, err = readLine("Password: ", true); err != nil { | ||
return err | ||
} else if opts.password == "" { | ||
return errors.New("password required") | ||
} | ||
} | ||
} else { | ||
fmt.Fprintln(os.Stderr, "WARNING! Using --password via the CLI is insecure. Use --password-stdin.") | ||
} | ||
|
||
// Login | ||
if err := cli.Login(context.Background(), opts.hostname, opts.username, opts.password); err != nil { | ||
return err | ||
} | ||
|
||
fmt.Println("Login Succeeded") | ||
return nil | ||
} | ||
|
||
func readLine(prompt string, slient bool) (string, error) { | ||
fmt.Print(prompt) | ||
if slient { | ||
fd := os.Stdin.Fd() | ||
state, err := term.SaveState(fd) | ||
if err != nil { | ||
return "", err | ||
} | ||
term.DisableEcho(fd, state) | ||
defer term.RestoreTerminal(fd, state) | ||
} | ||
|
||
reader := bufio.NewReader(os.Stdin) | ||
line, _, err := reader.ReadLine() | ||
if err != nil { | ||
return "", err | ||
} | ||
if slient { | ||
fmt.Println() | ||
} | ||
|
||
return string(line), nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package main | ||
|
||
import ( | ||
"context" | ||
|
||
auth "github.com/deislabs/oras/pkg/auth/docker" | ||
|
||
"github.com/sirupsen/logrus" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
type logoutOptions struct { | ||
hostname string | ||
|
||
debug bool | ||
configs []string | ||
} | ||
|
||
func logoutCmd() *cobra.Command { | ||
var opts logoutOptions | ||
cmd := &cobra.Command{ | ||
Use: "logout registry", | ||
Short: "Log out from a remote registry", | ||
Long: `Log out from a remote registry | ||
Example - Logout: | ||
oras logout localhost:5000 | ||
`, | ||
Args: cobra.ExactArgs(1), | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
opts.hostname = args[0] | ||
return runLogout(opts) | ||
}, | ||
} | ||
|
||
cmd.Flags().BoolVarP(&opts.debug, "debug", "d", false, "debug mode") | ||
cmd.Flags().StringArrayVarP(&opts.configs, "config", "c", nil, "auth config path") | ||
return cmd | ||
} | ||
|
||
func runLogout(opts logoutOptions) error { | ||
if opts.debug { | ||
logrus.SetLevel(logrus.DebugLevel) | ||
} | ||
|
||
cli, err := auth.NewClient(opts.configs...) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return cli.Logout(context.Background(), opts.hostname) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,35 +1,32 @@ | ||
package main | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"os" | ||
|
||
auth "github.com/deislabs/oras/pkg/auth/docker" | ||
|
||
"github.com/containerd/containerd/remotes" | ||
"github.com/containerd/containerd/remotes/docker" | ||
"github.com/docker/cli/cli/config" | ||
"github.com/docker/docker/registry" | ||
) | ||
|
||
func newResolver(username, password string) remotes.Resolver { | ||
cfg := config.LoadDefaultConfigFile(os.Stderr) | ||
credential := func(hostName string) (string, string, error) { | ||
if hostName == registry.DefaultV2Registry.Host { | ||
hostName = registry.IndexServer | ||
} | ||
auth, err := cfg.GetAuthConfig(hostName) | ||
if err != nil { | ||
return "", "", err | ||
} | ||
if auth.IdentityToken != "" { | ||
return "", auth.IdentityToken, nil | ||
} | ||
return auth.Username, auth.Password, nil | ||
} | ||
func newResolver(username, password string, configs ...string) remotes.Resolver { | ||
if username != "" || password != "" { | ||
credential = func(hostName string) (string, string, error) { | ||
return username, password, nil | ||
} | ||
return docker.NewResolver(docker.ResolverOptions{ | ||
Credentials: func(hostName string) (string, string, error) { | ||
return username, password, nil | ||
}, | ||
}) | ||
} | ||
cli, err := auth.NewClient(configs...) | ||
if err != nil { | ||
fmt.Fprintf(os.Stderr, "WARNING: Error loading auth file: %v\n", err) | ||
} | ||
resolver, err := cli.Resolver(context.Background()) | ||
if err != nil { | ||
fmt.Fprintf(os.Stderr, "WARNING: Error loading resolver: %v\n", err) | ||
resolver = docker.NewResolver(docker.ResolverOptions{}) | ||
} | ||
return docker.NewResolver(docker.ResolverOptions{ | ||
Credentials: credential, | ||
}) | ||
return resolver | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package auth | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/containerd/containerd/remotes" | ||
) | ||
|
||
// Client provides authentication operations for remotes. | ||
type Client interface { | ||
// Login logs in to a remote server identified by the hostname. | ||
Login(ctx context.Context, hostname, username, secret string) error | ||
// Logout logs out from a remote server identified by the hostname. | ||
Logout(ctx context.Context, hostname string) error | ||
// Resolver returns a new authenticated resolver. | ||
Resolver(ctx context.Context) (remotes.Resolver, error) | ||
} |
Oops, something went wrong.