summaryrefslogtreecommitdiff
path: root/pkg
diff options
context:
space:
mode:
Diffstat (limited to 'pkg')
-rw-r--r--pkg/api/handlers/libpod/pods.go6
-rw-r--r--pkg/domain/entities/pods.go2
-rw-r--r--pkg/specgen/generate/kube/kube.go2
-rw-r--r--pkg/specgen/generate/namespaces.go59
-rw-r--r--pkg/specgen/generate/pod_create.go8
-rw-r--r--pkg/specgen/namespaces.go58
-rw-r--r--pkg/specgen/podspecgen.go4
7 files changed, 95 insertions, 44 deletions
diff --git a/pkg/api/handlers/libpod/pods.go b/pkg/api/handlers/libpod/pods.go
index 4dc8740e2..ff105bc48 100644
--- a/pkg/api/handlers/libpod/pods.go
+++ b/pkg/api/handlers/libpod/pods.go
@@ -30,6 +30,12 @@ func PodCreate(w http.ResponseWriter, r *http.Request) {
utils.Error(w, "failed to decode specgen", http.StatusInternalServerError, errors.Wrap(err, "failed to decode specgen"))
return
}
+ // parse userns so we get the valid default value of userns
+ psg.Userns, err = specgen.ParseUserNamespace(psg.Userns.String())
+ if err != nil {
+ utils.Error(w, "failed to parse userns", http.StatusInternalServerError, errors.Wrap(err, "failed to parse userns"))
+ return
+ }
pod, err := generate.MakePod(&psg, runtime)
if err != nil {
httpCode := http.StatusInternalServerError
diff --git a/pkg/domain/entities/pods.go b/pkg/domain/entities/pods.go
index 68e335f8d..c66bf96fc 100644
--- a/pkg/domain/entities/pods.go
+++ b/pkg/domain/entities/pods.go
@@ -122,6 +122,7 @@ type PodCreateOptions struct {
Pid string
Cpus float64
CpusetCpus string
+ Userns specgen.Namespace
}
type PodCreateReport struct {
@@ -217,6 +218,7 @@ func (p *PodCreateOptions) ToPodSpecGen(s *specgen.PodSpecGenerator) error {
s.CPUQuota = *cpuDat.Quota
}
}
+ s.Userns = p.Userns
return nil
}
diff --git a/pkg/specgen/generate/kube/kube.go b/pkg/specgen/generate/kube/kube.go
index fb7eb99a2..d6d479c67 100644
--- a/pkg/specgen/generate/kube/kube.go
+++ b/pkg/specgen/generate/kube/kube.go
@@ -303,6 +303,8 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener
if opts.NetNSIsHost {
s.NetNS.NSMode = specgen.Host
}
+ // Always set the userns to host since k8s doesn't have support for userns yet
+ s.UserNS.NSMode = specgen.Host
// Add labels that come from kube
if len(s.Labels) == 0 {
diff --git a/pkg/specgen/generate/namespaces.go b/pkg/specgen/generate/namespaces.go
index f41186ae4..1d7373093 100644
--- a/pkg/specgen/generate/namespaces.go
+++ b/pkg/specgen/generate/namespaces.go
@@ -175,6 +175,11 @@ func namespaceOptions(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.
if pod == nil || infraCtr == nil {
return nil, errNoInfra
}
+ // Inherit the user from the infra container if it is set and --user has not
+ // been set explicitly
+ if infraCtr.User() != "" && s.User == "" {
+ toReturn = append(toReturn, libpod.WithUser(infraCtr.User()))
+ }
toReturn = append(toReturn, libpod.WithUserNSFrom(infraCtr))
case specgen.FromContainer:
userCtr, err := rt.LookupContainer(s.UserNS.Value)
@@ -184,7 +189,10 @@ func namespaceOptions(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.
toReturn = append(toReturn, libpod.WithUserNSFrom(userCtr))
}
- if s.IDMappings != nil {
+ // This wipes the UserNS settings that get set from the infra container
+ // when we are inheritting from the pod. So only apply this if the container
+ // is not being created in a pod.
+ if s.IDMappings != nil && pod == nil {
toReturn = append(toReturn, libpod.WithIDMappings(*s.IDMappings))
}
if s.User != "" {
@@ -379,46 +387,8 @@ func specConfigureNamespaces(s *specgen.SpecGenerator, g *generate.Generator, rt
}
// User
- switch s.UserNS.NSMode {
- case specgen.Path:
- if _, err := os.Stat(s.UserNS.Value); err != nil {
- return errors.Wrap(err, "cannot find specified user namespace path")
- }
- if err := g.AddOrReplaceLinuxNamespace(string(spec.UserNamespace), s.UserNS.Value); err != nil {
- return err
- }
- // runc complains if no mapping is specified, even if we join another ns. So provide a dummy mapping
- g.AddLinuxUIDMapping(uint32(0), uint32(0), uint32(1))
- g.AddLinuxGIDMapping(uint32(0), uint32(0), uint32(1))
- case specgen.Host:
- if err := g.RemoveLinuxNamespace(string(spec.UserNamespace)); err != nil {
- return err
- }
- case specgen.KeepID:
- var (
- err error
- uid, gid int
- )
- s.IDMappings, uid, gid, err = util.GetKeepIDMapping()
- if err != nil {
- return err
- }
- g.SetProcessUID(uint32(uid))
- g.SetProcessGID(uint32(gid))
- fallthrough
- case specgen.Private:
- if err := g.AddOrReplaceLinuxNamespace(string(spec.UserNamespace), ""); err != nil {
- return err
- }
- if s.IDMappings == nil || (len(s.IDMappings.UIDMap) == 0 && len(s.IDMappings.GIDMap) == 0) {
- return errors.Errorf("must provide at least one UID or GID mapping to configure a user namespace")
- }
- for _, uidmap := range s.IDMappings.UIDMap {
- g.AddLinuxUIDMapping(uint32(uidmap.HostID), uint32(uidmap.ContainerID), uint32(uidmap.Size))
- }
- for _, gidmap := range s.IDMappings.GIDMap {
- g.AddLinuxGIDMapping(uint32(gidmap.HostID), uint32(gidmap.ContainerID), uint32(gidmap.Size))
- }
+ if _, err := specgen.SetupUserNS(s.IDMappings, s.UserNS, g); err != nil {
+ return err
}
// Cgroup
@@ -474,7 +444,7 @@ func specConfigureNamespaces(s *specgen.SpecGenerator, g *generate.Generator, rt
// GetNamespaceOptions transforms a slice of kernel namespaces
// into a slice of pod create options. Currently, not all
// kernel namespaces are supported, and they will be returned in an error
-func GetNamespaceOptions(ns []string) ([]libpod.PodCreateOption, error) {
+func GetNamespaceOptions(ns []string, netnsIsHost bool) ([]libpod.PodCreateOption, error) {
var options []libpod.PodCreateOption
var erroredOptions []libpod.PodCreateOption
if ns == nil {
@@ -486,7 +456,10 @@ func GetNamespaceOptions(ns []string) ([]libpod.PodCreateOption, error) {
case "cgroup":
options = append(options, libpod.WithPodCgroups())
case "net":
- options = append(options, libpod.WithPodNet())
+ // share the netns setting with other containers in the pod only when it is not set to host
+ if !netnsIsHost {
+ options = append(options, libpod.WithPodNet())
+ }
case "mnt":
return erroredOptions, errors.Errorf("Mount sharing functionality not supported on pod level")
case "pid":
diff --git a/pkg/specgen/generate/pod_create.go b/pkg/specgen/generate/pod_create.go
index aab29499e..426cf1b6d 100644
--- a/pkg/specgen/generate/pod_create.go
+++ b/pkg/specgen/generate/pod_create.go
@@ -27,11 +27,16 @@ func createPodOptions(p *specgen.PodSpecGenerator, rt *libpod.Runtime) ([]libpod
)
if !p.NoInfra {
options = append(options, libpod.WithInfraContainer())
- nsOptions, err := GetNamespaceOptions(p.SharedNamespaces)
+ nsOptions, err := GetNamespaceOptions(p.SharedNamespaces, p.NetNS.IsHost())
if err != nil {
return nil, err
}
options = append(options, nsOptions...)
+ // Use pod user and infra userns only when --userns is not set to host
+ if !p.Userns.IsHost() {
+ options = append(options, libpod.WithPodUser())
+ options = append(options, libpod.WithPodUserns(p.Userns))
+ }
// Make our exit command
storageConfig := rt.StorageConfig()
@@ -154,5 +159,6 @@ func createPodOptions(p *specgen.PodSpecGenerator, rt *libpod.Runtime) ([]libpod
if len(p.InfraConmonPidFile) > 0 {
options = append(options, libpod.WithInfraConmonPidFile(p.InfraConmonPidFile))
}
+
return options, nil
}
diff --git a/pkg/specgen/namespaces.go b/pkg/specgen/namespaces.go
index 76fa66bc7..2f4c48811 100644
--- a/pkg/specgen/namespaces.go
+++ b/pkg/specgen/namespaces.go
@@ -1,10 +1,16 @@
package specgen
import (
+ "fmt"
+ "os"
"strings"
"github.com/containers/podman/v3/pkg/cgroups"
"github.com/containers/podman/v3/pkg/rootless"
+ "github.com/containers/podman/v3/pkg/util"
+ "github.com/containers/storage"
+ spec "github.com/opencontainers/runtime-spec/specs-go"
+ "github.com/opencontainers/runtime-tools/generate"
"github.com/pkg/errors"
)
@@ -103,6 +109,13 @@ func (n *Namespace) IsKeepID() bool {
return n.NSMode == KeepID
}
+func (n *Namespace) String() string {
+ if n.Value != "" {
+ return fmt.Sprintf("%s:%s", n.NSMode, n.Value)
+ }
+ return string(n.NSMode)
+}
+
func validateUserNS(n *Namespace) error {
if n == nil {
return nil
@@ -323,3 +336,48 @@ func ParseNetworkString(network string) (Namespace, []string, map[string][]strin
}
return ns, cniNets, networkOptions, nil
}
+
+func SetupUserNS(idmappings *storage.IDMappingOptions, userns Namespace, g *generate.Generator) (string, error) {
+ // User
+ var user string
+ switch userns.NSMode {
+ case Path:
+ if _, err := os.Stat(userns.Value); err != nil {
+ return user, errors.Wrap(err, "cannot find specified user namespace path")
+ }
+ if err := g.AddOrReplaceLinuxNamespace(string(spec.UserNamespace), userns.Value); err != nil {
+ return user, err
+ }
+ // runc complains if no mapping is specified, even if we join another ns. So provide a dummy mapping
+ g.AddLinuxUIDMapping(uint32(0), uint32(0), uint32(1))
+ g.AddLinuxGIDMapping(uint32(0), uint32(0), uint32(1))
+ case Host:
+ if err := g.RemoveLinuxNamespace(string(spec.UserNamespace)); err != nil {
+ return user, err
+ }
+ case KeepID:
+ mappings, uid, gid, err := util.GetKeepIDMapping()
+ if err != nil {
+ return user, err
+ }
+ idmappings = mappings
+ g.SetProcessUID(uint32(uid))
+ g.SetProcessGID(uint32(gid))
+ user = fmt.Sprintf("%d:%d", uid, gid)
+ fallthrough
+ case Private:
+ if err := g.AddOrReplaceLinuxNamespace(string(spec.UserNamespace), ""); err != nil {
+ return user, err
+ }
+ if idmappings == nil || (len(idmappings.UIDMap) == 0 && len(idmappings.GIDMap) == 0) {
+ return user, errors.Errorf("must provide at least one UID or GID mapping to configure a user namespace")
+ }
+ for _, uidmap := range idmappings.UIDMap {
+ g.AddLinuxUIDMapping(uint32(uidmap.HostID), uint32(uidmap.ContainerID), uint32(uidmap.Size))
+ }
+ for _, gidmap := range idmappings.GIDMap {
+ g.AddLinuxGIDMapping(uint32(gidmap.HostID), uint32(gidmap.ContainerID), uint32(gidmap.Size))
+ }
+ }
+ return user, nil
+}
diff --git a/pkg/specgen/podspecgen.go b/pkg/specgen/podspecgen.go
index 02237afe9..893ebf675 100644
--- a/pkg/specgen/podspecgen.go
+++ b/pkg/specgen/podspecgen.go
@@ -67,6 +67,10 @@ type PodBasicConfig struct {
// Optional (defaults to private if unset). This sets the PID namespace of the infra container
// This configuration will then be shared with the entire pod if PID namespace sharing is enabled via --share
Pid Namespace `json:"pid,omitempty:"`
+ // Userns is used to indicate which kind of Usernamespace to enter.
+ // Any containers created within the pod will inherit the pod's userns settings.
+ // Optional
+ Userns Namespace `json:"userns,omitempty"`
}
// PodNetworkConfig contains networking configuration for a pod.