diff --git a/src/backend/commons/common-utils/src/main/java/com/tencent/bk/job/common/util/FilePathValidateUtil.java b/src/backend/commons/common-utils/src/main/java/com/tencent/bk/job/common/util/FilePathValidateUtil.java index bea83ad478..e1c0a588f8 100644 --- a/src/backend/commons/common-utils/src/main/java/com/tencent/bk/job/common/util/FilePathValidateUtil.java +++ b/src/backend/commons/common-utils/src/main/java/com/tencent/bk/job/common/util/FilePathValidateUtil.java @@ -1,5 +1,6 @@ package com.tencent.bk.job.common.util; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import java.util.regex.Pattern; @@ -7,17 +8,25 @@ /** * 文件路径合法性校验工具类 */ +@Slf4j public class FilePathValidateUtil { // 传统DOS正则表达式 - private static final String CONVENTIONAL_DOS_PATH_REGEX = "(^[A-Za-z]:\\\\([^\\\\])(([^\\\\/:*?\"<>|])*\\\\?)*)|" + - "(^[A-Za-z]:[\\\\])"; + private static final String CONVENTIONAL_DOS_PATH_REGEX = "(^[A-Za-z]:\\\\([^\\\\])(([^\\\\/:?\"<>|]" + + "|REGEX:(.*))*\\\\?)*)|(^[A-Za-z]:[\\\\])"; + // Linux路径正则表达式 private static final String LINUX_PATH_REGEX = "^/(((../)*|(./)*)|(\\.?[^.].*/{0,1}))+"; + // 内置变量或全局变量正则表达式 + private static final String VARIABLE_REGEX = "(([A-Za-z]:\\\\)|(/)).*\\[[a-zA-Z0-9:/_-]*\\].*" + + "|.*\\$\\{[a-zA-Z_][a-zA-Z0-9_-]*\\}.*"; + // 传统DOS Pattern private static final Pattern CONVENTIONAL_DOS_PATH_PATTERN = Pattern.compile(CONVENTIONAL_DOS_PATH_REGEX); // Linux路径Pattern private static final Pattern LINUX_PATH_PATTERN = Pattern.compile(LINUX_PATH_REGEX); + // 内置变量或全局变量Pattern + private static final Pattern VARIABLE_PATTERN = Pattern.compile(VARIABLE_REGEX); /** * 验证文件系统绝对路径的合法性 @@ -28,11 +37,25 @@ public static boolean validateFileSystemAbsolutePath(String path) { if (StringUtils.isBlank(path)) { return false; } + + // 路径中有合法的内置变量或全局变量通过校验 + if (validateVariable(path)) { + return true; + } + + boolean result; if (isLinuxAbsolutePath(path)) { - return validateLinuxFileSystemAbsolutePath(path); + result = validateLinuxFileSystemAbsolutePath(path); } else { - return validateWindowsFileSystemAbsolutePath(path); + result = validateWindowsFileSystemAbsolutePath(path); + } + if (!result) { + // 路径不合法 + log.warn("The path {} is invalid and the verification fails", path); + // 路径校验失败输出日志,验证阶段不拦截返回true + result = true; } + return result; } /** @@ -50,10 +73,11 @@ private static boolean isLinuxAbsolutePath(String path) { /** * 1 传统DOS路径 - * 标准的DOS路径可由以下三部分组成: - * 1)卷号或驱动器号,后跟卷分隔符(:)。 - * 2)目录名称。目录分隔符用来分隔嵌套目录层次结构中的子目录。 - * 3)文件名。目录分隔符用来分隔文件路径和文件名。 + * 标准的DOS路径可由以下三部分组成: + * 1)卷号或驱动器号,后跟卷分隔符(:)。 + * 2)目录名称。目录分隔符用来分隔嵌套目录层次结构中的子目录。 + * 3)文件名。目录分隔符用来分隔文件路径和文件名。 + * * @param path * @return boolean */ @@ -77,4 +101,19 @@ private static boolean validateLinuxFileSystemAbsolutePath(String path) { } return false; } + + /** + * 验证路径中变量合法性 + * 1 ${全局变量},其中变量只能是英文字符、下划线开头;只允许英文字符、数字、下划线、和- + * 2 [内置变量],根路径开头 + * + * @param path + * @return boolean + */ + private static boolean validateVariable(String path) { + if (VARIABLE_PATTERN.matcher(path).matches()) { + return true; + } + return false; + } } diff --git a/src/backend/commons/common-utils/src/test/java/com/tencent/bk/job/common/util/FilePathValidateUtilTest.java b/src/backend/commons/common-utils/src/test/java/com/tencent/bk/job/common/util/FilePathValidateUtilTest.java index d8dae63f9e..e69732d57f 100644 --- a/src/backend/commons/common-utils/src/test/java/com/tencent/bk/job/common/util/FilePathValidateUtilTest.java +++ b/src/backend/commons/common-utils/src/test/java/com/tencent/bk/job/common/util/FilePathValidateUtilTest.java @@ -1,36 +1,60 @@ package com.tencent.bk.job.common.util; -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; - public class FilePathValidateUtilTest { - @Test - void testFileSystemAbsolutePath(){ - // 传统DOS路径 - assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("C:\\Documents\\abc.txt")).isTrue(); - assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("c:\\Documents\\abc.txt")).isTrue(); - assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("C:\\Documents\\嘉 abc.txt")).isTrue(); - assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath(":\\abc.txt")).isFalse(); - assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("C:")).isFalse(); - assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("C:\\\\")).isFalse(); - assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("C:\\")).isTrue(); - assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("C:\\logs\\..\\access.log")).isTrue(); - assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("C:\\.config\\conf")).isTrue(); - assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("C:\\user\\abc>a")).isFalse(); - - // linux路径 - assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("/data/test_2022-04-12.apk")).isTrue(); - assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("/data/test_2022 04 12.apk")).isTrue(); - assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("/")).isTrue(); - assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("/tmp/")).isTrue(); - assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("/tmp/.conf/abc")).isTrue(); - assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("/tmp/test/../test.log")).isTrue(); - assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("data/test_2022-04-12.apk")).isFalse(); - assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("///")).isTrue(); // 根目录 - assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("/tmp////")).isTrue(); // /tmp/ - assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("/tmp//test/")).isTrue();// /tmp/test/ - assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("///")).isTrue(); - } - + // 验证阶段,路径只判断是否非空,测试用例先注释了 +// @Test +// void testWindowsFilePath(){ +// assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("C:\\Documents\\abc.txt")).isTrue(); +// assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("c:\\Documents\\abc.txt")).isTrue(); +// assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("C:\\Documents\\嘉 abc.txt")).isTrue(); +// assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath(":\\abc.txt")).isFalse(); +// assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("C:")).isFalse(); +// assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("C:\\\\")).isFalse(); +// assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("C:\\")).isTrue(); +// assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("C:\\logs\\..\\access.log")).isTrue(); +// assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("C:\\.config\\conf")).isTrue(); +// assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("C:\\user\\abc>a")).isFalse(); +// assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("C:\\user\\abc:a")).isFalse(); +// assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("C:\\user\\abc|a")).isFalse(); +// assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("C:\\user\\abc?a")).isFalse(); +// assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("C:\\user\\abc