diff --git a/.travis.yml b/.travis.yml index 6b7d62c90..dd6102f94 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,6 +14,7 @@ install: - sudo apt-get install btrfs-tools - sudo apt-get install libseccomp2/trusty-backports - sudo apt-get install libseccomp-dev/trusty-backports + - sudo apt-get install libapparmor-dev - sudo apt-get install socat - docker run --rm -v /usr/local/bin:/target jpetazzo/nsenter diff --git a/Makefile b/Makefile index 8e6228614..4ca355072 100644 --- a/Makefile +++ b/Makefile @@ -42,7 +42,7 @@ help: @echo " * 'clean' - Clean artifacts" @echo " * 'verify' - Execute the source code verification tools" @echo " * 'install.tools' - Install tools used by verify" - @echo " * 'install.deps' - Install dependencies of cri-containerd (containerd, runc, cni)" + @echo " * 'install.deps' - Install dependencies of cri-containerd (containerd, runc, cni) Note: BUILDTAGS defaults to 'seccomp apparmor' for runc build" @echo " * 'uninstall' - Remove installed binaries from system locations" @echo " * 'version' - Print current cri-containerd release version" diff --git a/README.md b/README.md index e4a6c8b29..87dfa57d2 100644 --- a/README.md +++ b/README.md @@ -26,9 +26,12 @@ will also do our best to update `cri-containerd` to the latest releases of these specifications as appropriate. ### Install Dependencies 1. Install runc dependencies. -* runc requires installation of the libsecomp development library appropriate for your distribution. `libseccomp-dev` (Ubuntu, Debian) / `libseccomp-devel` (Fedora, CentOS, RHEL). On releases of Ubuntu <=Trusty and Debian <=jessie a backport version of -`libsecomp-dev` is required. See [travis.yml](.travis.yml) for an example on -trusty. +* runc requires installation of the libsecomp development library appropriate +for your distribution. `libseccomp-dev` (Ubuntu, Debian) / `libseccomp-devel` +(Fedora, CentOS, RHEL). On releases of Ubuntu <=Trusty and Debian <=jessie a +backport version of `libsecomp-dev` is required. See [travis.yml](.travis.yml) +for an example on trusty. To use apparmor on Debian, Ubuntu, and related +distributions runc requires the installation of `libapparmor-dev`. 2. Install containerd dependencies. * containerd requires installation of a btrfs development library. `btrfs-tools`(Ubuntu, Debian) / `btrfs-progs-devel`(Fedora, CentOS, RHEL) 3. Install other dependencies: diff --git a/hack/install-deps.sh b/hack/install-deps.sh index 2f9e999ff..9bd643a20 100755 --- a/hack/install-deps.sh +++ b/hack/install-deps.sh @@ -41,7 +41,8 @@ go get -d ${RUNC_PKG}/... cd ${GOPATH}/src/${RUNC_PKG} git fetch --all git checkout ${RUNC_VERSION} -make +BUILDTAGS=${BUILDTAGS:-seccomp apparmor} +make BUILDTAGS="$BUILDTAGS" sudo make install which runc diff --git a/hack/test-e2e-node.sh b/hack/test-e2e-node.sh index 9673c0940..bef842999 100755 --- a/hack/test-e2e-node.sh +++ b/hack/test-e2e-node.sh @@ -20,7 +20,6 @@ source $(dirname "${BASH_SOURCE[0]}")/test-utils.sh DEFAULT_SKIP="\[Flaky\]|\[Slow\]|\[Serial\]" DEFAULT_SKIP+="|querying\s\/stats\/summary" -DEFAULT_SKIP+="|AppArmor" DEFAULT_SKIP+="|pull\sfrom\sprivate\sregistry\swith\ssecret" # FOCUS focuses the test to run. diff --git a/pkg/server/container_create.go b/pkg/server/container_create.go index f45dc2bac..def6b9ec5 100644 --- a/pkg/server/container_create.go +++ b/pkg/server/container_create.go @@ -22,6 +22,7 @@ import ( "time" "github.com/containerd/containerd" + "github.com/containerd/containerd/contrib/apparmor" "github.com/golang/glog" imagespec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/opencontainers/runc/libcontainer/devices" @@ -37,6 +38,17 @@ import ( "github.com/kubernetes-incubator/cri-containerd/pkg/util" ) +const ( + // 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 + // runtimeDefault indicates that we should use or create a runtime default apparmor profile. + runtimeDefault = "runtime/default" + // appArmorDefaultProfileName is name to use when creating a default apparmor profile. + appArmorDefaultProfileName = "cri-containerd.apparmor.d" + // appArmorEnabled is a flag for globally enabling/disabling apparmor profiles for containers. + appArmorEnabled = true // TODO (mikebrow): make these apparmor defaults configurable +) + // CreateContainer creates a new container in the given PodSandbox. func (c *criContainerdService) CreateContainer(ctx context.Context, r *runtime.CreateContainerRequest) (_ *runtime.CreateContainerResponse, retErr error) { config := r.GetConfig() @@ -156,6 +168,23 @@ func (c *criContainerdService) CreateContainer(ctx context.Context, r *runtime.C if username := config.GetLinux().GetSecurityContext().GetRunAsUsername(); username != "" { specOpts = append(specOpts, containerd.WithUsername(username)) } + // Set apparmor profile, (privileged or not) if apparmor is enabled + if appArmorEnabled { + appArmorProf := config.GetLinux().GetSecurityContext().GetApparmorProfile() + switch appArmorProf { + case runtimeDefault: + // TODO (mikebrow): delete created apparmor default profile + specOpts = append(specOpts, apparmor.WithDefaultProfile(appArmorDefaultProfileName)) + case "": + // TODO (mikebrow): handle no apparmor profile case see kubernetes/kubernetes#51746 + default: + // Require and Trim default profile name prefix + if !strings.HasPrefix(appArmorProf, profileNamePrefix) { + return nil, fmt.Errorf("invalid apparmor profile %q", appArmorProf) + } + specOpts = append(specOpts, apparmor.WithProfile(strings.TrimPrefix(appArmorProf, profileNamePrefix))) + } + } opts = append(opts, containerd.WithSpec(spec, specOpts...), containerd.WithRuntime(defaultRuntime, nil), @@ -264,9 +293,7 @@ func (c *criContainerdService) generateContainerSpec(id string, sandboxPid uint3 return nil, fmt.Errorf("failed to set capabilities %+v: %v", securityContext.GetCapabilities(), err) } - - // TODO(random-liu): [P2] Add apparmor and seccomp. - + // TODO(random-liu): [P2] Add seccomp not privileged only. } g.SetProcessSelinuxLabel(processLabel) @@ -275,7 +302,7 @@ func (c *criContainerdService) generateContainerSpec(id string, sandboxPid uint3 // TODO: Figure out whether we should set no new privilege for sandbox container by default g.SetProcessNoNewPrivileges(securityContext.GetNoNewPrivs()) - // TODO(random-liu): [P1] Set selinux options. + // TODO(random-liu): [P1] Set selinux options (privileged or not). g.SetRootReadonly(securityContext.GetReadonlyRootfs()) diff --git a/pkg/server/sandbox_run.go b/pkg/server/sandbox_run.go index 7de870ed1..2f1302135 100644 --- a/pkg/server/sandbox_run.go +++ b/pkg/server/sandbox_run.go @@ -294,7 +294,9 @@ func (c *criContainerdService) generateSandboxContainerSpec(id string, config *r g.AddLinuxSysctl(key, value) } - // TODO(random-liu): [P2] Set apparmor and seccomp from annotations. + // TODO(random-liu): [P2] Set seccomp + + // Note: LinuxSandboxSecurityContext does not currently provide an apparmor profile g.SetLinuxResourcesCPUShares(uint64(defaultSandboxCPUshares)) g.SetProcessOOMScoreAdj(int(defaultSandboxOOMAdj))