mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 12:18:16 +00:00 
			
		
		
		
	Add seccomp and apparmor support.
This commit is contained in:
		@@ -166,7 +166,11 @@ func (ds *dockerService) CreateContainer(podSandboxID string, config *runtimeApi
 | 
				
			|||||||
		// Note: ShmSize is handled in kube_docker_client.go
 | 
							// Note: ShmSize is handled in kube_docker_client.go
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hc.SecurityOpt = []string{getSeccompOpts()}
 | 
						var err error
 | 
				
			||||||
 | 
						hc.SecurityOpt, err = getContainerSecurityOpts(config.Metadata.GetName(), sandboxConfig, ds.seccompProfileRoot)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return "", fmt.Errorf("failed to generate container security options for container %q: %v", config.Metadata.GetName(), err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	// TODO: Add or drop capabilities.
 | 
						// TODO: Add or drop capabilities.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	createConfig.HostConfig = hc
 | 
						createConfig.HostConfig = hc
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -53,7 +53,10 @@ func (ds *dockerService) RunPodSandbox(config *runtimeApi.PodSandboxConfig) (str
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Step 2: Create the sandbox container.
 | 
						// Step 2: Create the sandbox container.
 | 
				
			||||||
	createConfig := makeSandboxDockerConfig(config, image)
 | 
						createConfig, err := ds.makeSandboxDockerConfig(config, image)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return "", fmt.Errorf("failed to make sandbox docker config for pod %q: %v", config.Metadata.GetName(), err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	createResp, err := ds.client.CreateContainer(*createConfig)
 | 
						createResp, err := ds.client.CreateContainer(*createConfig)
 | 
				
			||||||
	if err != nil || createResp == nil {
 | 
						if err != nil || createResp == nil {
 | 
				
			||||||
		return "", fmt.Errorf("failed to create a sandbox for pod %q: %v", config.Metadata.GetName(), err)
 | 
							return "", fmt.Errorf("failed to create a sandbox for pod %q: %v", config.Metadata.GetName(), err)
 | 
				
			||||||
@@ -194,7 +197,7 @@ func (ds *dockerService) ListPodSandbox(filter *runtimeApi.PodSandboxFilter) ([]
 | 
				
			|||||||
	return result, nil
 | 
						return result, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func makeSandboxDockerConfig(c *runtimeApi.PodSandboxConfig, image string) *dockertypes.ContainerCreateConfig {
 | 
					func (ds *dockerService) makeSandboxDockerConfig(c *runtimeApi.PodSandboxConfig, image string) (*dockertypes.ContainerCreateConfig, error) {
 | 
				
			||||||
	// Merge annotations and labels because docker supports only labels.
 | 
						// Merge annotations and labels because docker supports only labels.
 | 
				
			||||||
	labels := makeLabels(c.GetLabels(), c.GetAnnotations())
 | 
						labels := makeLabels(c.GetLabels(), c.GetAnnotations())
 | 
				
			||||||
	// Apply a label to distinguish sandboxes from regular containers.
 | 
						// Apply a label to distinguish sandboxes from regular containers.
 | 
				
			||||||
@@ -252,9 +255,12 @@ func makeSandboxDockerConfig(c *runtimeApi.PodSandboxConfig, image string) *dock
 | 
				
			|||||||
	setSandboxResources(hc)
 | 
						setSandboxResources(hc)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Set security options.
 | 
						// Set security options.
 | 
				
			||||||
	hc.SecurityOpt = []string{getSeccompOpts()}
 | 
						var err error
 | 
				
			||||||
 | 
						hc.SecurityOpt, err = getSandboxSecurityOpts(c, ds.seccompProfileRoot)
 | 
				
			||||||
	return createConfig
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("failed to generate sandbox security options for sandbox %q: %v", c.Metadata.GetName(), err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return createConfig, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func setSandboxResources(hc *dockercontainer.HostConfig) {
 | 
					func setSandboxResources(hc *dockercontainer.HostConfig) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -53,8 +53,10 @@ const (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
var internalLabelKeys []string = []string{containerTypeLabelKey, sandboxIDLabelKey}
 | 
					var internalLabelKeys []string = []string{containerTypeLabelKey, sandboxIDLabelKey}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewDockerService(client dockertools.DockerInterface) DockerLegacyService {
 | 
					// 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 dockertools.DockerInterface, seccompProfileRoot string) DockerLegacyService {
 | 
				
			||||||
	return &dockerService{
 | 
						return &dockerService{
 | 
				
			||||||
 | 
							seccompProfileRoot: seccompProfileRoot,
 | 
				
			||||||
		client:             dockertools.NewInstrumentedDockerInterface(client),
 | 
							client:             dockertools.NewInstrumentedDockerInterface(client),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -76,6 +78,9 @@ type DockerLegacyService interface {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type dockerService struct {
 | 
					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
 | 
						client             dockertools.DockerInterface
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,6 +28,7 @@ import (
 | 
				
			|||||||
	"github.com/golang/glog"
 | 
						"github.com/golang/glog"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	runtimeApi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime"
 | 
						runtimeApi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime"
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/pkg/kubelet/dockertools"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
@@ -179,12 +180,30 @@ func makePortsAndBindings(pm []*runtimeApi.PortMapping) (map[dockernat.Port]stru
 | 
				
			|||||||
	return exposedPorts, portBindings
 | 
						return exposedPorts, portBindings
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TODO: Seccomp support. Need to figure out how to pass seccomp options
 | 
					// getContainerSecurityOpt gets container security options from container and sandbox config, currently from sandbox
 | 
				
			||||||
// through the runtime API (annotations?).See dockerManager.getSecurityOpts()
 | 
					// annotations.
 | 
				
			||||||
// for the details. Always set the default seccomp profile for now.
 | 
					// It is an experimental feature and may be promoted to official runtime api in the future.
 | 
				
			||||||
// Also need to support syntax for different docker versions.
 | 
					func getContainerSecurityOpts(containerName string, sandboxConfig *runtimeApi.PodSandboxConfig, seccompProfileRoot string) ([]string, error) {
 | 
				
			||||||
func getSeccompOpts() string {
 | 
						appArmorOpts, err := dockertools.GetAppArmorOpts(sandboxConfig.GetAnnotations(), containerName)
 | 
				
			||||||
	return fmt.Sprintf("%s=%s", "seccomp", defaultSeccompProfile)
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						seccompOpts, err := dockertools.GetSeccompOpts(sandboxConfig.GetAnnotations(), containerName, seccompProfileRoot)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						securityOpts := append(appArmorOpts, seccompOpts...)
 | 
				
			||||||
 | 
						var opts []string
 | 
				
			||||||
 | 
						for _, securityOpt := range securityOpts {
 | 
				
			||||||
 | 
							k, v := securityOpt.GetKV()
 | 
				
			||||||
 | 
							opts = append(opts, fmt.Sprintf("%s=%s", k, v))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return opts, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getSandboxSecurityOpts(sandboxConfig *runtimeApi.PodSandboxConfig, seccompProfileRoot string) ([]string, error) {
 | 
				
			||||||
 | 
						// sandboxContainerName doesn't exist in the pod, so pod security options will be returned by default.
 | 
				
			||||||
 | 
						return getContainerSecurityOpts(sandboxContainerName, sandboxConfig, seccompProfileRoot)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func getNetworkNamespace(c *dockertypes.ContainerJSON) string {
 | 
					func getNetworkNamespace(c *dockertypes.ContainerJSON) string {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1126,6 +1126,11 @@ type dockerOpt struct {
 | 
				
			|||||||
	msg string
 | 
						msg string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Expose key/value from dockertools
 | 
				
			||||||
 | 
					func (d dockerOpt) GetKV() (string, string) {
 | 
				
			||||||
 | 
						return d.key, d.value
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Get the docker security options for seccomp.
 | 
					// Get the docker security options for seccomp.
 | 
				
			||||||
func (dm *DockerManager) getSeccompOpts(pod *api.Pod, ctrName string) ([]dockerOpt, error) {
 | 
					func (dm *DockerManager) getSeccompOpts(pod *api.Pod, ctrName string) ([]dockerOpt, error) {
 | 
				
			||||||
	version, err := dm.APIVersion()
 | 
						version, err := dm.APIVersion()
 | 
				
			||||||
@@ -1140,10 +1145,16 @@ func (dm *DockerManager) getSeccompOpts(pod *api.Pod, ctrName string) ([]dockerO
 | 
				
			|||||||
		return nil, nil // return early for Docker < 1.10
 | 
							return nil, nil // return early for Docker < 1.10
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	profile, profileOK := pod.ObjectMeta.Annotations[api.SeccompContainerAnnotationKeyPrefix+ctrName]
 | 
						return GetSeccompOpts(pod.ObjectMeta.Annotations, ctrName, dm.seccompProfileRoot)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Temporarily export this function to share with dockershim.
 | 
				
			||||||
 | 
					// TODO: clean this up.
 | 
				
			||||||
 | 
					func GetSeccompOpts(annotations map[string]string, ctrName, profileRoot string) ([]dockerOpt, error) {
 | 
				
			||||||
 | 
						profile, profileOK := annotations[api.SeccompContainerAnnotationKeyPrefix+ctrName]
 | 
				
			||||||
	if !profileOK {
 | 
						if !profileOK {
 | 
				
			||||||
		// try the pod profile
 | 
							// try the pod profile
 | 
				
			||||||
		profile, profileOK = pod.ObjectMeta.Annotations[api.SeccompPodAnnotationKey]
 | 
							profile, profileOK = annotations[api.SeccompPodAnnotationKey]
 | 
				
			||||||
		if !profileOK {
 | 
							if !profileOK {
 | 
				
			||||||
			// return early the default
 | 
								// return early the default
 | 
				
			||||||
			return defaultSeccompOpt, nil
 | 
								return defaultSeccompOpt, nil
 | 
				
			||||||
@@ -1165,7 +1176,7 @@ func (dm *DockerManager) getSeccompOpts(pod *api.Pod, ctrName string) ([]dockerO
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	name := strings.TrimPrefix(profile, "localhost/") // by pod annotation validation, name is a valid subpath
 | 
						name := strings.TrimPrefix(profile, "localhost/") // by pod annotation validation, name is a valid subpath
 | 
				
			||||||
	fname := filepath.Join(dm.seccompProfileRoot, filepath.FromSlash(name))
 | 
						fname := filepath.Join(profileRoot, filepath.FromSlash(name))
 | 
				
			||||||
	file, err := ioutil.ReadFile(fname)
 | 
						file, err := ioutil.ReadFile(fname)
 | 
				
			||||||
	if err != nil {
 | 
						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", name, err)
 | 
				
			||||||
@@ -1183,7 +1194,13 @@ func (dm *DockerManager) getSeccompOpts(pod *api.Pod, ctrName string) ([]dockerO
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// Get the docker security options for AppArmor.
 | 
					// Get the docker security options for AppArmor.
 | 
				
			||||||
func (dm *DockerManager) getAppArmorOpts(pod *api.Pod, ctrName string) ([]dockerOpt, error) {
 | 
					func (dm *DockerManager) getAppArmorOpts(pod *api.Pod, ctrName string) ([]dockerOpt, error) {
 | 
				
			||||||
	profile := apparmor.GetProfileName(pod, ctrName)
 | 
						return GetAppArmorOpts(pod.Annotations, ctrName)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Temporarily export this function to share with dockershim.
 | 
				
			||||||
 | 
					// TODO: clean this up.
 | 
				
			||||||
 | 
					func GetAppArmorOpts(annotations map[string]string, ctrName string) ([]dockerOpt, error) {
 | 
				
			||||||
 | 
						profile := apparmor.GetProfileNameFromPodAnnotations(annotations, ctrName)
 | 
				
			||||||
	if profile == "" || profile == apparmor.ProfileRuntimeDefault {
 | 
						if profile == "" || profile == apparmor.ProfileRuntimeDefault {
 | 
				
			||||||
		// The docker applies the default profile by default.
 | 
							// The docker applies the default profile by default.
 | 
				
			||||||
		return nil, nil
 | 
							return nil, nil
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -535,7 +535,7 @@ func NewMainKubelet(kubeCfg *componentconfig.KubeletConfiguration, kubeDeps *Kub
 | 
				
			|||||||
		case "cri":
 | 
							case "cri":
 | 
				
			||||||
			// Use the new CRI shim for docker. This is need for testing the
 | 
								// Use the new CRI shim for docker. This is need for testing the
 | 
				
			||||||
			// docker integration through CRI, and may be removed in the future.
 | 
								// docker integration through CRI, and may be removed in the future.
 | 
				
			||||||
			dockerService := dockershim.NewDockerService(klet.dockerClient)
 | 
								dockerService := dockershim.NewDockerService(klet.dockerClient, kubeCfg.SeccompProfileRoot)
 | 
				
			||||||
			klet.containerRuntime, err = kuberuntime.NewKubeGenericRuntimeManager(
 | 
								klet.containerRuntime, err = kuberuntime.NewKubeGenericRuntimeManager(
 | 
				
			||||||
				kubecontainer.FilterEventRecorder(kubeDeps.Recorder),
 | 
									kubecontainer.FilterEventRecorder(kubeDeps.Recorder),
 | 
				
			||||||
				klet.livenessManager,
 | 
									klet.livenessManager,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -49,7 +49,13 @@ func isRequired(pod *api.Pod) bool {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// Returns the name of the profile to use with the container.
 | 
					// Returns the name of the profile to use with the container.
 | 
				
			||||||
func GetProfileName(pod *api.Pod, containerName string) string {
 | 
					func GetProfileName(pod *api.Pod, containerName string) string {
 | 
				
			||||||
	return pod.Annotations[ContainerAnnotationKeyPrefix+containerName]
 | 
						return GetProfileNameFromPodAnnotations(pod.Annotations, containerName)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetProfileNameFromPodAnnotations gets the name of the profile to use with container from
 | 
				
			||||||
 | 
					// pod annotations
 | 
				
			||||||
 | 
					func GetProfileNameFromPodAnnotations(annotations map[string]string, containerName string) string {
 | 
				
			||||||
 | 
						return annotations[ContainerAnnotationKeyPrefix+containerName]
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Sets the name of the profile to use with the container.
 | 
					// Sets the name of the profile to use with the container.
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user