diff options
author | Daniel J Walsh <dwalsh@redhat.com> | 2018-04-23 20:42:53 -0400 |
---|---|---|
committer | Atomic Bot <atomic-devel@projectatomic.io> | 2018-05-04 17:15:55 +0000 |
commit | b51d7379987581da82902027fe91cdf298047bc0 (patch) | |
tree | f9d7fbebf3b946caea5eb5e2c626a19413c795c8 /cmd/podman | |
parent | 1f5debd43806cc3bd07f562ff00ef4c426540f98 (diff) | |
download | podman-b51d7379987581da82902027fe91cdf298047bc0.tar.gz podman-b51d7379987581da82902027fe91cdf298047bc0.tar.bz2 podman-b51d7379987581da82902027fe91cdf298047bc0.zip |
Begin wiring in USERNS Support into podman
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
Closes: #690
Approved by: mheon
Diffstat (limited to 'cmd/podman')
-rw-r--r-- | cmd/podman/common.go | 17 | ||||
-rw-r--r-- | cmd/podman/create.go | 71 | ||||
-rw-r--r-- | cmd/podman/inspect.go | 2 | ||||
-rw-r--r-- | cmd/podman/libpodruntime/runtime.go | 37 | ||||
-rw-r--r-- | cmd/podman/run.go | 16 | ||||
-rw-r--r-- | cmd/podman/run_test.go | 3 | ||||
-rw-r--r-- | cmd/podman/spec.go | 17 |
7 files changed, 117 insertions, 46 deletions
diff --git a/cmd/podman/common.go b/cmd/podman/common.go index 68d22b629..635869609 100644 --- a/cmd/podman/common.go +++ b/cmd/podman/common.go @@ -200,6 +200,10 @@ var createFlags = []cli.Flag{ Usage: "Expose a port or a range of ports (default [])", }, cli.StringSliceFlag{ + Name: "gidmap", + Usage: "GID map to use for the user namespace", + }, + cli.StringSliceFlag{ Name: "group-add", Usage: "Add additional groups to join (default [])", }, @@ -341,6 +345,15 @@ var createFlags = []cli.Flag{ Name: "storage-opt", Usage: "Storage driver options per container (default [])", }, + cli.StringFlag{ + Name: "subgidname", + Usage: "Name of range listed in /etc/subgid for use in user namespace", + }, + cli.StringFlag{ + Name: "subuidname", + Usage: "Name of range listed in /etc/subuid for use in user namespace", + }, + cli.StringSliceFlag{ Name: "sysctl", Usage: "Sysctl options (default [])", @@ -354,6 +367,10 @@ var createFlags = []cli.Flag{ Usage: "Allocate a pseudo-TTY for container", }, cli.StringSliceFlag{ + Name: "uidmap", + Usage: "UID map to use for the user namespace", + }, + cli.StringSliceFlag{ Name: "ulimit", Usage: "Ulimit options (default [])", }, diff --git a/cmd/podman/create.go b/cmd/podman/create.go index 54a542ee5..7740da8e1 100644 --- a/cmd/podman/create.go +++ b/cmd/podman/create.go @@ -1,6 +1,7 @@ package main import ( + "context" "encoding/json" "fmt" "net" @@ -9,6 +10,7 @@ import ( "strings" "syscall" + "github.com/containers/storage" "github.com/docker/docker/api/types/container" "github.com/docker/docker/pkg/signal" "github.com/docker/go-connections/nat" @@ -92,7 +94,8 @@ type createConfig struct { Hostname string //hostname Image string ImageID string - BuiltinImgVolumes map[string]struct{} // volumes defined in the image config + BuiltinImgVolumes map[string]struct{} // volumes defined in the image config + IDMappings *storage.IDMappingOptions ImageVolumeType string // how to handle the image volume, either bind, tmpfs, or ignore Interactive bool //interactive IpcMode container.IpcMode //ipc @@ -108,8 +111,7 @@ type createConfig struct { Network string //network NetworkAlias []string //network-alias PidMode container.PidMode //pid - NsUser string - Pod string //pod + Pod string //pod PortBindings nat.PortMap Privileged bool //privileged Publish []string //publish @@ -119,20 +121,21 @@ type createConfig struct { Resources createResourceConfig Rm bool //rm ShmDir string - StopSignal syscall.Signal // stop-signal - StopTimeout uint // stop-timeout - Sysctl map[string]string //sysctl - Tmpfs []string // tmpfs - Tty bool //tty - User string //user - UtsMode container.UTSMode //uts - Volumes []string //volume - WorkDir string //workdir - MountLabel string //SecurityOpts - ProcessLabel string //SecurityOpts - NoNewPrivs bool //SecurityOpts - ApparmorProfile string //SecurityOpts - SeccompProfilePath string //SecurityOpts + StopSignal syscall.Signal // stop-signal + StopTimeout uint // stop-timeout + Sysctl map[string]string //sysctl + Tmpfs []string // tmpfs + Tty bool //tty + UsernsMode container.UsernsMode //userns + User string //user + UtsMode container.UTSMode //uts + Volumes []string //volume + WorkDir string //workdir + MountLabel string //SecurityOpts + ProcessLabel string //SecurityOpts + NoNewPrivs bool //SecurityOpts + ApparmorProfile string //SecurityOpts + SeccompProfilePath string //SecurityOpts SecurityOpts []string } @@ -174,7 +177,15 @@ func createCmd(c *cli.Context) error { return errors.Errorf("image name or ID is required") } - runtime, err := libpodruntime.GetRuntime(c) + mappings, err := util.ParseIDMapping(c.StringSlice("uidmap"), c.StringSlice("gidmap"), c.String("subuidmap"), c.String("subgidmap")) + if err != nil { + return err + } + storageOpts := storage.DefaultStoreOptions + storageOpts.UIDMap = mappings.UIDMap + storageOpts.GIDMap = mappings.GIDMap + + runtime, err := libpodruntime.GetRuntimeWithStorageOpts(c, &storageOpts) if err != nil { return errors.Wrapf(err, "error creating libpod runtime") } @@ -188,7 +199,7 @@ func createCmd(c *cli.Context) error { return err } data, err := newImage.Inspect(ctx) - createConfig, err := parseCreateOpts(c, runtime, newImage.Names()[0], data) + createConfig, err := parseCreateOpts(ctx, c, runtime, newImage.Names()[0], data) if err != nil { return err } @@ -211,6 +222,7 @@ func createCmd(c *cli.Context) error { options = append(options, libpod.WithShmDir(createConfig.ShmDir)) options = append(options, libpod.WithShmSize(createConfig.Resources.ShmSize)) options = append(options, libpod.WithGroups(createConfig.GroupAdd)) + options = append(options, libpod.WithIDMappings(*createConfig.IDMappings)) ctr, err := runtime.NewContainer(ctx, runtimeSpec, options...) if err != nil { return err @@ -414,10 +426,16 @@ func getRandomPort() (int, error) { // Parses CLI options related to container creation into a config which can be // parsed into an OCI runtime spec -func parseCreateOpts(c *cli.Context, runtime *libpod.Runtime, imageName string, data *inspect.ImageData) (*createConfig, error) { - var inputCommand, command []string - var memoryLimit, memoryReservation, memorySwap, memoryKernel int64 - var blkioWeight uint16 +func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtime, imageName string, data *inspect.ImageData) (*createConfig, error) { + var ( + inputCommand, command []string + memoryLimit, memoryReservation, memorySwap, memoryKernel int64 + blkioWeight uint16 + ) + idmappings, err := util.ParseIDMapping(c.StringSlice("uidmap"), c.StringSlice("gidmap"), c.String("subuidname"), c.String("subgidname")) + if err != nil { + return nil, err + } imageID := data.ID @@ -473,6 +491,11 @@ func parseCreateOpts(c *cli.Context, runtime *libpod.Runtime, imageName string, return nil, errors.Errorf("--pid %q is not valid", c.String("pid")) } + usernsMode := container.UsernsMode(c.String("userns")) + if !usernsMode.Valid() { + return nil, errors.Errorf("--userns %q is not valid", c.String("userns")) + } + if c.Bool("detach") && c.Bool("rm") { return nil, errors.Errorf("--rm and --detach can not be specified together") } @@ -653,6 +676,7 @@ func parseCreateOpts(c *cli.Context, runtime *libpod.Runtime, imageName string, GroupAdd: c.StringSlice("group-add"), Hostname: c.String("hostname"), HostAdd: c.StringSlice("add-host"), + IDMappings: idmappings, Image: imageName, ImageID: imageID, Interactive: c.Bool("interactive"), @@ -712,6 +736,7 @@ func parseCreateOpts(c *cli.Context, runtime *libpod.Runtime, imageName string, Tmpfs: c.StringSlice("tmpfs"), Tty: tty, User: user, + UsernsMode: usernsMode, Volumes: c.StringSlice("volume"), WorkDir: workDir, } diff --git a/cmd/podman/inspect.go b/cmd/podman/inspect.go index f54eb6d10..0fd1760a9 100644 --- a/cmd/podman/inspect.go +++ b/cmd/podman/inspect.go @@ -225,7 +225,7 @@ func getCtrInspectInfo(ctr *libpod.Container, ctrInspectData *inspect.ContainerI IpcMode: string(createArtifact.IpcMode), Cgroup: cgroup, UTSMode: string(createArtifact.UtsMode), - UsernsMode: createArtifact.NsUser, + UsernsMode: string(createArtifact.UsernsMode), GroupAdd: spec.Process.User.AdditionalGids, ContainerIDFile: createArtifact.CidFile, AutoRemove: createArtifact.Rm, diff --git a/cmd/podman/libpodruntime/runtime.go b/cmd/podman/libpodruntime/runtime.go index f9c14f6e7..d1657325d 100644 --- a/cmd/podman/libpodruntime/runtime.go +++ b/cmd/podman/libpodruntime/runtime.go @@ -8,27 +8,28 @@ import ( // GetRuntime generates a new libpod runtime configured by command line options func GetRuntime(c *cli.Context) (*libpod.Runtime, error) { + storageOpts := storage.DefaultStoreOptions + return GetRuntimeWithStorageOpts(c, &storageOpts) +} + +// GetRuntime generates a new libpod runtime configured by command line options +func GetRuntimeWithStorageOpts(c *cli.Context, storageOpts *storage.StoreOptions) (*libpod.Runtime, error) { options := []libpod.RuntimeOption{} - if c.GlobalIsSet("root") || c.GlobalIsSet("runroot") || - c.GlobalIsSet("storage-opt") || c.GlobalIsSet("storage-driver") { - storageOpts := storage.DefaultStoreOptions - - if c.GlobalIsSet("root") { - storageOpts.GraphRoot = c.GlobalString("root") - } - if c.GlobalIsSet("runroot") { - storageOpts.RunRoot = c.GlobalString("runroot") - } - if c.GlobalIsSet("storage-driver") { - storageOpts.GraphDriverName = c.GlobalString("storage-driver") - } - if c.GlobalIsSet("storage-opt") { - storageOpts.GraphDriverOptions = c.GlobalStringSlice("storage-opt") - } - - options = append(options, libpod.WithStorageConfig(storageOpts)) + if c.GlobalIsSet("root") { + storageOpts.GraphRoot = c.GlobalString("root") + } + if c.GlobalIsSet("runroot") { + storageOpts.RunRoot = c.GlobalString("runroot") } + if c.GlobalIsSet("storage-driver") { + storageOpts.GraphDriverName = c.GlobalString("storage-driver") + } + if c.GlobalIsSet("storage-opt") { + storageOpts.GraphDriverOptions = c.GlobalStringSlice("storage-opt") + } + + options = append(options, libpod.WithStorageConfig(*storageOpts)) // TODO CLI flags for image config? // TODO CLI flag for signature policy? diff --git a/cmd/podman/run.go b/cmd/podman/run.go index 5f0034e90..06bc0e9df 100644 --- a/cmd/podman/run.go +++ b/cmd/podman/run.go @@ -9,10 +9,12 @@ import ( "strconv" "strings" + "github.com/containers/storage" "github.com/pkg/errors" "github.com/projectatomic/libpod/cmd/podman/libpodruntime" "github.com/projectatomic/libpod/libpod" "github.com/projectatomic/libpod/libpod/image" + "github.com/projectatomic/libpod/pkg/util" "github.com/sirupsen/logrus" "github.com/urfave/cli" ) @@ -50,7 +52,15 @@ func runCmd(c *cli.Context) error { } } - runtime, err := libpodruntime.GetRuntime(c) + storageOpts := storage.DefaultStoreOptions + mappings, err := util.ParseIDMapping(c.StringSlice("uidmap"), c.StringSlice("gidmap"), c.String("subuidmap"), c.String("subgidmap")) + if err != nil { + return err + } + storageOpts.UIDMap = mappings.UIDMap + storageOpts.GIDMap = mappings.GIDMap + + runtime, err := libpodruntime.GetRuntimeWithStorageOpts(c, &storageOpts) if err != nil { return errors.Wrapf(err, "error creating libpod runtime") } @@ -60,7 +70,6 @@ func runCmd(c *cli.Context) error { } ctx := getContext() - rtc := runtime.GetConfig() newImage, err := runtime.ImageRuntime().New(ctx, c.Args()[0], rtc.SignaturePolicyPath, "", os.Stderr, nil, image.SigningOptions{}, false, false) if err != nil { @@ -76,7 +85,7 @@ func runCmd(c *cli.Context) error { } else { imageName = newImage.Names()[0] } - createConfig, err := parseCreateOpts(c, runtime, imageName, data) + createConfig, err := parseCreateOpts(ctx, c, runtime, imageName, data) if err != nil { return err } @@ -101,6 +110,7 @@ func runCmd(c *cli.Context) error { options = append(options, libpod.WithShmDir(createConfig.ShmDir)) options = append(options, libpod.WithShmSize(createConfig.Resources.ShmSize)) options = append(options, libpod.WithGroups(createConfig.GroupAdd)) + options = append(options, libpod.WithIDMappings(*createConfig.IDMappings)) // Default used if not overridden on command line diff --git a/cmd/podman/run_test.go b/cmd/podman/run_test.go index 3baee4615..bbcdcc60a 100644 --- a/cmd/podman/run_test.go +++ b/cmd/podman/run_test.go @@ -75,7 +75,8 @@ func getRuntimeSpec(c *cli.Context) (*spec.Spec, error) { } createConfig, err := parseCreateOpts(c, runtime, "alpine", generateAlpineImageData()) */ - createConfig, err := parseCreateOpts(c, nil, "alpine", generateAlpineImageData()) + ctx := getContext() + createConfig, err := parseCreateOpts(ctx, c, nil, "alpine", generateAlpineImageData()) if err != nil { return nil, err } diff --git a/cmd/podman/spec.go b/cmd/podman/spec.go index fc2ab267d..15dab6c4d 100644 --- a/cmd/podman/spec.go +++ b/cmd/podman/spec.go @@ -66,6 +66,13 @@ func addPidNS(config *createConfig, g *generate.Generator) error { return nil } +func addUserNS(config *createConfig, g *generate.Generator) error { + if (len(config.IDMappings.UIDMap) > 0 || len(config.IDMappings.GIDMap) > 0) && !config.UsernsMode.IsHost() { + g.AddOrReplaceLinuxNamespace(spec.UserNamespace, "") + } + return nil +} + func addNetNS(config *createConfig, g *generate.Generator) error { netMode := config.NetMode if netMode.IsHost() { @@ -257,6 +264,12 @@ func createConfigToOCISpec(config *createConfig) (*spec.Spec, error) { } } + for _, uidmap := range config.IDMappings.UIDMap { + g.AddLinuxUIDMapping(uint32(uidmap.HostID), uint32(uidmap.ContainerID), uint32(uidmap.Size)) + } + for _, gidmap := range config.IDMappings.GIDMap { + g.AddLinuxGIDMapping(uint32(gidmap.HostID), uint32(gidmap.ContainerID), uint32(gidmap.Size)) + } // SECURITY OPTS g.SetProcessNoNewPrivileges(config.NoNewPrivs) g.SetProcessApparmorProfile(config.ApparmorProfile) @@ -300,6 +313,10 @@ func createConfigToOCISpec(config *createConfig) (*spec.Spec, error) { return nil, err } + if err := addUserNS(config, &g); err != nil { + return nil, err + } + if err := addNetNS(config, &g); err != nil { return nil, err } |