Support selinux options/label

Support selinux optios/label

Signed-off-by: Yanqiang Miao <miao.yanqiang@zte.com.cn>
This commit is contained in:
Yanqiang Miao
2017-08-23 21:33:43 +08:00
parent c311f10a77
commit 0c3304e006
14 changed files with 1294 additions and 5 deletions

View File

@@ -27,7 +27,9 @@ import (
"github.com/opencontainers/runc/libcontainer/devices"
runtimespec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/runtime-tools/generate"
"github.com/opencontainers/selinux/go-selinux/label"
"golang.org/x/net/context"
"golang.org/x/sys/unix"
"k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
cio "github.com/kubernetes-incubator/cri-containerd/pkg/server/io"
@@ -234,9 +236,17 @@ func (c *criContainerdService) generateContainerSpec(id string, sandboxPid uint3
}
securityContext := config.GetLinux().GetSecurityContext()
selinuxOpt := securityContext.GetSelinuxOptions()
processLabel, mountLabel, err := initSelinuxOpts(selinuxOpt)
if err != nil {
return nil, fmt.Errorf("failed to init selinux options %+v: %v", securityContext.GetSelinuxOptions(), err)
}
// Add extra mounts first so that CRI specified mounts can override.
addOCIBindMounts(&g, append(extraMounts, config.GetMounts()...))
mounts := append(extraMounts, config.GetMounts()...)
if err := addOCIBindMounts(&g, mounts, mountLabel); err != nil {
return nil, fmt.Errorf("failed to set OCI bind mounts %+v: %v", mounts, err)
}
if securityContext.GetPrivileged() {
if !sandboxConfig.GetLinux().GetSecurityContext().GetPrivileged() {
@@ -259,6 +269,9 @@ func (c *criContainerdService) generateContainerSpec(id string, sandboxPid uint3
}
g.SetProcessSelinuxLabel(processLabel)
g.SetLinuxMountLabel(mountLabel)
// TODO: Figure out whether we should set no new privilege for sandbox container by default
g.SetProcessNoNewPrivileges(securityContext.GetNoNewPrivs())
@@ -435,7 +448,7 @@ func setOCIDevicesPrivileged(g *generate.Generator) error {
// addOCIBindMounts adds bind mounts.
// TODO(random-liu): Figure out whether we need to change all CRI mounts to readonly when
// rootfs is readonly. (https://github.com/moby/moby/blob/master/daemon/oci_linux.go)
func addOCIBindMounts(g *generate.Generator, mounts []*runtime.Mount) {
func addOCIBindMounts(g *generate.Generator, mounts []*runtime.Mount, mountLabel string) error {
// Mount cgroup into the container as readonly, which inherits docker's behavior.
g.AddCgroupsMount("ro") // nolint: errcheck
for _, mount := range mounts {
@@ -447,9 +460,16 @@ func addOCIBindMounts(g *generate.Generator, mounts []*runtime.Mount) {
} else {
options = append(options, "rw")
}
// TODO(random-liu): [P1] Apply selinux label
if mount.GetSelinuxRelabel() {
if err := label.Relabel(src, mountLabel, true); err != nil && err != unix.ENOTSUP {
return fmt.Errorf("relabel %q with %q failed: %v", src, mountLabel, err)
}
}
g.AddBindMount(src, dst, options)
}
return nil
}
func setOCIBindMountsPrivileged(g *generate.Generator) {

View File

@@ -419,7 +419,7 @@ func TestPrivilegedBindMount(t *testing.T) {
t.Logf("TestCase %q", desc)
g := generate.New()
g.SetRootReadonly(test.readonlyRootFS)
addOCIBindMounts(&g, nil)
addOCIBindMounts(&g, nil, "")
if test.privileged {
setOCIBindMountsPrivileged(&g)
}

View File

@@ -33,6 +33,8 @@ import (
"github.com/opencontainers/image-spec/identity"
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
specs "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/selinux/go-selinux"
"github.com/opencontainers/selinux/go-selinux/label"
"golang.org/x/net/context"
"k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
@@ -374,3 +376,16 @@ func getImageInfo(ctx context.Context, image containerd.Image, provider content.
config: ociimage.Config,
}, nil
}
func initSelinuxOpts(selinuxOpt *runtime.SELinuxOption) (string, string, error) {
if selinuxOpt == nil {
return "", "", nil
}
labelOpts := fmt.Sprintf("%s:%s:%s:%s",
selinuxOpt.GetUser(),
selinuxOpt.GetRole(),
selinuxOpt.GetRole(),
selinuxOpt.GetType())
return label.InitLabels(selinux.DupSecOpt(labelOpts))
}

View File

@@ -0,0 +1,71 @@
// +build selinux
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package server
import (
"testing"
"github.com/opencontainers/selinux/go-selinux"
"github.com/stretchr/testify/assert"
"k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
)
func TestInitSelinuxOpts(t *testing.T) {
if !selinux.GetEnabled() {
return
}
for desc, test := range map[string]struct {
selinuxOpt *runtime.SELinuxOption
processLabel string
mountLabels []string
}{
"testNullValue": {
selinuxOpt: nil,
processLabel: "",
mountLabels: []string{"", ""},
},
"testEmptyString": {
selinuxOpt: &runtime.SELinuxOption{
User: "",
Role: "",
Type: "",
Level: "",
},
processLabel: ":::",
mountLabels: []string{":object_r:container_file_t:", ":object_r:svirt_sandbox_file_t:"},
},
"testUser": {
selinuxOpt: &runtime.SELinuxOption{
User: "user_u",
Role: "user_r",
Type: "user_t",
Level: "s0:c1,c2",
},
processLabel: "user_u:user_r:user_t:s0:c1,c2",
mountLabels: []string{"user_u:object_r:container_file_t:s0:c1,c2", "user_u:object_r:svirt_sandbox_file_t:s0:c1,c2"},
},
} {
t.Logf("TestCase %q", desc)
processLabel, mountLabel, err := initSelinuxOpts(test.selinuxOpt)
assert.NoError(t, err)
assert.Equal(t, test.processLabel, processLabel)
assert.Contains(t, test.mountLabels, mountLabel)
}
}

View File

@@ -271,7 +271,13 @@ func (c *criContainerdService) generateSandboxContainerSpec(id string, config *r
g.RemoveLinuxNamespace(string(runtimespec.IPCNamespace)) // nolint: errcheck
}
// TODO(random-liu): [P1] Apply SeLinux options.
selinuxOpt := securityContext.GetSelinuxOptions()
processLabel, mountLabel, err := initSelinuxOpts(selinuxOpt)
if err != nil {
return nil, fmt.Errorf("failed to init selinux options %+v: %v", securityContext.GetSelinuxOptions(), err)
}
g.SetProcessSelinuxLabel(processLabel)
g.SetLinuxMountLabel(mountLabel)
supplementalGroups := securityContext.GetSupplementalGroups()
for _, group := range supplementalGroups {