Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce new tests for new field Apparmor alongside the old ApparmorProfile #1400

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
130 changes: 119 additions & 11 deletions pkg/validate/apparmor_linux.go
Expand Up @@ -53,6 +53,9 @@ profile cri-validate-apparmor-test-audit-write flags=(attach_disconnected) {
`
)

// The AppArmor profile to the CRI via the deprecated apparmor_profile field
// in favor of the newer structured apparmor field.
// CRI provides the AppArmor profile via both fields to maintain backwards compatibility.
var _ = framework.KubeDescribe("AppArmor", func() {
f := framework.NewDefaultCRIFramework()

Expand All @@ -66,7 +69,7 @@ var _ = framework.KubeDescribe("AppArmor", func() {
Expect(loadTestProfiles()).NotTo(HaveOccurred())
})

Context("runtime should support apparmor", func() {
Context("runtime should support depracated apparmor_profile field", func() {
var sandboxID string
var sandboxConfig *runtimeapi.PodSandboxConfig

Expand All @@ -81,38 +84,143 @@ var _ = framework.KubeDescribe("AppArmor", func() {
rc.RemovePodSandbox(context.TODO(), sandboxID)
})

It("should fail with an unloaded profile", func() {
profile := apparmorProfileNamePrefix + "non-existent-profile"
It("should fail with an unloaded apparmor_profile", func() {
profile := &runtimeapi.LinuxContainerSecurityContext{
ApparmorProfile: apparmorProfileNamePrefix + "non-existent-profile",
}
roman-kiselenko marked this conversation as resolved.
Show resolved Hide resolved
containerID := createContainerWithAppArmor(rc, ic, sandboxID, sandboxConfig, profile, false)
Expect(containerID).To(BeEmpty())
})

It("should enforce a profile blocking writes", func() {
profile := apparmorProfileNamePrefix + "cri-validate-apparmor-test-deny-write"
It("should enforce a apparmor_profile blocking writes", func() {
profile := &runtimeapi.LinuxContainerSecurityContext{
ApparmorProfile: apparmorProfileNamePrefix + "cri-validate-apparmor-test-deny-write",
}
containerID := createContainerWithAppArmor(rc, ic, sandboxID, sandboxConfig, profile, true)
checkContainerApparmor(rc, containerID, false)
})

It("should enforce a permissive profile", func() {
profile := apparmorProfileNamePrefix + "cri-validate-apparmor-test-audit-write"
It("should enforce a permissive depracated profile", func() {
profile := &runtimeapi.LinuxContainerSecurityContext{
ApparmorProfile: apparmorProfileNamePrefix + "cri-validate-apparmor-test-audit-write",
}
containerID := createContainerWithAppArmor(rc, ic, sandboxID, sandboxConfig, profile, true)
checkContainerApparmor(rc, containerID, true)
})
})

Context("runtime should support apparmor field", func() {
var sandboxID string
var sandboxConfig *runtimeapi.PodSandboxConfig

BeforeEach(func() {
sandboxID, sandboxConfig = framework.CreatePodSandboxForContainer(rc)
})

AfterEach(func() {
By("stop PodSandbox")
rc.StopPodSandbox(context.TODO(), sandboxID)
By("delete PodSandbox")
rc.RemovePodSandbox(context.TODO(), sandboxID)
})

It("should fail with an unloaded apparmor_profile", func() {
profile := &runtimeapi.LinuxContainerSecurityContext{
Apparmor: &runtimeapi.SecurityProfile{
ProfileType: runtimeapi.SecurityProfile_Localhost,
LocalhostRef: apparmorProfileNamePrefix + "non-existent-profile",
},
}
containerID := createContainerWithAppArmor(rc, ic, sandboxID, sandboxConfig, profile, false)
Expect(containerID).To(BeEmpty())
})

It("should enforce a apparmor_profile blocking writes", func() {
profile := &runtimeapi.LinuxContainerSecurityContext{
Apparmor: &runtimeapi.SecurityProfile{
ProfileType: runtimeapi.SecurityProfile_Localhost,
LocalhostRef: apparmorProfileNamePrefix + "cri-validate-apparmor-test-deny-write",
},
}
containerID := createContainerWithAppArmor(rc, ic, sandboxID, sandboxConfig, profile, true)
checkContainerApparmor(rc, containerID, false)
})

It("should enforce a permissive depracated profile", func() {
profile := &runtimeapi.LinuxContainerSecurityContext{
Apparmor: &runtimeapi.SecurityProfile{
ProfileType: runtimeapi.SecurityProfile_Localhost,
LocalhostRef: apparmorProfileNamePrefix + "cri-validate-apparmor-test-audit-write",
},
}
containerID := createContainerWithAppArmor(rc, ic, sandboxID, sandboxConfig, profile, true)
checkContainerApparmor(rc, containerID, true)
})
})

Context("runtime should prefer new apparmor field", func() {
var sandboxID string
var sandboxConfig *runtimeapi.PodSandboxConfig

BeforeEach(func() {
sandboxID, sandboxConfig = framework.CreatePodSandboxForContainer(rc)
})

AfterEach(func() {
By("stop PodSandbox")
rc.StopPodSandbox(context.TODO(), sandboxID)
By("delete PodSandbox")
rc.RemovePodSandbox(context.TODO(), sandboxID)
})

It("should fail with an unloaded apparmor_profile", func() {
profile := &runtimeapi.LinuxContainerSecurityContext{
ApparmorProfile: apparmorProfileNamePrefix + "non-existent-profile",
Apparmor: &runtimeapi.SecurityProfile{
ProfileType: runtimeapi.SecurityProfile_Localhost,
LocalhostRef: apparmorProfileNamePrefix + "non-existent-profile",
},
}
containerID := createContainerWithAppArmor(rc, ic, sandboxID, sandboxConfig, profile, false)
Expect(containerID).To(BeEmpty())
})

It("should enforce a apparmor_profile blocking writes", func() {
profile := &runtimeapi.LinuxContainerSecurityContext{
ApparmorProfile: apparmorProfileNamePrefix + "non-existent-profile",
Apparmor: &runtimeapi.SecurityProfile{
ProfileType: runtimeapi.SecurityProfile_Localhost,
LocalhostRef: apparmorProfileNamePrefix + "cri-validate-apparmor-test-deny-write",
},
}
containerID := createContainerWithAppArmor(rc, ic, sandboxID, sandboxConfig, profile, true)
checkContainerApparmor(rc, containerID, false)
})

It("should work with apparmor profile", func() {
profile := &runtimeapi.LinuxContainerSecurityContext{
ApparmorProfile: apparmorProfileNamePrefix + "non-existent-profile",
Apparmor: &runtimeapi.SecurityProfile{
ProfileType: runtimeapi.SecurityProfile_Localhost,
LocalhostRef: apparmorProfileNamePrefix + "cri-validate-apparmor-test-audit-write",
},
}
containerID := createContainerWithAppArmor(rc, ic, sandboxID, sandboxConfig, profile, true)
checkContainerApparmor(rc, containerID, true)
})
})
}
})

func createContainerWithAppArmor(rc internalapi.RuntimeService, ic internalapi.ImageManagerService, sandboxID string, sandboxConfig *runtimeapi.PodSandboxConfig, profile string, shouldSucceed bool) string {
func createContainerWithAppArmor(rc internalapi.RuntimeService, ic internalapi.ImageManagerService, sandboxID string, sandboxConfig *runtimeapi.PodSandboxConfig, profile *runtimeapi.LinuxContainerSecurityContext, shouldSucceed bool) string {
By("create a container with apparmor")
containerName := "apparmor-test-" + framework.NewUUID()
containerConfig := &runtimeapi.ContainerConfig{
Metadata: framework.BuildContainerMetadata(containerName, framework.DefaultAttempt),
Image: &runtimeapi.ImageSpec{Image: framework.TestContext.TestImageList.DefaultTestContainerImage},
Command: []string{"touch", "/tmp/foo"},
Linux: &runtimeapi.LinuxContainerConfig{
SecurityContext: &runtimeapi.LinuxContainerSecurityContext{
ApparmorProfile: profile,
},
SecurityContext: profile,
},
}

Expand Down