summaryrefslogtreecommitdiff
path: root/pkg/specgen/generate
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/specgen/generate')
-rw-r--r--pkg/specgen/generate/container.go83
-rw-r--r--pkg/specgen/generate/namespaces.go62
-rw-r--r--pkg/specgen/generate/security.go110
3 files changed, 106 insertions, 149 deletions
diff --git a/pkg/specgen/generate/container.go b/pkg/specgen/generate/container.go
index 7233acb8a..31465d8bf 100644
--- a/pkg/specgen/generate/container.go
+++ b/pkg/specgen/generate/container.go
@@ -20,17 +20,27 @@ func CompleteSpec(ctx context.Context, r *libpod.Runtime, s *specgen.SpecGenerat
}
// Image stop signal
- if s.StopSignal == nil && newImage.Config != nil {
- sig, err := signal.ParseSignalNameOrNumber(newImage.Config.StopSignal)
+ if s.StopSignal == nil {
+ stopSignal, err := newImage.StopSignal(ctx)
+ if err != nil {
+ return err
+ }
+ sig, err := signal.ParseSignalNameOrNumber(stopSignal)
if err != nil {
return err
}
s.StopSignal = &sig
}
+
// Image envs from the image if they don't exist
// already
- if newImage.Config != nil && len(newImage.Config.Env) > 0 {
- envs, err := envLib.ParseSlice(newImage.Config.Env)
+ env, err := newImage.Env(ctx)
+ if err != nil {
+ return err
+ }
+
+ if len(env) > 0 {
+ envs, err := envLib.ParseSlice(env)
if err != nil {
return err
}
@@ -41,12 +51,15 @@ func CompleteSpec(ctx context.Context, r *libpod.Runtime, s *specgen.SpecGenerat
}
}
+ labels, err := newImage.Labels(ctx)
+ if err != nil {
+ return err
+ }
+
// labels from the image that dont exist already
- if config := newImage.Config; config != nil {
- for k, v := range config.Labels {
- if _, exists := s.Labels[k]; !exists {
- s.Labels[k] = v
- }
+ for k, v := range labels {
+ if _, exists := s.Labels[k]; !exists {
+ s.Labels[k] = v
}
}
@@ -75,20 +88,30 @@ func CompleteSpec(ctx context.Context, r *libpod.Runtime, s *specgen.SpecGenerat
}
// entrypoint
- if config := newImage.Config; config != nil {
- if len(s.Entrypoint) < 1 && len(config.Entrypoint) > 0 {
- s.Entrypoint = config.Entrypoint
- }
- if len(s.Command) < 1 && len(config.Cmd) > 0 {
- s.Command = config.Cmd
- }
- if len(s.Command) < 1 && len(s.Entrypoint) < 1 {
- return errors.Errorf("No command provided or as CMD or ENTRYPOINT in this image")
- }
- // workdir
- if len(s.WorkDir) < 1 && len(config.WorkingDir) > 1 {
- s.WorkDir = config.WorkingDir
- }
+ entrypoint, err := newImage.Entrypoint(ctx)
+ if err != nil {
+ return err
+ }
+ if len(s.Entrypoint) < 1 && len(entrypoint) > 0 {
+ s.Entrypoint = entrypoint
+ }
+ command, err := newImage.Cmd(ctx)
+ if err != nil {
+ return err
+ }
+ if len(s.Command) < 1 && len(command) > 0 {
+ s.Command = command
+ }
+ if len(s.Command) < 1 && len(s.Entrypoint) < 1 {
+ return errors.Errorf("No command provided or as CMD or ENTRYPOINT in this image")
+ }
+ // workdir
+ workingDir, err := newImage.WorkingDir(ctx)
+ if err != nil {
+ return err
+ }
+ if len(s.WorkDir) < 1 && len(workingDir) > 1 {
+ s.WorkDir = workingDir
}
if len(s.SeccompProfilePath) < 1 {
@@ -99,15 +122,17 @@ func CompleteSpec(ctx context.Context, r *libpod.Runtime, s *specgen.SpecGenerat
s.SeccompProfilePath = p
}
- if user := s.User; len(user) == 0 {
- switch {
+ if len(s.User) == 0 {
+ s.User, err = newImage.User(ctx)
+ if err != nil {
+ return err
+ }
+
// TODO This should be enabled when namespaces actually work
//case usernsMode.IsKeepID():
// user = fmt.Sprintf("%d:%d", rootless.GetRootlessUID(), rootless.GetRootlessGID())
- case newImage.Config == nil || (newImage.Config != nil && len(newImage.Config.User) == 0):
+ if len(s.User) == 0 {
s.User = "0"
- default:
- s.User = newImage.Config.User
}
}
if err := finishThrottleDevices(s); err != nil {
@@ -116,7 +141,7 @@ func CompleteSpec(ctx context.Context, r *libpod.Runtime, s *specgen.SpecGenerat
// Unless already set via the CLI, check if we need to disable process
// labels or set the defaults.
if len(s.SelinuxOpts) == 0 {
- if err := SetLabelOpts(s, r, s.PidNS, s.IpcNS); err != nil {
+ if err := setLabelOpts(s, r, s.PidNS, s.IpcNS); err != nil {
return err
}
}
diff --git a/pkg/specgen/generate/namespaces.go b/pkg/specgen/generate/namespaces.go
index cdd7d86da..53ae335c3 100644
--- a/pkg/specgen/generate/namespaces.go
+++ b/pkg/specgen/generate/namespaces.go
@@ -3,9 +3,7 @@ package generate
import (
"os"
- "github.com/containers/common/pkg/capabilities"
"github.com/containers/libpod/libpod"
- "github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/pkg/specgen"
"github.com/cri-o/ocicni/pkg/ocicni"
spec "github.com/opencontainers/runtime-spec/specs-go"
@@ -324,66 +322,6 @@ func userConfigureGenerator(s *specgen.SpecGenerator, g *generate.Generator) err
return nil
}
-func securityConfigureGenerator(s *specgen.SpecGenerator, g *generate.Generator, newImage *image.Image) error {
- // HANDLE CAPABILITIES
- // NOTE: Must happen before SECCOMP
- if s.Privileged {
- g.SetupPrivileged(true)
- }
-
- useNotRoot := func(user string) bool {
- if user == "" || user == "root" || user == "0" {
- return false
- }
- return true
- }
- configSpec := g.Config
- var err error
- var caplist []string
- bounding := configSpec.Process.Capabilities.Bounding
- if useNotRoot(s.User) {
- configSpec.Process.Capabilities.Bounding = caplist
- }
- caplist, err = capabilities.MergeCapabilities(configSpec.Process.Capabilities.Bounding, s.CapAdd, s.CapDrop)
- if err != nil {
- return err
- }
-
- configSpec.Process.Capabilities.Bounding = caplist
- configSpec.Process.Capabilities.Permitted = caplist
- configSpec.Process.Capabilities.Inheritable = caplist
- configSpec.Process.Capabilities.Effective = caplist
- configSpec.Process.Capabilities.Ambient = caplist
- if useNotRoot(s.User) {
- caplist, err = capabilities.MergeCapabilities(bounding, s.CapAdd, s.CapDrop)
- if err != nil {
- return err
- }
- }
- configSpec.Process.Capabilities.Bounding = caplist
-
- // HANDLE SECCOMP
- if s.SeccompProfilePath != "unconfined" {
- seccompConfig, err := getSeccompConfig(s, configSpec, newImage)
- if err != nil {
- return err
- }
- configSpec.Linux.Seccomp = seccompConfig
- }
-
- // Clear default Seccomp profile from Generator for privileged containers
- if s.SeccompProfilePath == "unconfined" || s.Privileged {
- configSpec.Linux.Seccomp = nil
- }
-
- g.SetRootReadonly(s.ReadOnlyFilesystem)
- for sysctlKey, sysctlVal := range s.Sysctl {
- g.AddLinuxSysctl(sysctlKey, sysctlVal)
- }
-
- return nil
-}
-
// 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
diff --git a/pkg/specgen/generate/security.go b/pkg/specgen/generate/security.go
index ef4b3b47a..e2da9e976 100644
--- a/pkg/specgen/generate/security.go
+++ b/pkg/specgen/generate/security.go
@@ -1,15 +1,22 @@
package generate
import (
+ "strings"
+
+ "github.com/containers/common/pkg/capabilities"
"github.com/containers/libpod/libpod"
+ "github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/pkg/specgen"
+ "github.com/containers/libpod/pkg/util"
+ "github.com/opencontainers/runtime-tools/generate"
"github.com/opencontainers/selinux/go-selinux/label"
"github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
)
-// SetLabelOpts sets the label options of the SecurityConfig according to the
+// setLabelOpts sets the label options of the SecurityConfig according to the
// input.
-func SetLabelOpts(s *specgen.SpecGenerator, runtime *libpod.Runtime, pidConfig specgen.Namespace, ipcConfig specgen.Namespace) error {
+func setLabelOpts(s *specgen.SpecGenerator, runtime *libpod.Runtime, pidConfig specgen.Namespace, ipcConfig specgen.Namespace) error {
if !runtime.EnableLabeling() || s.Privileged {
s.SelinuxOpts = label.DisableSecOpt()
return nil
@@ -48,12 +55,10 @@ func SetLabelOpts(s *specgen.SpecGenerator, runtime *libpod.Runtime, pidConfig s
return nil
}
-// ConfigureGenerator configures the generator according to the input.
-/*
-func (c *SecurityConfig) ConfigureGenerator(g *generate.Generator, user *UserConfig) error {
+func securityConfigureGenerator(s *specgen.SpecGenerator, g *generate.Generator, newImage *image.Image) error {
// HANDLE CAPABILITIES
// NOTE: Must happen before SECCOMP
- if c.Privileged {
+ if s.Privileged {
g.SetupPrivileged(true)
}
@@ -63,56 +68,66 @@ func (c *SecurityConfig) ConfigureGenerator(g *generate.Generator, user *UserCon
}
return true
}
-
configSpec := g.Config
var err error
- var defaultCaplist []string
+ var caplist []string
bounding := configSpec.Process.Capabilities.Bounding
- if useNotRoot(user.User) {
- configSpec.Process.Capabilities.Bounding = defaultCaplist
+ if useNotRoot(s.User) {
+ configSpec.Process.Capabilities.Bounding = caplist
}
- defaultCaplist, err = capabilities.MergeCapabilities(configSpec.Process.Capabilities.Bounding, c.CapAdd, c.CapDrop)
+ caplist, err = capabilities.MergeCapabilities(configSpec.Process.Capabilities.Bounding, s.CapAdd, s.CapDrop)
if err != nil {
return err
}
+ privCapsRequired := []string{}
+
+ // If the container image specifies an label with a
+ // capabilities.ContainerImageLabel then split the comma separated list
+ // of capabilities and record them. This list indicates the only
+ // capabilities, required to run the container.
+ var capsRequiredRequested []string
+ for key, val := range s.Labels {
+ if util.StringInSlice(key, capabilities.ContainerImageLabels) {
+ capsRequiredRequested = strings.Split(val, ",")
+ }
+ }
+ if !s.Privileged && len(capsRequiredRequested) > 0 {
- privCapRequired := []string{}
-
- if !c.Privileged && len(c.CapRequired) > 0 {
- // Pass CapRequired in CapAdd field to normalize capabilities names
- capRequired, err := capabilities.MergeCapabilities(nil, c.CapRequired, nil)
+ // Pass capRequiredRequested in CapAdd field to normalize capabilities names
+ capsRequired, err := capabilities.MergeCapabilities(nil, capsRequiredRequested, nil)
if err != nil {
- logrus.Errorf("capabilities requested by user or image are not valid: %q", strings.Join(c.CapRequired, ","))
+ logrus.Errorf("capabilities requested by user or image are not valid: %q", strings.Join(capsRequired, ","))
} else {
- // Verify all capRequiered are in the defaultCapList
- for _, cap := range capRequired {
- if !util.StringInSlice(cap, defaultCaplist) {
- privCapRequired = append(privCapRequired, cap)
+ // Verify all capRequiered are in the capList
+ for _, cap := range capsRequired {
+ if !util.StringInSlice(cap, caplist) {
+ privCapsRequired = append(privCapsRequired, cap)
}
}
}
- if len(privCapRequired) == 0 {
- defaultCaplist = capRequired
+ if len(privCapsRequired) == 0 {
+ caplist = capsRequired
} else {
- logrus.Errorf("capabilities requested by user or image are not allowed by default: %q", strings.Join(privCapRequired, ","))
+ logrus.Errorf("capabilities requested by user or image are not allowed by default: %q", strings.Join(privCapsRequired, ","))
}
}
- configSpec.Process.Capabilities.Bounding = defaultCaplist
- configSpec.Process.Capabilities.Permitted = defaultCaplist
- configSpec.Process.Capabilities.Inheritable = defaultCaplist
- configSpec.Process.Capabilities.Effective = defaultCaplist
- configSpec.Process.Capabilities.Ambient = defaultCaplist
- if useNotRoot(user.User) {
- defaultCaplist, err = capabilities.MergeCapabilities(bounding, c.CapAdd, c.CapDrop)
+
+ configSpec.Process.Capabilities.Bounding = caplist
+ configSpec.Process.Capabilities.Permitted = caplist
+ configSpec.Process.Capabilities.Inheritable = caplist
+ configSpec.Process.Capabilities.Effective = caplist
+ configSpec.Process.Capabilities.Ambient = caplist
+ if useNotRoot(s.User) {
+ caplist, err = capabilities.MergeCapabilities(bounding, s.CapAdd, s.CapDrop)
if err != nil {
return err
}
}
- configSpec.Process.Capabilities.Bounding = defaultCaplist
+ configSpec.Process.Capabilities.Bounding = caplist
// HANDLE SECCOMP
- if c.SeccompProfilePath != "unconfined" {
- seccompConfig, err := getSeccompConfig(c, configSpec)
+ if s.SeccompProfilePath != "unconfined" {
+ seccompConfig, err := getSeccompConfig(s, configSpec, newImage)
if err != nil {
return err
}
@@ -120,35 +135,14 @@ func (c *SecurityConfig) ConfigureGenerator(g *generate.Generator, user *UserCon
}
// Clear default Seccomp profile from Generator for privileged containers
- if c.SeccompProfilePath == "unconfined" || c.Privileged {
+ if s.SeccompProfilePath == "unconfined" || s.Privileged {
configSpec.Linux.Seccomp = nil
}
- for _, opt := range c.SecurityOpts {
- // Split on both : and =
- splitOpt := strings.Split(opt, "=")
- if len(splitOpt) == 1 {
- splitOpt = strings.Split(opt, ":")
- }
- if len(splitOpt) < 2 {
- continue
- }
- switch splitOpt[0] {
- case "label":
- configSpec.Annotations[libpod.InspectAnnotationLabel] = splitOpt[1]
- case "seccomp":
- configSpec.Annotations[libpod.InspectAnnotationSeccomp] = splitOpt[1]
- case "apparmor":
- configSpec.Annotations[libpod.InspectAnnotationApparmor] = splitOpt[1]
- }
- }
-
- g.SetRootReadonly(c.ReadOnlyRootfs)
- for sysctlKey, sysctlVal := range c.Sysctl {
+ g.SetRootReadonly(s.ReadOnlyFilesystem)
+ for sysctlKey, sysctlVal := range s.Sysctl {
g.AddLinuxSysctl(sysctlKey, sysctlVal)
}
return nil
}
-
-*/