Merge pull request #33663 from pmorie/selinux-fixes

Automatic merge from submit-queue

SELinux Overhaul

Overhauls handling of SELinux in Kubernetes.  TLDR: Kubelet dir no longer has to be labeled `svirt_sandbox_file_t`.

Fixes #33351 and #33510.  Implements #33951.
This commit is contained in:
Kubernetes Submit Queue 2016-11-01 05:04:17 -07:00 committed by GitHub
commit 44b684ad53
17 changed files with 81 additions and 217 deletions

View File

@ -418,18 +418,6 @@ function start_kubelet {
mkdir -p /var/lib/kubelet mkdir -p /var/lib/kubelet
if [[ -z "${DOCKERIZE_KUBELET}" ]]; then if [[ -z "${DOCKERIZE_KUBELET}" ]]; then
# On selinux enabled systems, it might
# require to relabel /var/lib/kubelet
if which selinuxenabled &> /dev/null && \
selinuxenabled && \
which chcon > /dev/null ; then
if [[ ! $(ls -Zd /var/lib/kubelet) =~ system_u:object_r:svirt_sandbox_file_t:s0 ]] ; then
echo "Applying SELinux label to /var/lib/kubelet directory."
if ! sudo chcon -Rt svirt_sandbox_file_t /var/lib/kubelet; then
echo "Failed to apply selinux label to /var/lib/kubelet."
fi
fi
fi
# Enable dns # Enable dns
if [[ "${ENABLE_CLUSTER_DNS}" = true ]]; then if [[ "${ENABLE_CLUSTER_DNS}" = true ]]; then
dns_args="--cluster-dns=${DNS_SERVER_IP} --cluster-domain=${DNS_DOMAIN}" dns_args="--cluster-dns=${DNS_SERVER_IP} --cluster-domain=${DNS_DOMAIN}"
@ -509,7 +497,7 @@ function start_kubelet {
--volume=/var/run:/var/run:rw \ --volume=/var/run:/var/run:rw \
--volume=/sys:/sys:ro \ --volume=/sys:/sys:ro \
--volume=/var/lib/docker/:/var/lib/docker:ro \ --volume=/var/lib/docker/:/var/lib/docker:ro \
--volume=/var/lib/kubelet/:/var/lib/kubelet:rw,z \ --volume=/var/lib/kubelet/:/var/lib/kubelet:rw \
--volume=/dev:/dev \ --volume=/dev:/dev \
${cred_bind} \ ${cred_bind} \
--net=host \ --net=host \

View File

@ -152,20 +152,6 @@ else
test_args="$test_args --disable-kubenet=true" test_args="$test_args --disable-kubenet=true"
fi fi
# On selinux enabled systems, it might
# require to relabel /var/lib/kubelet
if which selinuxenabled &> /dev/null && \
selinuxenabled && \
which chcon > /dev/null ; then
mkdir -p /var/lib/kubelet
if [[ ! $(ls -Zd /var/lib/kubelet) =~ svirt_sandbox_file_t ]] ; then
echo "Applying SELinux label to /var/lib/kubelet directory."
if ! sudo chcon -Rt svirt_sandbox_file_t /var/lib/kubelet; then
echo "Failed to apply selinux label to /var/lib/kubelet."
fi
fi
fi
# Test using the host the script was run on # Test using the host the script was run on
# Provided for backwards compatibility # Provided for backwards compatibility
go run test/e2e_node/runner/local/run_local.go --ginkgo-flags="$ginkgoflags" \ go run test/e2e_node/runner/local/run_local.go --ginkgo-flags="$ginkgoflags" \

View File

@ -106,7 +106,6 @@ go_library(
"//pkg/util/oom:go_default_library", "//pkg/util/oom:go_default_library",
"//pkg/util/procfs:go_default_library", "//pkg/util/procfs:go_default_library",
"//pkg/util/runtime:go_default_library", "//pkg/util/runtime:go_default_library",
"//pkg/util/selinux:go_default_library",
"//pkg/util/sets:go_default_library", "//pkg/util/sets:go_default_library",
"//pkg/util/term:go_default_library", "//pkg/util/term:go_default_library",
"//pkg/util/validation:go_default_library", "//pkg/util/validation:go_default_library",

View File

@ -56,6 +56,7 @@ go_library(
"//pkg/util/oom:go_default_library", "//pkg/util/oom:go_default_library",
"//pkg/util/procfs:go_default_library", "//pkg/util/procfs:go_default_library",
"//pkg/util/runtime:go_default_library", "//pkg/util/runtime:go_default_library",
"//pkg/util/selinux:go_default_library",
"//pkg/util/sets:go_default_library", "//pkg/util/sets:go_default_library",
"//pkg/util/strings:go_default_library", "//pkg/util/strings:go_default_library",
"//pkg/util/term:go_default_library", "//pkg/util/term:go_default_library",

View File

@ -65,6 +65,7 @@ import (
"k8s.io/kubernetes/pkg/util/oom" "k8s.io/kubernetes/pkg/util/oom"
"k8s.io/kubernetes/pkg/util/procfs" "k8s.io/kubernetes/pkg/util/procfs"
utilruntime "k8s.io/kubernetes/pkg/util/runtime" utilruntime "k8s.io/kubernetes/pkg/util/runtime"
"k8s.io/kubernetes/pkg/util/selinux"
"k8s.io/kubernetes/pkg/util/sets" "k8s.io/kubernetes/pkg/util/sets"
utilstrings "k8s.io/kubernetes/pkg/util/strings" utilstrings "k8s.io/kubernetes/pkg/util/strings"
"k8s.io/kubernetes/pkg/util/term" "k8s.io/kubernetes/pkg/util/term"
@ -507,20 +508,14 @@ func makeEnvList(envs []kubecontainer.EnvVar) (result []string) {
// '<HostPath>:<ContainerPath>', or // '<HostPath>:<ContainerPath>', or
// '<HostPath>:<ContainerPath>:ro', if the path is read only, or // '<HostPath>:<ContainerPath>:ro', if the path is read only, or
// '<HostPath>:<ContainerPath>:Z', if the volume requires SELinux // '<HostPath>:<ContainerPath>:Z', if the volume requires SELinux
// relabeling and the pod provides an SELinux label // relabeling
func makeMountBindings(mounts []kubecontainer.Mount, podHasSELinuxLabel bool) (result []string) { func makeMountBindings(mounts []kubecontainer.Mount) (result []string) {
for _, m := range mounts { for _, m := range mounts {
bind := fmt.Sprintf("%s:%s", m.HostPath, m.ContainerPath) bind := fmt.Sprintf("%s:%s", m.HostPath, m.ContainerPath)
if m.ReadOnly { if m.ReadOnly {
bind += ":ro" bind += ":ro"
} }
// Only request relabeling if the pod provides an if m.SELinuxRelabel && selinux.SELinuxEnabled() {
// SELinux context. If the pod does not provide an
// SELinux context relabeling will label the volume
// with the container's randomly allocated MCS label.
// This would restrict access to the volume to the
// container which mounts it first.
if m.SELinuxRelabel && podHasSELinuxLabel {
if m.ReadOnly { if m.ReadOnly {
bind += ",Z" bind += ",Z"
} else { } else {
@ -646,8 +641,7 @@ func (dm *DockerManager) runContainer(
{PathOnHost: "/dev/nvidia-uvm", PathInContainer: "/dev/nvidia-uvm", CgroupPermissions: "mrw"}, {PathOnHost: "/dev/nvidia-uvm", PathInContainer: "/dev/nvidia-uvm", CgroupPermissions: "mrw"},
} }
} }
podHasSELinuxLabel := pod.Spec.SecurityContext != nil && pod.Spec.SecurityContext.SELinuxOptions != nil binds := makeMountBindings(opts.Mounts)
binds := makeMountBindings(opts.Mounts, podHasSELinuxLabel)
// The reason we create and mount the log file in here (not in kubelet) is because // The reason we create and mount the log file in here (not in kubelet) is because
// the file's location depends on the ID of the container, and we need to create and // the file's location depends on the ID of the container, and we need to create and
// mount the file before actually starting the container. // mount the file before actually starting the container.
@ -666,6 +660,13 @@ func (dm *DockerManager) runContainer(
} else { } else {
fs.Close() // Close immediately; we're just doing a `touch` here fs.Close() // Close immediately; we're just doing a `touch` here
b := fmt.Sprintf("%s:%s", containerLogPath, container.TerminationMessagePath) b := fmt.Sprintf("%s:%s", containerLogPath, container.TerminationMessagePath)
// Have docker relabel the termination log path if SELinux is
// enabled.
if selinux.SELinuxEnabled() {
b += ":Z"
}
binds = append(binds, b) binds = append(binds, b)
} }
} }

View File

@ -133,10 +133,11 @@ func makeHostsMount(podDir, podIP, hostName, hostDomainName string) (*kubecontai
return nil, err return nil, err
} }
return &kubecontainer.Mount{ return &kubecontainer.Mount{
Name: "k8s-managed-etc-hosts", Name: "k8s-managed-etc-hosts",
ContainerPath: etcHostsPath, ContainerPath: etcHostsPath,
HostPath: hostsFilePath, HostPath: hostsFilePath,
ReadOnly: false, ReadOnly: false,
SELinuxRelabel: true,
}, nil }, nil
} }
@ -251,15 +252,6 @@ func (kl *Kubelet) GenerateRunContainerOptions(pod *api.Pod, container *api.Cont
volumes := kl.volumeManager.GetMountedVolumesForPod(podName) volumes := kl.volumeManager.GetMountedVolumesForPod(podName)
opts.PortMappings = makePortMappings(container) opts.PortMappings = makePortMappings(container)
// Docker does not relabel volumes if the container is running
// in the host pid or ipc namespaces so the kubelet must
// relabel the volumes
if pod.Spec.SecurityContext != nil && (pod.Spec.SecurityContext.HostIPC || pod.Spec.SecurityContext.HostPID) {
err = kl.relabelVolumes(pod, volumes)
if err != nil {
return nil, err
}
}
opts.Mounts, err = makeMounts(pod, kl.getPodDir(pod.UID), container, hostname, hostDomainName, podIP, volumes) opts.Mounts, err = makeMounts(pod, kl.getPodDir(pod.UID), container, hostname, hostDomainName, podIP, volumes)
if err != nil { if err != nil {

View File

@ -19,16 +19,13 @@ package kubelet
import ( import (
"fmt" "fmt"
"os" "os"
"path/filepath"
"github.com/golang/glog" "github.com/golang/glog"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
"k8s.io/kubernetes/pkg/securitycontext"
"k8s.io/kubernetes/pkg/types" "k8s.io/kubernetes/pkg/types"
utilerrors "k8s.io/kubernetes/pkg/util/errors" utilerrors "k8s.io/kubernetes/pkg/util/errors"
"k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/util/mount"
"k8s.io/kubernetes/pkg/util/selinux"
"k8s.io/kubernetes/pkg/util/sets" "k8s.io/kubernetes/pkg/util/sets"
"k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume"
volumetypes "k8s.io/kubernetes/pkg/volume/util/types" volumetypes "k8s.io/kubernetes/pkg/volume/util/types"
@ -81,51 +78,6 @@ func (kl *Kubelet) newVolumeMounterFromPlugins(spec *volume.Spec, pod *api.Pod,
return physicalMounter, nil return physicalMounter, nil
} }
// relabelVolumes relabels SELinux volumes to match the pod's
// SELinuxOptions specification. This is only needed if the pod uses
// hostPID or hostIPC. Otherwise relabeling is delegated to docker.
func (kl *Kubelet) relabelVolumes(pod *api.Pod, volumes kubecontainer.VolumeMap) error {
if pod.Spec.SecurityContext.SELinuxOptions == nil {
return nil
}
rootDirContext, err := kl.getRootDirContext()
if err != nil {
return err
}
selinuxRunner := selinux.NewSelinuxContextRunner()
// Apply the pod's Level to the rootDirContext
rootDirSELinuxOptions, err := securitycontext.ParseSELinuxOptions(rootDirContext)
if err != nil {
return err
}
rootDirSELinuxOptions.Level = pod.Spec.SecurityContext.SELinuxOptions.Level
volumeContext := fmt.Sprintf("%s:%s:%s:%s", rootDirSELinuxOptions.User, rootDirSELinuxOptions.Role, rootDirSELinuxOptions.Type, rootDirSELinuxOptions.Level)
for _, vol := range volumes {
if vol.Mounter.GetAttributes().Managed && vol.Mounter.GetAttributes().SupportsSELinux {
// Relabel the volume and its content to match the 'Level' of the pod
path, err := volume.GetPath(vol.Mounter)
if err != nil {
return err
}
err = filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
return selinuxRunner.SetContext(path, volumeContext)
})
if err != nil {
return err
}
vol.SELinuxLabeled = true
}
}
return nil
}
// cleanupOrphanedPodDirs removes the volumes of pods that should not be // cleanupOrphanedPodDirs removes the volumes of pods that should not be
// running and that have no containers running. // running and that have no containers running.
func (kl *Kubelet) cleanupOrphanedPodDirs( func (kl *Kubelet) cleanupOrphanedPodDirs(

View File

@ -1082,7 +1082,7 @@ func (r *Runtime) preparePodArgs(manifest *appcschema.PodManifest, manifestFileN
} }
func (r *Runtime) getSelinuxContext(opt *api.SELinuxOptions) (string, error) { func (r *Runtime) getSelinuxContext(opt *api.SELinuxOptions) (string, error) {
selinuxRunner := selinux.NewSelinuxContextRunner() selinuxRunner := selinux.NewSELinuxRunner()
str, err := selinuxRunner.Getfilecon(r.config.Dir) str, err := selinuxRunner.Getfilecon(r.config.Dir)
if err != nil { if err != nil {
return "", err return "", err

View File

@ -14,5 +14,6 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
// Package selinux contains selinux utility functions. // Package selinux contains wrapper functions for the libcontainer SELinux
// package. A NOP implementation is provided for non-linux platforms.
package selinux // import "k8s.io/kubernetes/pkg/util/selinux" package selinux // import "k8s.io/kubernetes/pkg/util/selinux"

View File

@ -16,14 +16,24 @@ limitations under the License.
package selinux package selinux
// SelinuxContextRunner knows how to chcon of a directory and // Note: the libcontainer SELinux package is only built for Linux, so it is
// how to get the selinux context of a file. // necessary to have a NOP wrapper which is built for non-Linux platforms to
type SelinuxContextRunner interface { // allow code that links to this package not to differentiate its own methods
SetContext(dir, context string) error // for Linux and non-Linux platforms.
//
// SELinuxRunner wraps certain libcontainer SELinux calls. For more
// information, see:
//
// https://github.com/opencontainers/runc/blob/master/libcontainer/selinux/selinux.go
type SELinuxRunner interface {
// Getfilecon returns the SELinux context for the given path or returns an
// error.
Getfilecon(path string) (string, error) Getfilecon(path string) (string, error)
} }
// NewSelinuxContextRunner returns a new chconRunner. // NewSELinuxRunner returns a new SELinuxRunner appropriate for the platform.
func NewSelinuxContextRunner() SelinuxContextRunner { // On Linux, all methods short-circuit and return NOP values if SELinux is
return &realSelinuxContextRunner{} // disabled. On non-Linux platforms, a NOP implementation is returned.
func NewSELinuxRunner() SELinuxRunner {
return &realSELinuxRunner{}
} }

View File

@ -19,25 +19,34 @@ limitations under the License.
package selinux package selinux
import ( import (
"fmt"
"github.com/opencontainers/runc/libcontainer/selinux" "github.com/opencontainers/runc/libcontainer/selinux"
) )
type realSelinuxContextRunner struct{} // SELinuxEnabled returns whether SELinux is enabled on the system. SELinux
// has a tri-state:
func (_ *realSelinuxContextRunner) SetContext(dir, context string) error { //
// If SELinux is not enabled, return an empty string // 1. disabled: SELinux Kernel modules not loaded, SELinux policy is not
if !selinux.SelinuxEnabled() { // checked during Kernel MAC checks
return nil // 2. enforcing: Enabled; SELinux policy violations are denied and logged
} // in the audit log
// 3. permissive: Enabled, but SELinux policy violations are permitted and
return selinux.Setfilecon(dir, context) // logged in the audit log
//
// SELinuxEnabled returns true if SELinux is enforcing or permissive, and
// false if it is disabled.
func SELinuxEnabled() bool {
return selinux.SelinuxEnabled()
} }
func (_ *realSelinuxContextRunner) Getfilecon(path string) (string, error) { // realSELinuxRunner is the real implementation of SELinuxRunner interface for
if !selinux.SelinuxEnabled() { // Linux.
return "", fmt.Errorf("SELinux is not enabled") type realSELinuxRunner struct{}
var _ SELinuxRunner = &realSELinuxRunner{}
func (_ *realSELinuxRunner) Getfilecon(path string) (string, error) {
if !SELinuxEnabled() {
return "", nil
} }
return selinux.Getfilecon(path) return selinux.Getfilecon(path)
} }

View File

@ -18,14 +18,16 @@ limitations under the License.
package selinux package selinux
type realSelinuxContextRunner struct{} // SELinuxEnabled always returns false on non-linux platforms.
func SELinuxEnabled() bool {
func (_ *realSelinuxContextRunner) SetContext(dir, context string) error { return false
// NOP
return nil
} }
func (_ *realSelinuxContextRunner) Getfilecon(path string) (string, error) { // realSELinuxRunner is the NOP implementation of the SELinuxRunner interface.
// NOP type realSELinuxRunner struct{}
var _ SELinuxRunner = &realSELinuxRunner{}
func (_ *realSELinuxRunner) Getfilecon(path string) (string, error) {
return "", nil return "", nil
} }

View File

@ -26,7 +26,6 @@ go_library(
"//pkg/volume:go_default_library", "//pkg/volume:go_default_library",
"//pkg/volume/util:go_default_library", "//pkg/volume/util:go_default_library",
"//vendor:github.com/golang/glog", "//vendor:github.com/golang/glog",
"//vendor:github.com/opencontainers/runc/libcontainer/selinux",
], ],
) )

View File

@ -105,7 +105,6 @@ func (plugin *emptyDirPlugin) newMounterInternal(spec *volume.Spec, pod *api.Pod
mounter: mounter, mounter: mounter,
mountDetector: mountDetector, mountDetector: mountDetector,
plugin: plugin, plugin: plugin,
rootContext: plugin.host.GetRootContext(),
MetricsProvider: volume.NewMetricsDu(getPath(pod.UID, spec.Name(), plugin.host)), MetricsProvider: volume.NewMetricsDu(getPath(pod.UID, spec.Name(), plugin.host)),
}, nil }, nil
} }
@ -164,7 +163,6 @@ type emptyDir struct {
mounter mount.Interface mounter mount.Interface
mountDetector mountDetector mountDetector mountDetector
plugin *emptyDirPlugin plugin *emptyDirPlugin
rootContext string
volume.MetricsProvider volume.MetricsProvider
} }
@ -202,17 +200,11 @@ func (ed *emptyDir) SetUpAt(dir string, fsGroup *int64) error {
} }
} }
// Determine the effective SELinuxOptions to use for this volume.
securityContext := ""
if selinuxEnabled() {
securityContext = ed.rootContext
}
switch ed.medium { switch ed.medium {
case api.StorageMediumDefault: case api.StorageMediumDefault:
err = ed.setupDir(dir) err = ed.setupDir(dir)
case api.StorageMediumMemory: case api.StorageMediumMemory:
err = ed.setupTmpfs(dir, securityContext) err = ed.setupTmpfs(dir)
default: default:
err = fmt.Errorf("unknown storage medium %q", ed.medium) err = fmt.Errorf("unknown storage medium %q", ed.medium)
} }
@ -228,7 +220,7 @@ func (ed *emptyDir) SetUpAt(dir string, fsGroup *int64) error {
// setupTmpfs creates a tmpfs mount at the specified directory with the // setupTmpfs creates a tmpfs mount at the specified directory with the
// specified SELinux context. // specified SELinux context.
func (ed *emptyDir) setupTmpfs(dir string, selinux string) error { func (ed *emptyDir) setupTmpfs(dir string) error {
if ed.mounter == nil { if ed.mounter == nil {
return fmt.Errorf("memory storage requested, but mounter is nil") return fmt.Errorf("memory storage requested, but mounter is nil")
} }
@ -246,17 +238,8 @@ func (ed *emptyDir) setupTmpfs(dir string, selinux string) error {
return nil return nil
} }
// By default a tmpfs mount will receive a different SELinux context glog.V(3).Infof("pod %v: mounting tmpfs for volume %v", ed.pod.UID, ed.volName)
// which is not readable from the SELinux context of a docker container. return ed.mounter.Mount("tmpfs", dir, "tmpfs", nil /* options */)
var opts []string
if selinux != "" {
opts = []string{fmt.Sprintf("rootcontext=\"%v\"", selinux)}
} else {
opts = []string{}
}
glog.V(3).Infof("pod %v: mounting tmpfs for volume %v with opts %v", ed.pod.UID, ed.volName, opts)
return ed.mounter.Mount("tmpfs", dir, "tmpfs", opts)
} }
// setupDir creates the directory with the specified SELinux context and // setupDir creates the directory with the specified SELinux context and

View File

@ -23,7 +23,6 @@ import (
"syscall" "syscall"
"github.com/golang/glog" "github.com/golang/glog"
"github.com/opencontainers/runc/libcontainer/selinux"
"k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/util/mount"
) )
@ -52,8 +51,3 @@ func (m *realMountDetector) GetMountMedium(path string) (storageMedium, bool, er
} }
return mediumUnknown, !notMnt, nil return mediumUnknown, !notMnt, nil
} }
// selinuxEnabled determines whether SELinux is enabled.
func selinuxEnabled() bool {
return selinux.SelinuxEnabled()
}

View File

@ -33,9 +33,9 @@ import (
) )
// Construct an instance of a plugin, by name. // Construct an instance of a plugin, by name.
func makePluginUnderTest(t *testing.T, plugName, basePath, rootContext string) volume.VolumePlugin { func makePluginUnderTest(t *testing.T, plugName, basePath string) volume.VolumePlugin {
plugMgr := volume.VolumePluginMgr{} plugMgr := volume.VolumePluginMgr{}
plugMgr.InitPlugins(ProbeVolumePlugins(), volumetest.NewFakeVolumeHost(basePath, nil, nil, rootContext)) plugMgr.InitPlugins(ProbeVolumePlugins(), volumetest.NewFakeVolumeHost(basePath, nil, nil, "" /* rootContext */))
plug, err := plugMgr.FindPluginByName(plugName) plug, err := plugMgr.FindPluginByName(plugName)
if err != nil { if err != nil {
@ -50,7 +50,7 @@ func TestCanSupport(t *testing.T) {
t.Fatalf("can't make a temp dir: %v", err) t.Fatalf("can't make a temp dir: %v", err)
} }
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
plug := makePluginUnderTest(t, "kubernetes.io/empty-dir", tmpDir, "" /* rootContext */) plug := makePluginUnderTest(t, "kubernetes.io/empty-dir", tmpDir)
if plug.GetPluginName() != "kubernetes.io/empty-dir" { if plug.GetPluginName() != "kubernetes.io/empty-dir" {
t.Errorf("Wrong name: %s", plug.GetPluginName()) t.Errorf("Wrong name: %s", plug.GetPluginName())
@ -75,44 +75,13 @@ func (fake *fakeMountDetector) GetMountMedium(path string) (storageMedium, bool,
func TestPluginEmptyRootContext(t *testing.T) { func TestPluginEmptyRootContext(t *testing.T) {
doTestPlugin(t, pluginTestConfig{ doTestPlugin(t, pluginTestConfig{
medium: api.StorageMediumDefault, medium: api.StorageMediumDefault,
rootContext: "",
expectedSetupMounts: 0, expectedSetupMounts: 0,
expectedTeardownMounts: 0}) expectedTeardownMounts: 0})
} }
func TestPluginRootContextSet(t *testing.T) {
if !selinuxEnabled() {
return
}
doTestPlugin(t, pluginTestConfig{
medium: api.StorageMediumDefault,
rootContext: "user:role:type:range",
expectedSELinux: "user:role:type:range",
expectedSetupMounts: 0,
expectedTeardownMounts: 0})
}
func TestPluginTmpfs(t *testing.T) {
if !selinuxEnabled() {
return
}
doTestPlugin(t, pluginTestConfig{
medium: api.StorageMediumMemory,
rootContext: "user:role:type:range",
expectedSELinux: "user:role:type:range",
expectedSetupMounts: 1,
shouldBeMountedBeforeTeardown: true,
expectedTeardownMounts: 1})
}
type pluginTestConfig struct { type pluginTestConfig struct {
medium api.StorageMedium medium api.StorageMedium
rootContext string
SELinuxOptions *api.SELinuxOptions
idempotent bool idempotent bool
expectedSELinux string
expectedSetupMounts int expectedSetupMounts int
shouldBeMountedBeforeTeardown bool shouldBeMountedBeforeTeardown bool
expectedTeardownMounts int expectedTeardownMounts int
@ -130,7 +99,7 @@ func doTestPlugin(t *testing.T, config pluginTestConfig) {
volumePath = path.Join(basePath, "pods/poduid/volumes/kubernetes.io~empty-dir/test-volume") volumePath = path.Join(basePath, "pods/poduid/volumes/kubernetes.io~empty-dir/test-volume")
metadataDir = path.Join(basePath, "pods/poduid/plugins/kubernetes.io~empty-dir/test-volume") metadataDir = path.Join(basePath, "pods/poduid/plugins/kubernetes.io~empty-dir/test-volume")
plug = makePluginUnderTest(t, "kubernetes.io/empty-dir", basePath, config.rootContext) plug = makePluginUnderTest(t, "kubernetes.io/empty-dir", basePath)
volumeName = "test-volume" volumeName = "test-volume"
spec = &api.Volume{ spec = &api.Volume{
Name: volumeName, Name: volumeName,
@ -142,24 +111,6 @@ func doTestPlugin(t *testing.T, config pluginTestConfig) {
pod = &api.Pod{ObjectMeta: api.ObjectMeta{UID: types.UID("poduid")}} pod = &api.Pod{ObjectMeta: api.ObjectMeta{UID: types.UID("poduid")}}
) )
// Set up the SELinux options on the pod
if config.SELinuxOptions != nil {
pod.Spec = api.PodSpec{
Containers: []api.Container{
{
SecurityContext: &api.SecurityContext{
SELinuxOptions: config.SELinuxOptions,
},
VolumeMounts: []api.VolumeMount{
{
Name: volumeName,
},
},
},
},
}
}
if config.idempotent { if config.idempotent {
physicalMounter.MountPoints = []mount.MountPoint{ physicalMounter.MountPoints = []mount.MountPoint{
{ {
@ -258,7 +209,7 @@ func TestPluginBackCompat(t *testing.T) {
} }
defer os.RemoveAll(basePath) defer os.RemoveAll(basePath)
plug := makePluginUnderTest(t, "kubernetes.io/empty-dir", basePath, "" /* rootContext */) plug := makePluginUnderTest(t, "kubernetes.io/empty-dir", basePath)
spec := &api.Volume{ spec := &api.Volume{
Name: "vol1", Name: "vol1",
@ -287,7 +238,7 @@ func TestMetrics(t *testing.T) {
} }
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
plug := makePluginUnderTest(t, "kubernetes.io/empty-dir", tmpDir, "" /* rootContext */) plug := makePluginUnderTest(t, "kubernetes.io/empty-dir", tmpDir)
spec := &api.Volume{ spec := &api.Volume{
Name: "vol1", Name: "vol1",

View File

@ -30,7 +30,3 @@ type realMountDetector struct {
func (m *realMountDetector) GetMountMedium(path string) (storageMedium, bool, error) { func (m *realMountDetector) GetMountMedium(path string) (storageMedium, bool, error) {
return mediumUnknown, false, nil return mediumUnknown, false, nil
} }
func selinuxEnabled() bool {
return false
}