Support volume relabling for pods which specify an SELinux label

This commit is contained in:
Sami Wagiaalla
2015-10-07 15:19:06 -04:00
parent 1524d7490a
commit 1d352a16b8
30 changed files with 344 additions and 76 deletions

View File

@@ -1,27 +0,0 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
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 empty_dir
// chconRunner knows how to chcon a directory.
type chconRunner interface {
SetContext(dir, context string) error
}
// newChconRunner returns a new chconRunner.
func newChconRunner() chconRunner {
return &realChconRunner{}
}

View File

@@ -1,34 +0,0 @@
// +build linux
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
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 empty_dir
import (
"github.com/docker/libcontainer/selinux"
)
type realChconRunner struct{}
func (_ *realChconRunner) SetContext(dir, context string) error {
// If SELinux is not enabled, return an empty string
if !selinux.SelinuxEnabled() {
return nil
}
return selinux.Setfilecon(dir, context)
}

View File

@@ -1,26 +0,0 @@
// +build !linux
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
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 empty_dir
type realChconRunner struct{}
func (_ *realChconRunner) SetContext(dir, context string) error {
// NOP
return nil
}

View File

@@ -70,10 +70,10 @@ func (plugin *emptyDirPlugin) CanSupport(spec *volume.Spec) bool {
}
func (plugin *emptyDirPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, opts volume.VolumeOptions) (volume.Builder, error) {
return plugin.newBuilderInternal(spec, pod, plugin.host.GetMounter(), &realMountDetector{plugin.host.GetMounter()}, opts, newChconRunner())
return plugin.newBuilderInternal(spec, pod, plugin.host.GetMounter(), &realMountDetector{plugin.host.GetMounter()}, opts)
}
func (plugin *emptyDirPlugin) newBuilderInternal(spec *volume.Spec, pod *api.Pod, mounter mount.Interface, mountDetector mountDetector, opts volume.VolumeOptions, chconRunner chconRunner) (volume.Builder, error) {
func (plugin *emptyDirPlugin) newBuilderInternal(spec *volume.Spec, pod *api.Pod, mounter mount.Interface, mountDetector mountDetector, opts volume.VolumeOptions) (volume.Builder, error) {
medium := api.StorageMediumDefault
if spec.Volume.EmptyDir != nil { // Support a non-specified source as EmptyDir.
medium = spec.Volume.EmptyDir.Medium
@@ -86,7 +86,6 @@ func (plugin *emptyDirPlugin) newBuilderInternal(spec *volume.Spec, pod *api.Pod
mountDetector: mountDetector,
plugin: plugin,
rootContext: opts.RootContext,
chconRunner: chconRunner,
}, nil
}
@@ -134,7 +133,6 @@ type emptyDir struct {
mountDetector mountDetector
plugin *emptyDirPlugin
rootContext string
chconRunner chconRunner
}
func (_ *emptyDir) SupportsOwnershipManagement() bool {
@@ -175,7 +173,7 @@ func (ed *emptyDir) SetUpAt(dir string) error {
switch ed.medium {
case api.StorageMediumDefault:
err = ed.setupDir(dir, securityContext)
err = ed.setupDir(dir)
case api.StorageMediumMemory:
err = ed.setupTmpfs(dir, securityContext)
default:
@@ -193,13 +191,17 @@ func (ed *emptyDir) IsReadOnly() bool {
return false
}
func (ed *emptyDir) SupportsSELinux() bool {
return true
}
// setupTmpfs creates a tmpfs mount at the specified directory with the
// specified SELinux context.
func (ed *emptyDir) setupTmpfs(dir string, selinuxContext string) error {
if ed.mounter == nil {
return fmt.Errorf("memory storage requested, but mounter is nil")
}
if err := ed.setupDir(dir, selinuxContext); err != nil {
if err := ed.setupDir(dir); err != nil {
return err
}
// Make SetUp idempotent.
@@ -228,7 +230,7 @@ func (ed *emptyDir) setupTmpfs(dir string, selinuxContext string) error {
// setupDir creates the directory with the specified SELinux context and
// the default permissions specified by the perm constant.
func (ed *emptyDir) setupDir(dir, selinuxContext string) error {
func (ed *emptyDir) setupDir(dir string) error {
// Create the directory if it doesn't already exist.
if err := os.MkdirAll(dir, perm); err != nil {
return err
@@ -262,12 +264,6 @@ func (ed *emptyDir) setupDir(dir, selinuxContext string) error {
}
}
// Set the context on the directory, if appropriate
if selinuxContext != "" {
glog.V(3).Infof("Setting SELinux context for %v to %v", dir, selinuxContext)
return ed.chconRunner.SetContext(dir, selinuxContext)
}
return nil
}

View File

@@ -69,30 +69,10 @@ func (fake *fakeMountDetector) GetMountMedium(path string) (storageMedium, bool,
return fake.medium, fake.isMount, nil
}
type fakeChconRequest struct {
dir string
context string
}
type fakeChconRunner struct {
requests []fakeChconRequest
}
func newFakeChconRunner() *fakeChconRunner {
return &fakeChconRunner{}
}
func (f *fakeChconRunner) SetContext(dir, context string) error {
f.requests = append(f.requests, fakeChconRequest{dir, context})
return nil
}
func TestPluginEmptyRootContext(t *testing.T) {
doTestPlugin(t, pluginTestConfig{
medium: api.StorageMediumDefault,
rootContext: "",
expectedChcons: 0,
expectedSetupMounts: 0,
expectedTeardownMounts: 0})
}
@@ -106,7 +86,6 @@ func TestPluginRootContextSet(t *testing.T) {
medium: api.StorageMediumDefault,
rootContext: "user:role:type:range",
expectedSELinuxContext: "user:role:type:range",
expectedChcons: 1,
expectedSetupMounts: 0,
expectedTeardownMounts: 0})
}
@@ -120,7 +99,6 @@ func TestPluginTmpfs(t *testing.T) {
medium: api.StorageMediumMemory,
rootContext: "user:role:type:range",
expectedSELinuxContext: "user:role:type:range",
expectedChcons: 1,
expectedSetupMounts: 1,
shouldBeMountedBeforeTeardown: true,
expectedTeardownMounts: 1})
@@ -132,7 +110,6 @@ type pluginTestConfig struct {
SELinuxOptions *api.SELinuxOptions
idempotent bool
expectedSELinuxContext string
expectedChcons int
expectedSetupMounts int
shouldBeMountedBeforeTeardown bool
expectedTeardownMounts int
@@ -160,7 +137,6 @@ func doTestPlugin(t *testing.T, config pluginTestConfig) {
mounter = mount.FakeMounter{}
mountDetector = fakeMountDetector{}
pod = &api.Pod{ObjectMeta: api.ObjectMeta{UID: types.UID("poduid")}}
fakeChconRnr = &fakeChconRunner{}
)
// Set up the SELinux options on the pod
@@ -194,8 +170,7 @@ func doTestPlugin(t *testing.T, config pluginTestConfig) {
pod,
&mounter,
&mountDetector,
volume.VolumeOptions{RootContext: config.rootContext},
fakeChconRnr)
volume.VolumeOptions{RootContext: config.rootContext})
if err != nil {
t.Errorf("Failed to make a new Builder: %v", err)
}
@@ -231,19 +206,6 @@ func doTestPlugin(t *testing.T, config pluginTestConfig) {
t.Errorf("Volume directory was created unexpectedly")
}
// Check the number of chcons during setup
if e, a := config.expectedChcons, len(fakeChconRnr.requests); e != a {
t.Errorf("Expected %v chcon calls, got %v", e, a)
}
if config.expectedChcons == 1 {
if e, a := config.expectedSELinuxContext, fakeChconRnr.requests[0].context; e != a {
t.Errorf("Unexpected chcon context argument; expected: %v, got: %v", e, a)
}
if e, a := volPath, fakeChconRnr.requests[0].dir; e != a {
t.Errorf("Unexpected chcon path argument: expected: %v, got: %v", e, a)
}
}
// Check the number of mounts performed during setup
if e, a := config.expectedSetupMounts, len(mounter.Log); e != a {
t.Errorf("Expected %v mounter calls during setup, got %v", e, a)