diff options
Diffstat (limited to 'pkg/specgen/generate')
-rw-r--r-- | pkg/specgen/generate/kube/kube.go | 9 | ||||
-rw-r--r-- | pkg/specgen/generate/namespaces.go | 67 | ||||
-rw-r--r-- | pkg/specgen/generate/pod_create.go | 8 | ||||
-rw-r--r-- | pkg/specgen/generate/ports.go | 32 | ||||
-rw-r--r-- | pkg/specgen/generate/storage.go | 57 |
5 files changed, 95 insertions, 78 deletions
diff --git a/pkg/specgen/generate/kube/kube.go b/pkg/specgen/generate/kube/kube.go index fb7eb99a2..04b4e5ab3 100644 --- a/pkg/specgen/generate/kube/kube.go +++ b/pkg/specgen/generate/kube/kube.go @@ -12,6 +12,7 @@ import ( "github.com/containers/common/pkg/parse" "github.com/containers/common/pkg/secrets" "github.com/containers/image/v5/manifest" + "github.com/containers/podman/v3/libpod/network/types" ann "github.com/containers/podman/v3/pkg/annotations" "github.com/containers/podman/v3/pkg/specgen" "github.com/containers/podman/v3/pkg/specgen/generate" @@ -303,6 +304,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 { @@ -586,8 +589,8 @@ func envVarValue(env v1.EnvVar, opts *CtrSpecGenOptions) (string, error) { // getPodPorts converts a slice of kube container descriptions to an // array of portmapping -func getPodPorts(containers []v1.Container) []specgen.PortMapping { - var infraPorts []specgen.PortMapping +func getPodPorts(containers []v1.Container) []types.PortMapping { + var infraPorts []types.PortMapping for _, container := range containers { for _, p := range container.Ports { if p.HostPort != 0 && p.ContainerPort == 0 { @@ -596,7 +599,7 @@ func getPodPorts(containers []v1.Container) []specgen.PortMapping { if p.Protocol == "" { p.Protocol = "tcp" } - portBinding := specgen.PortMapping{ + portBinding := types.PortMapping{ HostPort: uint16(p.HostPort), ContainerPort: uint16(p.ContainerPort), Protocol: strings.ToLower(string(p.Protocol)), diff --git a/pkg/specgen/generate/namespaces.go b/pkg/specgen/generate/namespaces.go index f41186ae4..80790dcc1 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 != "" { @@ -234,7 +242,7 @@ func namespaceOptions(ctx context.Context, s *specgen.SpecGenerator, rt *libpod. } toReturn = append(toReturn, libpod.WithNetNSFrom(netCtr)) case specgen.Slirp: - portMappings, err := createPortMappings(ctx, s, imageData) + portMappings, expose, err := createPortMappings(ctx, s, imageData) if err != nil { return nil, err } @@ -242,15 +250,15 @@ func namespaceOptions(ctx context.Context, s *specgen.SpecGenerator, rt *libpod. if s.NetNS.Value != "" { val = fmt.Sprintf("slirp4netns:%s", s.NetNS.Value) } - toReturn = append(toReturn, libpod.WithNetNS(portMappings, postConfigureNetNS, val, nil)) + toReturn = append(toReturn, libpod.WithNetNS(portMappings, expose, postConfigureNetNS, val, nil)) case specgen.Private: fallthrough case specgen.Bridge: - portMappings, err := createPortMappings(ctx, s, imageData) + portMappings, expose, err := createPortMappings(ctx, s, imageData) if err != nil { return nil, err } - toReturn = append(toReturn, libpod.WithNetNS(portMappings, postConfigureNetNS, "bridge", s.CNINetworks)) + toReturn = append(toReturn, libpod.WithNetNS(portMappings, expose, postConfigureNetNS, "bridge", s.CNINetworks)) } if s.UseImageHosts { @@ -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/generate/ports.go b/pkg/specgen/generate/ports.go index c00ad19fb..a300f8014 100644 --- a/pkg/specgen/generate/ports.go +++ b/pkg/specgen/generate/ports.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/containers/common/libimage" + "github.com/containers/podman/v3/libpod/network/types" "github.com/containers/podman/v3/utils" "github.com/containers/podman/v3/pkg/specgen" @@ -24,7 +25,7 @@ const ( // Parse port maps to OCICNI port mappings. // Returns a set of OCICNI port mappings, and maps of utilized container and // host ports. -func ParsePortMapping(portMappings []specgen.PortMapping) ([]ocicni.PortMapping, map[string]map[string]map[uint16]uint16, map[string]map[string]map[uint16]uint16, error) { +func ParsePortMapping(portMappings []types.PortMapping) ([]ocicni.PortMapping, map[string]map[string]map[uint16]uint16, map[string]map[string]map[uint16]uint16, error) { // First, we need to validate the ports passed in the specgen, and then // convert them into CNI port mappings. type tempMapping struct { @@ -253,17 +254,15 @@ func ParsePortMapping(portMappings []specgen.PortMapping) ([]ocicni.PortMapping, } // Make final port mappings for the container -func createPortMappings(ctx context.Context, s *specgen.SpecGenerator, imageData *libimage.ImageData) ([]ocicni.PortMapping, error) { +func createPortMappings(ctx context.Context, s *specgen.SpecGenerator, imageData *libimage.ImageData) ([]ocicni.PortMapping, map[uint16][]string, error) { finalMappings, containerPortValidate, hostPortValidate, err := ParsePortMapping(s.PortMappings) if err != nil { - return nil, err + return nil, nil, err } - // If not publishing exposed ports, or if we are publishing and there is - // nothing to publish - then just return the port mappings we've made so - // far. - if !s.PublishExposedPorts || (len(s.Expose) == 0 && imageData == nil) { - return finalMappings, nil + // No exposed ports so return the port mappings we've made so far. + if len(s.Expose) == 0 && imageData == nil { + return finalMappings, nil, nil } logrus.Debugf("Adding exposed ports") @@ -272,7 +271,7 @@ func createPortMappings(ctx context.Context, s *specgen.SpecGenerator, imageData if imageData != nil { expose, err = GenExposedPorts(imageData.Config.ExposedPorts) if err != nil { - return nil, err + return nil, nil, err } } @@ -288,11 +287,11 @@ func createPortMappings(ctx context.Context, s *specgen.SpecGenerator, imageData // Validate protocol first protocols, err := checkProtocol(proto, false) if err != nil { - return nil, errors.Wrapf(err, "error validating protocols for exposed port %d", port) + return nil, nil, errors.Wrapf(err, "error validating protocols for exposed port %d", port) } if port == 0 { - return nil, errors.Errorf("cannot expose 0 as it is not a valid port number") + return nil, nil, errors.Errorf("cannot expose 0 as it is not a valid port number") } // Check to see if the port is already present in existing @@ -316,6 +315,11 @@ func createPortMappings(ctx context.Context, s *specgen.SpecGenerator, imageData } } + // If not publishing exposed ports return mappings and exposed ports. + if !s.PublishExposedPorts { + return finalMappings, toExpose, nil + } + // We now have a final list of ports that we want exposed. // Let's find empty, unallocated host ports for them. for port, protocols := range toExpose { @@ -331,7 +335,7 @@ func createPortMappings(ctx context.Context, s *specgen.SpecGenerator, imageData // unfortunate for the UDP case. candidate, err := utils.GetRandomPort() if err != nil { - return nil, err + return nil, nil, err } // Check if the host port is already bound @@ -362,12 +366,12 @@ func createPortMappings(ctx context.Context, s *specgen.SpecGenerator, imageData } if tries == 0 && hostPort == 0 { // We failed to find an open port. - return nil, errors.Errorf("failed to find an open port to expose container port %d on the host", port) + return nil, nil, errors.Errorf("failed to find an open port to expose container port %d on the host", port) } } } - return finalMappings, nil + return finalMappings, nil, nil } // Check a string to ensure it is a comma-separated set of valid protocols diff --git a/pkg/specgen/generate/storage.go b/pkg/specgen/generate/storage.go index 13f336594..de655ad7d 100644 --- a/pkg/specgen/generate/storage.go +++ b/pkg/specgen/generate/storage.go @@ -10,6 +10,7 @@ import ( "github.com/containers/common/libimage" "github.com/containers/common/pkg/config" + "github.com/containers/common/pkg/parse" "github.com/containers/podman/v3/libpod" "github.com/containers/podman/v3/libpod/define" "github.com/containers/podman/v3/pkg/specgen" @@ -59,6 +60,9 @@ func finalizeMounts(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Ru for _, m := range s.Mounts { // Ensure that mount dest is clean, so that it can be // compared against named volumes and avoid duplicate mounts. + if err = parse.ValidateVolumeCtrDir(m.Destination); err != nil { + return nil, nil, nil, err + } cleanDestination := filepath.Clean(m.Destination) if _, ok := unifiedMounts[cleanDestination]; ok { return nil, nil, nil, errors.Wrapf(errDuplicateDest, "conflict in specified mounts - multiple mounts at %q", cleanDestination) @@ -67,34 +71,54 @@ func finalizeMounts(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Ru } for _, m := range commonMounts { - if _, ok := unifiedMounts[m.Destination]; !ok { - unifiedMounts[m.Destination] = m + if err = parse.ValidateVolumeCtrDir(m.Destination); err != nil { + return nil, nil, nil, err + } + cleanDestination := filepath.Clean(m.Destination) + if _, ok := unifiedMounts[cleanDestination]; !ok { + unifiedMounts[cleanDestination] = m } } for _, v := range s.Volumes { - if _, ok := unifiedVolumes[v.Dest]; ok { - return nil, nil, nil, errors.Wrapf(errDuplicateDest, "conflict in specified volumes - multiple volumes at %q", v.Dest) + if err = parse.ValidateVolumeCtrDir(v.Dest); err != nil { + return nil, nil, nil, err } - unifiedVolumes[v.Dest] = v + cleanDestination := filepath.Clean(v.Dest) + if _, ok := unifiedVolumes[cleanDestination]; ok { + return nil, nil, nil, errors.Wrapf(errDuplicateDest, "conflict in specified volumes - multiple volumes at %q", cleanDestination) + } + unifiedVolumes[cleanDestination] = v } for _, v := range commonVolumes { - if _, ok := unifiedVolumes[v.Dest]; !ok { - unifiedVolumes[v.Dest] = v + if err = parse.ValidateVolumeCtrDir(v.Dest); err != nil { + return nil, nil, nil, err + } + cleanDestination := filepath.Clean(v.Dest) + if _, ok := unifiedVolumes[cleanDestination]; !ok { + unifiedVolumes[cleanDestination] = v } } for _, v := range s.OverlayVolumes { - if _, ok := unifiedOverlays[v.Destination]; ok { - return nil, nil, nil, errors.Wrapf(errDuplicateDest, "conflict in specified volumes - multiple volumes at %q", v.Destination) + if err = parse.ValidateVolumeCtrDir(v.Destination); err != nil { + return nil, nil, nil, err } - unifiedOverlays[v.Destination] = v + cleanDestination := filepath.Clean(v.Destination) + if _, ok := unifiedOverlays[cleanDestination]; ok { + return nil, nil, nil, errors.Wrapf(errDuplicateDest, "conflict in specified volumes - multiple volumes at %q", cleanDestination) + } + unifiedOverlays[cleanDestination] = v } for _, v := range commonOverlayVolumes { - if _, ok := unifiedOverlays[v.Destination]; ok { - unifiedOverlays[v.Destination] = v + if err = parse.ValidateVolumeCtrDir(v.Destination); err != nil { + return nil, nil, nil, err + } + cleanDestination := filepath.Clean(v.Destination) + if _, ok := unifiedOverlays[cleanDestination]; !ok { + unifiedOverlays[cleanDestination] = v } } @@ -190,6 +214,9 @@ func getImageVolumes(ctx context.Context, img *libimage.Image, s *specgen.SpecGe } for volume := range inspect.Config.Volumes { logrus.Debugf("Image has volume at %q", volume) + if err = parse.ValidateVolumeCtrDir(volume); err != nil { + return nil, nil, err + } cleanDest := filepath.Clean(volume) switch mode { case "", "anonymous": @@ -304,9 +331,13 @@ func getVolumesFrom(volumesFrom []string, runtime *libpod.Runtime) (map[string]s if _, ok := finalMounts[namedVol.Dest]; ok { logrus.Debugf("Overriding named volume mount to %s with new named volume from container %s", namedVol.Dest, ctr.ID()) } + if err = parse.ValidateVolumeCtrDir(namedVol.Dest); err != nil { + return nil, nil, err + } + cleanDest := filepath.Clean(namedVol.Dest) newVol := new(specgen.NamedVolume) - newVol.Dest = namedVol.Dest + newVol.Dest = cleanDest newVol.Options = namedVol.Options newVol.Name = namedVol.Name |