diff --git a/pkg/kubelet/dockertools/docker_manager.go b/pkg/kubelet/dockertools/docker_manager.go index eaa332796c5..28ba651e65c 100644 --- a/pkg/kubelet/dockertools/docker_manager.go +++ b/pkg/kubelet/dockertools/docker_manager.go @@ -104,8 +104,8 @@ var ( // TODO: make this a TTL based pull (if image older than X policy, pull) podInfraContainerImagePullPolicy = api.PullIfNotPresent - // Default set of security options. - defaultSecurityOpt = []string{"seccomp:unconfined"} + // Default security option, only seccomp for now + defaultSeccompProfile = "unconfined" ) type DockerManager struct { @@ -558,7 +558,7 @@ func (dm *DockerManager) runContainer( ContainerName: container.Name, } - securityOpts, err := dm.getSecurityOpt(pod, container.Name) + securityOpts, err := dm.getSecurityOpts(pod, container.Name) if err != nil { return kubecontainer.ContainerID{}, err } @@ -977,7 +977,7 @@ func (dm *DockerManager) checkVersionCompatibility() error { return nil } -func (dm *DockerManager) getSecurityOpt(pod *api.Pod, ctrName string) ([]string, error) { +func (dm *DockerManager) getSecurityOpts(pod *api.Pod, ctrName string) ([]string, error) { version, err := dm.APIVersion() if err != nil { return nil, err @@ -988,24 +988,31 @@ func (dm *DockerManager) getSecurityOpt(pod *api.Pod, ctrName string) ([]string, if err != nil { return nil, err } - if result < 0 { - // return early for old versions - return nil, nil + var optFmt string + switch { + case result < 0: + return nil, nil // return early for Docker < 1.10 + case result == 0: + optFmt = "%s:%s" // use colon notation for Docker 1.10 + case result > 0: + optFmt = "%s=%s" // use = notation for Docker >= 1.11 } + defaultSecurityOpts := []string{fmt.Sprintf(optFmt, "seccomp", defaultSeccompProfile)} + profile, profileOK := pod.ObjectMeta.Annotations[api.SeccompContainerAnnotationKeyPrefix+ctrName] if !profileOK { // try the pod profile profile, profileOK = pod.ObjectMeta.Annotations[api.SeccompPodAnnotationKey] if !profileOK { // return early the default - return defaultSecurityOpt, nil + return defaultSecurityOpts, nil } } if profile == "unconfined" { // return early the default - return defaultSecurityOpt, nil + return defaultSecurityOpts, nil } if profile == "docker/default" { @@ -1029,7 +1036,7 @@ func (dm *DockerManager) getSecurityOpt(pod *api.Pod, ctrName string) ([]string, return nil, err } - return []string{fmt.Sprintf("seccomp=%s", b.Bytes())}, nil + return []string{fmt.Sprintf(optFmt, "seccomp", b.Bytes())}, nil } type dockerExitError struct { diff --git a/pkg/kubelet/dockertools/docker_manager_test.go b/pkg/kubelet/dockertools/docker_manager_test.go index 6924728780f..97cad5e5669 100644 --- a/pkg/kubelet/dockertools/docker_manager_test.go +++ b/pkg/kubelet/dockertools/docker_manager_test.go @@ -1717,6 +1717,39 @@ func verifySyncResults(t *testing.T, expectedResults []*kubecontainer.SyncResult } } +func TestSecurityOptsOperator(t *testing.T) { + dm110, _ := newTestDockerManagerWithVersion("1.10.1", "1.22") + dm111, _ := newTestDockerManagerWithVersion("1.11.0", "1.23") + + pod := &api.Pod{ + ObjectMeta: api.ObjectMeta{ + UID: "12345678", + Name: "foo", + Namespace: "new", + }, + Spec: api.PodSpec{ + Containers: []api.Container{ + {Name: "bar"}, + }, + }, + } + opts, err := dm110.getSecurityOpts(pod, "bar") + if err != nil { + t.Fatalf("error getting security opts for Docker 1.10: %v", err) + } + if expected := []string{"seccomp:unconfined"}; len(opts) != 1 || opts[0] != expected[0] { + t.Fatalf("security opts for Docker 1.10: expected %v, got: %v", expected, opts) + } + + opts, err = dm111.getSecurityOpts(pod, "bar") + if err != nil { + t.Fatalf("error getting security opts for Docker 1.11: %v", err) + } + if expected := []string{"seccomp=unconfined"}; len(opts) != 1 || opts[0] != expected[0] { + t.Fatalf("security opts for Docker 1.11: expected %v, got: %v", expected, opts) + } +} + func TestSeccompIsUnconfinedByDefaultWithDockerV110(t *testing.T) { dm, fakeDocker := newTestDockerManagerWithVersion("1.10.1", "1.22") pod := &api.Pod{ @@ -1910,7 +1943,7 @@ func TestSeccompLocalhostProfileIsLoaded(t *testing.T) { } for _, test := range tests { - dm, fakeDocker := newTestDockerManagerWithVersion("1.10.1", "1.22") + dm, fakeDocker := newTestDockerManagerWithVersion("1.11.0", "1.23") _, filename, _, _ := goruntime.Caller(0) dm.seccompProfileRoot = path.Join(path.Dir(filename), "fixtures", "seccomp")