diff options
author | cdoern <cdoern@redhat.com> | 2021-08-11 16:14:57 -0400 |
---|---|---|
committer | cdoern <cbdoer23@g.holycross.edu> | 2021-11-05 12:04:20 -0400 |
commit | ffa5ed0e0e00f79a1f3b6a88bf9efce3dbb19207 (patch) | |
tree | e8f64c52d0785e84d46ae6879f9ecb7c590b55fd /pkg | |
parent | 85bad0cc7c68b71ab7ddb6ed09b862145c6c6d0e (diff) | |
download | podman-ffa5ed0e0e00f79a1f3b6a88bf9efce3dbb19207.tar.gz podman-ffa5ed0e0e00f79a1f3b6a88bf9efce3dbb19207.tar.bz2 podman-ffa5ed0e0e00f79a1f3b6a88bf9efce3dbb19207.zip |
Podman Image SCP rootful to rootless transfer
Added functionality for users to transfer images from root storage to rootless storage without using sshd. This is
done through rootful podman by running `sudo podman image scp root@localhost::image user@localhost:: the user is needed
in order to find and use their uid/gid to exec a new process.
added necessary tests, and functions for this implementation. Created new image function Transfer so that
the underlying code is majorly removed from CLI
Signed-off-by: cdoern <cdoern@redhat.com>
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/domain/entities/engine_image.go | 1 | ||||
-rw-r--r-- | pkg/domain/entities/images.go | 4 | ||||
-rw-r--r-- | pkg/domain/infra/abi/images.go | 65 | ||||
-rw-r--r-- | pkg/domain/infra/tunnel/images.go | 5 |
4 files changed, 75 insertions, 0 deletions
diff --git a/pkg/domain/entities/engine_image.go b/pkg/domain/entities/engine_image.go index b0f9ae408..d72f64b5e 100644 --- a/pkg/domain/entities/engine_image.go +++ b/pkg/domain/entities/engine_image.go @@ -27,6 +27,7 @@ type ImageEngine interface { ShowTrust(ctx context.Context, args []string, options ShowTrustOptions) (*ShowTrustReport, error) Shutdown(ctx context.Context) Tag(ctx context.Context, nameOrID string, tags []string, options ImageTagOptions) error + Transfer(ctx context.Context, scpOpts ImageScpOptions) error Tree(ctx context.Context, nameOrID string, options ImageTreeOptions) (*ImageTreeReport, error) Unmount(ctx context.Context, images []string, options ImageUnmountOptions) ([]*ImageUnmountReport, error) Untag(ctx context.Context, nameOrID string, tags []string, options ImageUntagOptions) error diff --git a/pkg/domain/entities/images.go b/pkg/domain/entities/images.go index ac5e6f410..7ac07a8b3 100644 --- a/pkg/domain/entities/images.go +++ b/pkg/domain/entities/images.go @@ -328,6 +328,10 @@ type ImageScpOptions struct { Save ImageSaveOptions // Load options used for the second half of the scp operation Load ImageLoadOptions + // Rootless determines whether we are loading locally from root storage to rootless storage + Rootless bool + // User is used in conjunction with Rootless to determine which user to use to obtain the uid + User string } // ImageTreeOptions provides options for ImageEngine.Tree() diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go index 8878bf128..e9528acf1 100644 --- a/pkg/domain/infra/abi/images.go +++ b/pkg/domain/infra/abi/images.go @@ -6,9 +6,12 @@ import ( "io/ioutil" "net/url" "os" + "os/exec" + "os/user" "path" "path/filepath" "strconv" + "strings" "github.com/containers/common/libimage" "github.com/containers/common/pkg/config" @@ -18,6 +21,7 @@ import ( "github.com/containers/image/v5/signature" "github.com/containers/image/v5/transports" "github.com/containers/image/v5/transports/alltransports" + "github.com/containers/podman/v3/libpod/define" "github.com/containers/podman/v3/pkg/domain/entities" "github.com/containers/podman/v3/pkg/domain/entities/reports" domainUtils "github.com/containers/podman/v3/pkg/domain/utils" @@ -330,6 +334,67 @@ func (ir *ImageEngine) Push(ctx context.Context, source string, destination stri return pushError } +// Transfer moves images from root to rootless storage so the user specified in the scp call can access and use the image modified by root +func (ir *ImageEngine) Transfer(ctx context.Context, scpOpts entities.ImageScpOptions) error { + if scpOpts.User == "" { + return errors.Wrapf(define.ErrInvalidArg, "you must define a user when transferring from root to rootless storage") + } + var u *user.User + scpOpts.User = strings.Split(scpOpts.User, ":")[0] // split in case provided with uid:gid + _, err := strconv.Atoi(scpOpts.User) + if err != nil { + u, err = user.Lookup(scpOpts.User) + if err != nil { + return err + } + } else { + u, err = user.LookupId(scpOpts.User) + if err != nil { + return err + } + } + uid, err := strconv.Atoi(u.Uid) + if err != nil { + return err + } + gid, err := strconv.Atoi(u.Gid) + if err != nil { + return err + } + err = os.Chown(scpOpts.Save.Output, uid, gid) // chown the output because was created by root so we need to give th euser read access + if err != nil { + return err + } + + podman, err := os.Executable() + if err != nil { + return err + } + machinectl, err := exec.LookPath("machinectl") + if err != nil { + logrus.Warn("defaulting to su since machinectl is not available, su will fail if no user session is available") + cmd := exec.Command("su", "-l", u.Username, "--command", podman+" --log-level="+logrus.GetLevel().String()+" --cgroup-manager=cgroupfs load --input="+scpOpts.Save.Output) // load the new image to the rootless storage + cmd.Stderr = os.Stderr + cmd.Stdout = os.Stdout + logrus.Debug("Executing load command su") + err = cmd.Run() + if err != nil { + return err + } + } else { + cmd := exec.Command(machinectl, "shell", "-q", u.Username+"@.host", podman, "--log-level="+logrus.GetLevel().String(), "--cgroup-manager=cgroupfs", "load", "--input", scpOpts.Save.Output) // load the new image to the rootless storage + cmd.Stderr = os.Stderr + cmd.Stdout = os.Stdout + logrus.Debug("Executing load command machinectl") + err = cmd.Run() + if err != nil { + return err + } + } + + return nil +} + func (ir *ImageEngine) Tag(ctx context.Context, nameOrID string, tags []string, options entities.ImageTagOptions) error { // Allow tagging manifest list instead of resolving instances from manifest lookupOptions := &libimage.LookupImageOptions{ManifestList: true} diff --git a/pkg/domain/infra/tunnel/images.go b/pkg/domain/infra/tunnel/images.go index b8af2de68..ed0c35de4 100644 --- a/pkg/domain/infra/tunnel/images.go +++ b/pkg/domain/infra/tunnel/images.go @@ -12,6 +12,7 @@ import ( "github.com/containers/common/pkg/config" "github.com/containers/image/v5/docker/reference" "github.com/containers/image/v5/types" + "github.com/containers/podman/v3/libpod/define" "github.com/containers/podman/v3/pkg/bindings/images" "github.com/containers/podman/v3/pkg/domain/entities" "github.com/containers/podman/v3/pkg/domain/entities/reports" @@ -122,6 +123,10 @@ func (ir *ImageEngine) Pull(ctx context.Context, rawImage string, opts entities. return &entities.ImagePullReport{Images: pulledImages}, nil } +func (ir *ImageEngine) Transfer(ctx context.Context, scpOpts entities.ImageScpOptions) error { + return errors.Wrapf(define.ErrNotImplemented, "cannot use the remote client to transfer images between root and rootless storage") +} + func (ir *ImageEngine) Tag(ctx context.Context, nameOrID string, tags []string, opt entities.ImageTagOptions) error { options := new(images.TagOptions) for _, newTag := range tags { |