This is an automated email from the ASF dual-hosted git repository.
yiguolei pushed a commit to branch branch-4.2
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/branch-4.2 by this push:
new 309b8a6cbdc branch-4.2: [Fix](auth) Restrict processlist visibility by
user identity #66746 (#70113)
309b8a6cbdc is described below
commit 309b8a6cbdc0514ca2cc654719b9ccf1b79c89d8
Author: morrySnow <[email protected]>
AuthorDate: Wed Nov 4 08:31:20 2026 +0800
branch-4.2: [Fix](auth) Restrict processlist visibility by user identity
#66746 (#70113)
picked from master #66746
Co-authored-by: linrrarity <[email protected]>
---
.../schema_processlist_scanner.cpp | 1 +
.../apache/doris/service/FrontendServiceImpl.java | 10 ++---
.../doris/service/FrontendServiceImplTest.java | 11 +++++
.../suites/show_p0/test_show_processlist.groovy | 48 +++++++++++++++++++++-
4 files changed, 64 insertions(+), 6 deletions(-)
diff --git a/be/src/information_schema/schema_processlist_scanner.cpp
b/be/src/information_schema/schema_processlist_scanner.cpp
index 43f97d5248c..6e06830a58d 100644
--- a/be/src/information_schema/schema_processlist_scanner.cpp
+++ b/be/src/information_schema/schema_processlist_scanner.cpp
@@ -59,6 +59,7 @@ Status SchemaProcessListScanner::start(RuntimeState* state) {
TShowProcessListRequest request;
request.__set_show_full_sql(true);
request.__set_time_zone(state->timezone());
+
request.__set_current_user_ident(*_param->common_param->current_user_ident);
for (const auto& fe_addr : _param->common_param->fe_addr_list) {
TShowProcessListResult tmp_ret;
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/service/FrontendServiceImpl.java
b/fe/fe-core/src/main/java/org/apache/doris/service/FrontendServiceImpl.java
index 30493552832..8834be5cb48 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/service/FrontendServiceImpl.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/service/FrontendServiceImpl.java
@@ -5078,15 +5078,15 @@ public class FrontendServiceImpl implements
FrontendService.Iface {
}
@Override
- public TShowProcessListResult showProcessList(TShowProcessListRequest
request) {
+ public TShowProcessListResult showProcessList(TShowProcessListRequest
request) throws TException {
+ if (!request.isSetCurrentUserIdent()) {
+ throw new TException("Current user identity is not set");
+ }
boolean isShowFullSql = false;
if (request.isSetShowFullSql()) {
isShowFullSql = request.isShowFullSql();
}
- UserIdentity userIdentity = UserIdentity.ROOT;
- if (request.isSetCurrentUserIdent()) {
- userIdentity =
UserIdentity.fromThrift(request.getCurrentUserIdent());
- }
+ UserIdentity userIdentity =
UserIdentity.fromThrift(request.getCurrentUserIdent());
String timeZone =
VariableMgr.getDefaultSessionVariable().getTimeZone();
if (request.isSetTimeZone()) {
timeZone = request.getTimeZone();
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/service/FrontendServiceImplTest.java
b/fe/fe-core/src/test/java/org/apache/doris/service/FrontendServiceImplTest.java
index b97c34058f6..1bcb6c0b815 100644
---
a/fe/fe-core/src/test/java/org/apache/doris/service/FrontendServiceImplTest.java
+++
b/fe/fe-core/src/test/java/org/apache/doris/service/FrontendServiceImplTest.java
@@ -70,6 +70,7 @@ import org.apache.doris.thrift.TPrivilegeType;
import org.apache.doris.thrift.TRollbackTxnRequest;
import org.apache.doris.thrift.TSchemaTableName;
import org.apache.doris.thrift.TSchemaTableRequestParams;
+import org.apache.doris.thrift.TShowProcessListRequest;
import org.apache.doris.thrift.TShowUserRequest;
import org.apache.doris.thrift.TShowUserResult;
import org.apache.doris.thrift.TStatusCode;
@@ -84,6 +85,7 @@ import org.apache.doris.utframe.UtFrameUtils;
import com.google.common.collect.Sets;
import mockit.Mocked;
import org.apache.logging.log4j.Level;
+import org.apache.thrift.TException;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
@@ -190,6 +192,15 @@ public class FrontendServiceImplTest {
}
}
+ @Test
+ public void testShowProcessListRejectsMissingUserIdentity() {
+ FrontendServiceImpl impl = new FrontendServiceImpl(exeEnv);
+ TShowProcessListRequest request = new TShowProcessListRequest();
+
+ TException exception = Assert.assertThrows(TException.class, () ->
impl.showProcessList(request));
+ Assert.assertEquals("Current user identity is not set",
exception.getMessage());
+ }
+
@Test
public void testGetTableNamesWithSysTablePattern() throws Exception {
FrontendServiceImpl impl = new FrontendServiceImpl(exeEnv);
diff --git a/regression-test/suites/show_p0/test_show_processlist.groovy
b/regression-test/suites/show_p0/test_show_processlist.groovy
index fbadaafa703..abba471b35e 100644
--- a/regression-test/suites/show_p0/test_show_processlist.groovy
+++ b/regression-test/suites/show_p0/test_show_processlist.groovy
@@ -18,6 +18,20 @@
import org.apache.doris.regression.util.Http
suite("test_show_processlist") {
+ def victimUser = "test_processlist_victim"
+ def attackerUser = "test_processlist_attacker"
+ def userPassword = "C123_567p"
+ try_sql "DROP USER '${victimUser}'"
+ try_sql "DROP USER '${attackerUser}'"
+ sql "CREATE USER '${victimUser}' IDENTIFIED BY '${userPassword}'"
+ sql "CREATE USER '${attackerUser}' IDENTIFIED BY '${userPassword}'"
+ sql "GRANT SELECT_PRIV ON regression_test.* TO '${victimUser}'"
+ sql "GRANT SELECT_PRIV ON regression_test.* TO '${attackerUser}'"
+ if (isCloudMode()) {
+ sql "GRANT USAGE_PRIV ON COMPUTE GROUP '%' TO '${victimUser}'"
+ sql "GRANT USAGE_PRIV ON COMPUTE GROUP '%' TO '${attackerUser}'"
+ }
+
sql """set fetch_all_fe_for_system_table = false;"""
def result = sql """show processlist;"""
logger.info("result:${result}")
@@ -42,7 +56,39 @@ suite("test_show_processlist") {
logger.info("result:${result}")
assertTrue(result[0].size() == 15)
-
+ connect(victimUser, userPassword, context.config.jdbcUrl) {
+ sql "select 1"
+ connect(attackerUser, userPassword, context.config.jdbcUrl) {
+ def attackerRows = sql """
+ SELECT User, Info
+ FROM information_schema.processlist
+ WHERE User IN ('${victimUser}', '${attackerUser}')
+ ORDER BY User
+ """
+ assertFalse(attackerRows.isEmpty())
+ assertTrue(attackerRows.every { row -> row[0] == attackerUser })
+ assertFalse(attackerRows.any { row -> row[0] == victimUser })
+ assertTrue(attackerRows.any { row ->
+ row[1] != null &&
row[1].toString().contains("information_schema.processlist")
+ })
+
+ def showRows = sql "SHOW FULL PROCESSLIST"
+ assertFalse(showRows.isEmpty())
+ assertTrue(showRows.every { row -> row[2] == attackerUser })
+
+ connect('root', context.config.getRootPassword(),
context.config.jdbcUrl) {
+ def adminRows = sql """
+ SELECT User
+ FROM information_schema.processlist
+ WHERE User IN ('${victimUser}', '${attackerUser}')
+ ORDER BY User
+ """
+ assertTrue(adminRows.any { row -> row[0] == victimUser })
+ assertTrue(adminRows.any { row -> row[0] == attackerUser })
+ }
+ }
+ }
+
def result1 = connect('root', context.config.getRootPassword(),
context.config.jdbcUrl) {
// execute sql with admin user
sql 'select 99 + 1'
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]