diff --git a/pkg/validate/security_context.go b/pkg/validate/security_context.go index b30be617b7..566e3b269a 100644 --- a/pkg/validate/security_context.go +++ b/pkg/validate/security_context.go @@ -59,6 +59,8 @@ const ( } ] }` + + noNewPrivsImage = "gcr.io/google_containers/nonewprivs:1.2" ) var _ = framework.KubeDescribe("Security Context", func() { @@ -619,6 +621,80 @@ var _ = framework.KubeDescribe("Security Context", func() { checkSetHostname(rc, containerID, false) }) }) + + Context("NoNewPrivs", func() { + var podID, logPath string + var podConfig *runtimeapi.PodSandboxConfig + + BeforeEach(func() { + podID, podConfig, logPath = createPodSandboxWithLogDirectory(rc) + }) + + AfterEach(func() { + By("stop PodSandbox") + rc.StopPodSandbox(podID) + By("delete PodSandbox") + rc.RemovePodSandbox(podID) + By("clean up the log dir") + os.RemoveAll(logPath) + }) + + createContainerWithNoNewPrivs := func(name string, noNewPrivs *bool, uid int64) string { + By(fmt.Sprintf("create container %s", name)) + containerConfig := &runtimeapi.ContainerConfig{ + Metadata: framework.BuildContainerMetadata(name, framework.DefaultAttempt), + Image: &runtimeapi.ImageSpec{Image: noNewPrivsImage}, + Linux: &runtimeapi.LinuxContainerConfig{ + SecurityContext: &runtimeapi.LinuxContainerSecurityContext{ + RunAsUser: &runtimeapi.Int64Value{ + Value: uid, + }, + }, + }, + LogPath: fmt.Sprintf("%s.log", name), + } + if noNewPrivs != nil { + containerConfig.Linux.SecurityContext.NoNewPrivs = *noNewPrivs + } + containerID := framework.CreateContainer(rc, ic, containerConfig, podID, podConfig) + + // wait container started and check the status. + startContainer(rc, containerID) + Eventually(func() runtimeapi.ContainerState { + return getContainerStatus(rc, containerID).State + }, time.Minute, time.Second*4).Should(Equal(runtimeapi.ContainerState_CONTAINER_EXITED)) + + return containerID + } + matchOutput := func(name, output string) { + By("check container's output") + expectedLog := &logMessage{ + log: []byte(output + "\n"), + stream: stdoutType, + } + verifyLogContents(podConfig, fmt.Sprintf("%s.log", name), expectedLog) + } + + It("should allow privilege escalation when not explicitly set and uid != 0", func() { + containerName := "alpine-nnp-nil-" + string(framework.NewUUID()) + createContainerWithNoNewPrivs(containerName, nil, 1000) + matchOutput(containerName, "Effective uid: 0") + }) + + It("should not allow privilege escalation when true", func() { + containerName := "alpine-nnp-true-" + string(framework.NewUUID()) + noNewPrivsTrue := true + createContainerWithNoNewPrivs(containerName, &noNewPrivsTrue, 1000) + matchOutput(containerName, "Effective uid: 1000") + }) + + It("should allow privilege escalation when false", func() { + containerName := "alpine-nnp-false-" + string(framework.NewUUID()) + noNewPrivsFalse := false + createContainerWithNoNewPrivs(containerName, &noNewPrivsFalse, 1000) + matchOutput(containerName, "Effective uid: 0") + }) + }) }) // createRunAsUserContainer creates the container with specified RunAsUser in ContainerConfig.