adds seccomp support

Signed-off-by: Mike Brown <brownwm@us.ibm.com>
This commit is contained in:
Mike Brown 2017-09-06 08:09:27 -05:00
parent 2ac9262091
commit c0a2d152d9
2 changed files with 68 additions and 5 deletions

View File

@ -25,6 +25,7 @@ import (
"github.com/containerd/containerd" "github.com/containerd/containerd"
"github.com/containerd/containerd/contrib/apparmor" "github.com/containerd/containerd/contrib/apparmor"
"github.com/containerd/containerd/contrib/seccomp"
"github.com/containerd/containerd/typeurl" "github.com/containerd/containerd/typeurl"
"github.com/docker/docker/pkg/mount" "github.com/docker/docker/pkg/mount"
"github.com/golang/glog" "github.com/golang/glog"
@ -48,10 +49,20 @@ import (
const ( const (
// profileNamePrefix is the prefix for loading profiles on a localhost. Eg. AppArmor localhost/profileName. // profileNamePrefix is the prefix for loading profiles on a localhost. Eg. AppArmor localhost/profileName.
profileNamePrefix = "localhost/" // TODO (mikebrow): get localhost/ & runtime/default from CRI kubernetes/kubernetes#51747 profileNamePrefix = "localhost/" // TODO (mikebrow): get localhost/ & runtime/default from CRI kubernetes/kubernetes#51747
// runtimeDefault indicates that we should use or create a runtime default apparmor profile. // runtimeDefault indicates that we should use or create a runtime default profile.
runtimeDefault = "runtime/default" runtimeDefault = "runtime/default"
// runtimeDefault indicates that we should use or create a docker default profile.
dockerDefault = "docker/default"
// appArmorDefaultProfileName is name to use when creating a default apparmor profile. // appArmorDefaultProfileName is name to use when creating a default apparmor profile.
appArmorDefaultProfileName = "cri-containerd.apparmor.d" appArmorDefaultProfileName = "cri-containerd.apparmor.d"
// unconfinedProfile is a string indicating one should run a pod/containerd without a security profile
unconfinedProfile = "unconfined"
// seccompDefaultPodProfile is the default seccomp profile for pods.
seccompDefaultSandboxProfile = unconfinedProfile
// seccompDefaultContainerProfile is the default seccomp profile for containers.
seccompDefaultContainerProfile = dockerDefault
// seccompEnabled is a flag for globally enabling/disabling seccomp profiles for containers.
seccompEnabled = true // TODO (mikebrow): make these seccomp defaults configurable
) )
func init() { func init() {
@ -211,6 +222,33 @@ func (c *criContainerdService) CreateContainer(ctx context.Context, r *runtime.C
specOpts = append(specOpts, apparmor.WithProfile(strings.TrimPrefix(appArmorProf, profileNamePrefix))) specOpts = append(specOpts, apparmor.WithProfile(strings.TrimPrefix(appArmorProf, profileNamePrefix)))
} }
} }
// Set seccomp profile
seccompProf := config.GetLinux().GetSecurityContext().GetSeccompProfilePath()
if seccompProf == runtimeDefault || seccompProf == dockerDefault {
// use correct default profile (Eg. if not configured otherwise, the default is docker/default for containers)
seccompProf = seccompDefaultContainerProfile
}
// Unset the seccomp profile, if seccomp is not enabled, unconfined, unset, or the security context is privileged
if !seccompEnabled ||
seccompProf == unconfinedProfile ||
seccompProf == "" ||
config.GetLinux().GetSecurityContext().GetPrivileged() {
spec.Linux.Seccomp = nil
} else {
switch seccompProf {
case dockerDefault:
// Note: WithDefaultProfile specOpts must be added after capabilities
specOpts = append(specOpts, seccomp.WithDefaultProfile())
default:
// Require and Trim default profile name prefix
if !strings.HasPrefix(seccompProf, profileNamePrefix) {
return nil, fmt.Errorf("invalid seccomp profile %q", seccompProf)
}
specOpts = append(specOpts, seccomp.WithProfile(strings.TrimPrefix(seccompProf, profileNamePrefix)))
}
}
opts = append(opts, opts = append(opts,
containerd.WithSpec(spec, specOpts...), containerd.WithSpec(spec, specOpts...),
containerd.WithRuntime(defaultRuntime, nil), containerd.WithRuntime(defaultRuntime, nil),
@ -312,7 +350,7 @@ func (c *criContainerdService) generateContainerSpec(id string, sandboxPid uint3
if err := setOCIPrivileged(&g, config); err != nil { if err := setOCIPrivileged(&g, config); err != nil {
return nil, err return nil, err
} }
} else { } else { // not privileged
if err := c.addOCIDevices(&g, config.GetDevices()); err != nil { if err := c.addOCIDevices(&g, config.GetDevices()); err != nil {
return nil, fmt.Errorf("failed to set devices mapping %+v: %v", config.GetDevices(), err) return nil, fmt.Errorf("failed to set devices mapping %+v: %v", config.GetDevices(), err)
} }
@ -321,7 +359,6 @@ func (c *criContainerdService) generateContainerSpec(id string, sandboxPid uint3
return nil, fmt.Errorf("failed to set capabilities %+v: %v", return nil, fmt.Errorf("failed to set capabilities %+v: %v",
securityContext.GetCapabilities(), err) securityContext.GetCapabilities(), err)
} }
// TODO(random-liu): [P2] Add seccomp not privileged only.
} }
g.SetProcessSelinuxLabel(processLabel) g.SetProcessSelinuxLabel(processLabel)

View File

@ -22,6 +22,7 @@ import (
"strings" "strings"
"github.com/containerd/containerd" "github.com/containerd/containerd"
"github.com/containerd/containerd/contrib/seccomp"
"github.com/containerd/containerd/typeurl" "github.com/containerd/containerd/typeurl"
"github.com/cri-o/ocicni/pkg/ocicni" "github.com/cri-o/ocicni/pkg/ocicni"
"github.com/golang/glog" "github.com/golang/glog"
@ -127,6 +128,33 @@ func (c *criContainerdService) RunPodSandbox(ctx context.Context, r *runtime.Run
if uid := config.GetLinux().GetSecurityContext().GetRunAsUser(); uid != nil { if uid := config.GetLinux().GetSecurityContext().GetRunAsUser(); uid != nil {
specOpts = append(specOpts, containerd.WithUserID(uint32(uid.GetValue()))) specOpts = append(specOpts, containerd.WithUserID(uint32(uid.GetValue())))
} }
// Set seccomp profile
seccompProf := config.GetLinux().GetSecurityContext().GetSeccompProfilePath()
if seccompProf == runtimeDefault || seccompProf == dockerDefault {
// use correct default profile (Eg. if not configured otherwise, the default is unconfined for pods)
seccompProf = seccompDefaultSandboxProfile
}
// Unset the seccomp profile, if seccomp is not enabled, unconfined, unset, or the security context is privileged
if !seccompEnabled ||
seccompProf == unconfinedProfile ||
seccompProf == "" ||
config.GetLinux().GetSecurityContext().GetPrivileged() {
spec.Linux.Seccomp = nil
} else {
switch seccompProf {
case dockerDefault:
// Note: WithDefaultProfile specOpts must be added after capabilities
specOpts = append(specOpts, seccomp.WithDefaultProfile())
default:
// Require and Trim default profile name prefix
if !strings.HasPrefix(seccompProf, profileNamePrefix) {
return nil, fmt.Errorf("invalid seccomp profile %q", seccompProf)
}
specOpts = append(specOpts, seccomp.WithProfile(strings.TrimPrefix(seccompProf, profileNamePrefix)))
}
}
opts := []containerd.NewContainerOpts{ opts := []containerd.NewContainerOpts{
containerd.WithSnapshotter(c.config.ContainerdSnapshotter), containerd.WithSnapshotter(c.config.ContainerdSnapshotter),
containerd.WithNewSnapshot(id, image.Image), containerd.WithNewSnapshot(id, image.Image),
@ -288,8 +316,6 @@ func (c *criContainerdService) generateSandboxContainerSpec(id string, config *r
g.AddLinuxSysctl(key, value) g.AddLinuxSysctl(key, value)
} }
// TODO(random-liu): [P2] Set seccomp
// Note: LinuxSandboxSecurityContext does not currently provide an apparmor profile // Note: LinuxSandboxSecurityContext does not currently provide an apparmor profile
g.SetLinuxResourcesCPUShares(uint64(defaultSandboxCPUshares)) g.SetLinuxResourcesCPUShares(uint64(defaultSandboxCPUshares))