summaryrefslogtreecommitdiff
path: root/pkg/specgen
diff options
context:
space:
mode:
authorcdoern <cdoern@redhat.com>2021-11-04 23:48:35 -0400
committercdoern <cdoern@redhat.com>2021-12-27 13:39:36 -0500
commit289270375a54c26b86f9e2d99aab18b427e56b88 (patch)
treeee7b7c5614e0ea07ddc4c41842602740e9c8f25c /pkg/specgen
parente06631d6c22f4d5b7a62f70ccdf623379a9d5fe7 (diff)
downloadpodman-289270375a54c26b86f9e2d99aab18b427e56b88.tar.gz
podman-289270375a54c26b86f9e2d99aab18b427e56b88.tar.bz2
podman-289270375a54c26b86f9e2d99aab18b427e56b88.zip
Pod Security Option support
Added support for pod security options. These are applied to infra and passed down to the containers as added (unless overridden). Modified the inheritance process from infra, creating a new function Inherit() which reads the config, and marshals the compatible options into an intermediate struct `InfraInherit` This is then unmarshaled into a container config and all of this is added to the CtrCreateOptions. Removes the need (mostly) for special additons which complicate the Container_create code and pod creation. resolves #12173 Signed-off-by: cdoern <cdoern@redhat.com>
Diffstat (limited to 'pkg/specgen')
-rw-r--r--pkg/specgen/generate/container_create.go111
-rw-r--r--pkg/specgen/generate/oci.go37
-rw-r--r--pkg/specgen/podspecgen.go5
3 files changed, 103 insertions, 50 deletions
diff --git a/pkg/specgen/generate/container_create.go b/pkg/specgen/generate/container_create.go
index 7ab9d1b29..7d792b3b1 100644
--- a/pkg/specgen/generate/container_create.go
+++ b/pkg/specgen/generate/container_create.go
@@ -2,13 +2,14 @@ package generate
import (
"context"
- "fmt"
+ "encoding/json"
"path/filepath"
"strings"
cdi "github.com/container-orchestrated-devices/container-device-interface/pkg"
"github.com/containers/common/libimage"
"github.com/containers/podman/v3/libpod"
+ "github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/pkg/namespaces"
"github.com/containers/podman/v3/pkg/specgen"
"github.com/containers/podman/v3/pkg/util"
@@ -29,43 +30,30 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener
// If joining a pod, retrieve the pod for use, and its infra container
var pod *libpod.Pod
- var infraConfig *libpod.ContainerConfig
+ var infra *libpod.Container
if s.Pod != "" {
pod, err = rt.LookupPod(s.Pod)
if err != nil {
return nil, nil, nil, errors.Wrapf(err, "error retrieving pod %s", s.Pod)
}
if pod.HasInfraContainer() {
- infra, err := pod.InfraContainer()
+ infra, err = pod.InfraContainer()
if err != nil {
return nil, nil, nil, err
}
- infraConfig = infra.Config()
}
}
- if infraConfig != nil && (len(infraConfig.NamedVolumes) > 0 || len(infraConfig.UserVolumes) > 0 || len(infraConfig.ImageVolumes) > 0 || len(infraConfig.OverlayVolumes) > 0) {
- s.VolumesFrom = append(s.VolumesFrom, infraConfig.ID)
- }
-
- if infraConfig != nil && len(infraConfig.Spec.Linux.Devices) > 0 {
- s.DevicesFrom = append(s.DevicesFrom, infraConfig.ID)
- }
- if infraConfig != nil && infraConfig.Spec.Linux.Resources != nil && infraConfig.Spec.Linux.Resources.BlockIO != nil && len(infraConfig.Spec.Linux.Resources.BlockIO.ThrottleReadBpsDevice) > 0 {
- tempDev := make(map[string]spec.LinuxThrottleDevice)
- for _, val := range infraConfig.Spec.Linux.Resources.BlockIO.ThrottleReadBpsDevice {
- nodes, err := util.FindDeviceNodes()
- if err != nil {
- return nil, nil, nil, err
- }
- key := fmt.Sprintf("%d:%d", val.Major, val.Minor)
- tempDev[nodes[key]] = spec.LinuxThrottleDevice{Rate: uint64(val.Rate)}
- }
- for i, dev := range s.ThrottleReadBpsDevice {
- tempDev[i] = dev
+ options := []libpod.CtrCreateOption{}
+ compatibleOptions := &libpod.InfraInherit{}
+ var infraSpec *spec.Spec
+ if infra != nil {
+ options, infraSpec, compatibleOptions, err = Inherit(*infra)
+ if err != nil {
+ return nil, nil, nil, err
}
- s.ThrottleReadBpsDevice = tempDev
}
+
if err := FinishThrottleDevices(s); err != nil {
return nil, nil, nil, err
}
@@ -119,8 +107,6 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener
s.CgroupNS = defaultNS
}
- options := []libpod.CtrCreateOption{}
-
if s.ContainerCreateCommand != nil {
options = append(options, libpod.WithCreateCommand(s.ContainerCreateCommand))
}
@@ -165,7 +151,8 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener
return nil, nil, nil, err
}
- opts, err := createContainerOptions(ctx, rt, s, pod, finalVolumes, finalOverlays, imageData, command)
+ infraVolumes := (len(compatibleOptions.InfraVolumes) > 0 || len(compatibleOptions.InfraUserVolumes) > 0 || len(compatibleOptions.InfraImageVolumes) > 0)
+ opts, err := createContainerOptions(ctx, rt, s, pod, finalVolumes, finalOverlays, imageData, command, infraVolumes, *compatibleOptions)
if err != nil {
return nil, nil, nil, err
}
@@ -178,27 +165,29 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener
logrus.Debugf("setting container name %s", s.Name)
options = append(options, libpod.WithName(s.Name))
}
- if len(s.DevicesFrom) > 0 {
- for _, dev := range s.DevicesFrom {
- ctr, err := rt.GetContainer(dev)
- if err != nil {
- return nil, nil, nil, err
- }
- devices := ctr.DeviceHostSrc()
- s.Devices = append(s.Devices, devices...)
- }
- }
if len(s.Devices) > 0 {
- opts = extractCDIDevices(s)
+ opts = ExtractCDIDevices(s)
options = append(options, opts...)
}
- runtimeSpec, err := SpecGenToOCI(ctx, s, rt, rtc, newImage, finalMounts, pod, command)
+ runtimeSpec, err := SpecGenToOCI(ctx, s, rt, rtc, newImage, finalMounts, pod, command, compatibleOptions)
if err != nil {
return nil, nil, nil, err
}
if len(s.HostDeviceList) > 0 {
options = append(options, libpod.WithHostDevice(s.HostDeviceList))
}
+ if infraSpec != nil && infraSpec.Linux != nil { // if we are inheriting Linux info from a pod...
+ // Pass Security annotations
+ if len(infraSpec.Annotations[define.InspectAnnotationLabel]) > 0 && len(runtimeSpec.Annotations[define.InspectAnnotationLabel]) == 0 {
+ runtimeSpec.Annotations[define.InspectAnnotationLabel] = infraSpec.Annotations[define.InspectAnnotationLabel]
+ }
+ if len(infraSpec.Annotations[define.InspectAnnotationSeccomp]) > 0 && len(runtimeSpec.Annotations[define.InspectAnnotationSeccomp]) == 0 {
+ runtimeSpec.Annotations[define.InspectAnnotationSeccomp] = infraSpec.Annotations[define.InspectAnnotationSeccomp]
+ }
+ if len(infraSpec.Annotations[define.InspectAnnotationApparmor]) > 0 && len(runtimeSpec.Annotations[define.InspectAnnotationApparmor]) == 0 {
+ runtimeSpec.Annotations[define.InspectAnnotationApparmor] = infraSpec.Annotations[define.InspectAnnotationApparmor]
+ }
+ }
return runtimeSpec, s, options, err
}
func ExecuteCreate(ctx context.Context, rt *libpod.Runtime, runtimeSpec *spec.Spec, s *specgen.SpecGenerator, infra bool, options ...libpod.CtrCreateOption) (*libpod.Container, error) {
@@ -210,7 +199,7 @@ func ExecuteCreate(ctx context.Context, rt *libpod.Runtime, runtimeSpec *spec.Sp
return ctr, rt.PrepareVolumeOnCreateContainer(ctx, ctr)
}
-func extractCDIDevices(s *specgen.SpecGenerator) []libpod.CtrCreateOption {
+func ExtractCDIDevices(s *specgen.SpecGenerator) []libpod.CtrCreateOption {
devs := make([]spec.LinuxDevice, 0, len(s.Devices))
var cdiDevs []string
var options []libpod.CtrCreateOption
@@ -224,19 +213,16 @@ func extractCDIDevices(s *specgen.SpecGenerator) []libpod.CtrCreateOption {
cdiDevs = append(cdiDevs, device.Path)
continue
}
-
devs = append(devs, device)
}
-
s.Devices = devs
if len(cdiDevs) > 0 {
options = append(options, libpod.WithCDI(cdiDevs))
}
-
return options
}
-func createContainerOptions(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGenerator, pod *libpod.Pod, volumes []*specgen.NamedVolume, overlays []*specgen.OverlayVolume, imageData *libimage.ImageData, command []string) ([]libpod.CtrCreateOption, error) {
+func createContainerOptions(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGenerator, pod *libpod.Pod, volumes []*specgen.NamedVolume, overlays []*specgen.OverlayVolume, imageData *libimage.ImageData, command []string, infraVolumes bool, compatibleOptions libpod.InfraInherit) ([]libpod.CtrCreateOption, error) {
var options []libpod.CtrCreateOption
var err error
@@ -317,7 +303,10 @@ func createContainerOptions(ctx context.Context, rt *libpod.Runtime, s *specgen.
for _, imageVolume := range s.ImageVolumes {
destinations = append(destinations, imageVolume.Destination)
}
- options = append(options, libpod.WithUserVolumes(destinations))
+
+ if len(destinations) > 0 || !infraVolumes {
+ options = append(options, libpod.WithUserVolumes(destinations))
+ }
if len(volumes) != 0 {
var vols []*libpod.ContainerNamedVolume
@@ -405,7 +394,7 @@ func createContainerOptions(ctx context.Context, rt *libpod.Runtime, s *specgen.
if len(s.SelinuxOpts) > 0 {
options = append(options, libpod.WithSecLabels(s.SelinuxOpts))
} else {
- if pod != nil {
+ if pod != nil && len(compatibleOptions.InfraLabels) == 0 {
// duplicate the security options from the pod
processLabel, err := pod.ProcessLabel()
if err != nil {
@@ -498,3 +487,33 @@ func createContainerOptions(ctx context.Context, rt *libpod.Runtime, s *specgen.
return options, nil
}
+
+func Inherit(infra libpod.Container) (opts []libpod.CtrCreateOption, infraS *spec.Spec, compat *libpod.InfraInherit, err error) {
+ options := []libpod.CtrCreateOption{}
+ compatibleOptions := &libpod.InfraInherit{}
+ infraConf := infra.Config()
+ infraSpec := infraConf.Spec
+
+ config, err := json.Marshal(infraConf)
+ if err != nil {
+ return nil, nil, nil, err
+ }
+ err = json.Unmarshal(config, compatibleOptions)
+ if err != nil {
+ return nil, nil, nil, err
+ }
+ if infraSpec.Linux != nil && infraSpec.Linux.Resources != nil {
+ resources, err := json.Marshal(infraSpec.Linux.Resources)
+ if err != nil {
+ return nil, nil, nil, err
+ }
+ err = json.Unmarshal(resources, &compatibleOptions.InfraResources)
+ if err != nil {
+ return nil, nil, nil, err
+ }
+ }
+ if compatibleOptions != nil {
+ options = append(options, libpod.WithInfraConfig(*compatibleOptions))
+ }
+ return options, infraSpec, compatibleOptions, nil
+}
diff --git a/pkg/specgen/generate/oci.go b/pkg/specgen/generate/oci.go
index efac53104..ee3a990fc 100644
--- a/pkg/specgen/generate/oci.go
+++ b/pkg/specgen/generate/oci.go
@@ -2,6 +2,7 @@ package generate
import (
"context"
+ "encoding/json"
"path"
"strings"
@@ -174,7 +175,7 @@ func getCGroupPermissons(unmask []string) string {
}
// SpecGenToOCI returns the base configuration for the container.
-func SpecGenToOCI(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Runtime, rtc *config.Config, newImage *libimage.Image, mounts []spec.Mount, pod *libpod.Pod, finalCmd []string) (*spec.Spec, error) {
+func SpecGenToOCI(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Runtime, rtc *config.Config, newImage *libimage.Image, mounts []spec.Mount, pod *libpod.Pod, finalCmd []string, compatibleOptions *libpod.InfraInherit) (*spec.Spec, error) {
cgroupPerm := getCGroupPermissons(s.Unmask)
g, err := generate.New("linux")
@@ -299,9 +300,32 @@ func SpecGenToOCI(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Runt
g.AddAnnotation(key, val)
}
- g.Config.Linux.Resources = s.ResourceLimits
+ if compatibleOptions.InfraResources == nil && s.ResourceLimits != nil {
+ g.Config.Linux.Resources = s.ResourceLimits
+ } else if s.ResourceLimits != nil { // if we have predefined resource limits we need to make sure we keep the infra and container limits
+ originalResources, err := json.Marshal(s.ResourceLimits)
+ if err != nil {
+ return nil, err
+ }
+ infraResources, err := json.Marshal(compatibleOptions.InfraResources)
+ if err != nil {
+ return nil, err
+ }
+ err = json.Unmarshal(infraResources, s.ResourceLimits) // put infra's resource limits in the container
+ if err != nil {
+ return nil, err
+ }
+ err = json.Unmarshal(originalResources, s.ResourceLimits) // make sure we did not override anything
+ if err != nil {
+ return nil, err
+ }
+ g.Config.Linux.Resources = s.ResourceLimits
+ } else {
+ g.Config.Linux.Resources = compatibleOptions.InfraResources
+ }
// Devices
+ var userDevices []spec.LinuxDevice
if s.Privileged {
// If privileged, we need to add all the host devices to the
// spec. We do not add the user provided ones because we are
@@ -316,14 +340,19 @@ func SpecGenToOCI(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Runt
return nil, err
}
}
+ if len(compatibleOptions.InfraDevices) > 0 && len(s.Devices) == 0 {
+ userDevices = compatibleOptions.InfraDevices
+ } else {
+ userDevices = s.Devices
+ }
// add default devices specified by caller
- for _, device := range s.Devices {
+ for _, device := range userDevices {
if err = DevicesFromPath(&g, device.Path); err != nil {
return nil, err
}
}
}
- s.HostDeviceList = s.Devices
+ s.HostDeviceList = userDevices
// set the devices cgroup when not running in a user namespace
if !inUserNS && !s.Privileged {
diff --git a/pkg/specgen/podspecgen.go b/pkg/specgen/podspecgen.go
index e59d11c0a..33e8422fd 100644
--- a/pkg/specgen/podspecgen.go
+++ b/pkg/specgen/podspecgen.go
@@ -196,6 +196,7 @@ type PodSpecGenerator struct {
PodCgroupConfig
PodResourceConfig
PodStorageConfig
+ PodSecurityConfig
InfraContainerSpec *SpecGenerator `json:"-"`
}
@@ -210,6 +211,10 @@ type PodResourceConfig struct {
ThrottleReadBpsDevice map[string]spec.LinuxThrottleDevice `json:"throttleReadBpsDevice,omitempty"`
}
+type PodSecurityConfig struct {
+ SecurityOpt []string `json:"security_opt,omitempty"`
+}
+
// NewPodSpecGenerator creates a new pod spec
func NewPodSpecGenerator() *PodSpecGenerator {
return &PodSpecGenerator{}