diff options
Diffstat (limited to 'cmd/podman/system')
-rw-r--r-- | cmd/podman/system/connection/add.go | 125 | ||||
-rw-r--r-- | cmd/podman/system/connection/remove.go | 3 | ||||
-rw-r--r-- | cmd/podman/system/connection/shared.go | 27 | ||||
-rw-r--r-- | cmd/podman/system/dial_stdio.go | 12 | ||||
-rw-r--r-- | cmd/podman/system/service_abi.go | 36 | ||||
-rw-r--r-- | cmd/podman/system/unshare.go | 6 |
6 files changed, 54 insertions, 155 deletions
diff --git a/cmd/podman/system/connection/add.go b/cmd/podman/system/connection/add.go index d77a39bcc..191603718 100644 --- a/cmd/podman/system/connection/add.go +++ b/cmd/podman/system/connection/add.go @@ -2,25 +2,22 @@ package connection import ( "encoding/json" + "errors" "fmt" "net" "net/url" "os" - "os/user" "regexp" - "time" "github.com/containers/common/pkg/completion" "github.com/containers/common/pkg/config" "github.com/containers/podman/v4/cmd/podman/registry" "github.com/containers/podman/v4/cmd/podman/system" "github.com/containers/podman/v4/libpod/define" - "github.com/containers/podman/v4/pkg/terminal" - "github.com/pkg/errors" + "github.com/containers/podman/v4/pkg/domain/utils" "github.com/sirupsen/logrus" "github.com/spf13/cobra" "golang.org/x/crypto/ssh" - "golang.org/x/crypto/ssh/agent" ) var ( @@ -79,7 +76,7 @@ func add(cmd *cobra.Command, args []string) error { // Default to ssh schema if none given dest := args[1] if match, err := regexp.Match("^[A-Za-z][A-Za-z0-9+.-]*://", []byte(dest)); err != nil { - return errors.Wrapf(err, "invalid destination") + return fmt.Errorf("invalid destination: %w", err) } else if !match { dest = "ssh://" + dest } @@ -95,7 +92,7 @@ func add(cmd *cobra.Command, args []string) error { switch uri.Scheme { case "ssh": if uri.User.Username() == "" { - if uri.User, err = GetUserInfo(uri); err != nil { + if uri.User, err = utils.GetUserInfo(uri); err != nil { return err } } @@ -180,44 +177,20 @@ func add(cmd *cobra.Command, args []string) error { return cfg.Write() } -func GetUserInfo(uri *url.URL) (*url.Userinfo, error) { - var ( - usr *user.User - err error - ) - if u, found := os.LookupEnv("_CONTAINERS_ROOTLESS_UID"); found { - usr, err = user.LookupId(u) - if err != nil { - return nil, errors.Wrapf(err, "failed to look up rootless user") - } - } else { - usr, err = user.Current() - if err != nil { - return nil, errors.Wrapf(err, "failed to obtain current user") - } - } - - pw, set := uri.User.Password() - if set { - return url.UserPassword(usr.Username, pw), nil - } - return url.User(usr.Username), nil -} - func getUDS(uri *url.URL, iden string) (string, error) { - cfg, err := ValidateAndConfigure(uri, iden) + cfg, err := utils.ValidateAndConfigure(uri, iden) if err != nil { - return "", errors.Wrapf(err, "failed to validate") + return "", fmt.Errorf("failed to validate: %w", err) } dial, err := ssh.Dial("tcp", uri.Host, cfg) if err != nil { - return "", errors.Wrapf(err, "failed to connect") + return "", fmt.Errorf("failed to connect: %w", err) } defer dial.Close() session, err := dial.NewSession() if err != nil { - return "", errors.Wrapf(err, "failed to create new ssh session on %q", uri.Host) + return "", fmt.Errorf("failed to create new ssh session on %q: %w", uri.Host, err) } defer session.Close() @@ -226,94 +199,18 @@ func getUDS(uri *url.URL, iden string) (string, error) { if v, found := os.LookupEnv("PODMAN_BINARY"); found { podman = v } - infoJSON, err := ExecRemoteCommand(dial, podman+" info --format=json") + infoJSON, err := utils.ExecRemoteCommand(dial, podman+" info --format=json") if err != nil { return "", err } var info define.Info if err := json.Unmarshal(infoJSON, &info); err != nil { - return "", errors.Wrapf(err, "failed to parse 'podman info' results") + return "", fmt.Errorf("failed to parse 'podman info' results: %w", err) } if info.Host.RemoteSocket == nil || len(info.Host.RemoteSocket.Path) == 0 { - return "", errors.Errorf("remote podman %q failed to report its UDS socket", uri.Host) + return "", fmt.Errorf("remote podman %q failed to report its UDS socket", uri.Host) } return info.Host.RemoteSocket.Path, nil } - -// ValidateAndConfigure will take a ssh url and an identity key (rsa and the like) and ensure the information given is valid -// iden iden can be blank to mean no identity key -// once the function validates the information it creates and returns an ssh.ClientConfig. -func ValidateAndConfigure(uri *url.URL, iden string) (*ssh.ClientConfig, error) { - var signers []ssh.Signer - passwd, passwdSet := uri.User.Password() - if iden != "" { // iden might be blank if coming from image scp or if no validation is needed - value := iden - s, err := terminal.PublicKey(value, []byte(passwd)) - if err != nil { - return nil, errors.Wrapf(err, "failed to read identity %q", value) - } - signers = append(signers, s) - logrus.Debugf("SSH Ident Key %q %s %s", value, ssh.FingerprintSHA256(s.PublicKey()), s.PublicKey().Type()) - } - if sock, found := os.LookupEnv("SSH_AUTH_SOCK"); found { // validate ssh information, specifically the unix file socket used by the ssh agent. - logrus.Debugf("Found SSH_AUTH_SOCK %q, ssh-agent signer enabled", sock) - - c, err := net.Dial("unix", sock) - if err != nil { - return nil, err - } - agentSigners, err := agent.NewClient(c).Signers() - if err != nil { - return nil, err - } - - signers = append(signers, agentSigners...) - - if logrus.IsLevelEnabled(logrus.DebugLevel) { - for _, s := range agentSigners { - logrus.Debugf("SSH Agent Key %s %s", ssh.FingerprintSHA256(s.PublicKey()), s.PublicKey().Type()) - } - } - } - var authMethods []ssh.AuthMethod // now we validate and check for the authorization methods, most notaibly public key authorization - if len(signers) > 0 { - var dedup = make(map[string]ssh.Signer) - for _, s := range signers { - fp := ssh.FingerprintSHA256(s.PublicKey()) - if _, found := dedup[fp]; found { - logrus.Debugf("Dedup SSH Key %s %s", ssh.FingerprintSHA256(s.PublicKey()), s.PublicKey().Type()) - } - dedup[fp] = s - } - - var uniq []ssh.Signer - for _, s := range dedup { - uniq = append(uniq, s) - } - authMethods = append(authMethods, ssh.PublicKeysCallback(func() ([]ssh.Signer, error) { - return uniq, nil - })) - } - if passwdSet { // if password authentication is given and valid, add to the list - authMethods = append(authMethods, ssh.Password(passwd)) - } - if len(authMethods) == 0 { - authMethods = append(authMethods, ssh.PasswordCallback(func() (string, error) { - pass, err := terminal.ReadPassword(fmt.Sprintf("%s's login password:", uri.User.Username())) - return string(pass), err - })) - } - tick, err := time.ParseDuration("40s") - if err != nil { - return nil, err - } - cfg := &ssh.ClientConfig{ - User: uri.User.Username(), - Auth: authMethods, - HostKeyCallback: ssh.InsecureIgnoreHostKey(), - Timeout: tick, - } - return cfg, nil -} diff --git a/cmd/podman/system/connection/remove.go b/cmd/podman/system/connection/remove.go index 463eae9fa..29bf98c43 100644 --- a/cmd/podman/system/connection/remove.go +++ b/cmd/podman/system/connection/remove.go @@ -1,11 +1,12 @@ package connection import ( + "errors" + "github.com/containers/common/pkg/config" "github.com/containers/podman/v4/cmd/podman/common" "github.com/containers/podman/v4/cmd/podman/registry" "github.com/containers/podman/v4/cmd/podman/system" - "github.com/pkg/errors" "github.com/spf13/cobra" ) diff --git a/cmd/podman/system/connection/shared.go b/cmd/podman/system/connection/shared.go deleted file mode 100644 index 714ae827d..000000000 --- a/cmd/podman/system/connection/shared.go +++ /dev/null @@ -1,27 +0,0 @@ -package connection - -import ( - "bytes" - - "github.com/pkg/errors" - "golang.org/x/crypto/ssh" -) - -// ExecRemoteCommand takes a ssh client connection and a command to run and executes the -// command on the specified client. The function returns the Stdout from the client or the Stderr -func ExecRemoteCommand(dial *ssh.Client, run string) ([]byte, error) { - sess, err := dial.NewSession() // new ssh client session - if err != nil { - return nil, err - } - defer sess.Close() - - var buffer bytes.Buffer - var bufferErr bytes.Buffer - sess.Stdout = &buffer // output from client funneled into buffer - sess.Stderr = &bufferErr // err form client funneled into buffer - if err := sess.Run(run); err != nil { // run the command on the ssh client - return nil, errors.Wrapf(err, bufferErr.String()) - } - return buffer.Bytes(), nil -} diff --git a/cmd/podman/system/dial_stdio.go b/cmd/podman/system/dial_stdio.go index 8b665bedc..42ce65746 100644 --- a/cmd/podman/system/dial_stdio.go +++ b/cmd/podman/system/dial_stdio.go @@ -2,13 +2,15 @@ package system import ( "context" + "fmt" "io" "os" + "errors" + "github.com/containers/podman/v4/cmd/podman/registry" "github.com/containers/podman/v4/cmd/podman/validate" "github.com/containers/podman/v4/pkg/bindings" - "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -40,15 +42,15 @@ func runDialStdio() error { defer cancel() bindCtx, err := bindings.NewConnection(ctx, cfg.URI) if err != nil { - return errors.Wrap(err, "failed to open connection to podman") + return fmt.Errorf("failed to open connection to podman: %w", err) } conn, err := bindings.GetClient(bindCtx) if err != nil { - return errors.Wrap(err, "failed to get connection after initialization") + return fmt.Errorf("failed to get connection after initialization: %w", err) } netConn, err := conn.GetDialer(bindCtx) if err != nil { - return errors.Wrap(err, "failed to open the raw stream connection") + return fmt.Errorf("failed to open the raw stream connection: %w", err) } defer netConn.Close() @@ -95,7 +97,7 @@ func copier(to halfWriteCloser, from halfReadCloser, debugDescription string) er } }() if _, err := io.Copy(to, from); err != nil { - return errors.Wrapf(err, "error while Copy (%s)", debugDescription) + return fmt.Errorf("error while Copy (%s): %w", debugDescription, err) } return nil } diff --git a/cmd/podman/system/service_abi.go b/cmd/podman/system/service_abi.go index 7cb1b8084..6823d77ba 100644 --- a/cmd/podman/system/service_abi.go +++ b/cmd/podman/system/service_abi.go @@ -4,24 +4,46 @@ package system import ( + "errors" "fmt" "net" "net/url" "os" "path/filepath" + "github.com/containers/common/pkg/cgroups" "github.com/containers/podman/v4/cmd/podman/registry" api "github.com/containers/podman/v4/pkg/api/server" "github.com/containers/podman/v4/pkg/domain/entities" "github.com/containers/podman/v4/pkg/domain/infra" "github.com/containers/podman/v4/pkg/servicereaper" + "github.com/containers/podman/v4/utils" "github.com/coreos/go-systemd/v22/activation" - "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/spf13/pflag" "golang.org/x/sys/unix" ) +// maybeMoveToSubCgroup moves the current process in a sub cgroup when +// it is running in the root cgroup on a system that uses cgroupv2. +func maybeMoveToSubCgroup() error { + unifiedMode, err := cgroups.IsCgroup2UnifiedMode() + if err != nil { + return err + } + if !unifiedMode { + return nil + } + cgroup, err := utils.GetOwnCgroup() + if err != nil { + return err + } + if cgroup == "/" { + return utils.MoveUnderCgroupSubtree("init") + } + return nil +} + func restService(flags *pflag.FlagSet, cfg *entities.PodmanConfig, opts entities.ServiceOptions) error { var ( listener net.Listener @@ -48,13 +70,13 @@ func restService(flags *pflag.FlagSet, cfg *entities.PodmanConfig, opts entities listener = listeners[0] // note that activation.Listeners() returns nil when it cannot listen on the fd (i.e. udp connection) if listener == nil { - return fmt.Errorf("unexpected fd received from systemd: cannot listen on it") + return errors.New("unexpected fd received from systemd: cannot listen on it") } libpodRuntime.SetRemoteURI(listeners[0].Addr().String()) } else { uri, err := url.Parse(opts.URI) if err != nil { - return errors.Errorf("%s is an invalid socket destination", opts.URI) + return fmt.Errorf("%s is an invalid socket destination", opts.URI) } switch uri.Scheme { @@ -74,7 +96,7 @@ func restService(flags *pflag.FlagSet, cfg *entities.PodmanConfig, opts entities } else { listener, err = net.Listen(uri.Scheme, path) if err != nil { - return errors.Wrapf(err, "unable to create socket") + return fmt.Errorf("unable to create socket: %w", err) } } case "tcp": @@ -85,7 +107,7 @@ func restService(flags *pflag.FlagSet, cfg *entities.PodmanConfig, opts entities } listener, err = net.Listen(uri.Scheme, host) if err != nil { - return errors.Wrapf(err, "unable to create socket %v", host) + return fmt.Errorf("unable to create socket %v: %w", host, err) } default: logrus.Debugf("Attempting API Service endpoint scheme %q", uri.Scheme) @@ -103,6 +125,10 @@ func restService(flags *pflag.FlagSet, cfg *entities.PodmanConfig, opts entities return err } + if err := maybeMoveToSubCgroup(); err != nil { + return err + } + servicereaper.Start() infra.StartWatcher(libpodRuntime) server, err := api.NewServerWithSettings(libpodRuntime, listener, opts) diff --git a/cmd/podman/system/unshare.go b/cmd/podman/system/unshare.go index 1ed08eac3..6d9c33b64 100644 --- a/cmd/podman/system/unshare.go +++ b/cmd/podman/system/unshare.go @@ -1,6 +1,7 @@ package system import ( + "errors" "os" "github.com/containers/common/pkg/completion" @@ -8,7 +9,6 @@ import ( "github.com/containers/podman/v4/cmd/podman/utils" "github.com/containers/podman/v4/pkg/domain/entities" "github.com/containers/podman/v4/pkg/rootless" - "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/spf13/pflag" ) @@ -47,14 +47,14 @@ func init() { func unshare(cmd *cobra.Command, args []string) error { if isRootless := rootless.IsRootless(); !isRootless { - return errors.Errorf("please use unshare with rootless") + return errors.New("please use unshare with rootless") } // exec the specified command, if there is one if len(args) < 1 { // try to exec the shell, if one's set shell, shellSet := os.LookupEnv("SHELL") if !shellSet { - return errors.Errorf("no command specified and no $SHELL specified") + return errors.New("no command specified and no $SHELL specified") } args = []string{shell} } |