Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
c8a17837
Commit
c8a17837
authored
Oct 28, 2015
by
k8s-merge-robot
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #15323 from swagiaal/pod-volume-selinux
Auto commit by PR queue bot
parents
0f99c59d
1d352a16
Show whitespace changes
Inline
Side-by-side
Showing
30 changed files
with
341 additions
and
73 deletions
+341
-73
runtime.go
pkg/kubelet/container/runtime.go
+12
-1
manager.go
pkg/kubelet/dockertools/manager.go
+20
-3
kubelet.go
pkg/kubelet/kubelet.go
+65
-1
kubelet_test.go
pkg/kubelet/kubelet_test.go
+27
-3
rkt.go
pkg/kubelet/rkt/rkt.go
+1
-1
root_context_linux.go
pkg/kubelet/root_context_linux.go
+1
-1
volumes.go
pkg/kubelet/volumes.go
+1
-1
doc.go
pkg/util/selinux/doc.go
+18
-0
selinux.go
pkg/util/selinux/selinux.go
+3
-3
selinux_linux.go
pkg/util/selinux/selinux_linux.go
+1
-1
selinux_unsupported.go
pkg/util/selinux/selinux_unsupported.go
+1
-1
aws_ebs.go
pkg/volume/aws_ebs/aws_ebs.go
+4
-0
cephfs.go
pkg/volume/cephfs/cephfs.go
+4
-0
cinder.go
pkg/volume/cinder/cinder.go
+4
-0
downwardapi.go
pkg/volume/downwardapi/downwardapi.go
+4
-0
empty_dir.go
pkg/volume/empty_dir/empty_dir.go
+9
-13
empty_dir_test.go
pkg/volume/empty_dir/empty_dir_test.go
+1
-39
fc.go
pkg/volume/fc/fc.go
+4
-0
plugin.go
pkg/volume/flocker/plugin.go
+4
-0
gce_pd.go
pkg/volume/gce_pd/gce_pd.go
+4
-0
git_repo.go
pkg/volume/git_repo/git_repo.go
+4
-0
glusterfs.go
pkg/volume/glusterfs/glusterfs.go
+4
-0
host_path.go
pkg/volume/host_path/host_path.go
+4
-0
iscsi.go
pkg/volume/iscsi/iscsi.go
+4
-0
nfs.go
pkg/volume/nfs/nfs.go
+4
-0
rbd.go
pkg/volume/rbd/rbd.go
+4
-0
secret.go
pkg/volume/secret/secret.go
+4
-0
testing.go
pkg/volume/testing.go
+4
-0
volume.go
pkg/volume/volume.go
+4
-0
security_context.go
test/e2e/security_context.go
+117
-5
No files found.
pkg/kubelet/container/runtime.go
View file @
c8a17837
...
@@ -238,6 +238,8 @@ type Mount struct {
...
@@ -238,6 +238,8 @@ type Mount struct {
HostPath
string
HostPath
string
// Whether the mount is read-only.
// Whether the mount is read-only.
ReadOnly
bool
ReadOnly
bool
// Whether the mount needs SELinux relabeling
SELinuxRelabel
bool
}
}
type
PortMapping
struct
{
type
PortMapping
struct
{
...
@@ -273,7 +275,16 @@ type RunContainerOptions struct {
...
@@ -273,7 +275,16 @@ type RunContainerOptions struct {
CgroupParent
string
CgroupParent
string
}
}
type
VolumeMap
map
[
string
]
volume
.
Volume
// VolumeInfo contains information about the volume.
type
VolumeInfo
struct
{
// Builder is the volume's builder
Builder
volume
.
Builder
// SELinuxLabeled indicates whether this volume has had the
// pod's SELinux label applied to it or not
SELinuxLabeled
bool
}
type
VolumeMap
map
[
string
]
VolumeInfo
type
Pods
[]
*
Pod
type
Pods
[]
*
Pod
...
...
pkg/kubelet/dockertools/manager.go
View file @
c8a17837
...
@@ -606,13 +606,29 @@ func makeEnvList(envs []kubecontainer.EnvVar) (result []string) {
...
@@ -606,13 +606,29 @@ func makeEnvList(envs []kubecontainer.EnvVar) (result []string) {
// can be understood by docker.
// can be understood by docker.
// Each element in the string is in the form of:
// Each element in the string is in the form of:
// '<HostPath>:<ContainerPath>', or
// '<HostPath>:<ContainerPath>', or
// '<HostPath>:<ContainerPath>:ro', if the path is read only.
// '<HostPath>:<ContainerPath>:ro', if the path is read only, or
func
makeMountBindings
(
mounts
[]
kubecontainer
.
Mount
)
(
result
[]
string
)
{
// '<HostPath>:<ContainerPath>:Z', if the volume requires SELinux
// relabeling and the pod provides an SELinux label
func
makeMountBindings
(
mounts
[]
kubecontainer
.
Mount
,
podHasSELinuxLabel
bool
)
(
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
// 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
{
bind
+=
",Z"
}
else
{
bind
+=
":Z"
}
}
result
=
append
(
result
,
bind
)
result
=
append
(
result
,
bind
)
}
}
return
return
...
@@ -766,7 +782,8 @@ func (dm *DockerManager) runContainer(
...
@@ -766,7 +782,8 @@ func (dm *DockerManager) runContainer(
dm
.
recorder
.
Eventf
(
ref
,
"Created"
,
"Created with docker id %v"
,
util
.
ShortenString
(
dockerContainer
.
ID
,
12
))
dm
.
recorder
.
Eventf
(
ref
,
"Created"
,
"Created with docker id %v"
,
util
.
ShortenString
(
dockerContainer
.
ID
,
12
))
}
}
binds
:=
makeMountBindings
(
opts
.
Mounts
)
podHasSELinuxLabel
:=
pod
.
Spec
.
SecurityContext
!=
nil
&&
pod
.
Spec
.
SecurityContext
.
SELinuxOptions
!=
nil
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
...
...
pkg/kubelet/kubelet.go
View file @
c8a17837
...
@@ -29,6 +29,7 @@ import (
...
@@ -29,6 +29,7 @@ import (
"net/http"
"net/http"
"os"
"os"
"path"
"path"
"path/filepath"
"sort"
"sort"
"strings"
"strings"
"sync"
"sync"
...
@@ -62,6 +63,7 @@ import (
...
@@ -62,6 +63,7 @@ import (
kubeletutil
"k8s.io/kubernetes/pkg/kubelet/util"
kubeletutil
"k8s.io/kubernetes/pkg/kubelet/util"
"k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/securitycontext"
"k8s.io/kubernetes/pkg/types"
"k8s.io/kubernetes/pkg/types"
"k8s.io/kubernetes/pkg/util"
"k8s.io/kubernetes/pkg/util"
"k8s.io/kubernetes/pkg/util/bandwidth"
"k8s.io/kubernetes/pkg/util/bandwidth"
...
@@ -73,6 +75,7 @@ import (
...
@@ -73,6 +75,7 @@ import (
nodeutil
"k8s.io/kubernetes/pkg/util/node"
nodeutil
"k8s.io/kubernetes/pkg/util/node"
"k8s.io/kubernetes/pkg/util/oom"
"k8s.io/kubernetes/pkg/util/oom"
"k8s.io/kubernetes/pkg/util/procfs"
"k8s.io/kubernetes/pkg/util/procfs"
"k8s.io/kubernetes/pkg/util/selinux"
"k8s.io/kubernetes/pkg/util/sets"
"k8s.io/kubernetes/pkg/util/sets"
"k8s.io/kubernetes/pkg/version"
"k8s.io/kubernetes/pkg/version"
"k8s.io/kubernetes/pkg/volume"
"k8s.io/kubernetes/pkg/volume"
...
@@ -975,6 +978,47 @@ func (kl *Kubelet) syncNodeStatus() {
...
@@ -975,6 +978,47 @@ func (kl *Kubelet) syncNodeStatus() {
}
}
}
}
// 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
}
chconRunner
:=
selinux
.
NewChconRunner
()
// 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
_
,
volume
:=
range
volumes
{
if
volume
.
Builder
.
SupportsSELinux
()
&&
!
volume
.
Builder
.
IsReadOnly
()
{
// Relabel the volume and its content to match the 'Level' of the pod
err
:=
filepath
.
Walk
(
volume
.
Builder
.
GetPath
(),
func
(
path
string
,
info
os
.
FileInfo
,
err
error
)
error
{
if
err
!=
nil
{
return
err
}
return
chconRunner
.
SetContext
(
path
,
volumeContext
)
})
if
err
!=
nil
{
return
err
}
volume
.
SELinuxLabeled
=
true
}
}
return
nil
}
func
makeMounts
(
pod
*
api
.
Pod
,
podDir
string
,
container
*
api
.
Container
,
podVolumes
kubecontainer
.
VolumeMap
)
([]
kubecontainer
.
Mount
,
error
)
{
func
makeMounts
(
pod
*
api
.
Pod
,
podDir
string
,
container
*
api
.
Container
,
podVolumes
kubecontainer
.
VolumeMap
)
([]
kubecontainer
.
Mount
,
error
)
{
// Kubernetes only mounts on /etc/hosts if :
// Kubernetes only mounts on /etc/hosts if :
// - container does not use hostNetwork and
// - container does not use hostNetwork and
...
@@ -991,11 +1035,21 @@ func makeMounts(pod *api.Pod, podDir string, container *api.Container, podVolume
...
@@ -991,11 +1035,21 @@ func makeMounts(pod *api.Pod, podDir string, container *api.Container, podVolume
glog
.
Warningf
(
"Mount cannot be satisified for container %q, because the volume is missing: %q"
,
container
.
Name
,
mount
)
glog
.
Warningf
(
"Mount cannot be satisified for container %q, because the volume is missing: %q"
,
container
.
Name
,
mount
)
continue
continue
}
}
relabelVolume
:=
false
// If the volume supports SELinux and it has not been
// relabeled already and it is not a read-only volume,
// relabel it and mark it as labeled
if
vol
.
Builder
.
SupportsSELinux
()
&&
!
vol
.
SELinuxLabeled
&&
!
vol
.
Builder
.
IsReadOnly
()
{
vol
.
SELinuxLabeled
=
true
relabelVolume
=
true
}
mounts
=
append
(
mounts
,
kubecontainer
.
Mount
{
mounts
=
append
(
mounts
,
kubecontainer
.
Mount
{
Name
:
mount
.
Name
,
Name
:
mount
.
Name
,
ContainerPath
:
mount
.
MountPath
,
ContainerPath
:
mount
.
MountPath
,
HostPath
:
vol
.
GetPath
(),
HostPath
:
vol
.
Builder
.
GetPath
(),
ReadOnly
:
mount
.
ReadOnly
,
ReadOnly
:
mount
.
ReadOnly
,
SELinuxRelabel
:
relabelVolume
,
})
})
}
}
if
mountEtcHostsFile
{
if
mountEtcHostsFile
{
...
@@ -1080,6 +1134,16 @@ func (kl *Kubelet) GenerateRunContainerOptions(pod *api.Pod, container *api.Cont
...
@@ -1080,6 +1134,16 @@ func (kl *Kubelet) GenerateRunContainerOptions(pod *api.Pod, container *api.Cont
}
}
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
,
vol
)
if
err
!=
nil
{
return
nil
,
err
}
}
opts
.
Mounts
,
err
=
makeMounts
(
pod
,
kl
.
getPodDir
(
pod
.
UID
),
container
,
vol
)
opts
.
Mounts
,
err
=
makeMounts
(
pod
,
kl
.
getPodDir
(
pod
.
UID
),
container
,
vol
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
...
...
pkg/kubelet/kubelet_test.go
View file @
c8a17837
...
@@ -510,6 +510,26 @@ func (f *stubVolume) GetPath() string {
...
@@ -510,6 +510,26 @@ func (f *stubVolume) GetPath() string {
return
f
.
path
return
f
.
path
}
}
func
(
f
*
stubVolume
)
IsReadOnly
()
bool
{
return
false
}
func
(
f
*
stubVolume
)
SetUp
()
error
{
return
nil
}
func
(
f
*
stubVolume
)
SetUpAt
(
dir
string
)
error
{
return
nil
}
func
(
f
*
stubVolume
)
SupportsSELinux
()
bool
{
return
false
}
func
(
f
*
stubVolume
)
SupportsOwnershipManagement
()
bool
{
return
false
}
func
TestMakeVolumeMounts
(
t
*
testing
.
T
)
{
func
TestMakeVolumeMounts
(
t
*
testing
.
T
)
{
container
:=
api
.
Container
{
container
:=
api
.
Container
{
VolumeMounts
:
[]
api
.
VolumeMount
{
VolumeMounts
:
[]
api
.
VolumeMount
{
...
@@ -537,9 +557,9 @@ func TestMakeVolumeMounts(t *testing.T) {
...
@@ -537,9 +557,9 @@ func TestMakeVolumeMounts(t *testing.T) {
}
}
podVolumes
:=
kubecontainer
.
VolumeMap
{
podVolumes
:=
kubecontainer
.
VolumeMap
{
"disk"
:
&
stubVolume
{
"/mnt/disk"
},
"disk"
:
kubecontainer
.
VolumeInfo
{
Builder
:
&
stubVolume
{
"/mnt/disk"
}
},
"disk4"
:
&
stubVolume
{
"/mnt/host"
},
"disk4"
:
kubecontainer
.
VolumeInfo
{
Builder
:
&
stubVolume
{
"/mnt/host"
}
},
"disk5"
:
&
stubVolume
{
"/var/lib/kubelet/podID/volumes/empty/disk5"
},
"disk5"
:
kubecontainer
.
VolumeInfo
{
Builder
:
&
stubVolume
{
"/var/lib/kubelet/podID/volumes/empty/disk5"
}
},
}
}
pod
:=
api
.
Pod
{
pod
:=
api
.
Pod
{
...
@@ -558,24 +578,28 @@ func TestMakeVolumeMounts(t *testing.T) {
...
@@ -558,24 +578,28 @@ func TestMakeVolumeMounts(t *testing.T) {
"/etc/hosts"
,
"/etc/hosts"
,
"/mnt/disk"
,
"/mnt/disk"
,
false
,
false
,
false
,
},
},
{
{
"disk"
,
"disk"
,
"/mnt/path3"
,
"/mnt/path3"
,
"/mnt/disk"
,
"/mnt/disk"
,
true
,
true
,
false
,
},
},
{
{
"disk4"
,
"disk4"
,
"/mnt/path4"
,
"/mnt/path4"
,
"/mnt/host"
,
"/mnt/host"
,
false
,
false
,
false
,
},
},
{
{
"disk5"
,
"disk5"
,
"/mnt/path5"
,
"/mnt/path5"
,
"/var/lib/kubelet/podID/volumes/empty/disk5"
,
"/var/lib/kubelet/podID/volumes/empty/disk5"
,
false
,
false
,
false
,
},
},
}
}
if
!
reflect
.
DeepEqual
(
mounts
,
expectedMounts
)
{
if
!
reflect
.
DeepEqual
(
mounts
,
expectedMounts
)
{
...
...
pkg/kubelet/rkt/rkt.go
View file @
c8a17837
...
@@ -488,7 +488,7 @@ func (r *Runtime) makePodManifest(pod *api.Pod, pullSecrets []api.Secret) (*appc
...
@@ -488,7 +488,7 @@ func (r *Runtime) makePodManifest(pod *api.Pod, pullSecrets []api.Secret) (*appc
manifest
.
Volumes
=
append
(
manifest
.
Volumes
,
appctypes
.
Volume
{
manifest
.
Volumes
=
append
(
manifest
.
Volumes
,
appctypes
.
Volume
{
Name
:
*
volName
,
Name
:
*
volName
,
Kind
:
"host"
,
Kind
:
"host"
,
Source
:
volume
.
GetPath
(),
Source
:
volume
.
Builder
.
GetPath
(),
})
})
}
}
...
...
pkg/kubelet/root_context_linux.go
View file @
c8a17837
...
@@ -22,7 +22,7 @@ import (
...
@@ -22,7 +22,7 @@ import (
"github.com/docker/libcontainer/selinux"
"github.com/docker/libcontainer/selinux"
)
)
// getRootContext gets the SELinux context of the kubelet rootDir
// getRoot
Dir
Context gets the SELinux context of the kubelet rootDir
// or returns an error.
// or returns an error.
func
(
kl
*
Kubelet
)
getRootDirContext
()
(
string
,
error
)
{
func
(
kl
*
Kubelet
)
getRootDirContext
()
(
string
,
error
)
{
// If SELinux is not enabled, return an empty string
// If SELinux is not enabled, return an empty string
...
...
pkg/kubelet/volumes.go
View file @
c8a17837
...
@@ -146,7 +146,7 @@ func (kl *Kubelet) mountExternalVolumes(pod *api.Pod) (kubecontainer.VolumeMap,
...
@@ -146,7 +146,7 @@ func (kl *Kubelet) mountExternalVolumes(pod *api.Pod) (kubecontainer.VolumeMap,
return
nil
,
err
return
nil
,
err
}
}
}
}
podVolumes
[
volSpec
.
Name
]
=
builder
podVolumes
[
volSpec
.
Name
]
=
kubecontainer
.
VolumeInfo
{
Builder
:
builder
}
}
}
return
podVolumes
,
nil
return
podVolumes
,
nil
}
}
...
...
pkg/util/selinux/doc.go
0 → 100644
View file @
c8a17837
/*
Copyright 2015 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 selinux contains selinux utility functions.
package
selinux
pkg/
volume/empty_dir/chcon_runner
.go
→
pkg/
util/selinux/selinux
.go
View file @
c8a17837
...
@@ -14,14 +14,14 @@ See the License for the specific language governing permissions and
...
@@ -14,14 +14,14 @@ See the License for the specific language governing permissions and
limitations under the License.
limitations under the License.
*/
*/
package
empty_dir
package
selinux
// chconRunner knows how to chcon a directory.
// chconRunner knows how to chcon a directory.
type
c
hconRunner
interface
{
type
C
hconRunner
interface
{
SetContext
(
dir
,
context
string
)
error
SetContext
(
dir
,
context
string
)
error
}
}
// newChconRunner returns a new chconRunner.
// newChconRunner returns a new chconRunner.
func
newChconRunner
()
c
hconRunner
{
func
NewChconRunner
()
C
hconRunner
{
return
&
realChconRunner
{}
return
&
realChconRunner
{}
}
}
pkg/
volume/empty_dir/chcon_runner
_linux.go
→
pkg/
util/selinux/selinux
_linux.go
View file @
c8a17837
...
@@ -16,7 +16,7 @@ See the License for the specific language governing permissions and
...
@@ -16,7 +16,7 @@ See the License for the specific language governing permissions and
limitations under the License.
limitations under the License.
*/
*/
package
empty_dir
package
selinux
import
(
import
(
"github.com/docker/libcontainer/selinux"
"github.com/docker/libcontainer/selinux"
...
...
pkg/
volume/empty_dir/chcon_runner
_unsupported.go
→
pkg/
util/selinux/selinux
_unsupported.go
View file @
c8a17837
...
@@ -16,7 +16,7 @@ See the License for the specific language governing permissions and
...
@@ -16,7 +16,7 @@ See the License for the specific language governing permissions and
limitations under the License.
limitations under the License.
*/
*/
package
empty_dir
package
selinux
type
realChconRunner
struct
{}
type
realChconRunner
struct
{}
...
...
pkg/volume/aws_ebs/aws_ebs.go
View file @
c8a17837
...
@@ -250,6 +250,10 @@ func (b *awsElasticBlockStoreBuilder) IsReadOnly() bool {
...
@@ -250,6 +250,10 @@ func (b *awsElasticBlockStoreBuilder) IsReadOnly() bool {
return
b
.
readOnly
return
b
.
readOnly
}
}
func
(
b
*
awsElasticBlockStoreBuilder
)
SupportsSELinux
()
bool
{
return
true
}
func
makeGlobalPDPath
(
host
volume
.
VolumeHost
,
volumeID
string
)
string
{
func
makeGlobalPDPath
(
host
volume
.
VolumeHost
,
volumeID
string
)
string
{
// Clean up the URI to be more fs-friendly
// Clean up the URI to be more fs-friendly
name
:=
volumeID
name
:=
volumeID
...
...
pkg/volume/cephfs/cephfs.go
View file @
c8a17837
...
@@ -187,6 +187,10 @@ func (cephfsVolume *cephfsBuilder) IsReadOnly() bool {
...
@@ -187,6 +187,10 @@ func (cephfsVolume *cephfsBuilder) IsReadOnly() bool {
return
cephfsVolume
.
readonly
return
cephfsVolume
.
readonly
}
}
func
(
cephfsVolume
*
cephfsBuilder
)
SupportsSELinux
()
bool
{
return
false
}
type
cephfsCleaner
struct
{
type
cephfsCleaner
struct
{
*
cephfs
*
cephfs
}
}
...
...
pkg/volume/cinder/cinder.go
View file @
c8a17837
...
@@ -225,6 +225,10 @@ func (b *cinderVolumeBuilder) IsReadOnly() bool {
...
@@ -225,6 +225,10 @@ func (b *cinderVolumeBuilder) IsReadOnly() bool {
return
b
.
readOnly
return
b
.
readOnly
}
}
func
(
b
*
cinderVolumeBuilder
)
SupportsSELinux
()
bool
{
return
true
}
func
makeGlobalPDName
(
host
volume
.
VolumeHost
,
devName
string
)
string
{
func
makeGlobalPDName
(
host
volume
.
VolumeHost
,
devName
string
)
string
{
return
path
.
Join
(
host
.
GetPluginDir
(
cinderVolumePluginName
),
"mounts"
,
devName
)
return
path
.
Join
(
host
.
GetPluginDir
(
cinderVolumePluginName
),
"mounts"
,
devName
)
}
}
...
...
pkg/volume/downwardapi/downwardapi.go
View file @
c8a17837
...
@@ -157,6 +157,10 @@ func (d *downwardAPIVolume) IsReadOnly() bool {
...
@@ -157,6 +157,10 @@ func (d *downwardAPIVolume) IsReadOnly() bool {
return
true
return
true
}
}
func
(
d
*
downwardAPIVolume
)
SupportsSELinux
()
bool
{
return
true
}
// collectData collects requested downwardAPI in data map.
// collectData collects requested downwardAPI in data map.
// Map's key is the requested name of file to dump
// Map's key is the requested name of file to dump
// Map's value is the (sorted) content of the field to be dumped in the file.
// Map's value is the (sorted) content of the field to be dumped in the file.
...
...
pkg/volume/empty_dir/empty_dir.go
View file @
c8a17837
...
@@ -70,10 +70,10 @@ func (plugin *emptyDirPlugin) CanSupport(spec *volume.Spec) bool {
...
@@ -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
)
{
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
medium
:=
api
.
StorageMediumDefault
if
spec
.
Volume
.
EmptyDir
!=
nil
{
// Support a non-specified source as EmptyDir.
if
spec
.
Volume
.
EmptyDir
!=
nil
{
// Support a non-specified source as EmptyDir.
medium
=
spec
.
Volume
.
EmptyDir
.
Medium
medium
=
spec
.
Volume
.
EmptyDir
.
Medium
...
@@ -86,7 +86,6 @@ func (plugin *emptyDirPlugin) newBuilderInternal(spec *volume.Spec, pod *api.Pod
...
@@ -86,7 +86,6 @@ func (plugin *emptyDirPlugin) newBuilderInternal(spec *volume.Spec, pod *api.Pod
mountDetector
:
mountDetector
,
mountDetector
:
mountDetector
,
plugin
:
plugin
,
plugin
:
plugin
,
rootContext
:
opts
.
RootContext
,
rootContext
:
opts
.
RootContext
,
chconRunner
:
chconRunner
,
},
nil
},
nil
}
}
...
@@ -134,7 +133,6 @@ type emptyDir struct {
...
@@ -134,7 +133,6 @@ type emptyDir struct {
mountDetector
mountDetector
mountDetector
mountDetector
plugin
*
emptyDirPlugin
plugin
*
emptyDirPlugin
rootContext
string
rootContext
string
chconRunner
chconRunner
}
}
func
(
_
*
emptyDir
)
SupportsOwnershipManagement
()
bool
{
func
(
_
*
emptyDir
)
SupportsOwnershipManagement
()
bool
{
...
@@ -175,7 +173,7 @@ func (ed *emptyDir) SetUpAt(dir string) error {
...
@@ -175,7 +173,7 @@ func (ed *emptyDir) SetUpAt(dir string) error {
switch
ed
.
medium
{
switch
ed
.
medium
{
case
api
.
StorageMediumDefault
:
case
api
.
StorageMediumDefault
:
err
=
ed
.
setupDir
(
dir
,
securityContext
)
err
=
ed
.
setupDir
(
dir
)
case
api
.
StorageMediumMemory
:
case
api
.
StorageMediumMemory
:
err
=
ed
.
setupTmpfs
(
dir
,
securityContext
)
err
=
ed
.
setupTmpfs
(
dir
,
securityContext
)
default
:
default
:
...
@@ -193,13 +191,17 @@ func (ed *emptyDir) IsReadOnly() bool {
...
@@ -193,13 +191,17 @@ func (ed *emptyDir) IsReadOnly() bool {
return
false
return
false
}
}
func
(
ed
*
emptyDir
)
SupportsSELinux
()
bool
{
return
true
}
// 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
,
selinuxContext
string
)
error
{
func
(
ed
*
emptyDir
)
setupTmpfs
(
dir
string
,
selinuxContext
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"
)
}
}
if
err
:=
ed
.
setupDir
(
dir
,
selinuxContext
);
err
!=
nil
{
if
err
:=
ed
.
setupDir
(
dir
);
err
!=
nil
{
return
err
return
err
}
}
// Make SetUp idempotent.
// Make SetUp idempotent.
...
@@ -228,7 +230,7 @@ func (ed *emptyDir) setupTmpfs(dir string, selinuxContext string) error {
...
@@ -228,7 +230,7 @@ func (ed *emptyDir) setupTmpfs(dir string, selinuxContext string) error {
// setupDir creates the directory with the specified SELinux context and
// setupDir creates the directory with the specified SELinux context and
// the default permissions specified by the perm constant.
// 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.
// Create the directory if it doesn't already exist.
if
err
:=
os
.
MkdirAll
(
dir
,
perm
);
err
!=
nil
{
if
err
:=
os
.
MkdirAll
(
dir
,
perm
);
err
!=
nil
{
return
err
return
err
...
@@ -262,12 +264,6 @@ func (ed *emptyDir) setupDir(dir, selinuxContext string) error {
...
@@ -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
return
nil
}
}
...
...
pkg/volume/empty_dir/empty_dir_test.go
View file @
c8a17837
...
@@ -69,30 +69,10 @@ func (fake *fakeMountDetector) GetMountMedium(path string) (storageMedium, bool,
...
@@ -69,30 +69,10 @@ func (fake *fakeMountDetector) GetMountMedium(path string) (storageMedium, bool,
return
fake
.
medium
,
fake
.
isMount
,
nil
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
)
{
func
TestPluginEmptyRootContext
(
t
*
testing
.
T
)
{
doTestPlugin
(
t
,
pluginTestConfig
{
doTestPlugin
(
t
,
pluginTestConfig
{
medium
:
api
.
StorageMediumDefault
,
medium
:
api
.
StorageMediumDefault
,
rootContext
:
""
,
rootContext
:
""
,
expectedChcons
:
0
,
expectedSetupMounts
:
0
,
expectedSetupMounts
:
0
,
expectedTeardownMounts
:
0
})
expectedTeardownMounts
:
0
})
}
}
...
@@ -106,7 +86,6 @@ func TestPluginRootContextSet(t *testing.T) {
...
@@ -106,7 +86,6 @@ func TestPluginRootContextSet(t *testing.T) {
medium
:
api
.
StorageMediumDefault
,
medium
:
api
.
StorageMediumDefault
,
rootContext
:
"user:role:type:range"
,
rootContext
:
"user:role:type:range"
,
expectedSELinuxContext
:
"user:role:type:range"
,
expectedSELinuxContext
:
"user:role:type:range"
,
expectedChcons
:
1
,
expectedSetupMounts
:
0
,
expectedSetupMounts
:
0
,
expectedTeardownMounts
:
0
})
expectedTeardownMounts
:
0
})
}
}
...
@@ -120,7 +99,6 @@ func TestPluginTmpfs(t *testing.T) {
...
@@ -120,7 +99,6 @@ func TestPluginTmpfs(t *testing.T) {
medium
:
api
.
StorageMediumMemory
,
medium
:
api
.
StorageMediumMemory
,
rootContext
:
"user:role:type:range"
,
rootContext
:
"user:role:type:range"
,
expectedSELinuxContext
:
"user:role:type:range"
,
expectedSELinuxContext
:
"user:role:type:range"
,
expectedChcons
:
1
,
expectedSetupMounts
:
1
,
expectedSetupMounts
:
1
,
shouldBeMountedBeforeTeardown
:
true
,
shouldBeMountedBeforeTeardown
:
true
,
expectedTeardownMounts
:
1
})
expectedTeardownMounts
:
1
})
...
@@ -132,7 +110,6 @@ type pluginTestConfig struct {
...
@@ -132,7 +110,6 @@ type pluginTestConfig struct {
SELinuxOptions
*
api
.
SELinuxOptions
SELinuxOptions
*
api
.
SELinuxOptions
idempotent
bool
idempotent
bool
expectedSELinuxContext
string
expectedSELinuxContext
string
expectedChcons
int
expectedSetupMounts
int
expectedSetupMounts
int
shouldBeMountedBeforeTeardown
bool
shouldBeMountedBeforeTeardown
bool
expectedTeardownMounts
int
expectedTeardownMounts
int
...
@@ -160,7 +137,6 @@ func doTestPlugin(t *testing.T, config pluginTestConfig) {
...
@@ -160,7 +137,6 @@ func doTestPlugin(t *testing.T, config pluginTestConfig) {
mounter
=
mount
.
FakeMounter
{}
mounter
=
mount
.
FakeMounter
{}
mountDetector
=
fakeMountDetector
{}
mountDetector
=
fakeMountDetector
{}
pod
=
&
api
.
Pod
{
ObjectMeta
:
api
.
ObjectMeta
{
UID
:
types
.
UID
(
"poduid"
)}}
pod
=
&
api
.
Pod
{
ObjectMeta
:
api
.
ObjectMeta
{
UID
:
types
.
UID
(
"poduid"
)}}
fakeChconRnr
=
&
fakeChconRunner
{}
)
)
// Set up the SELinux options on the pod
// Set up the SELinux options on the pod
...
@@ -194,8 +170,7 @@ func doTestPlugin(t *testing.T, config pluginTestConfig) {
...
@@ -194,8 +170,7 @@ func doTestPlugin(t *testing.T, config pluginTestConfig) {
pod
,
pod
,
&
mounter
,
&
mounter
,
&
mountDetector
,
&
mountDetector
,
volume
.
VolumeOptions
{
RootContext
:
config
.
rootContext
},
volume
.
VolumeOptions
{
RootContext
:
config
.
rootContext
})
fakeChconRnr
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Errorf
(
"Failed to make a new Builder: %v"
,
err
)
t
.
Errorf
(
"Failed to make a new Builder: %v"
,
err
)
}
}
...
@@ -231,19 +206,6 @@ func doTestPlugin(t *testing.T, config pluginTestConfig) {
...
@@ -231,19 +206,6 @@ func doTestPlugin(t *testing.T, config pluginTestConfig) {
t
.
Errorf
(
"Volume directory was created unexpectedly"
)
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
// Check the number of mounts performed during setup
if
e
,
a
:=
config
.
expectedSetupMounts
,
len
(
mounter
.
Log
);
e
!=
a
{
if
e
,
a
:=
config
.
expectedSetupMounts
,
len
(
mounter
.
Log
);
e
!=
a
{
t
.
Errorf
(
"Expected %v mounter calls during setup, got %v"
,
e
,
a
)
t
.
Errorf
(
"Expected %v mounter calls during setup, got %v"
,
e
,
a
)
...
...
pkg/volume/fc/fc.go
View file @
c8a17837
...
@@ -191,6 +191,10 @@ func (b *fcDiskBuilder) IsReadOnly() bool {
...
@@ -191,6 +191,10 @@ func (b *fcDiskBuilder) IsReadOnly() bool {
return
b
.
readOnly
return
b
.
readOnly
}
}
func
(
b
*
fcDiskBuilder
)
SupportsSELinux
()
bool
{
return
true
}
// Unmounts the bind mount, and detaches the disk only if the disk
// Unmounts the bind mount, and detaches the disk only if the disk
// resource was the last reference to that disk on the kubelet.
// resource was the last reference to that disk on the kubelet.
func
(
c
*
fcDiskCleaner
)
TearDown
()
error
{
func
(
c
*
fcDiskCleaner
)
TearDown
()
error
{
...
...
pkg/volume/flocker/plugin.go
View file @
c8a17837
...
@@ -205,6 +205,10 @@ func (b flockerBuilder) IsReadOnly() bool {
...
@@ -205,6 +205,10 @@ func (b flockerBuilder) IsReadOnly() bool {
return
b
.
readOnly
return
b
.
readOnly
}
}
func
(
b
flockerBuilder
)
SupportsSELinux
()
bool
{
return
false
}
// updateDatasetPrimary will update the primary in Flocker and wait for it to
// updateDatasetPrimary will update the primary in Flocker and wait for it to
// be ready. If it never gets to ready state it will timeout and error.
// be ready. If it never gets to ready state it will timeout and error.
func
(
b
flockerBuilder
)
updateDatasetPrimary
(
datasetID
,
primaryUUID
string
)
error
{
func
(
b
flockerBuilder
)
updateDatasetPrimary
(
datasetID
,
primaryUUID
string
)
error
{
...
...
pkg/volume/gce_pd/gce_pd.go
View file @
c8a17837
...
@@ -238,6 +238,10 @@ func (b *gcePersistentDiskBuilder) IsReadOnly() bool {
...
@@ -238,6 +238,10 @@ func (b *gcePersistentDiskBuilder) IsReadOnly() bool {
return
b
.
readOnly
return
b
.
readOnly
}
}
func
(
b
*
gcePersistentDiskBuilder
)
SupportsSELinux
()
bool
{
return
true
}
func
makeGlobalPDName
(
host
volume
.
VolumeHost
,
devName
string
)
string
{
func
makeGlobalPDName
(
host
volume
.
VolumeHost
,
devName
string
)
string
{
return
path
.
Join
(
host
.
GetPluginDir
(
gcePersistentDiskPluginName
),
"mounts"
,
devName
)
return
path
.
Join
(
host
.
GetPluginDir
(
gcePersistentDiskPluginName
),
"mounts"
,
devName
)
}
}
...
...
pkg/volume/git_repo/git_repo.go
View file @
c8a17837
...
@@ -122,6 +122,10 @@ func (b *gitRepoVolumeBuilder) IsReadOnly() bool {
...
@@ -122,6 +122,10 @@ func (b *gitRepoVolumeBuilder) IsReadOnly() bool {
return
false
return
false
}
}
func
(
b
*
gitRepoVolumeBuilder
)
SupportsSELinux
()
bool
{
return
true
}
// This is the spec for the volume that this plugin wraps.
// This is the spec for the volume that this plugin wraps.
var
wrappedVolumeSpec
=
&
volume
.
Spec
{
var
wrappedVolumeSpec
=
&
volume
.
Spec
{
Volume
:
&
api
.
Volume
{
VolumeSource
:
api
.
VolumeSource
{
EmptyDir
:
&
api
.
EmptyDirVolumeSource
{}}},
Volume
:
&
api
.
Volume
{
VolumeSource
:
api
.
VolumeSource
{
EmptyDir
:
&
api
.
EmptyDirVolumeSource
{}}},
...
...
pkg/volume/glusterfs/glusterfs.go
View file @
c8a17837
...
@@ -189,6 +189,10 @@ func (b *glusterfsBuilder) IsReadOnly() bool {
...
@@ -189,6 +189,10 @@ func (b *glusterfsBuilder) IsReadOnly() bool {
return
b
.
readOnly
return
b
.
readOnly
}
}
func
(
b
*
glusterfsBuilder
)
SupportsSELinux
()
bool
{
return
false
}
func
(
glusterfsVolume
*
glusterfs
)
GetPath
()
string
{
func
(
glusterfsVolume
*
glusterfs
)
GetPath
()
string
{
name
:=
glusterfsPluginName
name
:=
glusterfsPluginName
return
glusterfsVolume
.
plugin
.
host
.
GetPodVolumeDir
(
glusterfsVolume
.
pod
.
UID
,
util
.
EscapeQualifiedNameForDisk
(
name
),
glusterfsVolume
.
volName
)
return
glusterfsVolume
.
plugin
.
host
.
GetPodVolumeDir
(
glusterfsVolume
.
pod
.
UID
,
util
.
EscapeQualifiedNameForDisk
(
name
),
glusterfsVolume
.
volName
)
...
...
pkg/volume/host_path/host_path.go
View file @
c8a17837
...
@@ -185,6 +185,10 @@ func (b *hostPathBuilder) IsReadOnly() bool {
...
@@ -185,6 +185,10 @@ func (b *hostPathBuilder) IsReadOnly() bool {
return
b
.
readOnly
return
b
.
readOnly
}
}
func
(
b
*
hostPathBuilder
)
SupportsSELinux
()
bool
{
return
false
}
func
(
b
*
hostPathBuilder
)
GetPath
()
string
{
func
(
b
*
hostPathBuilder
)
GetPath
()
string
{
return
b
.
path
return
b
.
path
}
}
...
...
pkg/volume/iscsi/iscsi.go
View file @
c8a17837
...
@@ -185,6 +185,10 @@ func (b *iscsiDiskBuilder) IsReadOnly() bool {
...
@@ -185,6 +185,10 @@ func (b *iscsiDiskBuilder) IsReadOnly() bool {
return
b
.
readOnly
return
b
.
readOnly
}
}
func
(
b
*
iscsiDiskBuilder
)
SupportsSELinux
()
bool
{
return
true
}
// Unmounts the bind mount, and detaches the disk only if the disk
// Unmounts the bind mount, and detaches the disk only if the disk
// resource was the last reference to that disk on the kubelet.
// resource was the last reference to that disk on the kubelet.
func
(
c
*
iscsiDiskCleaner
)
TearDown
()
error
{
func
(
c
*
iscsiDiskCleaner
)
TearDown
()
error
{
...
...
pkg/volume/nfs/nfs.go
View file @
c8a17837
...
@@ -226,6 +226,10 @@ func (b *nfsBuilder) IsReadOnly() bool {
...
@@ -226,6 +226,10 @@ func (b *nfsBuilder) IsReadOnly() bool {
return
b
.
readOnly
return
b
.
readOnly
}
}
func
(
b
*
nfsBuilder
)
SupportsSELinux
()
bool
{
return
false
}
//
//
//func (c *nfsCleaner) GetPath() string {
//func (c *nfsCleaner) GetPath() string {
// name := nfsPluginName
// name := nfsPluginName
...
...
pkg/volume/rbd/rbd.go
View file @
c8a17837
...
@@ -219,6 +219,10 @@ func (b *rbd) IsReadOnly() bool {
...
@@ -219,6 +219,10 @@ func (b *rbd) IsReadOnly() bool {
return
b
.
ReadOnly
return
b
.
ReadOnly
}
}
func
(
b
*
rbd
)
SupportsSELinux
()
bool
{
return
true
}
// Unmounts the bind mount, and detaches the disk only if the disk
// Unmounts the bind mount, and detaches the disk only if the disk
// resource was the last reference to that disk on the kubelet.
// resource was the last reference to that disk on the kubelet.
func
(
c
*
rbdCleaner
)
TearDown
()
error
{
func
(
c
*
rbdCleaner
)
TearDown
()
error
{
...
...
pkg/volume/secret/secret.go
View file @
c8a17837
...
@@ -176,6 +176,10 @@ func (sv *secretVolume) IsReadOnly() bool {
...
@@ -176,6 +176,10 @@ func (sv *secretVolume) IsReadOnly() bool {
return
false
return
false
}
}
func
(
sv
*
secretVolume
)
SupportsSELinux
()
bool
{
return
true
}
func
totalSecretBytes
(
secret
*
api
.
Secret
)
int
{
func
totalSecretBytes
(
secret
*
api
.
Secret
)
int
{
totalSize
:=
0
totalSize
:=
0
for
_
,
bytes
:=
range
secret
.
Data
{
for
_
,
bytes
:=
range
secret
.
Data
{
...
...
pkg/volume/testing.go
View file @
c8a17837
...
@@ -172,6 +172,10 @@ func (fv *FakeVolume) IsReadOnly() bool {
...
@@ -172,6 +172,10 @@ func (fv *FakeVolume) IsReadOnly() bool {
return
false
return
false
}
}
func
(
fv
*
FakeVolume
)
SupportsSELinux
()
bool
{
return
false
}
func
(
fv
*
FakeVolume
)
GetPath
()
string
{
func
(
fv
*
FakeVolume
)
GetPath
()
string
{
return
path
.
Join
(
fv
.
Plugin
.
Host
.
GetPodVolumeDir
(
fv
.
PodUID
,
util
.
EscapeQualifiedNameForDisk
(
fv
.
Plugin
.
PluginName
),
fv
.
VolName
))
return
path
.
Join
(
fv
.
Plugin
.
Host
.
GetPodVolumeDir
(
fv
.
PodUID
,
util
.
EscapeQualifiedNameForDisk
(
fv
.
Plugin
.
PluginName
),
fv
.
VolName
))
}
}
...
...
pkg/volume/volume.go
View file @
c8a17837
...
@@ -53,6 +53,10 @@ type Builder interface {
...
@@ -53,6 +53,10 @@ type Builder interface {
// 2. Set the setgid bit is set (new files created in the volume will be owned by FSGroup)
// 2. Set the setgid bit is set (new files created in the volume will be owned by FSGroup)
// 3. Logical OR the permission bits with rw-rw----
// 3. Logical OR the permission bits with rw-rw----
SupportsOwnershipManagement
()
bool
SupportsOwnershipManagement
()
bool
// SupportsSELinux reports whether the given builder supports
// SELinux and would like the kubelet to relabel the volume to
// match the pod to which it will be attached.
SupportsSELinux
()
bool
}
}
// Cleaner interface provides methods to cleanup/unmount the volumes.
// Cleaner interface provides methods to cleanup/unmount the volumes.
...
...
test/e2e/security_context.go
View file @
c8a17837
...
@@ -29,9 +29,10 @@ import (
...
@@ -29,9 +29,10 @@ import (
"k8s.io/kubernetes/pkg/util"
"k8s.io/kubernetes/pkg/util"
.
"github.com/onsi/ginkgo"
.
"github.com/onsi/ginkgo"
.
"github.com/onsi/gomega"
)
)
func
scTestPod
()
*
api
.
Pod
{
func
scTestPod
(
hostIPC
bool
,
hostPID
bool
)
*
api
.
Pod
{
podName
:=
"security-context-"
+
string
(
util
.
NewUUID
())
podName
:=
"security-context-"
+
string
(
util
.
NewUUID
())
pod
:=
&
api
.
Pod
{
pod
:=
&
api
.
Pod
{
ObjectMeta
:
api
.
ObjectMeta
{
ObjectMeta
:
api
.
ObjectMeta
{
...
@@ -39,7 +40,10 @@ func scTestPod() *api.Pod {
...
@@ -39,7 +40,10 @@ func scTestPod() *api.Pod {
Labels
:
map
[
string
]
string
{
"name"
:
podName
},
Labels
:
map
[
string
]
string
{
"name"
:
podName
},
},
},
Spec
:
api
.
PodSpec
{
Spec
:
api
.
PodSpec
{
SecurityContext
:
&
api
.
PodSecurityContext
{},
SecurityContext
:
&
api
.
PodSecurityContext
{
HostIPC
:
hostIPC
,
HostPID
:
hostPID
,
},
Containers
:
[]
api
.
Container
{
Containers
:
[]
api
.
Container
{
{
{
Name
:
"test-container"
,
Name
:
"test-container"
,
...
@@ -57,7 +61,7 @@ var _ = Describe("[Skipped] Security Context", func() {
...
@@ -57,7 +61,7 @@ var _ = Describe("[Skipped] Security Context", func() {
framework
:=
NewFramework
(
"security-context"
)
framework
:=
NewFramework
(
"security-context"
)
It
(
"should support pod.Spec.SecurityContext.SupplementalGroups"
,
func
()
{
It
(
"should support pod.Spec.SecurityContext.SupplementalGroups"
,
func
()
{
pod
:=
scTestPod
()
pod
:=
scTestPod
(
false
,
false
)
pod
.
Spec
.
Containers
[
0
]
.
Command
=
[]
string
{
"id"
,
"-G"
}
pod
.
Spec
.
Containers
[
0
]
.
Command
=
[]
string
{
"id"
,
"-G"
}
pod
.
Spec
.
SecurityContext
.
SupplementalGroups
=
[]
int64
{
1234
,
5678
}
pod
.
Spec
.
SecurityContext
.
SupplementalGroups
=
[]
int64
{
1234
,
5678
}
groups
:=
[]
string
{
"1234"
,
"5678"
}
groups
:=
[]
string
{
"1234"
,
"5678"
}
...
@@ -65,7 +69,7 @@ var _ = Describe("[Skipped] Security Context", func() {
...
@@ -65,7 +69,7 @@ var _ = Describe("[Skipped] Security Context", func() {
})
})
It
(
"should support pod.Spec.SecurityContext.RunAsUser"
,
func
()
{
It
(
"should support pod.Spec.SecurityContext.RunAsUser"
,
func
()
{
pod
:=
scTestPod
()
pod
:=
scTestPod
(
false
,
false
)
var
uid
int64
=
1001
var
uid
int64
=
1001
pod
.
Spec
.
SecurityContext
.
RunAsUser
=
&
uid
pod
.
Spec
.
SecurityContext
.
RunAsUser
=
&
uid
pod
.
Spec
.
Containers
[
0
]
.
Command
=
[]
string
{
"sh"
,
"-c"
,
"id -u"
}
pod
.
Spec
.
Containers
[
0
]
.
Command
=
[]
string
{
"sh"
,
"-c"
,
"id -u"
}
...
@@ -76,7 +80,7 @@ var _ = Describe("[Skipped] Security Context", func() {
...
@@ -76,7 +80,7 @@ var _ = Describe("[Skipped] Security Context", func() {
})
})
It
(
"should support container.SecurityContext.RunAsUser"
,
func
()
{
It
(
"should support container.SecurityContext.RunAsUser"
,
func
()
{
pod
:=
scTestPod
()
pod
:=
scTestPod
(
false
,
false
)
var
uid
int64
=
1001
var
uid
int64
=
1001
var
overrideUid
int64
=
1002
var
overrideUid
int64
=
1002
pod
.
Spec
.
SecurityContext
.
RunAsUser
=
&
uid
pod
.
Spec
.
SecurityContext
.
RunAsUser
=
&
uid
...
@@ -88,4 +92,112 @@ var _ = Describe("[Skipped] Security Context", func() {
...
@@ -88,4 +92,112 @@ var _ = Describe("[Skipped] Security Context", func() {
fmt
.
Sprintf
(
"%v"
,
overrideUid
),
fmt
.
Sprintf
(
"%v"
,
overrideUid
),
})
})
})
})
It
(
"should support volume SELinux relabeling"
,
func
()
{
testPodSELinuxLabeling
(
framework
,
false
,
false
)
})
It
(
"should support volume SELinux relabeling when using hostIPC"
,
func
()
{
testPodSELinuxLabeling
(
framework
,
true
,
false
)
})
It
(
"should support volume SELinux relabeling when using hostPID"
,
func
()
{
testPodSELinuxLabeling
(
framework
,
false
,
true
)
})
})
})
func
testPodSELinuxLabeling
(
framework
*
Framework
,
hostIPC
bool
,
hostPID
bool
)
{
// Write and read a file with an empty_dir volume
// with a pod with the MCS label s0:c0,c1
pod
:=
scTestPod
(
hostIPC
,
hostPID
)
volumeName
:=
"test-volume"
mountPath
:=
"/mounted_volume"
pod
.
Spec
.
Containers
[
0
]
.
VolumeMounts
=
[]
api
.
VolumeMount
{
{
Name
:
volumeName
,
MountPath
:
mountPath
,
},
}
pod
.
Spec
.
Volumes
=
[]
api
.
Volume
{
{
Name
:
volumeName
,
VolumeSource
:
api
.
VolumeSource
{
EmptyDir
:
&
api
.
EmptyDirVolumeSource
{
Medium
:
api
.
StorageMediumDefault
,
},
},
},
}
pod
.
Spec
.
SecurityContext
.
SELinuxOptions
=
&
api
.
SELinuxOptions
{
Level
:
"s0:c0,c1"
,
}
pod
.
Spec
.
Containers
[
0
]
.
Command
=
[]
string
{
"sleep"
,
"6000"
}
client
:=
framework
.
Client
.
Pods
(
framework
.
Namespace
.
Name
)
_
,
err
:=
client
.
Create
(
pod
)
expectNoError
(
err
,
"Error creating pod %v"
,
pod
)
defer
client
.
Delete
(
pod
.
Name
,
nil
)
expectNoError
(
waitForPodRunningInNamespace
(
framework
.
Client
,
pod
.
Name
,
framework
.
Namespace
.
Name
))
testContent
:=
"hello"
testFilePath
:=
mountPath
+
"/TEST"
err
=
framework
.
WriteFileViaContainer
(
pod
.
Name
,
pod
.
Spec
.
Containers
[
0
]
.
Name
,
testFilePath
,
testContent
)
Expect
(
err
)
.
To
(
BeNil
())
content
,
err
:=
framework
.
ReadFileViaContainer
(
pod
.
Name
,
pod
.
Spec
.
Containers
[
0
]
.
Name
,
testFilePath
)
Expect
(
err
)
.
To
(
BeNil
())
Expect
(
content
)
.
To
(
ContainSubstring
(
testContent
))
foundPod
,
err
:=
framework
.
Client
.
Pods
(
framework
.
Namespace
.
Name
)
.
Get
(
pod
.
Name
)
Expect
(
err
)
.
NotTo
(
HaveOccurred
())
// Confirm that the file can be accessed from a second
// pod using host_path with the same MCS label
volumeHostPath
:=
fmt
.
Sprintf
(
"/var/lib/kubelet/pods/%s/volumes/kubernetes.io~empty-dir/%s"
,
foundPod
.
UID
,
volumeName
)
By
(
"confirming a container with the same label can read the file"
)
pod
=
scTestPod
(
hostIPC
,
hostPID
)
pod
.
Spec
.
NodeName
=
foundPod
.
Spec
.
NodeName
volumeMounts
:=
[]
api
.
VolumeMount
{
{
Name
:
volumeName
,
MountPath
:
mountPath
,
},
}
volumes
:=
[]
api
.
Volume
{
{
Name
:
volumeName
,
VolumeSource
:
api
.
VolumeSource
{
HostPath
:
&
api
.
HostPathVolumeSource
{
Path
:
volumeHostPath
,
},
},
},
}
pod
.
Spec
.
Containers
[
0
]
.
VolumeMounts
=
volumeMounts
pod
.
Spec
.
Volumes
=
volumes
pod
.
Spec
.
Containers
[
0
]
.
Command
=
[]
string
{
"cat"
,
testFilePath
}
pod
.
Spec
.
SecurityContext
.
SELinuxOptions
=
&
api
.
SELinuxOptions
{
Level
:
"s0:c0,c1"
,
}
framework
.
TestContainerOutput
(
"Pod with same MCS label reading test file"
,
pod
,
0
,
[]
string
{
testContent
})
// Confirm that the same pod with a different MCS
// label cannot access the volume
pod
=
scTestPod
(
hostIPC
,
hostPID
)
pod
.
Spec
.
Volumes
=
volumes
pod
.
Spec
.
Containers
[
0
]
.
VolumeMounts
=
volumeMounts
pod
.
Spec
.
Containers
[
0
]
.
Command
=
[]
string
{
"sleep"
,
"6000"
}
pod
.
Spec
.
SecurityContext
.
SELinuxOptions
=
&
api
.
SELinuxOptions
{
Level
:
"s0:c2,c3"
,
}
_
,
err
=
client
.
Create
(
pod
)
expectNoError
(
err
,
"Error creating pod %v"
,
pod
)
defer
client
.
Delete
(
pod
.
Name
,
nil
)
err
=
framework
.
WaitForPodRunning
(
pod
.
Name
)
expectNoError
(
err
,
"Error waiting for pod to run %v"
,
pod
)
content
,
err
=
framework
.
ReadFileViaContainer
(
pod
.
Name
,
"test-container"
,
testFilePath
)
Expect
(
content
)
.
NotTo
(
ContainSubstring
(
testContent
))
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment