diff --git a/pkg/kubelet/dockershim/docker_container_test.go b/pkg/kubelet/dockershim/docker_container_test.go index 3e5f6e82dd4..21d296b1c7d 100644 --- a/pkg/kubelet/dockershim/docker_container_test.go +++ b/pkg/kubelet/dockershim/docker_container_test.go @@ -42,7 +42,7 @@ func makeContainerConfig(sConfig *runtimeApi.PodSandboxConfig, name, image strin // TestListContainers creates several containers and then list them to check // whether the correct metadatas, states, and labels are returned. func TestListContainers(t *testing.T) { - ds, _, _ := newTestDockerSevice() + ds, _, _ := newTestDockerService() podName, namespace := "foo", "bar" containerName, image := "sidecar", "logger" @@ -91,7 +91,7 @@ func TestListContainers(t *testing.T) { // TestContainerStatus tests the basic lifecycle operations and verify that // the status returned reflects the operations performed. func TestContainerStatus(t *testing.T) { - ds, _, fClock := newTestDockerSevice() + ds, _, fClock := newTestDockerService() sConfig := makeSandboxConfig("foo", "bar", "1", 0) labels := map[string]string{"abc.xyz": "foo"} annotations := map[string]string{"foo.bar.baz": "abc"} diff --git a/pkg/kubelet/dockershim/docker_sandbox_test.go b/pkg/kubelet/dockershim/docker_sandbox_test.go index 0e91c1b69cc..8fcf1f0c6d0 100644 --- a/pkg/kubelet/dockershim/docker_sandbox_test.go +++ b/pkg/kubelet/dockershim/docker_sandbox_test.go @@ -48,7 +48,7 @@ func makeSandboxConfigWithLabelsAndAnnotations(name, namespace, uid string, atte // TestListSandboxes creates several sandboxes and then list them to check // whether the correct metadatas, states, and labels are returned. func TestListSandboxes(t *testing.T) { - ds, _, _ := newTestDockerSevice() + ds, _, _ := newTestDockerService() name, namespace := "foo", "bar" configs := []*runtimeApi.PodSandboxConfig{} for i := 0; i < 3; i++ { @@ -86,7 +86,7 @@ func TestListSandboxes(t *testing.T) { // TestSandboxStatus tests the basic lifecycle operations and verify that // the status returned reflects the operations performed. func TestSandboxStatus(t *testing.T) { - ds, _, fClock := newTestDockerSevice() + ds, _, fClock := newTestDockerService() labels := map[string]string{"label": "foobar1"} annotations := map[string]string{"annotation": "abc"} config := makeSandboxConfigWithLabelsAndAnnotations("foo", "bar", "1", 0, labels, annotations) diff --git a/pkg/kubelet/dockershim/docker_service.go b/pkg/kubelet/dockershim/docker_service.go index 54aaefba4b5..3db96741ba9 100644 --- a/pkg/kubelet/dockershim/docker_service.go +++ b/pkg/kubelet/dockershim/docker_service.go @@ -78,8 +78,6 @@ type DockerLegacyService interface { } type dockerService struct { - // TODO: Current seccomp implementation is very docker specific. Move this somewhere else - // after we define more general seccomp api. seccompProfileRoot string client dockertools.DockerInterface } diff --git a/pkg/kubelet/dockershim/docker_service_test.go b/pkg/kubelet/dockershim/docker_service_test.go index 3a59592d36d..deba2de337d 100644 --- a/pkg/kubelet/dockershim/docker_service_test.go +++ b/pkg/kubelet/dockershim/docker_service_test.go @@ -23,7 +23,7 @@ import ( "k8s.io/kubernetes/pkg/util/clock" ) -func newTestDockerSevice() (*dockerService, *dockertools.FakeDockerClient, *clock.FakeClock) { +func newTestDockerService() (*dockerService, *dockertools.FakeDockerClient, *clock.FakeClock) { fakeClock := clock.NewFakeClock(time.Time{}) c := dockertools.NewFakeDockerClientWithClock(fakeClock) return &dockerService{client: c}, c, fakeClock diff --git a/pkg/kubelet/dockershim/helpers_test.go b/pkg/kubelet/dockershim/helpers_test.go index 742ab80a572..f2793627c23 100644 --- a/pkg/kubelet/dockershim/helpers_test.go +++ b/pkg/kubelet/dockershim/helpers_test.go @@ -20,6 +20,10 @@ import ( "testing" "github.com/stretchr/testify/assert" + + "k8s.io/kubernetes/pkg/api" + runtimeApi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime" + "k8s.io/kubernetes/pkg/security/apparmor" ) func TestLabelsAndAnnotationsRoundTrip(t *testing.T) { @@ -32,3 +36,114 @@ func TestLabelsAndAnnotationsRoundTrip(t *testing.T) { assert.Equal(t, expectedLabels, actualLabels) assert.Equal(t, expectedAnnotations, actualAnnotations) } + +// TestGetContainerSecurityOpts tests the logic of generating container security options from sandbox annotations. +// The actual profile loading logic is tested in dockertools. +// TODO: Migrate the corresponding test to dockershim. +func TestGetContainerSecurityOpts(t *testing.T) { + containerName := "bar" + makeConfig := func(annotations map[string]string) *runtimeApi.PodSandboxConfig { + return makeSandboxConfigWithLabelsAndAnnotations("pod", "ns", "1234", 1, nil, annotations) + } + + tests := []struct { + msg string + config *runtimeApi.PodSandboxConfig + expectedOpts []string + }{{ + msg: "No security annotations", + config: makeConfig(nil), + expectedOpts: []string{"seccomp=unconfined"}, + }, { + msg: "Seccomp unconfined", + config: makeConfig(map[string]string{ + api.SeccompContainerAnnotationKeyPrefix + containerName: "unconfined", + }), + expectedOpts: []string{"seccomp=unconfined"}, + }, { + msg: "Seccomp default", + config: makeConfig(map[string]string{ + api.SeccompContainerAnnotationKeyPrefix + containerName: "docker/default", + }), + expectedOpts: nil, + }, { + msg: "Seccomp pod default", + config: makeConfig(map[string]string{ + api.SeccompPodAnnotationKey: "docker/default", + }), + expectedOpts: nil, + }, { + msg: "AppArmor runtime/default", + config: makeConfig(map[string]string{ + apparmor.ContainerAnnotationKeyPrefix + containerName: apparmor.ProfileRuntimeDefault, + }), + expectedOpts: []string{"seccomp=unconfined"}, + }, { + msg: "AppArmor local profile", + config: makeConfig(map[string]string{ + apparmor.ContainerAnnotationKeyPrefix + containerName: apparmor.ProfileNamePrefix + "foo", + }), + expectedOpts: []string{"seccomp=unconfined", "apparmor=foo"}, + }, { + msg: "AppArmor and seccomp profile", + config: makeConfig(map[string]string{ + api.SeccompContainerAnnotationKeyPrefix + containerName: "docker/default", + apparmor.ContainerAnnotationKeyPrefix + containerName: apparmor.ProfileNamePrefix + "foo", + }), + expectedOpts: []string{"apparmor=foo"}, + }} + + for i, test := range tests { + opts, err := getContainerSecurityOpts(containerName, test.config, "test/seccomp/profile/root") + assert.NoError(t, err, "TestCase[%d]: %s", i, test.msg) + assert.Len(t, opts, len(test.expectedOpts), "TestCase[%d]: %s", i, test.msg) + for _, opt := range test.expectedOpts { + assert.Contains(t, opts, opt, "TestCase[%d]: %s", i, test.msg) + } + } +} + +// TestGetSandboxSecurityOpts tests the logic of generating sandbox security options from sandbox annotations. +func TestGetSandboxSecurityOpts(t *testing.T) { + makeConfig := func(annotations map[string]string) *runtimeApi.PodSandboxConfig { + return makeSandboxConfigWithLabelsAndAnnotations("pod", "ns", "1234", 1, nil, annotations) + } + + tests := []struct { + msg string + config *runtimeApi.PodSandboxConfig + expectedOpts []string + }{{ + msg: "No security annotations", + config: makeConfig(nil), + expectedOpts: []string{"seccomp=unconfined"}, + }, { + msg: "Seccomp default", + config: makeConfig(map[string]string{ + api.SeccompPodAnnotationKey: "docker/default", + }), + expectedOpts: nil, + }, { + msg: "Seccomp unconfined", + config: makeConfig(map[string]string{ + api.SeccompPodAnnotationKey: "unconfined", + }), + expectedOpts: []string{"seccomp=unconfined"}, + }, { + msg: "Seccomp pod and container profile", + config: makeConfig(map[string]string{ + api.SeccompContainerAnnotationKeyPrefix + "test-container": "unconfined", + api.SeccompPodAnnotationKey: "docker/default", + }), + expectedOpts: nil, + }} + + for i, test := range tests { + opts, err := getSandboxSecurityOpts(test.config, "test/seccomp/profile/root") + assert.NoError(t, err, "TestCase[%d]: %s", i, test.msg) + assert.Len(t, opts, len(test.expectedOpts), "TestCase[%d]: %s", i, test.msg) + for _, opt := range test.expectedOpts { + assert.Contains(t, opts, opt, "TestCase[%d]: %s", i, test.msg) + } + } +}