Update AppArmor e2e tests

This commit is contained in:
Tim Allclair 2024-02-21 11:58:54 -08:00
parent bf3c8464ba
commit 207a965b3f
3 changed files with 54 additions and 14 deletions

View File

@ -48,8 +48,8 @@ func LoadAppArmorProfiles(ctx context.Context, nsName string, clientset clientse
// CreateAppArmorTestPod creates a pod that tests apparmor profile enforcement. The pod exits with // CreateAppArmorTestPod creates a pod that tests apparmor profile enforcement. The pod exits with
// an error code if the profile is incorrectly enforced. If runOnce is true the pod will exit after // an error code if the profile is incorrectly enforced. If runOnce is true the pod will exit after
// a single test, otherwise it will repeat the test every 1 second until failure. // a single test, otherwise it will repeat the test every 1 second until failure.
func CreateAppArmorTestPod(ctx context.Context, nsName string, clientset clientset.Interface, podClient *e2epod.PodClient, unconfined bool, runOnce bool) *v1.Pod { func AppArmorTestPod(nsName string, unconfined bool, runOnce bool) *v1.Pod {
profile := "localhost/" + appArmorProfilePrefix + nsName localhostProfile := appArmorProfilePrefix + nsName
testCmd := fmt.Sprintf(` testCmd := fmt.Sprintf(`
if touch %[1]s; then if touch %[1]s; then
echo "FAILURE: write to %[1]s should be denied" echo "FAILURE: write to %[1]s should be denied"
@ -64,7 +64,6 @@ elif [[ $(< /proc/self/attr/current) != "%[3]s" ]]; then
fi`, appArmorDeniedPath, appArmorAllowedPath, appArmorProfilePrefix+nsName) fi`, appArmorDeniedPath, appArmorAllowedPath, appArmorProfilePrefix+nsName)
if unconfined { if unconfined {
profile = v1.AppArmorBetaProfileNameUnconfined
testCmd = ` testCmd = `
if cat /proc/sysrq-trigger 2>&1 | grep 'Permission denied'; then if cat /proc/sysrq-trigger 2>&1 | grep 'Permission denied'; then
echo 'FAILURE: reading /proc/sysrq-trigger should be allowed' echo 'FAILURE: reading /proc/sysrq-trigger should be allowed'
@ -94,17 +93,25 @@ done`, testCmd)
}, },
} }
profile := &v1.AppArmorProfile{}
if unconfined {
profile.Type = v1.AppArmorProfileTypeUnconfined
} else {
profile.Type = v1.AppArmorProfileTypeLocalhost
profile.LocalhostProfile = &localhostProfile
}
pod := &v1.Pod{ pod := &v1.Pod{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
GenerateName: "test-apparmor-", GenerateName: "test-apparmor-",
Annotations: map[string]string{
v1.AppArmorBetaContainerAnnotationKeyPrefix + "test": profile,
},
Labels: map[string]string{ Labels: map[string]string{
"test": "apparmor", "test": "apparmor",
}, },
}, },
Spec: v1.PodSpec{ Spec: v1.PodSpec{
SecurityContext: &v1.PodSecurityContext{
AppArmorProfile: profile,
},
Affinity: loaderAffinity, Affinity: loaderAffinity,
Containers: []v1.Container{{ Containers: []v1.Container{{
Name: "test", Name: "test",
@ -115,20 +122,24 @@ done`, testCmd)
}, },
} }
return pod
}
func RunAppArmorTestPod(ctx context.Context, pod *v1.Pod, clientset clientset.Interface, podClient *e2epod.PodClient, runOnce bool) *v1.Pod {
if runOnce { if runOnce {
pod = podClient.Create(ctx, pod) pod = podClient.Create(ctx, pod)
framework.ExpectNoError(e2epod.WaitForPodSuccessInNamespace(ctx, framework.ExpectNoError(e2epod.WaitForPodSuccessInNamespace(ctx,
clientset, pod.Name, nsName)) clientset, pod.Name, pod.Namespace))
var err error var err error
pod, err = podClient.Get(ctx, pod.Name, metav1.GetOptions{}) pod, err = podClient.Get(ctx, pod.Name, metav1.GetOptions{})
framework.ExpectNoError(err) framework.ExpectNoError(err)
} else { } else {
pod = podClient.CreateSync(ctx, pod) pod = podClient.CreateSync(ctx, pod)
framework.ExpectNoError(e2epod.WaitTimeoutForPodReadyInNamespace(ctx, clientset, pod.Name, nsName, framework.PodStartTimeout)) framework.ExpectNoError(e2epod.WaitTimeoutForPodReadyInNamespace(ctx, clientset, pod.Name, pod.Namespace, framework.PodStartTimeout))
} }
// Verify Pod affinity colocated the Pods. // Verify Pod affinity colocated the Pods.
loader := getRunningLoaderPod(ctx, nsName, clientset) loader := getRunningLoaderPod(ctx, pod.Namespace, clientset)
gomega.Expect(pod.Spec.NodeName).To(gomega.Equal(loader.Spec.NodeName)) gomega.Expect(pod.Spec.NodeName).To(gomega.Equal(loader.Spec.NodeName))
return pod return pod

View File

@ -19,6 +19,7 @@ package node
import ( import (
"context" "context"
v1 "k8s.io/api/core/v1"
"k8s.io/kubernetes/test/e2e/framework" "k8s.io/kubernetes/test/e2e/framework"
e2ekubectl "k8s.io/kubernetes/test/e2e/framework/kubectl" e2ekubectl "k8s.io/kubernetes/test/e2e/framework/kubectl"
e2epod "k8s.io/kubernetes/test/e2e/framework/pod" e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
@ -45,12 +46,38 @@ var _ = SIGDescribe("AppArmor", func() {
e2ekubectl.LogFailedContainers(ctx, f.ClientSet, f.Namespace.Name, framework.Logf) e2ekubectl.LogFailedContainers(ctx, f.ClientSet, f.Namespace.Name, framework.Logf)
}) })
ginkgo.It("should enforce an AppArmor profile", func(ctx context.Context) { ginkgo.It("should enforce an AppArmor profile specified on the pod", func(ctx context.Context) {
e2esecurity.CreateAppArmorTestPod(ctx, f.Namespace.Name, f.ClientSet, e2epod.NewPodClient(f), false, true) pod := e2esecurity.AppArmorTestPod(f.Namespace.Name, false, true)
e2esecurity.RunAppArmorTestPod(ctx, pod, f.ClientSet, e2epod.NewPodClient(f), true)
})
ginkgo.It("should enforce an AppArmor profile specified on the container", func(ctx context.Context) {
pod := e2esecurity.AppArmorTestPod(f.Namespace.Name, false, true)
// Move AppArmor profile to the container.
pod.Spec.Containers[0].SecurityContext = &v1.SecurityContext{
AppArmorProfile: pod.Spec.SecurityContext.AppArmorProfile,
}
pod.Spec.SecurityContext = nil
e2esecurity.RunAppArmorTestPod(ctx, pod, f.ClientSet, e2epod.NewPodClient(f), true)
})
ginkgo.It("should enforce an AppArmor profile specified in annotations", func(ctx context.Context) {
pod := e2esecurity.AppArmorTestPod(f.Namespace.Name, false, true)
// Move AppArmor profile to the annotations.
profile := pod.Spec.SecurityContext.AppArmorProfile
key := v1.AppArmorBetaContainerAnnotationKeyPrefix + pod.Spec.Containers[0].Name
pod.Annotations = map[string]string{
key: v1.AppArmorBetaProfileNamePrefix + *profile.LocalhostProfile,
}
pod.Spec.SecurityContext = nil
e2esecurity.RunAppArmorTestPod(ctx, pod, f.ClientSet, e2epod.NewPodClient(f), true)
}) })
ginkgo.It("can disable an AppArmor profile, using unconfined", func(ctx context.Context) { ginkgo.It("can disable an AppArmor profile, using unconfined", func(ctx context.Context) {
e2esecurity.CreateAppArmorTestPod(ctx, f.Namespace.Name, f.ClientSet, e2epod.NewPodClient(f), true, true) pod := e2esecurity.AppArmorTestPod(f.Namespace.Name, true, true)
e2esecurity.RunAppArmorTestPod(ctx, pod, f.ClientSet, e2epod.NewPodClient(f), true)
}) })
}) })
}) })

View File

@ -63,7 +63,8 @@ func (t *AppArmorUpgradeTest) Setup(ctx context.Context, f *framework.Framework)
// Create the initial test pod. // Create the initial test pod.
ginkgo.By("Creating a long-running AppArmor enabled pod.") ginkgo.By("Creating a long-running AppArmor enabled pod.")
t.pod = e2esecurity.CreateAppArmorTestPod(ctx, f.Namespace.Name, f.ClientSet, e2epod.NewPodClient(f), false, false) pod := e2esecurity.AppArmorTestPod(f.Namespace.Name, false, false)
t.pod = e2esecurity.RunAppArmorTestPod(ctx, pod, f.ClientSet, e2epod.NewPodClient(f), false)
// Verify initial state. // Verify initial state.
t.verifyNodesAppArmorEnabled(ctx, f) t.verifyNodesAppArmorEnabled(ctx, f)
@ -99,7 +100,8 @@ func (t *AppArmorUpgradeTest) verifyPodStillUp(ctx context.Context, f *framework
func (t *AppArmorUpgradeTest) verifyNewPodSucceeds(ctx context.Context, f *framework.Framework) { func (t *AppArmorUpgradeTest) verifyNewPodSucceeds(ctx context.Context, f *framework.Framework) {
ginkgo.By("Verifying an AppArmor profile is enforced for a new pod") ginkgo.By("Verifying an AppArmor profile is enforced for a new pod")
e2esecurity.CreateAppArmorTestPod(ctx, f.Namespace.Name, f.ClientSet, e2epod.NewPodClient(f), false, true) pod := e2esecurity.AppArmorTestPod(f.Namespace.Name, false, true)
t.pod = e2esecurity.RunAppArmorTestPod(ctx, pod, f.ClientSet, e2epod.NewPodClient(f), true)
} }
func (t *AppArmorUpgradeTest) verifyNodesAppArmorEnabled(ctx context.Context, f *framework.Framework) { func (t *AppArmorUpgradeTest) verifyNodesAppArmorEnabled(ctx context.Context, f *framework.Framework) {