From 7a50b719cfa03926a30e4f2877d66403a4a8a40b Mon Sep 17 00:00:00 2001 From: Mark Rossetti Date: Mon, 17 Oct 2022 14:05:25 -0700 Subject: [PATCH] Adding e2e test for running Windows hostprocess containers as members of a local usergroup Signed-off-by: Mark Rossetti --- test/e2e/windows/host_process.go | 90 ++++++++++++++++++++++++++++++++ test/e2e/windows/utils.go | 12 +++++ 2 files changed, 102 insertions(+) diff --git a/test/e2e/windows/host_process.go b/test/e2e/windows/host_process.go index ee53791b05d..66dc0bf9f19 100644 --- a/test/e2e/windows/host_process.go +++ b/test/e2e/windows/host_process.go @@ -770,6 +770,96 @@ var _ = SIGDescribe("[Feature:WindowsHostProcessContainers] [MinimumKubeletVersi false, "app logs should not contain 'status=failed") }) + + ginkgo.It("should run as localgroup accounts", func() { + // This functionality is only supported on containerd v1.7+ + ginkgo.By("Ensuring Windows nodes are running containerd v1.7+") + windowsNode, err := findWindowsNode(f) + framework.ExpectNoError(err, "error finding Windows node") + r, v, err := getNodeContainerRuntimeAndVersion(windowsNode) + framework.ExpectNoError(err, "error getting node container runtime and version") + framework.Logf("Got runtime: %s, version %v for node %s", r, v, windowsNode.Name) + + if !strings.EqualFold(r, "containerd") { + e2eskipper.Skipf("container runtime is not containerd") + } + + v1dot7 := semver.MustParse("1.7.0") + if v.LT(v1dot7) { + e2eskipper.Skipf("container runtime is < 1.7.0") + } + + ginkgo.By("Scheduling a pod that creates a localgroup from an init container then starts a container using that group") + localGroupName := getRandomUserGrounName() + podName := "host-process-localgroup-pod" + pod := &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: podName, + }, + Spec: v1.PodSpec{ + SecurityContext: &v1.PodSecurityContext{ + WindowsOptions: &v1.WindowsSecurityContextOptions{ + HostProcess: &trueVar, + RunAsUserName: &User_NTAuthoritySystem, + }, + }, + HostNetwork: true, + InitContainers: []v1.Container{ + { + Image: imageutils.GetE2EImage(imageutils.BusyBox), + Name: "setup", + Command: []string{"cmd", "/C", "net", "localgroup", localGroupName, "/add"}, + }, + }, + Containers: []v1.Container{ + { + Image: imageutils.GetE2EImage(imageutils.BusyBox), + Name: "localgroup-container", + Command: []string{"cmd", "/C", "whoami"}, + SecurityContext: &v1.SecurityContext{ + WindowsOptions: &v1.WindowsSecurityContextOptions{ + RunAsUserName: &localGroupName, + }, + }, + }, + }, + RestartPolicy: v1.RestartPolicyNever, + NodeSelector: map[string]string{ + "kubernetes.io/os": "windows", + }, + }, + } + + e2epod.NewPodClient(f).Create(pod) + + ginkgo.By("Waiting for pod to run") + e2epod.NewPodClient(f).WaitForFinish(podName, 3*time.Minute) + + ginkgo.By("Then ensuring pod finished running successfully") + p, err := f.ClientSet.CoreV1().Pods(f.Namespace.Name).Get( + context.TODO(), + podName, + metav1.GetOptions{}) + + framework.ExpectNoError(err, "error retrieving pod") + framework.ExpectEqual(p.Status.Phase, v1.PodSucceeded) + + // whoami will output %COMPUTER_NAME%/{randomly generated username} here. + // It is sufficient to just check that the logs do not container `nt authority` + // because all of the 'built-in' accounts that can be used with HostProcess + // are prefixed with this. + ginkgo.By("Then ensuring pod was not running as a system account") + logs, err := e2epod.GetPodLogs(f.ClientSet, f.Namespace.Name, podName, "localgroup-container") + framework.ExpectNoError(err, "error retrieving container logs") + framework.Logf("Pod logs: %s", logs) + framework.ExpectEqual( + strings.Contains( + strings.ToLower(logs), + "nt authority"), + false, + "Container runs 'whoami' and logs should not contain 'nt authority'") + }) + }) func makeTestPodWithVolumeMounts(name string) *v1.Pod { diff --git a/test/e2e/windows/utils.go b/test/e2e/windows/utils.go index f880f23fe81..2e0c4d0cc15 100644 --- a/test/e2e/windows/utils.go +++ b/test/e2e/windows/utils.go @@ -18,6 +18,7 @@ package windows import ( "fmt" + "math/rand" "strings" "time" @@ -66,3 +67,14 @@ func getNodeContainerRuntimeAndVersion(n v1.Node) (string, semver.Version, error return parts[0], v, nil } + +func getRandomUserGrounName() string { + var letters = []rune("abcdefghijklmnopqrstuvwxya") + + s := make([]rune, 8) + for i := range s { + s[i] = letters[rand.Intn(len(letters))] + } + + return "hpc-" + string(s) +}