diff options
author | Giuseppe Scrivano <gscrivan@redhat.com> | 2020-04-22 12:38:19 +0200 |
---|---|---|
committer | Giuseppe Scrivano <gscrivan@redhat.com> | 2020-04-23 18:05:03 +0200 |
commit | 48530acbd9a622cf88dbbb10cbc8e91575c476e5 (patch) | |
tree | 87ba5a727ec653d514e18e2686aa58453e20f70b | |
parent | 2fd6a84c09c4361c16f0bfe086dd4a190c5635b3 (diff) | |
download | podman-48530acbd9a622cf88dbbb10cbc8e91575c476e5.tar.gz podman-48530acbd9a622cf88dbbb10cbc8e91575c476e5.tar.bz2 podman-48530acbd9a622cf88dbbb10cbc8e91575c476e5.zip |
podman: handle namespaces specified on the CLI
and handle differently the user namespace as it supports additional
options.
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
-rw-r--r-- | cmd/podman/common/create.go | 15 | ||||
-rw-r--r-- | cmd/podman/common/specgen.go | 71 | ||||
-rw-r--r-- | cmd/podman/containers/create.go | 15 | ||||
-rw-r--r-- | pkg/specgen/container_validate.go | 2 | ||||
-rw-r--r-- | pkg/specgen/generate/namespaces.go | 3 | ||||
-rw-r--r-- | pkg/specgen/namespaces.go | 39 |
6 files changed, 88 insertions, 57 deletions
diff --git a/cmd/podman/common/create.go b/cmd/podman/common/create.go index e5ee76390..a0aed984c 100644 --- a/cmd/podman/common/create.go +++ b/cmd/podman/common/create.go @@ -49,8 +49,9 @@ func GetCreateFlags(cf *ContainerCLIOpts) *pflag.FlagSet { "cap-drop", []string{}, "Drop capabilities from the container", ) + cgroupNS := "" createFlags.StringVar( - &cf.CGroupsNS, + &cgroupNS, "cgroupns", containerConfig.CgroupNS(), "cgroup namespace to use", ) @@ -247,8 +248,9 @@ func GetCreateFlags(cf *ContainerCLIOpts) *pflag.FlagSet { "interactive", "i", false, "Keep STDIN open even if not attached", ) + ipcNS := "" createFlags.StringVar( - &cf.IPC, + &ipcNS, "ipc", containerConfig.IPCNS(), "IPC namespace to use", ) @@ -329,8 +331,9 @@ func GetCreateFlags(cf *ContainerCLIOpts) *pflag.FlagSet { "use `OS` instead of the running OS for choosing images", ) // markFlagHidden(createFlags, "override-os") + pid := "" createFlags.StringVar( - &cf.PID, + &pid, "pid", containerConfig.PidNS(), "PID namespace to use", ) @@ -461,13 +464,15 @@ func GetCreateFlags(cf *ContainerCLIOpts) *pflag.FlagSet { "user", "u", "", "Username or UID (format: <name|uid>[:<group|gid>])", ) + userNS := "" createFlags.StringVar( - &cf.UserNS, + &userNS, "userns", containerConfig.Containers.UserNS, "User namespace to use", ) + utsNS := "" createFlags.StringVar( - &cf.UTS, + &utsNS, "uts", containerConfig.Containers.UTSNS, "UTS namespace to use", ) diff --git a/cmd/podman/common/specgen.go b/cmd/podman/common/specgen.go index 994c5367e..b90030f7f 100644 --- a/cmd/podman/common/specgen.go +++ b/cmd/podman/common/specgen.go @@ -222,55 +222,28 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string s.PortMappings = ep s.Pod = c.Pod - //s.CgroupNS = specgen.Namespace{ - // NSMode: , - // Value: "", - //} - - //s.UserNS = specgen.Namespace{} - - // Kernel Namespaces - // TODO Fix handling of namespace from pod - // Instead of integrating here, should be done in libpod - // However, that also involves setting up security opts - // when the pod's namespace is integrated - //namespaces = map[string]string{ - // "cgroup": c.CGroupsNS, - // "pid": c.PID, - // //"net": c.Net.Network.Value, // TODO need help here - // "ipc": c.IPC, - // "user": c.User, - // "uts": c.UTS, - //} - // - //if len(c.PID) > 0 { - // split := strings.SplitN(c.PID, ":", 2) - // // need a way to do thsi - // specgen.Namespace{ - // NSMode: split[0], - // } - // //Value: split1 if len allows - //} - // TODO this is going to have be done after things like pod creation are done because - // pod creation changes these values. - //pidMode := ns.PidMode(namespaces["pid"]) - //usernsMode := ns.UsernsMode(namespaces["user"]) - //utsMode := ns.UTSMode(namespaces["uts"]) - //cgroupMode := ns.CgroupMode(namespaces["cgroup"]) - //ipcMode := ns.IpcMode(namespaces["ipc"]) - //// Make sure if network is set to container namespace, port binding is not also being asked for - //netMode := ns.NetworkMode(namespaces["net"]) - //if netMode.IsContainer() { - // if len(portBindings) > 0 { - // return nil, errors.Errorf("cannot set port bindings on an existing container network namespace") - // } - //} - - // TODO Remove when done with namespaces for realz - // Setting a default for IPC to get this working - s.IpcNS = specgen.Namespace{ - NSMode: specgen.Private, - Value: "", + for k, v := range map[string]*specgen.Namespace{ + c.IPC: &s.IpcNS, + c.PID: &s.PidNS, + c.UTS: &s.UtsNS, + c.CGroupsNS: &s.CgroupNS, + } { + if k != "" { + *v, err = specgen.ParseNamespace(k) + if err != nil { + return err + } + } + } + // userns must be treated differently + if c.UserNS != "" { + s.UserNS, err = specgen.ParseUserNamespace(c.UserNS) + if err != nil { + return err + } + } + if c.Net != nil { + s.NetNS = c.Net.Network } // TODO this is going to have to be done the libpod/server end of things diff --git a/cmd/podman/containers/create.go b/cmd/podman/containers/create.go index f8a7c07ef..8f140e2b8 100644 --- a/cmd/podman/containers/create.go +++ b/cmd/podman/containers/create.go @@ -149,6 +149,21 @@ func createInit(c *cobra.Command) error { if c.Flag("no-hosts").Changed && c.Flag("add-host").Changed { return errors.Errorf("--no-hosts and --add-host cannot be set together") } + if c.Flag("userns").Changed { + cliVals.UserNS = c.Flag("userns").Value.String() + } + if c.Flag("ipc").Changed { + cliVals.IPC = c.Flag("ipc").Value.String() + } + if c.Flag("uts").Changed { + cliVals.UTS = c.Flag("uts").Value.String() + } + if c.Flag("pid").Changed { + cliVals.PID = c.Flag("pid").Value.String() + } + if c.Flag("cgroupns").Changed { + cliVals.CGroupsNS = c.Flag("cgroupns").Value.String() + } // Docker-compatibility: the "-h" flag for run/create is reserved for // the hostname (see https://github.com/containers/libpod/issues/1367). diff --git a/pkg/specgen/container_validate.go b/pkg/specgen/container_validate.go index 219abfd9b..56c1a7ea9 100644 --- a/pkg/specgen/container_validate.go +++ b/pkg/specgen/container_validate.go @@ -129,7 +129,7 @@ func (s *SpecGenerator) Validate() error { if err := s.CgroupNS.validate(); err != nil { return err } - if err := s.UserNS.validate(); err != nil { + if err := validateUserNS(&s.UserNS); err != nil { return err } diff --git a/pkg/specgen/generate/namespaces.go b/pkg/specgen/generate/namespaces.go index 4ec1e859c..2aaeb9513 100644 --- a/pkg/specgen/generate/namespaces.go +++ b/pkg/specgen/generate/namespaces.go @@ -58,8 +58,7 @@ func GetDefaultNamespaceMode(nsType string, cfg *config.Config, pod *libpod.Pod) case "uts": return specgen.ParseNamespace(cfg.Containers.UTSNS) case "user": - // TODO: This may not work for --userns=auto - return specgen.ParseNamespace(cfg.Containers.UserNS) + return specgen.ParseUserNamespace(cfg.Containers.UserNS) case "net": ns, _, err := specgen.ParseNetworkNamespace(cfg.Containers.NetNS) return ns, err diff --git a/pkg/specgen/namespaces.go b/pkg/specgen/namespaces.go index 4f35b31bf..fffbd6d9e 100644 --- a/pkg/specgen/namespaces.go +++ b/pkg/specgen/namespaces.go @@ -33,6 +33,11 @@ const ( // Slirp indicates that a slirp4netns network stack should // be used Slirp NamespaceMode = "slirp4netns" + // KeepId indicates a user namespace to keep the owner uid inside + // of the namespace itself + KeepID NamespaceMode = "keep-id" + // KeepId indicates to automatically create a user namespace + Auto NamespaceMode = "auto" ) // Namespace describes the namespace @@ -71,6 +76,16 @@ func (n *Namespace) IsPod() bool { func (n *Namespace) IsPrivate() bool { return n.NSMode == Private } +func validateUserNS(n *Namespace) error { + if n == nil { + return nil + } + switch n.NSMode { + case Auto, KeepID: + return nil + } + return n.validate() +} func validateNetNS(n *Namespace) error { if n == nil { @@ -158,6 +173,30 @@ func ParseNamespace(ns string) (Namespace, error) { return toReturn, nil } +// ParseUserNamespace parses a user namespace specification in string +// form. +func ParseUserNamespace(ns string) (Namespace, error) { + toReturn := Namespace{} + switch { + case ns == "auto": + toReturn.NSMode = Auto + return toReturn, nil + case strings.HasPrefix(ns, "auto:"): + split := strings.SplitN(ns, ":", 2) + if len(split) != 2 { + return toReturn, errors.Errorf("invalid setting for auto: mode") + } + toReturn.NSMode = KeepID + toReturn.Value = split[1] + return toReturn, nil + case ns == "keep-id": + toReturn.NSMode = KeepID + toReturn.NSMode = FromContainer + return toReturn, nil + } + return ParseNamespace(ns) +} + // ParseNetworkNamespace parses a network namespace specification in string // form. // Returns a namespace and (optionally) a list of CNI networks to join. |