api: validate RecursiveReadOnlyMounts

Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
This commit is contained in:
Akihiro Suda 2024-03-09 09:48:15 +09:00
parent 8828530fd5
commit 8db07446f1
No known key found for this signature in database
GPG Key ID: 49524C6F9F638F1A
2 changed files with 36 additions and 0 deletions

View File

@ -1321,6 +1321,32 @@ func validateMountPropagation(mountPropagation *core.MountPropagationMode, conta
return allErrs
}
// validateMountRecursiveReadOnly validates RecursiveReadOnly mounts.
func validateMountRecursiveReadOnly(mount core.VolumeMount, fldPath *field.Path) field.ErrorList {
if mount.RecursiveReadOnly == nil {
return nil
}
allErrs := field.ErrorList{}
switch *mount.RecursiveReadOnly {
case core.RecursiveReadOnlyDisabled:
// NOP
case core.RecursiveReadOnlyEnabled, core.RecursiveReadOnlyIfPossible:
if !mount.ReadOnly {
allErrs = append(allErrs, field.Forbidden(fldPath, "may only be specified when readOnly is true"))
}
if mount.MountPropagation != nil && *mount.MountPropagation != core.MountPropagationNone {
allErrs = append(allErrs, field.Forbidden(fldPath, "may only be specified when mountPropagation is None or not specified"))
}
default:
supportedRRO := sets.New(
core.RecursiveReadOnlyDisabled,
core.RecursiveReadOnlyIfPossible,
core.RecursiveReadOnlyEnabled)
allErrs = append(allErrs, field.NotSupported(fldPath, *mount.RecursiveReadOnly, sets.List(supportedRRO)))
}
return allErrs
}
// ValidateLocalNonReservedPath makes sure targetPath:
// 1. is not abs path
// 2. does not contain any '..' elements
@ -2909,6 +2935,7 @@ func ValidateVolumeMounts(mounts []core.VolumeMount, voldevices map[string]strin
if mnt.MountPropagation != nil {
allErrs = append(allErrs, validateMountPropagation(mnt.MountPropagation, container, fldPath.Child("mountPropagation"))...)
}
allErrs = append(allErrs, validateMountRecursiveReadOnly(mnt, fldPath.Child("recursiveReadOnly"))...)
}
return allErrs
}

View File

@ -7118,6 +7118,12 @@ func TestValidateVolumeMounts(t *testing.T) {
{Name: "abc-123", MountPath: "/bac", SubPath: ".baz"},
{Name: "abc-123", MountPath: "/bad", SubPath: "..baz"},
{Name: "ephemeral", MountPath: "/foobar"},
{Name: "123", MountPath: "/rro-nil", ReadOnly: true, RecursiveReadOnly: nil},
{Name: "123", MountPath: "/rro-disabled", ReadOnly: true, RecursiveReadOnly: ptr.To(core.RecursiveReadOnlyDisabled)},
{Name: "123", MountPath: "/rro-disabled-2", ReadOnly: false, RecursiveReadOnly: ptr.To(core.RecursiveReadOnlyDisabled)},
{Name: "123", MountPath: "/rro-ifpossible", ReadOnly: true, RecursiveReadOnly: ptr.To(core.RecursiveReadOnlyIfPossible)},
{Name: "123", MountPath: "/rro-enabled", ReadOnly: true, RecursiveReadOnly: ptr.To(core.RecursiveReadOnlyEnabled)},
{Name: "123", MountPath: "/rro-enabled-2", ReadOnly: true, RecursiveReadOnly: ptr.To(core.RecursiveReadOnlyEnabled), MountPropagation: ptr.To(core.MountPropagationNone)},
}
goodVolumeDevices := []core.VolumeDevice{
{Name: "xyz", DevicePath: "/foofoo"},
@ -7140,6 +7146,9 @@ func TestValidateVolumeMounts(t *testing.T) {
"name exists in volumeDevice": {{Name: "xyz", MountPath: "/bar"}},
"mountpath exists in volumeDevice": {{Name: "uvw", MountPath: "/mnt/exists"}},
"both exist in volumeDevice": {{Name: "xyz", MountPath: "/mnt/exists"}},
"rro but not ro": {{Name: "123", MountPath: "/rro-bad1", ReadOnly: false, RecursiveReadOnly: ptr.To(core.RecursiveReadOnlyEnabled)}},
"rro with incompatible propagation": {{Name: "123", MountPath: "/rro-bad2", ReadOnly: true, RecursiveReadOnly: ptr.To(core.RecursiveReadOnlyEnabled), MountPropagation: ptr.To(core.MountPropagationHostToContainer)}},
"rro-if-possible but not ro": {{Name: "123", MountPath: "/rro-bad1", ReadOnly: false, RecursiveReadOnly: ptr.To(core.RecursiveReadOnlyIfPossible)}},
}
badVolumeDevice := []core.VolumeDevice{
{Name: "xyz", DevicePath: "/mnt/exists"},