[windows] Test: Check for failed sandbox pod when testing for RunAsUserName (#105943)

* Check for failed sandbox and failed workload containers

* Add test to confirm containers won't start
This commit is contained in:
James Sturtevant 2021-10-28 14:04:59 -07:00 committed by GitHub
parent 1d9d530ee1
commit d6db275cd3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -18,15 +18,22 @@ package windows
import ( import (
"context" "context"
"fmt"
"strings"
"time"
"github.com/onsi/ginkgo"
"github.com/onsi/gomega"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/util/uuid" "k8s.io/apimachinery/pkg/util/uuid"
clientset "k8s.io/client-go/kubernetes"
"k8s.io/kubernetes/pkg/kubelet/events"
"k8s.io/kubernetes/test/e2e/framework" "k8s.io/kubernetes/test/e2e/framework"
e2epod "k8s.io/kubernetes/test/e2e/framework/pod" e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
testutils "k8s.io/kubernetes/test/utils" testutils "k8s.io/kubernetes/test/utils"
imageutils "k8s.io/kubernetes/test/utils/image" imageutils "k8s.io/kubernetes/test/utils/image"
"github.com/onsi/ginkgo"
) )
const runAsUserNameContainerName = "run-as-username-container" const runAsUserNameContainerName = "run-as-username-container"
@ -43,10 +50,59 @@ var _ = SIGDescribe("[Feature:Windows] SecurityContext", func() {
f.TestContainerOutput("check set user", podUserName, 0, []string{"ContainerAdministrator"}) f.TestContainerOutput("check set user", podUserName, 0, []string{"ContainerAdministrator"})
}) })
ginkgo.It("should not be able to create pods with unknown usernames", func() { ginkgo.It("should not be able to create pods with unknown usernames at Pod level", func() {
ginkgo.By("Creating a pod with an invalid username") ginkgo.By("Creating a pod with an invalid username")
podInvalid := f.PodClient().Create(runAsUserNamePod(toPtr("FooLish"))) podInvalid := f.PodClient().Create(runAsUserNamePod(toPtr("FooLish")))
failedSandboxEventSelector := fields.Set{
"involvedObject.kind": "Pod",
"involvedObject.name": podInvalid.Name,
"involvedObject.namespace": podInvalid.Namespace,
"reason": events.FailedCreatePodSandBox,
}.AsSelector().String()
hcsschimError := "The user name or password is incorrect."
// Hostprocess updated the cri to pass RunAsUserName to sandbox: https://github.com/kubernetes/kubernetes/pull/99576/commits/51a02fdb80cb7ba042a66362eb76facd2fd82401
// Some runtimes might use that and set the username on the podsandbox. Containerd 1.6+ is known to do this.
// If there is an error when creating the pod sandbox then the pod stays in pending state by design
// See https://github.com/kubernetes/kubernetes/issues/104635
// Not all runtimes use the sandbox information. This means the test needs to check if the pod
// sandbox failed or workload pod failed.
framework.Logf("Waiting for pod %s to enter the error state.", podInvalid.Name)
gomega.Eventually(func() bool {
failedSandbox, err := eventOccurred(f.ClientSet, podInvalid.Namespace, failedSandboxEventSelector, hcsschimError)
if err != nil {
framework.Logf("Error retrieving events for pod. Ignoring...")
}
if failedSandbox {
framework.Logf("Found Expected Event 'Failed to Create Pod Sandbox' with message containing: %s", hcsschimError)
return true
}
framework.Logf("No Sandbox error found. Looking for failure in workload pods")
pod, err := f.PodClient().Get(context.Background(), podInvalid.Name, metav1.GetOptions{})
if err != nil {
framework.Logf("Error retrieving pod: %s", err)
return false
}
podTerminatedReason := testutils.TerminatedContainers(pod)[runAsUserNameContainerName]
podFailedToStart := podTerminatedReason == "ContainerCannotRun" || podTerminatedReason == "StartError"
if pod.Status.Phase == v1.PodFailed && podFailedToStart {
framework.Logf("Found terminated workload Pod that could not start")
return true
}
return false
}, framework.PodStartTimeout, 1*time.Second).Should(gomega.BeTrue())
})
ginkgo.It("should not be able to create pods with unknown usernames at Container level", func() {
ginkgo.By("Creating a pod with an invalid username at container level and pod running as ContainerUser")
p := runAsUserNamePod(toPtr("FooLish"))
p.Spec.SecurityContext.WindowsOptions.RunAsUserName = toPtr("ContainerUser")
podInvalid := f.PodClient().Create(p)
framework.Logf("Waiting for pod %s to enter the error state.", podInvalid.Name) framework.Logf("Waiting for pod %s to enter the error state.", podInvalid.Name)
framework.ExpectNoError(e2epod.WaitForPodTerminatedInNamespace(f.ClientSet, podInvalid.Name, "", f.Namespace.Name)) framework.ExpectNoError(e2epod.WaitForPodTerminatedInNamespace(f.ClientSet, podInvalid.Name, "", f.Namespace.Name))
@ -71,6 +127,7 @@ var _ = SIGDescribe("[Feature:Windows] SecurityContext", func() {
f.TestContainerOutput("check overridden username", pod, 0, []string{"ContainerUser"}) f.TestContainerOutput("check overridden username", pod, 0, []string{"ContainerUser"})
f.TestContainerOutput("check pod SecurityContext username", pod, 1, []string{"ContainerAdministrator"}) f.TestContainerOutput("check pod SecurityContext username", pod, 1, []string{"ContainerAdministrator"})
}) })
ginkgo.It("should ignore Linux Specific SecurityContext if set", func() { ginkgo.It("should ignore Linux Specific SecurityContext if set", func() {
ginkgo.By("Creating a pod with SELinux options") ginkgo.By("Creating a pod with SELinux options")
// It is sufficient to show that the pod comes up here. Since we're stripping the SELinux and other linux // It is sufficient to show that the pod comes up here. Since we're stripping the SELinux and other linux
@ -129,3 +186,18 @@ func runAsUserNamePod(username *string) *v1.Pod {
func toPtr(s string) *string { func toPtr(s string) *string {
return &s return &s
} }
func eventOccurred(c clientset.Interface, namespace, eventSelector, msg string) (bool, error) {
options := metav1.ListOptions{FieldSelector: eventSelector}
events, err := c.CoreV1().Events(namespace).List(context.TODO(), options)
if err != nil {
return false, fmt.Errorf("got error while getting events: %v", err)
}
for _, event := range events.Items {
if strings.Contains(event.Message, msg) {
return true, nil
}
}
return false, nil
}