From 6e78c5bdde69350cada54292d65715a2051bc9bb Mon Sep 17 00:00:00 2001 From: Tim Allclair Date: Thu, 23 May 2019 12:23:04 -0700 Subject: [PATCH 1/2] Add RunAsNonRoot test --- test/e2e/common/security_context.go | 66 +++++++++++++++++++++++++++++ test/images/busybox-user/BASEIMAGE | 5 +++ test/images/busybox-user/Dockerfile | 17 ++++++++ test/images/busybox-user/VERSION | 1 + test/utils/image/manifest.go | 3 ++ 5 files changed, 92 insertions(+) create mode 100644 test/images/busybox-user/BASEIMAGE create mode 100644 test/images/busybox-user/Dockerfile create mode 100644 test/images/busybox-user/VERSION diff --git a/test/e2e/common/security_context.go b/test/e2e/common/security_context.go index 1107cd6094..3e495621f3 100644 --- a/test/e2e/common/security_context.go +++ b/test/e2e/common/security_context.go @@ -23,11 +23,14 @@ import ( v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/uuid" + "k8s.io/kubernetes/pkg/kubelet/events" "k8s.io/kubernetes/test/e2e/framework" e2elog "k8s.io/kubernetes/test/e2e/framework/log" imageutils "k8s.io/kubernetes/test/utils/image" + "k8s.io/utils/pointer" . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" ) var _ = framework.KubeDescribe("Security Context", func() { @@ -92,6 +95,69 @@ var _ = framework.KubeDescribe("Security Context", func() { }) }) + Context("When creating a container with runAsNonRoot", func() { + rootImage := imageutils.GetE2EImage(imageutils.BusyBox) + nonRootImage := imageutils.GetE2EImage(imageutils.BusyBoxUser) + makeNonRootPod := func(podName, image string, userid *int64) *v1.Pod { + return &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: podName, + }, + Spec: v1.PodSpec{ + RestartPolicy: v1.RestartPolicyNever, + Containers: []v1.Container{ + { + Image: image, + Name: podName, + Command: []string{"id", "-u"}, // Print UID and exit + SecurityContext: &v1.SecurityContext{ + RunAsNonRoot: pointer.BoolPtr(true), + RunAsUser: userid, + }, + }, + }, + }, + } + } + + It("should run with an explicit non-root user ID", func() { + name := "explicit-nonroot-uid" + pod := makeNonRootPod(name, rootImage, pointer.Int64Ptr(1234)) + pod = podClient.Create(pod) + + podClient.WaitForSuccess(name, framework.PodStartTimeout) + framework.ExpectNoError(podClient.MatchContainerOutput(name, name, "1234")) + }) + It("should not run with an explicit root user ID", func() { + name := "explicit-root-uid" + pod := makeNonRootPod(name, nonRootImage, pointer.Int64Ptr(0)) + pod = podClient.Create(pod) + + ev, err := podClient.WaitForErrorEventOrSuccess(pod) + framework.ExpectNoError(err) + Expect(ev).NotTo(BeNil()) + Expect(ev.Reason).To(Equal(events.FailedToCreateContainer)) + }) + It("should run with an image specified user ID", func() { + name := "implicit-nonroot-uid" + pod := makeNonRootPod(name, nonRootImage, nil) + pod = podClient.Create(pod) + + podClient.WaitForSuccess(name, framework.PodStartTimeout) + framework.ExpectNoError(podClient.MatchContainerOutput(name, name, "1234")) + }) + It("should not run without a specified user ID", func() { + name := "implicit-root-uid" + pod := makeNonRootPod(name, rootImage, nil) + pod = podClient.Create(pod) + + ev, err := podClient.WaitForErrorEventOrSuccess(pod) + framework.ExpectNoError(err) + Expect(ev).NotTo(BeNil()) + Expect(ev.Reason).To(Equal(events.FailedToCreateContainer)) + }) + }) + Context("When creating a pod with readOnlyRootFilesystem", func() { makeUserPod := func(podName, image string, command []string, readOnlyRootFilesystem bool) *v1.Pod { return &v1.Pod{ diff --git a/test/images/busybox-user/BASEIMAGE b/test/images/busybox-user/BASEIMAGE new file mode 100644 index 0000000000..44329aaa5b --- /dev/null +++ b/test/images/busybox-user/BASEIMAGE @@ -0,0 +1,5 @@ +amd64=busybox +arm=arm32v6/busybox +arm64=arm64v8/busybox +ppc64le=ppc64le/busybox +s390x=s390x/busybox diff --git a/test/images/busybox-user/Dockerfile b/test/images/busybox-user/Dockerfile new file mode 100644 index 0000000000..f78bbeeb05 --- /dev/null +++ b/test/images/busybox-user/Dockerfile @@ -0,0 +1,17 @@ +# Copyright 2016 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FROM BASEIMAGE + +USER 1234 diff --git a/test/images/busybox-user/VERSION b/test/images/busybox-user/VERSION new file mode 100644 index 0000000000..d3827e75a5 --- /dev/null +++ b/test/images/busybox-user/VERSION @@ -0,0 +1 @@ +1.0 diff --git a/test/utils/image/manifest.go b/test/utils/image/manifest.go index 2e547833d8..2674235d49 100644 --- a/test/utils/image/manifest.go +++ b/test/utils/image/manifest.go @@ -108,6 +108,8 @@ const ( AuditProxy // BusyBox image BusyBox + // BusyBox image with default user 1234 + BusyBoxUser // CheckMetadataConcealment image CheckMetadataConcealment // CudaVectorAdd image @@ -202,6 +204,7 @@ func initImageConfigs() map[int]Config { configs[AppArmorLoader] = Config{e2eRegistry, "apparmor-loader", "1.0"} configs[AuditProxy] = Config{e2eRegistry, "audit-proxy", "1.0"} configs[BusyBox] = Config{dockerLibraryRegistry, "busybox", "1.29"} + configs[BusyBoxUser] = Config{e2eRegistry, "busybox-user", "1.0"} configs[CheckMetadataConcealment] = Config{e2eRegistry, "metadata-concealment", "1.2"} configs[CudaVectorAdd] = Config{e2eRegistry, "cuda-vector-add", "1.0"} configs[CudaVectorAdd2] = Config{e2eRegistry, "cuda-vector-add", "2.0"} From c851c480d32614ec5b311fbb837cd19fc46cfc60 Mon Sep 17 00:00:00 2001 From: Tim Allclair Date: Fri, 24 May 2019 11:57:43 -0700 Subject: [PATCH 2/2] Move to debian-base non-root image --- test/e2e/common/security_context.go | 2 +- test/images/busybox-user/BASEIMAGE | 5 ----- test/images/{busybox-user => nonroot}/Dockerfile | 4 ++-- test/images/{busybox-user => nonroot}/VERSION | 0 test/utils/image/manifest.go | 6 +++--- 5 files changed, 6 insertions(+), 11 deletions(-) delete mode 100644 test/images/busybox-user/BASEIMAGE rename test/images/{busybox-user => nonroot}/Dockerfile (88%) rename test/images/{busybox-user => nonroot}/VERSION (100%) diff --git a/test/e2e/common/security_context.go b/test/e2e/common/security_context.go index 3e495621f3..e3c94908db 100644 --- a/test/e2e/common/security_context.go +++ b/test/e2e/common/security_context.go @@ -97,7 +97,7 @@ var _ = framework.KubeDescribe("Security Context", func() { Context("When creating a container with runAsNonRoot", func() { rootImage := imageutils.GetE2EImage(imageutils.BusyBox) - nonRootImage := imageutils.GetE2EImage(imageutils.BusyBoxUser) + nonRootImage := imageutils.GetE2EImage(imageutils.NonRoot) makeNonRootPod := func(podName, image string, userid *int64) *v1.Pod { return &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ diff --git a/test/images/busybox-user/BASEIMAGE b/test/images/busybox-user/BASEIMAGE deleted file mode 100644 index 44329aaa5b..0000000000 --- a/test/images/busybox-user/BASEIMAGE +++ /dev/null @@ -1,5 +0,0 @@ -amd64=busybox -arm=arm32v6/busybox -arm64=arm64v8/busybox -ppc64le=ppc64le/busybox -s390x=s390x/busybox diff --git a/test/images/busybox-user/Dockerfile b/test/images/nonroot/Dockerfile similarity index 88% rename from test/images/busybox-user/Dockerfile rename to test/images/nonroot/Dockerfile index f78bbeeb05..0e8a09f63a 100644 --- a/test/images/busybox-user/Dockerfile +++ b/test/images/nonroot/Dockerfile @@ -1,4 +1,4 @@ -# Copyright 2016 The Kubernetes Authors. +# Copyright 2019 The Kubernetes Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,6 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM BASEIMAGE +FROM k8s.gcr.io/debian-base:v1.0.0 USER 1234 diff --git a/test/images/busybox-user/VERSION b/test/images/nonroot/VERSION similarity index 100% rename from test/images/busybox-user/VERSION rename to test/images/nonroot/VERSION diff --git a/test/utils/image/manifest.go b/test/utils/image/manifest.go index 2674235d49..dc6b2e1ad2 100644 --- a/test/utils/image/manifest.go +++ b/test/utils/image/manifest.go @@ -108,8 +108,6 @@ const ( AuditProxy // BusyBox image BusyBox - // BusyBox image with default user 1234 - BusyBoxUser // CheckMetadataConcealment image CheckMetadataConcealment // CudaVectorAdd image @@ -164,6 +162,8 @@ const ( NginxNew // Nonewprivs image Nonewprivs + // NonRoot runs with a default user of 1234 + NonRoot // NoSnatTest image NoSnatTest // NoSnatTestProxy image @@ -204,7 +204,6 @@ func initImageConfigs() map[int]Config { configs[AppArmorLoader] = Config{e2eRegistry, "apparmor-loader", "1.0"} configs[AuditProxy] = Config{e2eRegistry, "audit-proxy", "1.0"} configs[BusyBox] = Config{dockerLibraryRegistry, "busybox", "1.29"} - configs[BusyBoxUser] = Config{e2eRegistry, "busybox-user", "1.0"} configs[CheckMetadataConcealment] = Config{e2eRegistry, "metadata-concealment", "1.2"} configs[CudaVectorAdd] = Config{e2eRegistry, "cuda-vector-add", "1.0"} configs[CudaVectorAdd2] = Config{e2eRegistry, "cuda-vector-add", "2.0"} @@ -232,6 +231,7 @@ func initImageConfigs() map[int]Config { configs[Nginx] = Config{dockerLibraryRegistry, "nginx", "1.14-alpine"} configs[NginxNew] = Config{dockerLibraryRegistry, "nginx", "1.15-alpine"} configs[Nonewprivs] = Config{e2eRegistry, "nonewprivs", "1.0"} + configs[NonRoot] = Config{e2eRegistry, "nonroot", "1.0"} configs[NoSnatTest] = Config{e2eRegistry, "no-snat-test", "1.0"} configs[NoSnatTestProxy] = Config{e2eRegistry, "no-snat-test-proxy", "1.0"} // Pause - when these values are updated, also update cmd/kubelet/app/options/container_runtime.go