mirror of
https://github.com/containers/skopeo.git
synced 2025-07-03 18:06:54 +00:00
rootless: don't create a namespace unless for containers-storage
This change fixes skopeo usage in restricted environment such as bubblewrap where it doesn't need extra capabilities or user namespace to perform its action. Close #649 Signed-off-by: Tristan Cacqueray <tdecacqu@redhat.com>
This commit is contained in:
parent
9fef0eb3f3
commit
b46d16f48c
@ -50,7 +50,6 @@ func copyCmd(global *globalOptions) cli.Command {
|
|||||||
`, strings.Join(transports.ListNames(), ", ")),
|
`, strings.Join(transports.ListNames(), ", ")),
|
||||||
ArgsUsage: "SOURCE-IMAGE DESTINATION-IMAGE",
|
ArgsUsage: "SOURCE-IMAGE DESTINATION-IMAGE",
|
||||||
Action: commandAction(opts.run),
|
Action: commandAction(opts.run),
|
||||||
Before: needsRexec,
|
|
||||||
// FIXME: Do we need to namespace the GPG aspect?
|
// FIXME: Do we need to namespace the GPG aspect?
|
||||||
Flags: append(append(append([]cli.Flag{
|
Flags: append(append(append([]cli.Flag{
|
||||||
cli.StringSliceFlag{
|
cli.StringSliceFlag{
|
||||||
@ -86,6 +85,11 @@ func (opts *copyOptions) run(args []string, stdout io.Writer) error {
|
|||||||
if len(args) != 2 {
|
if len(args) != 2 {
|
||||||
return errorShouldDisplayUsage{errors.New("Exactly two arguments expected")}
|
return errorShouldDisplayUsage{errors.New("Exactly two arguments expected")}
|
||||||
}
|
}
|
||||||
|
imageNames := args
|
||||||
|
|
||||||
|
if err := reexecIfNecessaryForImages(imageNames...); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
policyContext, err := opts.global.getPolicyContext()
|
policyContext, err := opts.global.getPolicyContext()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -93,13 +97,13 @@ func (opts *copyOptions) run(args []string, stdout io.Writer) error {
|
|||||||
}
|
}
|
||||||
defer policyContext.Destroy()
|
defer policyContext.Destroy()
|
||||||
|
|
||||||
srcRef, err := alltransports.ParseImageName(args[0])
|
srcRef, err := alltransports.ParseImageName(imageNames[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Invalid source name %s: %v", args[0], err)
|
return fmt.Errorf("Invalid source name %s: %v", imageNames[0], err)
|
||||||
}
|
}
|
||||||
destRef, err := alltransports.ParseImageName(args[1])
|
destRef, err := alltransports.ParseImageName(imageNames[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Invalid destination name %s: %v", args[1], err)
|
return fmt.Errorf("Invalid destination name %s: %v", imageNames[1], err)
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceCtx, err := opts.srcImage.newSystemContext()
|
sourceCtx, err := opts.srcImage.newSystemContext()
|
||||||
|
@ -24,9 +24,8 @@ func deleteCmd(global *globalOptions) cli.Command {
|
|||||||
image: imageOpts,
|
image: imageOpts,
|
||||||
}
|
}
|
||||||
return cli.Command{
|
return cli.Command{
|
||||||
Before: needsRexec,
|
Name: "delete",
|
||||||
Name: "delete",
|
Usage: "Delete image IMAGE-NAME",
|
||||||
Usage: "Delete image IMAGE-NAME",
|
|
||||||
Description: fmt.Sprintf(`
|
Description: fmt.Sprintf(`
|
||||||
Delete an "IMAGE_NAME" from a transport
|
Delete an "IMAGE_NAME" from a transport
|
||||||
|
|
||||||
@ -45,10 +44,15 @@ func (opts *deleteOptions) run(args []string, stdout io.Writer) error {
|
|||||||
if len(args) != 1 {
|
if len(args) != 1 {
|
||||||
return errors.New("Usage: delete imageReference")
|
return errors.New("Usage: delete imageReference")
|
||||||
}
|
}
|
||||||
|
imageName := args[0]
|
||||||
|
|
||||||
ref, err := alltransports.ParseImageName(args[0])
|
if err := reexecIfNecessaryForImages(imageName); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ref, err := alltransports.ParseImageName(imageName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Invalid source name %s: %v", args[0], err)
|
return fmt.Errorf("Invalid source name %s: %v", imageName, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
sys, err := opts.image.newSystemContext()
|
sys, err := opts.image.newSystemContext()
|
||||||
|
@ -68,7 +68,6 @@ func inspectCmd(global *globalOptions) cli.Command {
|
|||||||
Destination: &opts.config,
|
Destination: &opts.config,
|
||||||
},
|
},
|
||||||
}, sharedFlags...), imageFlags...),
|
}, sharedFlags...), imageFlags...),
|
||||||
Before: needsRexec,
|
|
||||||
Action: commandAction(opts.run),
|
Action: commandAction(opts.run),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -80,7 +79,13 @@ func (opts *inspectOptions) run(args []string, stdout io.Writer) (retErr error)
|
|||||||
if len(args) != 1 {
|
if len(args) != 1 {
|
||||||
return errors.New("Exactly one argument expected")
|
return errors.New("Exactly one argument expected")
|
||||||
}
|
}
|
||||||
img, err := parseImage(ctx, opts.image, args[0])
|
imageName := args[0]
|
||||||
|
|
||||||
|
if err := reexecIfNecessaryForImages(imageName); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
img, err := parseImage(ctx, opts.image, imageName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,6 @@ func layersCmd(global *globalOptions) cli.Command {
|
|||||||
Name: "layers",
|
Name: "layers",
|
||||||
Usage: "Get layers of IMAGE-NAME",
|
Usage: "Get layers of IMAGE-NAME",
|
||||||
ArgsUsage: "IMAGE-NAME [LAYER...]",
|
ArgsUsage: "IMAGE-NAME [LAYER...]",
|
||||||
Before: needsRexec,
|
|
||||||
Hidden: true,
|
Hidden: true,
|
||||||
Action: commandAction(opts.run),
|
Action: commandAction(opts.run),
|
||||||
Flags: append(sharedFlags, imageFlags...),
|
Flags: append(sharedFlags, imageFlags...),
|
||||||
@ -44,6 +43,11 @@ func (opts *layersOptions) run(args []string, stdout io.Writer) (retErr error) {
|
|||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
return errors.New("Usage: layers imageReference [layer...]")
|
return errors.New("Usage: layers imageReference [layer...]")
|
||||||
}
|
}
|
||||||
|
imageName := args[0]
|
||||||
|
|
||||||
|
if err := reexecIfNecessaryForImages(imageName); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
ctx, cancel := opts.global.commandTimeoutContext()
|
ctx, cancel := opts.global.commandTimeoutContext()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
@ -53,7 +57,7 @@ func (opts *layersOptions) run(args []string, stdout io.Writer) (retErr error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
cache := blobinfocache.DefaultCache(sys)
|
cache := blobinfocache.DefaultCache(sys)
|
||||||
rawSource, err := parseImageSource(ctx, opts.image, args[0])
|
rawSource, err := parseImageSource(ctx, opts.image, imageName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -5,3 +5,7 @@ package main
|
|||||||
func maybeReexec() error {
|
func maybeReexec() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func reexecIfNecessaryForImages(inputImageNames ...string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -2,6 +2,8 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/containers/buildah/pkg/unshare"
|
"github.com/containers/buildah/pkg/unshare"
|
||||||
|
"github.com/containers/image/storage"
|
||||||
|
"github.com/containers/image/transports/alltransports"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/syndtr/gocapability/capability"
|
"github.com/syndtr/gocapability/capability"
|
||||||
)
|
)
|
||||||
@ -32,3 +34,13 @@ func maybeReexec() error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func reexecIfNecessaryForImages(imageNames ...string) error {
|
||||||
|
// Check if container-storage are used before doing unshare
|
||||||
|
for _, imageName := range imageNames {
|
||||||
|
if alltransports.TransportFromImageName(imageName).Name() == storage.Transport.Name() {
|
||||||
|
return maybeReexec()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -16,10 +16,6 @@ type errorShouldDisplayUsage struct {
|
|||||||
error
|
error
|
||||||
}
|
}
|
||||||
|
|
||||||
func needsRexec(c *cli.Context) error {
|
|
||||||
return maybeReexec()
|
|
||||||
}
|
|
||||||
|
|
||||||
// commandAction intermediates between the cli.ActionFunc interface and the real handler,
|
// commandAction intermediates between the cli.ActionFunc interface and the real handler,
|
||||||
// primarily to ensure that cli.Context is not available to the handler, which in turn
|
// primarily to ensure that cli.Context is not available to the handler, which in turn
|
||||||
// makes sure that the cli.String() etc. flag access functions are not used,
|
// makes sure that the cli.String() etc. flag access functions are not used,
|
||||||
|
Loading…
Reference in New Issue
Block a user