mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-20 02:11:09 +00:00
Windows: ensure runAsNonRoot does case-insensitive comparison on user name
Signed-off-by: Mark Rossetti <marosset@microsoft.com>
This commit is contained in:
parent
6adee9d4fb
commit
588ff515bc
@ -25,6 +25,7 @@ import (
|
|||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
"k8s.io/kubernetes/pkg/kubelet/util/format"
|
"k8s.io/kubernetes/pkg/kubelet/util/format"
|
||||||
"k8s.io/kubernetes/pkg/securitycontext"
|
"k8s.io/kubernetes/pkg/securitycontext"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -37,6 +38,7 @@ var (
|
|||||||
// According to the discussion of sig-windows, at present, we assume that ContainerAdministrator is the windows container root user,
|
// According to the discussion of sig-windows, at present, we assume that ContainerAdministrator is the windows container root user,
|
||||||
// and then optimize this logic according to the best time.
|
// and then optimize this logic according to the best time.
|
||||||
// https://docs.google.com/document/d/1Tjxzjjuy4SQsFSUVXZbvqVb64hjNAG5CQX8bK7Yda9w
|
// https://docs.google.com/document/d/1Tjxzjjuy4SQsFSUVXZbvqVb64hjNAG5CQX8bK7Yda9w
|
||||||
|
// note: usernames on Windows are NOT case sensitive!
|
||||||
func verifyRunAsNonRoot(pod *v1.Pod, container *v1.Container, uid *int64, username string) error {
|
func verifyRunAsNonRoot(pod *v1.Pod, container *v1.Container, uid *int64, username string) error {
|
||||||
effectiveSc := securitycontext.DetermineEffectiveSecurityContext(pod, container)
|
effectiveSc := securitycontext.DetermineEffectiveSecurityContext(pod, container)
|
||||||
// If the option is not set, or if running as root is allowed, return nil.
|
// If the option is not set, or if running as root is allowed, return nil.
|
||||||
@ -54,15 +56,17 @@ func verifyRunAsNonRoot(pod *v1.Pod, container *v1.Container, uid *int64, userna
|
|||||||
if effectiveSc.RunAsGroup != nil {
|
if effectiveSc.RunAsGroup != nil {
|
||||||
klog.InfoS("Windows container does not support SecurityContext.RunAsGroup", "pod", klog.KObj(pod), "containerName", container.Name)
|
klog.InfoS("Windows container does not support SecurityContext.RunAsGroup", "pod", klog.KObj(pod), "containerName", container.Name)
|
||||||
}
|
}
|
||||||
|
// Verify that if runAsUserName is set for the pod and/or container that it is not set to 'ContainerAdministrator'
|
||||||
if effectiveSc.WindowsOptions != nil {
|
if effectiveSc.WindowsOptions != nil {
|
||||||
if effectiveSc.WindowsOptions.RunAsUserName != nil {
|
if effectiveSc.WindowsOptions.RunAsUserName != nil {
|
||||||
if *effectiveSc.WindowsOptions.RunAsUserName == windowsRootUserName {
|
if strings.EqualFold(*effectiveSc.WindowsOptions.RunAsUserName, windowsRootUserName) {
|
||||||
return fmt.Errorf("container's runAsUser (%s) which will be regarded as root identity and will break non-root policy (pod: %q, container: %s)", username, format.Pod(pod), container.Name)
|
return fmt.Errorf("container's runAsUserName (%s) which will be regarded as root identity and will break non-root policy (pod: %q, container: %s)", *effectiveSc.WindowsOptions.RunAsUserName, format.Pod(pod), container.Name)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(username) > 0 && username == windowsRootUserName {
|
// Verify that if runAsUserName is NOT set for the pod and/or container that the default user for the container image is not set to 'ContainerAdministrator'
|
||||||
|
if len(username) > 0 && strings.EqualFold(username, windowsRootUserName) {
|
||||||
return fmt.Errorf("container's runAsUser (%s) which will be regarded as root identity and will break non-root policy (pod: %q, container: %s)", username, format.Pod(pod), container.Name)
|
return fmt.Errorf("container's runAsUser (%s) which will be regarded as root identity and will break non-root policy (pod: %q, container: %s)", username, format.Pod(pod), container.Name)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -47,6 +47,7 @@ func TestVerifyRunAsNonRoot(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
rootUser := "ContainerAdministrator"
|
rootUser := "ContainerAdministrator"
|
||||||
|
rootUserUppercase := "CONTAINERADMINISTRATOR"
|
||||||
anyUser := "anyone"
|
anyUser := "anyone"
|
||||||
runAsNonRootTrue := true
|
runAsNonRootTrue := true
|
||||||
runAsNonRootFalse := false
|
runAsNonRootFalse := false
|
||||||
@ -101,6 +102,17 @@ func TestVerifyRunAsNonRoot(t *testing.T) {
|
|||||||
username: rootUser,
|
username: rootUser,
|
||||||
fail: true,
|
fail: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
desc: "Fail if container's RunAsUser is root (case-insensitive) and RunAsNonRoot is true",
|
||||||
|
sc: &v1.SecurityContext{
|
||||||
|
RunAsNonRoot: &runAsNonRootTrue,
|
||||||
|
WindowsOptions: &v1.WindowsSecurityContextOptions{
|
||||||
|
RunAsUserName: &rootUserUppercase,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
username: anyUser,
|
||||||
|
fail: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
desc: "Fail if image's user is root and RunAsNonRoot is true",
|
desc: "Fail if image's user is root and RunAsNonRoot is true",
|
||||||
sc: &v1.SecurityContext{
|
sc: &v1.SecurityContext{
|
||||||
@ -109,6 +121,14 @@ func TestVerifyRunAsNonRoot(t *testing.T) {
|
|||||||
username: rootUser,
|
username: rootUser,
|
||||||
fail: true,
|
fail: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
desc: "Fail if image's user is root (case-insensitive) and RunAsNonRoot is true",
|
||||||
|
sc: &v1.SecurityContext{
|
||||||
|
RunAsNonRoot: &runAsNonRootTrue,
|
||||||
|
},
|
||||||
|
username: rootUserUppercase,
|
||||||
|
fail: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
desc: "Pass if image's user is non-root and RunAsNonRoot is true",
|
desc: "Pass if image's user is non-root and RunAsNonRoot is true",
|
||||||
sc: &v1.SecurityContext{
|
sc: &v1.SecurityContext{
|
||||||
@ -124,6 +144,28 @@ func TestVerifyRunAsNonRoot(t *testing.T) {
|
|||||||
},
|
},
|
||||||
fail: false,
|
fail: false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
desc: "Pass if image's user is root, container's RunAsUser is not root and RunAsNonRoot is true",
|
||||||
|
sc: &v1.SecurityContext{
|
||||||
|
RunAsNonRoot: &runAsNonRootTrue,
|
||||||
|
WindowsOptions: &v1.WindowsSecurityContextOptions{
|
||||||
|
RunAsUserName: &anyUser,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
username: rootUser,
|
||||||
|
fail: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "Pass if image's user is root (case-insensitive), container's RunAsUser is not root and RunAsNonRoot is true",
|
||||||
|
sc: &v1.SecurityContext{
|
||||||
|
RunAsNonRoot: &runAsNonRootTrue,
|
||||||
|
WindowsOptions: &v1.WindowsSecurityContextOptions{
|
||||||
|
RunAsUserName: &anyUser,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
username: rootUserUppercase,
|
||||||
|
fail: false,
|
||||||
|
},
|
||||||
} {
|
} {
|
||||||
pod.Spec.Containers[0].SecurityContext = test.sc
|
pod.Spec.Containers[0].SecurityContext = test.sc
|
||||||
err := verifyRunAsNonRoot(pod, &pod.Spec.Containers[0], test.uid, test.username)
|
err := verifyRunAsNonRoot(pod, &pod.Spec.Containers[0], test.uid, test.username)
|
||||||
|
@ -153,6 +153,42 @@ var _ = SIGDescribe("[Feature:Windows] SecurityContext", func() {
|
|||||||
framework.ExpectNoError(e2epod.WaitForPodNameRunningInNamespace(f.ClientSet, windowsPodWithSELinux.Name,
|
framework.ExpectNoError(e2epod.WaitForPodNameRunningInNamespace(f.ClientSet, windowsPodWithSELinux.Name,
|
||||||
f.Namespace.Name), "failed to wait for pod %s to be running", windowsPodWithSELinux.Name)
|
f.Namespace.Name), "failed to wait for pod %s to be running", windowsPodWithSELinux.Name)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
ginkgo.It("should not be able to create pods with containers running as ContainerAdministrator when runAsNonRoot is true", func() {
|
||||||
|
ginkgo.By("Creating a pod")
|
||||||
|
|
||||||
|
p := runAsUserNamePod(toPtr("ContainerAdministrator"))
|
||||||
|
p.Spec.SecurityContext.RunAsNonRoot = &trueVar
|
||||||
|
|
||||||
|
podInvalid, err := f.ClientSet.CoreV1().Pods(f.Namespace.Name).Create(context.TODO(), p, metav1.CreateOptions{})
|
||||||
|
framework.ExpectNoError(err, "Error creating pod")
|
||||||
|
|
||||||
|
ginkgo.By("Waiting for pod to finish")
|
||||||
|
event, err := f.PodClient().WaitForErrorEventOrSuccess(podInvalid)
|
||||||
|
framework.ExpectNoError(err)
|
||||||
|
framework.ExpectNotEqual(event, nil, "event should not be empty")
|
||||||
|
framework.Logf("Got event: %v", event)
|
||||||
|
expectedEventError := "container's runAsUserName (ContainerAdministrator) which will be regarded as root identity and will break non-root policy"
|
||||||
|
framework.ExpectEqual(true, strings.Contains(event.Message, expectedEventError), "Event error should indicate non-root policy caused container to not start")
|
||||||
|
})
|
||||||
|
|
||||||
|
ginkgo.It("should not be able to create pods with containers running as CONTAINERADMINISTRATOR when runAsNonRoot is true", func() {
|
||||||
|
ginkgo.By("Creating a pod")
|
||||||
|
|
||||||
|
p := runAsUserNamePod(toPtr("CONTAINERADMINISTRATOR"))
|
||||||
|
p.Spec.SecurityContext.RunAsNonRoot = &trueVar
|
||||||
|
|
||||||
|
podInvalid, err := f.ClientSet.CoreV1().Pods(f.Namespace.Name).Create(context.TODO(), p, metav1.CreateOptions{})
|
||||||
|
framework.ExpectNoError(err, "Error creating pod")
|
||||||
|
|
||||||
|
ginkgo.By("Waiting for pod to finish")
|
||||||
|
event, err := f.PodClient().WaitForErrorEventOrSuccess(podInvalid)
|
||||||
|
framework.ExpectNoError(err)
|
||||||
|
framework.ExpectNotEqual(event, nil, "event should not be empty")
|
||||||
|
framework.Logf("Got event: %v", event)
|
||||||
|
expectedEventError := "container's runAsUserName (CONTAINERADMINISTRATOR) which will be regarded as root identity and will break non-root policy"
|
||||||
|
framework.ExpectEqual(true, strings.Contains(event.Message, expectedEventError), "Event error should indicate non-root policy caused container to not start")
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
func runAsUserNamePod(username *string) *v1.Pod {
|
func runAsUserNamePod(username *string) *v1.Pod {
|
||||||
|
Loading…
Reference in New Issue
Block a user