diff options
Diffstat (limited to 'vendor/github.com')
5 files changed, 281 insertions, 2 deletions
diff --git a/vendor/github.com/containers/common/pkg/auth/auth.go b/vendor/github.com/containers/common/pkg/auth/auth.go new file mode 100644 index 000000000..769e5a9fa --- /dev/null +++ b/vendor/github.com/containers/common/pkg/auth/auth.go @@ -0,0 +1,182 @@ +package auth + +import ( + "bufio" + "context" + "fmt" + "os" + "strings" + + "github.com/containers/image/v5/docker" + "github.com/containers/image/v5/pkg/docker/config" + "github.com/containers/image/v5/types" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" + "golang.org/x/crypto/ssh/terminal" +) + +// GetDefaultAuthFile returns env value REGISTRY_AUTH_FILE as default --authfile path +// used in multiple --authfile flag definitions +func GetDefaultAuthFile() string { + return os.Getenv("REGISTRY_AUTH_FILE") +} + +// CheckAuthFile validates filepath given by --authfile +// used by command has --authfile flag +func CheckAuthFile(authfile string) error { + if authfile == "" { + return nil + } + if _, err := os.Stat(authfile); err != nil { + return errors.Wrapf(err, "error checking authfile path %s", authfile) + } + return nil +} + +// Login login to the server with creds from Stdin or CLI +func Login(ctx context.Context, systemContext *types.SystemContext, opts *LoginOptions, registry string) error { + server := getRegistryName(registry) + authConfig, err := config.GetCredentials(systemContext, server) + if err != nil { + return errors.Wrapf(err, "error reading auth file") + } + if opts.GetLoginSet { + if authConfig.Username == "" { + return errors.Errorf("not logged into %s", server) + } + fmt.Fprintf(opts.Stdout, "%s\n", authConfig.Username) + return nil + } + if authConfig.IdentityToken != "" { + return errors.Errorf("currently logged in, auth file contains an Identity token") + } + + password := opts.Password + if opts.StdinPassword { + var stdinPasswordStrBuilder strings.Builder + if opts.Password != "" { + return errors.Errorf("Can't specify both --password-stdin and --password") + } + if opts.Username == "" { + return errors.Errorf("Must provide --username with --password-stdin") + } + scanner := bufio.NewScanner(opts.Stdin) + for scanner.Scan() { + fmt.Fprint(&stdinPasswordStrBuilder, scanner.Text()) + } + password = stdinPasswordStrBuilder.String() + } + + // If no username and no password is specified, try to use existing ones. + if opts.Username == "" && password == "" && authConfig.Username != "" && authConfig.Password != "" { + fmt.Println("Authenticating with existing credentials...") + if err := docker.CheckAuth(ctx, systemContext, authConfig.Username, authConfig.Password, server); err == nil { + fmt.Fprintln(opts.Stdout, "Existing credentials are valid. Already logged in to", server) + return nil + } + fmt.Fprintln(opts.Stdout, "Existing credentials are invalid, please enter valid username and password") + } + + username, password, err := getUserAndPass(opts, password, authConfig.Username) + if err != nil { + return errors.Wrapf(err, "error getting username and password") + } + + if err = docker.CheckAuth(ctx, systemContext, username, password, server); err == nil { + // Write the new credentials to the authfile + if err = config.SetAuthentication(systemContext, server, username, password); err != nil { + return err + } + } + if err == nil { + fmt.Fprintln(opts.Stdout, "Login Succeeded!") + return nil + } + if unauthorized, ok := err.(docker.ErrUnauthorizedForCredentials); ok { + logrus.Debugf("error logging into %q: %v", server, unauthorized) + return errors.Errorf("error logging into %q: invalid username/password", server) + } + return errors.Wrapf(err, "error authenticating creds for %q", server) +} + +// getRegistryName scrubs and parses the input to get the server name +func getRegistryName(server string) string { + // removes 'http://' or 'https://' from the front of the + // server/registry string if either is there. This will be mostly used + // for user input from 'Buildah login' and 'Buildah logout'. + server = strings.TrimPrefix(strings.TrimPrefix(server, "https://"), "http://") + // gets the registry from the input. If the input is of the form + // quay.io/myuser/myimage, it will parse it and just return quay.io + split := strings.Split(server, "/") + if len(split) > 1 { + return split[0] + } + return split[0] +} + +// getUserAndPass gets the username and password from STDIN if not given +// using the -u and -p flags. If the username prompt is left empty, the +// displayed userFromAuthFile will be used instead. +func getUserAndPass(opts *LoginOptions, password, userFromAuthFile string) (string, string, error) { + var err error + reader := bufio.NewReader(opts.Stdin) + username := opts.Username + if username == "" { + if userFromAuthFile != "" { + fmt.Fprintf(opts.Stdout, "Username (%s): ", userFromAuthFile) + } else { + fmt.Fprint(opts.Stdout, "Username: ") + } + username, err = reader.ReadString('\n') + if err != nil { + return "", "", errors.Wrapf(err, "error reading username") + } + // If the user just hit enter, use the displayed user from the + // the authentication file. This allows to do a lazy + // `$ buildah login -p $NEW_PASSWORD` without specifying the + // user. + if strings.TrimSpace(username) == "" { + username = userFromAuthFile + } + } + if password == "" { + fmt.Fprint(opts.Stdout, "Password: ") + pass, err := terminal.ReadPassword(0) + if err != nil { + return "", "", errors.Wrapf(err, "error reading password") + } + password = string(pass) + fmt.Fprintln(opts.Stdout) + } + return strings.TrimSpace(username), password, err +} + +// Logout removes the authentication of server from authfile +// removes all authtication if specifies all in the options +func Logout(systemContext *types.SystemContext, opts *LogoutOptions, server string) error { + if server != "" { + server = getRegistryName(server) + } + if err := CheckAuthFile(opts.AuthFile); err != nil { + return err + } + + if opts.All { + if err := config.RemoveAllAuthentication(systemContext); err != nil { + return err + } + fmt.Fprintln(opts.Stdout, "Removed login credentials for all registries") + return nil + } + + err := config.RemoveAuthentication(systemContext, server) + switch err { + case nil: + fmt.Fprintf(opts.Stdout, "Removed login credentials for %s\n", server) + return nil + case config.ErrNotLoggedIn: + return errors.Errorf("Not logged into %s\n", server) + default: + return errors.Wrapf(err, "error logging out of %q", server) + } +} diff --git a/vendor/github.com/containers/common/pkg/auth/cli.go b/vendor/github.com/containers/common/pkg/auth/cli.go new file mode 100644 index 000000000..dffd06718 --- /dev/null +++ b/vendor/github.com/containers/common/pkg/auth/cli.go @@ -0,0 +1,47 @@ +package auth + +import ( + "io" + + "github.com/spf13/pflag" +) + +// LoginOptions represents common flags in login +// caller should define bool or optionalBool fields for flags --get-login and --tls-verify +type LoginOptions struct { + AuthFile string + CertDir string + GetLoginSet bool + Password string + Username string + StdinPassword bool + Stdin io.Reader + Stdout io.Writer +} + +// LogoutOptions represents the results for flags in logout +type LogoutOptions struct { + AuthFile string + All bool + Stdin io.Reader + Stdout io.Writer +} + +// GetLoginFlags defines and returns login flags for containers tools +func GetLoginFlags(flags *LoginOptions) *pflag.FlagSet { + fs := pflag.FlagSet{} + fs.StringVar(&flags.AuthFile, "authfile", GetDefaultAuthFile(), "path of the authentication file. Use REGISTRY_AUTH_FILE environment variable to override") + fs.StringVar(&flags.CertDir, "cert-dir", "", "use certificates at the specified path to access the registry") + fs.StringVarP(&flags.Password, "password", "p", "", "Password for registry") + fs.StringVarP(&flags.Username, "username", "u", "", "Username for registry") + fs.BoolVar(&flags.StdinPassword, "password-stdin", false, "Take the password from stdin") + return &fs +} + +// GetLogoutFlags defines and returns logout flags for containers tools +func GetLogoutFlags(flags *LogoutOptions) *pflag.FlagSet { + fs := pflag.FlagSet{} + fs.StringVar(&flags.AuthFile, "authfile", GetDefaultAuthFile(), "path of the authentication file. Use REGISTRY_AUTH_FILE environment variable to override") + fs.BoolVarP(&flags.All, "all", "a", false, "Remove the cached credentials for all registries in the auth file") + return &fs +} diff --git a/vendor/github.com/containers/common/pkg/config/default.go b/vendor/github.com/containers/common/pkg/config/default.go index 8b87d3725..446382ac7 100644 --- a/vendor/github.com/containers/common/pkg/config/default.go +++ b/vendor/github.com/containers/common/pkg/config/default.go @@ -141,13 +141,18 @@ func DefaultConfig() (*Config, error) { netns = "slirp4netns" } + cgroupNS := "host" + if cgroup2, _ := cgroupv2.Enabled(); cgroup2 { + cgroupNS = "private" + } + return &Config{ Containers: ContainersConfig{ Devices: []string{}, Volumes: []string{}, Annotations: []string{}, ApparmorProfile: DefaultApparmorProfile, - CgroupNS: "private", + CgroupNS: cgroupNS, Cgroups: "enabled", DefaultCapabilities: DefaultCapabilities, DefaultSysctls: []string{}, @@ -173,7 +178,7 @@ func DefaultConfig() (*Config, error) { SeccompProfile: SeccompDefaultPath, ShmSize: DefaultShmSize, UTSNS: "private", - UserNS: "private", + UserNS: "host", UserNSSize: DefaultUserNSSize, }, Network: NetworkConfig{ diff --git a/vendor/github.com/containers/common/pkg/config/libpodConfig.go b/vendor/github.com/containers/common/pkg/config/libpodConfig.go index cdb38a514..89566f789 100644 --- a/vendor/github.com/containers/common/pkg/config/libpodConfig.go +++ b/vendor/github.com/containers/common/pkg/config/libpodConfig.go @@ -224,6 +224,12 @@ func newLibpodConfig(c *Config) error { } } + // hard code EventsLogger to "file" to match older podman versions. + if config.EventsLogger != "file" { + logrus.Debugf("Ignoring lipod.conf EventsLogger setting %q. Use containers.conf if you want to change this setting and remove libpod.conf files.", config.EventsLogger) + config.EventsLogger = "file" + } + c.libpodToContainersConfig(config) return nil diff --git a/vendor/github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent/parent.go b/vendor/github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent/parent.go index 893bf1da9..8ffadd859 100644 --- a/vendor/github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent/parent.go +++ b/vendor/github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent/parent.go @@ -2,11 +2,14 @@ package parent import ( "context" + "fmt" "io" "io/ioutil" "net" "os" "path/filepath" + "strconv" + "strings" "sync" "syscall" @@ -84,6 +87,39 @@ func (d *driver) RunParentDriver(initComplete chan struct{}, quit <-chan struct{ return nil } +func isEPERM(err error) bool { + k := "permission denied" + // As of Go 1.14, errors.Is(err, syscall.EPERM) does not seem to work for + // "listen tcp 0.0.0.0:80: bind: permission denied" error from net.ListenTCP(). + return errors.Is(err, syscall.EPERM) || strings.Contains(err.Error(), k) +} + +// annotateEPERM annotates origErr for human-readability +func annotateEPERM(origErr error, spec port.Spec) error { + // Read "net.ipv4.ip_unprivileged_port_start" value (typically 1024) + // TODO: what for IPv6? + // NOTE: sync.Once should not be used here + b, e := ioutil.ReadFile("/proc/sys/net/ipv4/ip_unprivileged_port_start") + if e != nil { + return origErr + } + start, e := strconv.Atoi(strings.TrimSpace(string(b))) + if e != nil { + return origErr + } + if spec.ParentPort >= start { + // origErr is unrelated to ip_unprivileged_port_start + return origErr + } + text := fmt.Sprintf("cannot expose privileged port %d, you might need to add \"net.ipv4.ip_unprivileged_port_start=0\" (currently %d) to /etc/sysctl.conf", spec.ParentPort, start) + if filepath.Base(os.Args[0]) == "rootlesskit" { + // NOTE: The following sentence is appended only if Args[0] == "rootlesskit", because it does not apply to Podman (as of Podman v1.9). + // Podman launches the parent driver in the child user namespace (but in the parent network namespace), which disables the file capability. + text += ", or set CAP_NET_BIND_SERVICE on rootlesskit binary" + } + return errors.Wrap(origErr, text) +} + func (d *driver) AddPort(ctx context.Context, spec port.Spec) (*port.Status, error) { d.mu.Lock() err := portutil.ValidatePortSpec(spec, d.ports) @@ -106,6 +142,9 @@ func (d *driver) AddPort(ctx context.Context, spec port.Spec) (*port.Status, err return nil, errors.New("spec was not validated?") } if err != nil { + if isEPERM(err) { + err = annotateEPERM(err, spec) + } return nil, err } d.mu.Lock() |