Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions helper/funcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -568,3 +568,12 @@ func FindExecutableFiles(path string) (map[string]string, error) {
}
return executables, nil
}

// IsSubdirectory returns true if potentialParent is equal to or a parent directory of path.
func IsSubdirectory(potentialParent, path string) bool {
rel, err := filepath.Rel(potentialParent, path)
if err != nil {
return false
}
return !strings.HasPrefix(rel, "..")
}
20 changes: 20 additions & 0 deletions helper/funcs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -528,3 +528,23 @@ func TestFlattenMultiError(t *testing.T) {

`, err.Error())
}

func TestIsSubdirectory(t *testing.T) {
cases := []struct {
potentialParent string
path string
expected bool
}{
{potentialParent: "/dir", path: "/dir/local", expected: true},
{potentialParent: "/dir", path: "/other", expected: false},
{potentialParent: "/dir", path: "/directory", expected: false},
{potentialParent: "/dir", path: "/directory/../dir/local", expected: true},
}

for _, tc := range cases {
t.Run(fmt.Sprintf("parent=%q path=%q", tc.potentialParent, tc.path), func(t *testing.T) {
result := IsSubdirectory(tc.potentialParent, tc.path)
require.Equal(t, tc.expected, result)
})
}
}
2 changes: 1 addition & 1 deletion nomad/structs/structs.go
Original file line number Diff line number Diff line change
Expand Up @@ -8287,7 +8287,7 @@ func (t *Task) Validate(jobType string, tg *TaskGroup) error {
}

if t.CSIPluginConfig.StagePublishBaseDir != "" && t.CSIPluginConfig.MountDir != "" &&
strings.HasPrefix(t.CSIPluginConfig.StagePublishBaseDir, t.CSIPluginConfig.MountDir) {
helper.IsSubdirectory(t.CSIPluginConfig.MountDir, t.CSIPluginConfig.StagePublishBaseDir) {
mErr.Errors = append(mErr.Errors, fmt.Errorf("CSIPluginConfig StagePublishBaseDir must not be a subdirectory of MountDir, got: StagePublishBaseDir=\"%s\" MountDir=\"%s\"", t.CSIPluginConfig.StagePublishBaseDir, t.CSIPluginConfig.MountDir))
}

Expand Down
9 changes: 9 additions & 0 deletions nomad/structs/structs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3262,6 +3262,15 @@ func TestTask_Validate_CSIPluginConfig(t *testing.T) {
},
expectedErr: "CSIPluginConfig StagePublishBaseDir must not be a subdirectory of MountDir, got: StagePublishBaseDir=\"/csi/local\" MountDir=\"/csi\"",
},
{
name: "handles valid staging publish base dir",
pc: &TaskCSIPluginConfig{
ID: "com.hashicorp.csi",
Type: "monolith",
MountDir: "/csi",
StagePublishBaseDir: "/csilocal",
},
},
}

for _, tt := range table {
Expand Down
Loading