mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-10-31 02:08:13 +00:00 
			
		
		
		
	Use seccomp from security context
This commit is contained in:
		| @@ -150,7 +150,7 @@ func (ds *dockerService) CreateContainer(podSandboxID string, config *runtimeapi | ||||
| 	} | ||||
| 	hc.Resources.Devices = devices | ||||
|  | ||||
| 	securityOpts, err := ds.getSecurityOpts(config.Metadata.Name, sandboxConfig, securityOptSep) | ||||
| 	securityOpts, err := ds.getSecurityOpts(config.GetLinux().GetSecurityContext().GetSeccompProfilePath(), securityOptSep) | ||||
| 	if err != nil { | ||||
| 		return "", fmt.Errorf("failed to generate security options for container %q: %v", config.Metadata.Name, err) | ||||
| 	} | ||||
|   | ||||
| @@ -588,7 +588,7 @@ func (ds *dockerService) makeSandboxDockerConfig(c *runtimeapi.PodSandboxConfig, | ||||
| 	} | ||||
|  | ||||
| 	// Set security options. | ||||
| 	securityOpts, err := ds.getSecurityOpts(sandboxContainerName, c, securityOptSep) | ||||
| 	securityOpts, err := ds.getSecurityOpts(c.GetLinux().GetSecurityContext().GetSeccompProfilePath(), securityOptSep) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("failed to generate sandbox security options for sandbox %q: %v", c.Metadata.Name, err) | ||||
| 	} | ||||
|   | ||||
| @@ -146,7 +146,7 @@ type dockerNetworkHost struct { | ||||
| var internalLabelKeys []string = []string{containerTypeLabelKey, containerLogPathLabelKey, sandboxIDLabelKey} | ||||
|  | ||||
| // NOTE: Anything passed to DockerService should be eventually handled in another way when we switch to running the shim as a different process. | ||||
| func NewDockerService(client libdocker.Interface, seccompProfileRoot string, podSandboxImage string, streamingConfig *streaming.Config, | ||||
| func NewDockerService(client libdocker.Interface, podSandboxImage string, streamingConfig *streaming.Config, | ||||
| 	pluginSettings *NetworkPluginSettings, cgroupsName string, kubeCgroupDriver string, execHandlerName, dockershimRootDir string, disableSharedPID bool) (DockerService, error) { | ||||
| 	c := libdocker.NewInstrumentedInterface(client) | ||||
| 	checkpointHandler, err := NewPersistentCheckpointHandler(dockershimRootDir) | ||||
| @@ -165,10 +165,9 @@ func NewDockerService(client libdocker.Interface, seccompProfileRoot string, pod | ||||
| 	} | ||||
|  | ||||
| 	ds := &dockerService{ | ||||
| 		seccompProfileRoot: seccompProfileRoot, | ||||
| 		client:             c, | ||||
| 		os:                 kubecontainer.RealOS{}, | ||||
| 		podSandboxImage:    podSandboxImage, | ||||
| 		client:          c, | ||||
| 		os:              kubecontainer.RealOS{}, | ||||
| 		podSandboxImage: podSandboxImage, | ||||
| 		streamingRuntime: &streamingRuntime{ | ||||
| 			client:      client, | ||||
| 			execHandler: execHandler, | ||||
| @@ -244,12 +243,11 @@ type DockerService interface { | ||||
| } | ||||
|  | ||||
| type dockerService struct { | ||||
| 	seccompProfileRoot string | ||||
| 	client             libdocker.Interface | ||||
| 	os                 kubecontainer.OSInterface | ||||
| 	podSandboxImage    string | ||||
| 	streamingRuntime   *streamingRuntime | ||||
| 	streamingServer    streaming.Server | ||||
| 	client           libdocker.Interface | ||||
| 	os               kubecontainer.OSInterface | ||||
| 	podSandboxImage  string | ||||
| 	streamingRuntime *streamingRuntime | ||||
| 	streamingServer  streaming.Server | ||||
|  | ||||
| 	network *network.PluginManager | ||||
| 	// Map of podSandboxID :: network-is-ready | ||||
|   | ||||
| @@ -30,7 +30,6 @@ import ( | ||||
| 	"github.com/blang/semver" | ||||
| 	dockertypes "github.com/docker/docker/api/types" | ||||
| 	dockercontainer "github.com/docker/docker/api/types/container" | ||||
| 	"k8s.io/api/core/v1" | ||||
| 	runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" | ||||
| ) | ||||
|  | ||||
| @@ -38,46 +37,35 @@ func DefaultMemorySwap() int64 { | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| func (ds *dockerService) getSecurityOpts(containerName string, sandboxConfig *runtimeapi.PodSandboxConfig, separator rune) ([]string, error) { | ||||
| func (ds *dockerService) getSecurityOpts(seccompProfile string, separator rune) ([]string, error) { | ||||
| 	// Apply seccomp options. | ||||
| 	seccompSecurityOpts, err := getSeccompSecurityOpts(containerName, sandboxConfig, ds.seccompProfileRoot, separator) | ||||
| 	seccompSecurityOpts, err := getSeccompSecurityOpts(seccompProfile, separator) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("failed to generate seccomp security options for container %q: %v", containerName, err) | ||||
| 		return nil, fmt.Errorf("failed to generate seccomp security options for container: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	return seccompSecurityOpts, nil | ||||
| } | ||||
|  | ||||
| func getSeccompDockerOpts(annotations map[string]string, ctrName, profileRoot string) ([]dockerOpt, error) { | ||||
| 	profile, profileOK := annotations[v1.SeccompContainerAnnotationKeyPrefix+ctrName] | ||||
| 	if !profileOK { | ||||
| 		// try the pod profile | ||||
| 		profile, profileOK = annotations[v1.SeccompPodAnnotationKey] | ||||
| 		if !profileOK { | ||||
| 			// return early the default | ||||
| 			return defaultSeccompOpt, nil | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if profile == "unconfined" { | ||||
| func getSeccompDockerOpts(seccompProfile string) ([]dockerOpt, error) { | ||||
| 	if seccompProfile == "" || seccompProfile == "unconfined" { | ||||
| 		// return early the default | ||||
| 		return defaultSeccompOpt, nil | ||||
| 	} | ||||
|  | ||||
| 	if profile == "docker/default" { | ||||
| 	if seccompProfile == "docker/default" { | ||||
| 		// return nil so docker will load the default seccomp profile | ||||
| 		return nil, nil | ||||
| 	} | ||||
|  | ||||
| 	if !strings.HasPrefix(profile, "localhost/") { | ||||
| 		return nil, fmt.Errorf("unknown seccomp profile option: %s", profile) | ||||
| 	if !strings.HasPrefix(seccompProfile, "localhost/") { | ||||
| 		return nil, fmt.Errorf("unknown seccomp profile option: %s", seccompProfile) | ||||
| 	} | ||||
|  | ||||
| 	name := strings.TrimPrefix(profile, "localhost/") // by pod annotation validation, name is a valid subpath | ||||
| 	fname := filepath.Join(profileRoot, filepath.FromSlash(name)) | ||||
| 	file, err := ioutil.ReadFile(fname) | ||||
| 	fname := strings.TrimPrefix(seccompProfile, "localhost/") // by pod annotation validation, name is a valid subpath | ||||
| 	file, err := ioutil.ReadFile(filepath.FromSlash(fname)) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("cannot load seccomp profile %q: %v", name, err) | ||||
| 		return nil, fmt.Errorf("cannot load seccomp profile %q: %v", fname, err) | ||||
| 	} | ||||
|  | ||||
| 	b := bytes.NewBuffer(nil) | ||||
| @@ -85,16 +73,15 @@ func getSeccompDockerOpts(annotations map[string]string, ctrName, profileRoot st | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	// Rather than the full profile, just put the filename & md5sum in the event log. | ||||
| 	msg := fmt.Sprintf("%s(md5:%x)", name, md5.Sum(file)) | ||||
| 	msg := fmt.Sprintf("%s(md5:%x)", fname, md5.Sum(file)) | ||||
|  | ||||
| 	return []dockerOpt{{"seccomp", b.String(), msg}}, nil | ||||
| } | ||||
|  | ||||
| // getSeccompSecurityOpts gets container seccomp options from container and sandbox | ||||
| // config, currently from sandbox annotations. | ||||
| // getSeccompSecurityOpts gets container seccomp options from container security context. | ||||
| // It is an experimental feature and may be promoted to official runtime api in the future. | ||||
| func getSeccompSecurityOpts(containerName string, sandboxConfig *runtimeapi.PodSandboxConfig, seccompProfileRoot string, separator rune) ([]string, error) { | ||||
| 	seccompOpts, err := getSeccompDockerOpts(sandboxConfig.GetAnnotations(), containerName, seccompProfileRoot) | ||||
| func getSeccompSecurityOpts(seccompProfile string, separator rune) ([]string, error) { | ||||
| 	seccompOpts, err := getSeccompDockerOpts(seccompProfile) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|   | ||||
| @@ -20,51 +20,32 @@ package dockershim | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"path" | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| 	"k8s.io/api/core/v1" | ||||
|  | ||||
| 	runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" | ||||
| ) | ||||
|  | ||||
| func TestGetSeccompSecurityOpts(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            string | ||||
| 		seccompProfile string | ||||
| 		expectedOpts   []string | ||||
| 	}{{ | ||||
| 		msg:          "No security annotations", | ||||
| 		config:       makeConfig(nil), | ||||
| 		expectedOpts: []string{"seccomp=unconfined"}, | ||||
| 		msg:            "No security annotations", | ||||
| 		seccompProfile: "", | ||||
| 		expectedOpts:   []string{"seccomp=unconfined"}, | ||||
| 	}, { | ||||
| 		msg: "Seccomp unconfined", | ||||
| 		config: makeConfig(map[string]string{ | ||||
| 			v1.SeccompContainerAnnotationKeyPrefix + containerName: "unconfined", | ||||
| 		}), | ||||
| 		expectedOpts: []string{"seccomp=unconfined"}, | ||||
| 		msg:            "Seccomp unconfined", | ||||
| 		seccompProfile: "unconfined", | ||||
| 		expectedOpts:   []string{"seccomp=unconfined"}, | ||||
| 	}, { | ||||
| 		msg: "Seccomp default", | ||||
| 		config: makeConfig(map[string]string{ | ||||
| 			v1.SeccompContainerAnnotationKeyPrefix + containerName: "docker/default", | ||||
| 		}), | ||||
| 		expectedOpts: nil, | ||||
| 	}, { | ||||
| 		msg: "Seccomp pod default", | ||||
| 		config: makeConfig(map[string]string{ | ||||
| 			v1.SeccompPodAnnotationKey: "docker/default", | ||||
| 		}), | ||||
| 		expectedOpts: nil, | ||||
| 		msg:            "Seccomp default", | ||||
| 		seccompProfile: "docker/default", | ||||
| 		expectedOpts:   nil, | ||||
| 	}} | ||||
|  | ||||
| 	for i, test := range tests { | ||||
| 		opts, err := getSeccompSecurityOpts(containerName, test.config, "test/seccomp/profile/root", '=') | ||||
| 		opts, err := getSeccompSecurityOpts(test.seccompProfile, '=') | ||||
| 		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 { | ||||
| @@ -74,42 +55,30 @@ func TestGetSeccompSecurityOpts(t *testing.T) { | ||||
| } | ||||
|  | ||||
| func TestLoadSeccompLocalhostProfiles(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 | ||||
| 		expectErr    bool | ||||
| 		msg            string | ||||
| 		seccompProfile string | ||||
| 		expectedOpts   []string | ||||
| 		expectErr      bool | ||||
| 	}{{ | ||||
| 		msg: "Seccomp localhost/test profile", | ||||
| 		config: makeConfig(map[string]string{ | ||||
| 			v1.SeccompPodAnnotationKey: "localhost/test", | ||||
| 		}), | ||||
| 		expectedOpts: []string{`seccomp={"foo":"bar"}`}, | ||||
| 		expectErr:    false, | ||||
| 		msg:            "Seccomp localhost/test profile", | ||||
| 		seccompProfile: "localhost/fixtures/seccomp/test", | ||||
| 		expectedOpts:   []string{`seccomp={"foo":"bar"}`}, | ||||
| 		expectErr:      false, | ||||
| 	}, { | ||||
| 		msg: "Seccomp localhost/sub/subtest profile", | ||||
| 		config: makeConfig(map[string]string{ | ||||
| 			v1.SeccompPodAnnotationKey: "localhost/sub/subtest", | ||||
| 		}), | ||||
| 		expectedOpts: []string{`seccomp={"abc":"def"}`}, | ||||
| 		expectErr:    false, | ||||
| 		msg:            "Seccomp localhost/sub/subtest profile", | ||||
| 		seccompProfile: "localhost/fixtures/seccomp/sub/subtest", | ||||
| 		expectedOpts:   []string{`seccomp={"abc":"def"}`}, | ||||
| 		expectErr:      false, | ||||
| 	}, { | ||||
| 		msg: "Seccomp non-existent", | ||||
| 		config: makeConfig(map[string]string{ | ||||
| 			v1.SeccompPodAnnotationKey: "localhost/non-existent", | ||||
| 		}), | ||||
| 		expectedOpts: nil, | ||||
| 		expectErr:    true, | ||||
| 		msg:            "Seccomp non-existent", | ||||
| 		seccompProfile: "localhost/fixtures/seccomp/non-existent", | ||||
| 		expectedOpts:   nil, | ||||
| 		expectErr:      true, | ||||
| 	}} | ||||
|  | ||||
| 	profileRoot := path.Join("fixtures", "seccomp") | ||||
| 	for i, test := range tests { | ||||
| 		opts, err := getSeccompSecurityOpts(containerName, test.config, profileRoot, '=') | ||||
| 		opts, err := getSeccompSecurityOpts(test.seccompProfile, '=') | ||||
| 		if test.expectErr { | ||||
| 			assert.Error(t, err, fmt.Sprintf("TestCase[%d]: %s", i, test.msg)) | ||||
| 			continue | ||||
|   | ||||
| @@ -29,7 +29,7 @@ func DefaultMemorySwap() int64 { | ||||
| 	return -1 | ||||
| } | ||||
|  | ||||
| func (ds *dockerService) getSecurityOpts(containerName string, sandboxConfig *runtimeapi.PodSandboxConfig, separator rune) ([]string, error) { | ||||
| func (ds *dockerService) getSecurityOpts(seccompProfile string, separator rune) ([]string, error) { | ||||
| 	glog.Warningf("getSecurityOpts is unsupported in this build") | ||||
| 	return nil, nil | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Pengfei Ni
					Pengfei Ni