mirror of https://github.com/k3s-io/k3s
Make ConfigMap volume readable as non-root
parent
3307809722
commit
e838ff2893
|
@ -341,6 +341,15 @@ func (w *AtomicWriter) newTimestampDir() (string, error) {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 0755 permissions are needed to allow 'group' and 'other' to recurse the
|
||||||
|
// directory tree. do a chmod here to ensure that permissions are set correctly
|
||||||
|
// regardless of the process' umask.
|
||||||
|
err = os.Chmod(tsDir, 0755)
|
||||||
|
if err != nil {
|
||||||
|
glog.Errorf("%s: unable to set mode on new temp directory: %v", w.logContext, err)
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
return tsDir, nil
|
return tsDir, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -408,7 +417,6 @@ func (w *AtomicWriter) createUserVisibleFiles(payload map[string][]byte) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,147 +32,27 @@ var _ = KubeDescribe("ConfigMap", func() {
|
||||||
f := NewDefaultFramework("configmap")
|
f := NewDefaultFramework("configmap")
|
||||||
|
|
||||||
It("should be consumable from pods in volume [Conformance]", func() {
|
It("should be consumable from pods in volume [Conformance]", func() {
|
||||||
name := "configmap-test-volume-" + string(util.NewUUID())
|
doConfigMapE2EWithoutMappings(f, 0, 0)
|
||||||
volumeName := "configmap-volume"
|
})
|
||||||
volumeMountPath := "/etc/configmap-volume"
|
|
||||||
|
|
||||||
configMap := &api.ConfigMap{
|
It("should be consumable from pods in volume as non-root [Conformance]", func() {
|
||||||
ObjectMeta: api.ObjectMeta{
|
doConfigMapE2EWithoutMappings(f, 1000, 0)
|
||||||
Namespace: f.Namespace.Name,
|
})
|
||||||
Name: name,
|
|
||||||
},
|
|
||||||
Data: map[string]string{
|
|
||||||
"data-1": "value-1",
|
|
||||||
"data-2": "value-2",
|
|
||||||
"data-3": "value-3",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
By(fmt.Sprintf("Creating configMap with name %s", configMap.Name))
|
It("should be consumable from pods in volume as non-root with FSGroup [Feature:FSGroup]", func() {
|
||||||
defer func() {
|
doConfigMapE2EWithoutMappings(f, 1000, 1001)
|
||||||
By("Cleaning up the configMap")
|
|
||||||
if err := f.Client.ConfigMaps(f.Namespace.Name).Delete(configMap.Name); err != nil {
|
|
||||||
Failf("unable to delete configMap %v: %v", configMap.Name, err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
var err error
|
|
||||||
if configMap, err = f.Client.ConfigMaps(f.Namespace.Name).Create(configMap); err != nil {
|
|
||||||
Failf("unable to create test configMap %s: %v", configMap.Name, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
pod := &api.Pod{
|
|
||||||
ObjectMeta: api.ObjectMeta{
|
|
||||||
Name: "pod-configmaps-" + string(util.NewUUID()),
|
|
||||||
},
|
|
||||||
Spec: api.PodSpec{
|
|
||||||
Volumes: []api.Volume{
|
|
||||||
{
|
|
||||||
Name: volumeName,
|
|
||||||
VolumeSource: api.VolumeSource{
|
|
||||||
ConfigMap: &api.ConfigMapVolumeSource{
|
|
||||||
LocalObjectReference: api.LocalObjectReference{
|
|
||||||
Name: name,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Containers: []api.Container{
|
|
||||||
{
|
|
||||||
Name: "configmap-volume-test",
|
|
||||||
Image: "gcr.io/google_containers/mounttest:0.6",
|
|
||||||
Args: []string{"--file_content=/etc/configmap-volume/data-1"},
|
|
||||||
VolumeMounts: []api.VolumeMount{
|
|
||||||
{
|
|
||||||
Name: volumeName,
|
|
||||||
MountPath: volumeMountPath,
|
|
||||||
ReadOnly: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
RestartPolicy: api.RestartPolicyNever,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
testContainerOutput("consume configMaps", f.Client, pod, 0, []string{
|
|
||||||
"content of file \"/etc/configmap-volume/data-1\": value-1",
|
|
||||||
}, f.Namespace.Name)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
It("should be consumable from pods in volume with mappings [Conformance]", func() {
|
It("should be consumable from pods in volume with mappings [Conformance]", func() {
|
||||||
name := "configmap-test-volume-map-" + string(util.NewUUID())
|
doConfigMapE2EWithMappings(f, 0, 0)
|
||||||
volumeName := "configmap-volume"
|
})
|
||||||
volumeMountPath := "/etc/configmap-volume"
|
|
||||||
|
|
||||||
configMap := &api.ConfigMap{
|
It("should be consumable from pods in volume with mappings as non-root [Conformance]", func() {
|
||||||
ObjectMeta: api.ObjectMeta{
|
doConfigMapE2EWithMappings(f, 1000, 0)
|
||||||
Namespace: f.Namespace.Name,
|
})
|
||||||
Name: name,
|
|
||||||
},
|
|
||||||
Data: map[string]string{
|
|
||||||
"data-1": "value-1",
|
|
||||||
"data-2": "value-2",
|
|
||||||
"data-3": "value-3",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
By(fmt.Sprintf("Creating configMap with name %s", configMap.Name))
|
It("should be consumable from pods in volume with mappings as non-root with FSGroup [Feature:FSGroup]", func() {
|
||||||
defer func() {
|
doConfigMapE2EWithMappings(f, 1000, 1001)
|
||||||
By("Cleaning up the configMap")
|
|
||||||
if err := f.Client.ConfigMaps(f.Namespace.Name).Delete(configMap.Name); err != nil {
|
|
||||||
Failf("unable to delete configMap %v: %v", configMap.Name, err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
var err error
|
|
||||||
if configMap, err = f.Client.ConfigMaps(f.Namespace.Name).Create(configMap); err != nil {
|
|
||||||
Failf("unable to create test configMap %s: %v", configMap.Name, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
pod := &api.Pod{
|
|
||||||
ObjectMeta: api.ObjectMeta{
|
|
||||||
Name: "pod-configmaps-" + string(util.NewUUID()),
|
|
||||||
},
|
|
||||||
Spec: api.PodSpec{
|
|
||||||
Volumes: []api.Volume{
|
|
||||||
{
|
|
||||||
Name: volumeName,
|
|
||||||
VolumeSource: api.VolumeSource{
|
|
||||||
ConfigMap: &api.ConfigMapVolumeSource{
|
|
||||||
LocalObjectReference: api.LocalObjectReference{
|
|
||||||
Name: name,
|
|
||||||
},
|
|
||||||
Items: []api.KeyToPath{
|
|
||||||
{
|
|
||||||
Key: "data-2",
|
|
||||||
Path: "path/to/data-2",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Containers: []api.Container{
|
|
||||||
{
|
|
||||||
Name: "configmap-volume-test",
|
|
||||||
Image: "gcr.io/google_containers/mounttest:0.6",
|
|
||||||
Args: []string{"--file_content=/etc/configmap-volume/path/to/data-2"},
|
|
||||||
VolumeMounts: []api.VolumeMount{
|
|
||||||
{
|
|
||||||
Name: volumeName,
|
|
||||||
MountPath: volumeMountPath,
|
|
||||||
ReadOnly: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
RestartPolicy: api.RestartPolicyNever,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
testContainerOutput("consume configMaps", f.Client, pod, 0, []string{
|
|
||||||
"content of file \"/etc/configmap-volume/path/to/data-2\": value-2",
|
|
||||||
}, f.Namespace.Name)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
It("updates should be reflected in volume [Conformance]", func() {
|
It("updates should be reflected in volume [Conformance]", func() {
|
||||||
|
@ -273,18 +153,7 @@ var _ = KubeDescribe("ConfigMap", func() {
|
||||||
|
|
||||||
It("should be consumable via environment variable [Conformance]", func() {
|
It("should be consumable via environment variable [Conformance]", func() {
|
||||||
name := "configmap-test-" + string(util.NewUUID())
|
name := "configmap-test-" + string(util.NewUUID())
|
||||||
configMap := &api.ConfigMap{
|
configMap := newConfigMap(f, name)
|
||||||
ObjectMeta: api.ObjectMeta{
|
|
||||||
Namespace: f.Namespace.Name,
|
|
||||||
Name: name,
|
|
||||||
},
|
|
||||||
Data: map[string]string{
|
|
||||||
"data-1": "value-1",
|
|
||||||
"data-2": "value-2",
|
|
||||||
"data-3": "value-3",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
By(fmt.Sprintf("Creating configMap %v/%v", f.Namespace.Name, configMap.Name))
|
By(fmt.Sprintf("Creating configMap %v/%v", f.Namespace.Name, configMap.Name))
|
||||||
defer func() {
|
defer func() {
|
||||||
By("Cleaning up the configMap")
|
By("Cleaning up the configMap")
|
||||||
|
@ -331,3 +200,162 @@ var _ = KubeDescribe("ConfigMap", func() {
|
||||||
}, f.Namespace.Name)
|
}, f.Namespace.Name)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
func newConfigMap(f *Framework, name string) *api.ConfigMap {
|
||||||
|
return &api.ConfigMap{
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Namespace: f.Namespace.Name,
|
||||||
|
Name: name,
|
||||||
|
},
|
||||||
|
Data: map[string]string{
|
||||||
|
"data-1": "value-1",
|
||||||
|
"data-2": "value-2",
|
||||||
|
"data-3": "value-3",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func doConfigMapE2EWithoutMappings(f *Framework, uid, fsGroup int64) {
|
||||||
|
var (
|
||||||
|
name = "configmap-test-volume-" + string(util.NewUUID())
|
||||||
|
volumeName = "configmap-volume"
|
||||||
|
volumeMountPath = "/etc/configmap-volume"
|
||||||
|
configMap = newConfigMap(f, name)
|
||||||
|
)
|
||||||
|
|
||||||
|
By(fmt.Sprintf("Creating configMap with name %s", configMap.Name))
|
||||||
|
defer func() {
|
||||||
|
By("Cleaning up the configMap")
|
||||||
|
if err := f.Client.ConfigMaps(f.Namespace.Name).Delete(configMap.Name); err != nil {
|
||||||
|
Failf("unable to delete configMap %v: %v", configMap.Name, err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
var err error
|
||||||
|
if configMap, err = f.Client.ConfigMaps(f.Namespace.Name).Create(configMap); err != nil {
|
||||||
|
Failf("unable to create test configMap %s: %v", configMap.Name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
pod := &api.Pod{
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Name: "pod-configmaps-" + string(util.NewUUID()),
|
||||||
|
},
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
SecurityContext: &api.PodSecurityContext{},
|
||||||
|
Volumes: []api.Volume{
|
||||||
|
{
|
||||||
|
Name: volumeName,
|
||||||
|
VolumeSource: api.VolumeSource{
|
||||||
|
ConfigMap: &api.ConfigMapVolumeSource{
|
||||||
|
LocalObjectReference: api.LocalObjectReference{
|
||||||
|
Name: name,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Containers: []api.Container{
|
||||||
|
{
|
||||||
|
Name: "configmap-volume-test",
|
||||||
|
Image: "gcr.io/google_containers/mounttest:0.6",
|
||||||
|
Args: []string{"--file_content=/etc/configmap-volume/data-1"},
|
||||||
|
VolumeMounts: []api.VolumeMount{
|
||||||
|
{
|
||||||
|
Name: volumeName,
|
||||||
|
MountPath: volumeMountPath,
|
||||||
|
ReadOnly: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
RestartPolicy: api.RestartPolicyNever,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if uid != 0 {
|
||||||
|
pod.Spec.SecurityContext.RunAsUser = &uid
|
||||||
|
}
|
||||||
|
|
||||||
|
if fsGroup != 0 {
|
||||||
|
pod.Spec.SecurityContext.FSGroup = &fsGroup
|
||||||
|
}
|
||||||
|
|
||||||
|
testContainerOutput("consume configMaps", f.Client, pod, 0, []string{
|
||||||
|
"content of file \"/etc/configmap-volume/data-1\": value-1",
|
||||||
|
}, f.Namespace.Name)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func doConfigMapE2EWithMappings(f *Framework, uid, fsGroup int64) {
|
||||||
|
var (
|
||||||
|
name = "configmap-test-volume-map-" + string(util.NewUUID())
|
||||||
|
volumeName = "configmap-volume"
|
||||||
|
volumeMountPath = "/etc/configmap-volume"
|
||||||
|
configMap = newConfigMap(f, name)
|
||||||
|
)
|
||||||
|
|
||||||
|
By(fmt.Sprintf("Creating configMap with name %s", configMap.Name))
|
||||||
|
defer func() {
|
||||||
|
By("Cleaning up the configMap")
|
||||||
|
if err := f.Client.ConfigMaps(f.Namespace.Name).Delete(configMap.Name); err != nil {
|
||||||
|
Failf("unable to delete configMap %v: %v", configMap.Name, err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
var err error
|
||||||
|
if configMap, err = f.Client.ConfigMaps(f.Namespace.Name).Create(configMap); err != nil {
|
||||||
|
Failf("unable to create test configMap %s: %v", configMap.Name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
pod := &api.Pod{
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Name: "pod-configmaps-" + string(util.NewUUID()),
|
||||||
|
},
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
SecurityContext: &api.PodSecurityContext{},
|
||||||
|
Volumes: []api.Volume{
|
||||||
|
{
|
||||||
|
Name: volumeName,
|
||||||
|
VolumeSource: api.VolumeSource{
|
||||||
|
ConfigMap: &api.ConfigMapVolumeSource{
|
||||||
|
LocalObjectReference: api.LocalObjectReference{
|
||||||
|
Name: name,
|
||||||
|
},
|
||||||
|
Items: []api.KeyToPath{
|
||||||
|
{
|
||||||
|
Key: "data-2",
|
||||||
|
Path: "path/to/data-2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Containers: []api.Container{
|
||||||
|
{
|
||||||
|
Name: "configmap-volume-test",
|
||||||
|
Image: "gcr.io/google_containers/mounttest:0.6",
|
||||||
|
Args: []string{"--file_content=/etc/configmap-volume/path/to/data-2"},
|
||||||
|
VolumeMounts: []api.VolumeMount{
|
||||||
|
{
|
||||||
|
Name: volumeName,
|
||||||
|
MountPath: volumeMountPath,
|
||||||
|
ReadOnly: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
RestartPolicy: api.RestartPolicyNever,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if uid != 0 {
|
||||||
|
pod.Spec.SecurityContext.RunAsUser = &uid
|
||||||
|
}
|
||||||
|
|
||||||
|
if fsGroup != 0 {
|
||||||
|
pod.Spec.SecurityContext.FSGroup = &fsGroup
|
||||||
|
}
|
||||||
|
|
||||||
|
testContainerOutput("consume configMaps", f.Client, pod, 0, []string{
|
||||||
|
"content of file \"/etc/configmap-volume/path/to/data-2\": value-2",
|
||||||
|
}, f.Namespace.Name)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue