From 7fb99442a654f372fc0ce3dc8a4200cd02d87bf1 Mon Sep 17 00:00:00 2001 From: Paul Morie Date: Tue, 25 Oct 2016 11:51:11 -0400 Subject: [PATCH] Refactor pkg/util/selinux --- pkg/kubelet/kubelet_volumes.go | 4 +- pkg/kubelet/rkt/rkt.go | 2 +- pkg/util/selinux/doc.go | 3 +- pkg/util/selinux/selinux.go | 24 ++++++++---- pkg/util/selinux/selinux_linux.go | 37 ++++++++++++------- pkg/util/selinux/selinux_unsupported.go | 16 ++++---- pkg/volume/empty_dir/empty_dir.go | 3 +- pkg/volume/empty_dir/empty_dir_linux.go | 6 --- pkg/volume/empty_dir/empty_dir_unsupported.go | 4 -- 9 files changed, 56 insertions(+), 43 deletions(-) diff --git a/pkg/kubelet/kubelet_volumes.go b/pkg/kubelet/kubelet_volumes.go index 11f8aa1964..06eb5b9413 100644 --- a/pkg/kubelet/kubelet_volumes.go +++ b/pkg/kubelet/kubelet_volumes.go @@ -94,7 +94,7 @@ func (kl *Kubelet) relabelVolumes(pod *api.Pod, volumes kubecontainer.VolumeMap) return err } - selinuxRunner := selinux.NewSelinuxContextRunner() + selinuxRunner := selinux.NewSELinuxRunner() // Apply the pod's Level to the rootDirContext rootDirSELinuxOptions, err := securitycontext.ParseSELinuxOptions(rootDirContext) if err != nil { @@ -115,7 +115,7 @@ func (kl *Kubelet) relabelVolumes(pod *api.Pod, volumes kubecontainer.VolumeMap) if err != nil { return err } - return selinuxRunner.SetContext(path, volumeContext) + return selinuxRunner.Setfilecon(path, volumeContext) }) if err != nil { return err diff --git a/pkg/kubelet/rkt/rkt.go b/pkg/kubelet/rkt/rkt.go index 9f8595792d..16cb0db6b8 100644 --- a/pkg/kubelet/rkt/rkt.go +++ b/pkg/kubelet/rkt/rkt.go @@ -1082,7 +1082,7 @@ func (r *Runtime) preparePodArgs(manifest *appcschema.PodManifest, manifestFileN } func (r *Runtime) getSelinuxContext(opt *api.SELinuxOptions) (string, error) { - selinuxRunner := selinux.NewSelinuxContextRunner() + selinuxRunner := selinux.NewSELinuxRunner() str, err := selinuxRunner.Getfilecon(r.config.Dir) if err != nil { return "", err diff --git a/pkg/util/selinux/doc.go b/pkg/util/selinux/doc.go index 5061cd6bc8..2757203f93 100644 --- a/pkg/util/selinux/doc.go +++ b/pkg/util/selinux/doc.go @@ -14,5 +14,6 @@ See the License for the specific language governing permissions and 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" diff --git a/pkg/util/selinux/selinux.go b/pkg/util/selinux/selinux.go index c8c42afbd8..c367f7bbe7 100644 --- a/pkg/util/selinux/selinux.go +++ b/pkg/util/selinux/selinux.go @@ -16,14 +16,24 @@ limitations under the License. package selinux -// SelinuxContextRunner knows how to chcon of a directory and -// how to get the selinux context of a file. -type SelinuxContextRunner interface { - SetContext(dir, context string) error +// Note: the libcontainer SELinux package is only built for Linux, so it is +// necessary to have a NOP wrapper which is built for non-Linux platforms to +// allow code that links to this package not to differentiate its own methods +// 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) } -// NewSelinuxContextRunner returns a new chconRunner. -func NewSelinuxContextRunner() SelinuxContextRunner { - return &realSelinuxContextRunner{} +// NewSELinuxRunner returns a new SELinuxRunner appropriate for the platform. +// On Linux, all methods short-circuit and return NOP values if SELinux is +// disabled. On non-Linux platforms, a NOP implementation is returned. +func NewSELinuxRunner() SELinuxRunner { + return &realSELinuxRunner{} } diff --git a/pkg/util/selinux/selinux_linux.go b/pkg/util/selinux/selinux_linux.go index f3c720561a..47d35c91cb 100644 --- a/pkg/util/selinux/selinux_linux.go +++ b/pkg/util/selinux/selinux_linux.go @@ -19,25 +19,34 @@ limitations under the License. package selinux import ( - "fmt" - "github.com/opencontainers/runc/libcontainer/selinux" ) -type realSelinuxContextRunner struct{} - -func (_ *realSelinuxContextRunner) SetContext(dir, context string) error { - // If SELinux is not enabled, return an empty string - if !selinux.SelinuxEnabled() { - return nil - } - - return selinux.Setfilecon(dir, context) +// SELinuxEnabled returns whether SELinux is enabled on the system. SELinux +// has a tri-state: +// +// 1. disabled: SELinux Kernel modules not loaded, SELinux policy is not +// checked during Kernel MAC checks +// 2. enforcing: Enabled; SELinux policy violations are denied and logged +// in the audit log +// 3. permissive: Enabled, but SELinux policy violations are permitted and +// 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) { - if !selinux.SelinuxEnabled() { - return "", fmt.Errorf("SELinux is not enabled") +// realSELinuxRunner is the real implementation of SELinuxRunner interface for +// Linux. +type realSELinuxRunner struct{} + +var _ SELinuxRunner = &realSELinuxRunner{} + +func (_ *realSELinuxRunner) Getfilecon(path string) (string, error) { + if !SELinuxEnabled() { + return "", nil } return selinux.Getfilecon(path) } diff --git a/pkg/util/selinux/selinux_unsupported.go b/pkg/util/selinux/selinux_unsupported.go index 22a2f1a94b..4f7767472c 100644 --- a/pkg/util/selinux/selinux_unsupported.go +++ b/pkg/util/selinux/selinux_unsupported.go @@ -18,14 +18,16 @@ limitations under the License. package selinux -type realSelinuxContextRunner struct{} - -func (_ *realSelinuxContextRunner) SetContext(dir, context string) error { - // NOP - return nil +// SELinuxEnabled always returns false on non-linux platforms. +func SELinuxEnabled() bool { + return false } -func (_ *realSelinuxContextRunner) Getfilecon(path string) (string, error) { - // NOP +// realSELinuxRunner is the NOP implementation of the SELinuxRunner interface. +type realSELinuxRunner struct{} + +var _ SELinuxRunner = &realSELinuxRunner{} + +func (_ *realSELinuxRunner) Getfilecon(path string) (string, error) { return "", nil } diff --git a/pkg/volume/empty_dir/empty_dir.go b/pkg/volume/empty_dir/empty_dir.go index 2a545945d0..6b36a819a2 100644 --- a/pkg/volume/empty_dir/empty_dir.go +++ b/pkg/volume/empty_dir/empty_dir.go @@ -25,6 +25,7 @@ import ( "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/types" "k8s.io/kubernetes/pkg/util/mount" + "k8s.io/kubernetes/pkg/util/selinux" "k8s.io/kubernetes/pkg/util/strings" "k8s.io/kubernetes/pkg/volume" volumeutil "k8s.io/kubernetes/pkg/volume/util" @@ -204,7 +205,7 @@ func (ed *emptyDir) SetUpAt(dir string, fsGroup *int64) error { // Determine the effective SELinuxOptions to use for this volume. securityContext := "" - if selinuxEnabled() { + if selinux.SELinuxEnabled() { securityContext = ed.rootContext } diff --git a/pkg/volume/empty_dir/empty_dir_linux.go b/pkg/volume/empty_dir/empty_dir_linux.go index 41e474f9d7..0902e58d38 100644 --- a/pkg/volume/empty_dir/empty_dir_linux.go +++ b/pkg/volume/empty_dir/empty_dir_linux.go @@ -23,7 +23,6 @@ import ( "syscall" "github.com/golang/glog" - "github.com/opencontainers/runc/libcontainer/selinux" "k8s.io/kubernetes/pkg/util/mount" ) @@ -52,8 +51,3 @@ func (m *realMountDetector) GetMountMedium(path string) (storageMedium, bool, er } return mediumUnknown, !notMnt, nil } - -// selinuxEnabled determines whether SELinux is enabled. -func selinuxEnabled() bool { - return selinux.SelinuxEnabled() -} diff --git a/pkg/volume/empty_dir/empty_dir_unsupported.go b/pkg/volume/empty_dir/empty_dir_unsupported.go index 32ab046f1b..c389ace7c3 100644 --- a/pkg/volume/empty_dir/empty_dir_unsupported.go +++ b/pkg/volume/empty_dir/empty_dir_unsupported.go @@ -30,7 +30,3 @@ type realMountDetector struct { func (m *realMountDetector) GetMountMedium(path string) (storageMedium, bool, error) { return mediumUnknown, false, nil } - -func selinuxEnabled() bool { - return false -}