Skip to content

Commit

Permalink
adds support for seccomp testing
Browse files Browse the repository at this point in the history
Signed-off-by: Mike Brown <[email protected]>
  • Loading branch information
mikebrow committed Sep 15, 2017
1 parent fbf456b commit 8a05047
Showing 1 changed file with 143 additions and 24 deletions.
167 changes: 143 additions & 24 deletions pkg/validate/security_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package validate

import (
"fmt"
"io/ioutil"
"net"
"os"
"os/exec"
Expand All @@ -34,7 +35,18 @@ import (
)

const (
nginxContainerImage string = "nginx"
nginxContainerImage string = "nginx"
seccompBlockHostNameProfile = `
{
"defaultAction": "SCMP_ACT_ALLOW",
"syscalls": [
{
"name": "sethostname",
"action": "SCMP_ACT_ERRNO"
}
]
}
`
)

var _ = framework.KubeDescribe("Security Context", func() {
Expand Down Expand Up @@ -400,50 +412,137 @@ var _ = framework.KubeDescribe("Security Context", func() {

checkNetworkManagement(rc, containerID, false)
})
})

It("runtime should support setting seccomp profile", func() {
By("create pod")
podID, podConfig = framework.CreatePodSandboxForContainer(rc)
Context("runtime should support seccomp security context", func() {
var podID string
var podConfig *runtimeapi.PodSandboxConfig
sysCaps := []string{"ALL"}

By("create container with security context secomp profile and test")
containerID := createHostNameBlockedbySeccompContainer(rc, ic, podID, podConfig, "container-with-seccomp-profile-test-")
AfterEach(func() {
By("stop PodSandbox")
rc.StopPodSandbox(podID)
By("delete PodSandbox")
rc.RemovePodSandbox(podID)
})

It("runtime should support an seccomp profile that blocks setting hostname with no sysCaps", func() {
By("create pod")
podID, podConfig = framework.CreatePodSandboxForContainer(rc)
By("create container with seccompBlockHostNameProfile and test")
containerID := createSeccompContainerWithProfile(rc, ic, podID, podConfig,
"container-with-block-hostname-seccomp-profile-test-",
seccompBlockHostNameProfile, nil, false)
startContainer(rc, containerID)
Eventually(func() runtimeapi.ContainerState {
return getContainerStatus(rc, containerID).State
}, time.Minute, time.Second*4).Should(Equal(runtimeapi.ContainerState_CONTAINER_RUNNING))

checkSetHostname(rc, containerID, false)
})

By("create container without security context seccomp profile and test")
containerID = framework.CreateDefaultContainer(rc, ic, podID, podConfig, "container-with-no-seccomp-profile-test-")

It("runtime should ignore a seccomp profile that blocks setting hostname when privileged", func() {
By("create privileged pod")
podID, podConfig = createPrivilegedPodSandbox(rc, true)
By("create privileged container with seccompBlockHostNameProfile and test")
containerID := createSeccompContainerWithProfile(rc, ic, podID, podConfig,
"container-with-block-hostname-seccomp-profile-test-",
seccompBlockHostNameProfile, nil, true)
startContainer(rc, containerID)
Eventually(func() runtimeapi.ContainerState {
return getContainerStatus(rc, containerID).State
}, time.Minute, time.Second*4).Should(Equal(runtimeapi.ContainerState_CONTAINER_RUNNING))

checkSetHostname(rc, containerID, true)
})

By("create container with security context and docker/default seccomp profile and test")
containerID = createSeccompContainer(rc, ic, podID, podConfig, "container-with-dockerdefault-seccomp-profile-test-", "docker/default")
It("runtime should block setting hostname with no seccomp profile specified", func() {
By("create pod")
podID, podConfig = framework.CreatePodSandboxForContainer(rc)
By("create container without seccomp profile and test")
containerID := framework.CreateDefaultContainer(rc, ic, podID, podConfig,
"container-with-no-seccomp-profile-test-")
startContainer(rc, containerID)
Eventually(func() runtimeapi.ContainerState {
return getContainerStatus(rc, containerID).State
}, time.Minute, time.Second*4).Should(Equal(runtimeapi.ContainerState_CONTAINER_RUNNING))
checkSetHostname(rc, containerID, false)
})

It("runtime should support setting hostname with docker/default seccomp profile and sysCaps", func() {
By("create pod")
podID, podConfig = framework.CreatePodSandboxForContainer(rc)
By("create container with docker/default seccomp profile and test")
containerID := createSeccompContainer(rc, ic, podID, podConfig,
"container-with-dockerdefault-seccomp-profile-test-", "docker/default", sysCaps, false)
startContainer(rc, containerID)
Eventually(func() runtimeapi.ContainerState {
return getContainerStatus(rc, containerID).State
}, time.Minute, time.Second*4).Should(Equal(runtimeapi.ContainerState_CONTAINER_RUNNING))
checkSetHostname(rc, containerID, true)
})

It("runtime should support setting hostname with runtime/default seccomp profile and sysCaps", func() {
By("create pod")
podID, podConfig = framework.CreatePodSandboxForContainer(rc)
By("create container with runtime/default seccomp profile and test")
containerID := createSeccompContainer(rc, ic, podID, podConfig,
"container-with-runtimedefault-seccomp-profile-test-", "runtime/default", sysCaps, false)
startContainer(rc, containerID)
Eventually(func() runtimeapi.ContainerState {
return getContainerStatus(rc, containerID).State
}, time.Minute, time.Second*4).Should(Equal(runtimeapi.ContainerState_CONTAINER_RUNNING))
checkSetHostname(rc, containerID, true)
})

By("create container with security context and runtime/default seccomp profile and test")
containerID = createSeccompContainer(rc, ic, podID, podConfig, "container-with-runtimedefault-seccomp-profile-test-", "runtime/default")
It("runtime should block sethostname with docker/default seccomp profile and no sysCaps", func() {
By("create pod")
podID, podConfig = framework.CreatePodSandboxForContainer(rc)
By("create container with docker/default seccomp profile and test")
containerID := createSeccompContainer(rc, ic, podID, podConfig,
"container-with-dockerdefault-seccomp-profile-test-", "docker/default", nil, false)
startContainer(rc, containerID)
Eventually(func() runtimeapi.ContainerState {
return getContainerStatus(rc, containerID).State
}, time.Minute, time.Second*4).Should(Equal(runtimeapi.ContainerState_CONTAINER_RUNNING))
checkSetHostname(rc, containerID, false)
})

It("runtime should block sethostname with runtime/default seccomp profile and no sysCaps", func() {
By("create pod")
podID, podConfig = framework.CreatePodSandboxForContainer(rc)
By("create container with runtime/default seccomp profile and test")
containerID := createSeccompContainer(rc, ic, podID, podConfig,
"container-with-runtimedefault-seccomp-profile-test-", "runtime/default", nil, false)
startContainer(rc, containerID)
Eventually(func() runtimeapi.ContainerState {
return getContainerStatus(rc, containerID).State
}, time.Minute, time.Second*4).Should(Equal(runtimeapi.ContainerState_CONTAINER_RUNNING))
checkSetHostname(rc, containerID, false)
})

checkSetHostname(rc, containerID, true)
It("runtime should block sethostname with unconfined seccomp profile and no sysCaps", func() {
By("create pod")
podID, podConfig = framework.CreatePodSandboxForContainer(rc)
By("create container with runtime/default seccomp profile and test")
containerID := createSeccompContainer(rc, ic, podID, podConfig,
"container-with-runtimedefault-seccomp-profile-test-", "unconfined", nil, false)
startContainer(rc, containerID)
Eventually(func() runtimeapi.ContainerState {
return getContainerStatus(rc, containerID).State
}, time.Minute, time.Second*4).Should(Equal(runtimeapi.ContainerState_CONTAINER_RUNNING))
checkSetHostname(rc, containerID, false)
})

It("runtime should block sethostname with nil seccomp profile and no sysCaps", func() {
By("create pod")
podID, podConfig = framework.CreatePodSandboxForContainer(rc)
By("create container with runtime/default seccomp profile and test")
containerID := createSeccompContainer(rc, ic, podID, podConfig,
"container-with-runtimedefault-seccomp-profile-test-", "", nil, false)
startContainer(rc, containerID)
Eventually(func() runtimeapi.ContainerState {
return getContainerStatus(rc, containerID).State
}, time.Minute, time.Second*4).Should(Equal(runtimeapi.ContainerState_CONTAINER_RUNNING))
checkSetHostname(rc, containerID, false)
})
})
})
Expand Down Expand Up @@ -682,11 +781,24 @@ func createAndCheckHostNetwork(rc internalapi.RuntimeService, ic internalapi.Ima
return podID
}

// createHostNameBlockedbySeccompContainer creates container with specified seccompcontainer in ContainerConfig.
func createHostNameBlockedbySeccompContainer(rc internalapi.RuntimeService, ic internalapi.ImageManagerService, podID string, podConfig *runtimeapi.PodSandboxConfig, prefix string) string {
By("create HostNameBlocked container")
profile := "HostNameBlocked.seccomp"
return createSeccompContainer(rc, ic, podID, podConfig, prefix, "localhost/"+profile)
// createSeccompContainerWithProfile creates container with specified seccompcontainer in ContainerConfig.
func createSeccompContainerWithProfile(rc internalapi.RuntimeService,
ic internalapi.ImageManagerService,
podID string,
podConfig *runtimeapi.PodSandboxConfig,
prefix, profileContent string,
caps []string,
privileged bool) string {
By("create seccomp profile for container")
profile := "cri-tools-seccomp-profile.json"
f, err := ioutil.TempFile("/tmp", profile)
framework.ExpectNoError(err, "failed to open temp file: %v", err)
defer f.Close()

_, err = f.WriteString(profileContent)
framework.ExpectNoError(err, "failed to write profiles to file: %v", err)

return createSeccompContainer(rc, ic, podID, podConfig, prefix, "localhost/"+f.Name(), caps, privileged)
}

// createSeccompContainer creates container with the specified seccomp profile.
Expand All @@ -695,15 +807,21 @@ func createSeccompContainer(rc internalapi.RuntimeService,
podID string,
podConfig *runtimeapi.PodSandboxConfig,
prefix string,
profile string) string {
profile string,
caps []string,
privileged bool) string {
By("create " + profile + " Seccomp container")
containerName := prefix + framework.NewUUID()
containerConfig := &runtimeapi.ContainerConfig{
Metadata: framework.BuildContainerMetadata(containerName, framework.DefaultAttempt),
Image: &runtimeapi.ImageSpec{Image: framework.DefaultContainerImage},
Command: []string{"top"},
Command: []string{"sleep", "60"},
Linux: &runtimeapi.LinuxContainerConfig{
SecurityContext: &runtimeapi.LinuxContainerSecurityContext{
Privileged: privileged,
Capabilities: &runtimeapi.Capability{
AddCapabilities: caps,
},
SeccompProfilePath: profile,
},
},
Expand All @@ -713,8 +831,9 @@ func createSeccompContainer(rc internalapi.RuntimeService,

// checkSetHostname checks if the hostname can be set in the container.
func checkSetHostname(rc internalapi.RuntimeService, containerID string, setable bool) {
cmd := []string{"hostname", "ANewHostName"}
By("set hostname in container to determine whether sethostname is blocked")

cmd := []string{"hostname", "ANewHostName"}
stdout, stderr, err := rc.ExecSync(containerID, cmd, time.Duration(defaultExecSyncTimeout)*time.Second)
msg := fmt.Sprintf("cmd %v, stdout %q, stderr %q", cmd, stdout, stderr)

Expand Down

0 comments on commit 8a05047

Please sign in to comment.