This is an automated email from the ASF dual-hosted git repository.
kxiao pushed a commit to branch branch-2.0
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/branch-2.0 by this push:
new f1e7ae28e04 [Enhancement](jdbc catalog) Add security check on driver
when creating Jdbc Catalog (#31153) (#31225)
f1e7ae28e04 is described below
commit f1e7ae28e04d0fd3ac1601a9b4f8a03d2bce1e5a
Author: zy-kkk <[email protected]>
AuthorDate: Wed Feb 21 20:48:13 2024 +0800
[Enhancement](jdbc catalog) Add security check on driver when creating Jdbc
Catalog (#31153) (#31225)
---
.../main/java/org/apache/doris/common/Config.java | 8 ++++++++
.../org/apache/doris/catalog/JdbcResource.java | 19 +++++++++++++++--
.../doris/datasource/jdbc/JdbcExternalCatalog.java | 24 ++++++++++++++--------
.../org/apache/doris/catalog/JdbcResourceTest.java | 15 ++++++++++++++
4 files changed, 55 insertions(+), 11 deletions(-)
diff --git a/fe/fe-common/src/main/java/org/apache/doris/common/Config.java
b/fe/fe-common/src/main/java/org/apache/doris/common/Config.java
index 7dda751e8f6..ff61b17ff32 100644
--- a/fe/fe-common/src/main/java/org/apache/doris/common/Config.java
+++ b/fe/fe-common/src/main/java/org/apache/doris/common/Config.java
@@ -140,6 +140,14 @@ public class Config extends ConfigBase {
+ "if the specified driver file path is not an absolute
path, Doris will find jars from this path"})
public static String jdbc_drivers_dir = System.getenv("DORIS_HOME") +
"/jdbc_drivers";
+ @ConfField(description = {"JDBC 驱动的安全路径。在创建 JDBC Catalog
时,允许使用的文件或者网络路径,可配置多个,使用分号分隔"
+ + "默认为 * 全部允许,如果设置为空责全部不允许",
+ "The safe path of the JDBC driver. When creating a JDBC Catalog,"
+ + "you can configure multiple files or network paths that
are allowed to be used,"
+ + "separated by semicolons"
+ + "The default is * to allow all, if set to empty, all are
not allowed"})
+ public static String jdbc_driver_secure_path = "*";
+
@ConfField(mutable = true, masterOnly = true, description = {"broker load
时,单个节点上 load 执行计划的默认并行度",
"The default parallelism of the load execution plan on a single
node when the broker load is submitted"})
public static int default_load_parallelism = 1;
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/catalog/JdbcResource.java
b/fe/fe-core/src/main/java/org/apache/doris/catalog/JdbcResource.java
index c5b66e13f48..3291b64cbb0 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/JdbcResource.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/JdbcResource.java
@@ -42,6 +42,7 @@ import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
import java.time.ZoneId;
+import java.util.Arrays;
import java.util.Map;
@@ -275,14 +276,28 @@ public class JdbcResource extends Resource {
}
}
- public static String getFullDriverUrl(String driverUrl) {
+ public static String getFullDriverUrl(String driverUrl) throws
IllegalArgumentException {
try {
URI uri = new URI(driverUrl);
String schema = uri.getScheme();
if (schema == null && !driverUrl.startsWith("/")) {
return "file://" + Config.jdbc_drivers_dir + "/" + driverUrl;
+ } else {
+ if ("*".equals(Config.jdbc_driver_secure_path)) {
+ return driverUrl;
+ } else if (Config.jdbc_driver_secure_path.trim().isEmpty()) {
+ throw new IllegalArgumentException(
+ "jdbc_driver_secure_path is set to empty,
disallowing all driver URLs.");
+ } else {
+ boolean isAllowed =
Arrays.stream(Config.jdbc_driver_secure_path.split(";"))
+ .anyMatch(allowedPath ->
driverUrl.startsWith(allowedPath.trim()));
+ if (!isAllowed) {
+ throw new IllegalArgumentException("Driver URL does
not match any allowed paths: " + driverUrl);
+ } else {
+ return driverUrl;
+ }
+ }
}
- return driverUrl;
} catch (URISyntaxException e) {
LOG.warn("invalid jdbc driver url: " + driverUrl);
return driverUrl;
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/JdbcExternalCatalog.java
b/fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/JdbcExternalCatalog.java
index c8dfb7dfe4d..f74c93056ea 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/JdbcExternalCatalog.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/JdbcExternalCatalog.java
@@ -104,11 +104,6 @@ public class JdbcExternalCatalog extends ExternalCatalog {
jdbcUrl = JdbcResource.handleJdbcUrl(jdbcUrl);
properties.put(JdbcResource.JDBC_URL, jdbcUrl);
}
-
- if (properties.containsKey(JdbcResource.DRIVER_URL) &&
!properties.containsKey(JdbcResource.CHECK_SUM)) {
- properties.put(JdbcResource.CHECK_SUM,
-
JdbcResource.computeObjectChecksum(properties.get(JdbcResource.DRIVER_URL)));
- }
return properties;
}
@@ -231,10 +226,21 @@ public class JdbcExternalCatalog extends ExternalCatalog {
if (isReplay) {
return;
}
- Map<String, String> properties = Maps.newHashMap();
- if (properties.containsKey(JdbcResource.DRIVER_URL) &&
!properties.containsKey(JdbcResource.CHECK_SUM)) {
- properties.put(JdbcResource.CHECK_SUM,
-
JdbcResource.computeObjectChecksum(properties.get(JdbcResource.DRIVER_URL)));
+ Map<String, String> properties = catalogProperty.getProperties();
+ if (properties.containsKey(JdbcResource.DRIVER_URL)) {
+ String computedChecksum =
JdbcResource.computeObjectChecksum(properties.get(JdbcResource.DRIVER_URL));
+ if (properties.containsKey(JdbcResource.CHECK_SUM)) {
+ String providedChecksum =
properties.get(JdbcResource.CHECK_SUM);
+ if (!providedChecksum.equals(computedChecksum)) {
+ throw new DdlException(
+ "The provided checksum (" + providedChecksum
+ + ") does not match the computed checksum
(" + computedChecksum
+ + ") for the driver_url."
+ );
+ }
+ } else {
+ catalogProperty.addProperty(JdbcResource.CHECK_SUM,
computedChecksum);
+ }
}
}
}
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/catalog/JdbcResourceTest.java
b/fe/fe-core/src/test/java/org/apache/doris/catalog/JdbcResourceTest.java
index ee0d1949be2..b88597eca25 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/catalog/JdbcResourceTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/catalog/JdbcResourceTest.java
@@ -20,6 +20,7 @@ package org.apache.doris.catalog;
import org.apache.doris.analysis.AccessTestUtil;
import org.apache.doris.analysis.Analyzer;
import org.apache.doris.analysis.CreateResourceStmt;
+import org.apache.doris.common.Config;
import org.apache.doris.common.DdlException;
import org.apache.doris.common.FeConstants;
import org.apache.doris.common.UserException;
@@ -201,5 +202,19 @@ public class JdbcResourceTest {
// Ensure the result URL still contains ';'
Assert.assertTrue(resultUrl.contains(";"));
}
+
+ @Test
+ public void testJdbcDriverPtah() {
+ String driverPath = "postgresql-42.5.0.jar";
+ Config.jdbc_driver_secure_path = "";
+ String fullPath = JdbcResource.getFullDriverUrl(driverPath);
+ Assert.assertEquals(fullPath, "file://" + Config.jdbc_drivers_dir +
"/" + driverPath);
+ Config.jdbc_driver_secure_path = "file:///jdbc/;http://jdbc";
+ String driverPath2 = "file:///postgresql-42.5.0.jar";
+ Exception exception =
Assert.assertThrows(IllegalArgumentException.class, () -> {
+ JdbcResource.getFullDriverUrl(driverPath2);
+ });
+ Assert.assertEquals("Driver URL does not match any allowed paths:
file:///postgresql-42.5.0.jar", exception.getMessage());
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]