This is an automated email from the ASF dual-hosted git repository.
yiguolei pushed a commit to branch branch-4.1
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/branch-4.1 by this push:
new f320323ee0e branch-4.1: [fix](auth) Mask credentials in authentication
and Stream Load logs (#66917)
f320323ee0e is described below
commit f320323ee0e879c4a22b4a0ca0477f021543abc6
Author: bobhan1 <[email protected]>
AuthorDate: Fri Aug 21 10:16:40 2026 +0800
branch-4.1: [fix](auth) Mask credentials in authentication and Stream Load
logs (#66917)
## What problem does this PR solve?
Backport #66618 to `branch-4.1`.
Authentication credentials could be exposed by HTTP authentication and
Stream Load diagnostic logs. Several FE and BE paths formatted complete
requests containing `passwd`, `token`, `auth_code`, or `auth_code_uuid`;
the deprecated `auth_code` header was also missing from the
sensitive-header filter, and invalid-token errors included the token
value.
## What is changed?
- Log sanitized copies of authentication and Stream Load requests.
- Mask `passwd`, `token`, and `auth_code_uuid`, and omit numeric
`auth_code` from log-only copies.
- Treat the `auth_code` HTTP header as sensitive in FE and BE.
- Remove invalid token values from authentication errors.
- Preserve the `branch-4.1` JUnit4/JMockit test structure while porting
the new FE log assertion.
User impact: authentication failures and Stream Load diagnostics retain
non-sensitive request context without emitting these credential values.
## Validation
- `./run-fe-ut.sh --run
org.apache.doris.common.util.ThriftLogHelperTest,org.apache.doris.service.FrontendServiceImplTest,org.apache.doris.load.StreamLoadHandlerTest`
— 25 tests passed, 0 failures/errors.
- `clang-format --dry-run --Werror
be/src/load/stream_load/stream_load_executor.cpp
be/src/service/http/http_handler_with_auth.cpp
be/src/service/http/http_request.cpp
be/test/service/http/http_auth_test.cpp`
- `git diff --check upstream/branch-4.1...HEAD`
- BE UT was not rerun locally for this backport; upstream #66618
reported its targeted BE tests passing on master.
---
be/src/load/stream_load/stream_load_executor.cpp | 22 ++++++-
be/src/service/http/http_handler_with_auth.cpp | 8 ++-
be/src/service/http/http_request.cpp | 2 +-
be/test/service/http/http_auth_test.cpp | 60 +++++++++++++++++-
.../apache/doris/common/util/ThriftLogHelper.java | 57 +++++++++++++++++
.../org/apache/doris/httpv2/rest/LoadAction.java | 3 +-
.../org/apache/doris/load/StreamLoadHandler.java | 3 +-
.../apache/doris/service/FrontendServiceImpl.java | 25 +++++---
.../doris/common/util/ThriftLogHelperTest.java | 73 ++++++++++++++++++++++
.../doris/service/FrontendServiceImplTest.java | 33 ++++++++++
10 files changed, 268 insertions(+), 18 deletions(-)
diff --git a/be/src/load/stream_load/stream_load_executor.cpp
b/be/src/load/stream_load/stream_load_executor.cpp
index dd23f034e73..c7594917847 100644
--- a/be/src/load/stream_load/stream_load_executor.cpp
+++ b/be/src/load/stream_load/stream_load_executor.cpp
@@ -54,6 +54,25 @@
namespace doris {
using namespace ErrorCode;
+namespace {
+
+constexpr const char* MASKED_CREDENTIAL = "***MASKED***";
+
+TLoadTxnCommitRequest request_for_log(const TLoadTxnCommitRequest& request) {
+ TLoadTxnCommitRequest sanitized_request(request);
+ sanitized_request.__set_passwd(MASKED_CREDENTIAL);
+ if (sanitized_request.__isset.token) {
+ sanitized_request.__set_token(MASKED_CREDENTIAL);
+ }
+ sanitized_request.__isset.auth_code = false;
+ if (sanitized_request.__isset.auth_code_uuid) {
+ sanitized_request.__set_auth_code_uuid(MASKED_CREDENTIAL);
+ }
+ return sanitized_request;
+}
+
+} // namespace
+
#ifdef BE_TEST
TLoadTxnBeginResult k_stream_load_begin_result;
TLoadTxnCommitResult k_stream_load_commit_result;
@@ -307,7 +326,8 @@ void
StreamLoadExecutor::get_commit_request(StreamLoadContext* ctx,
request.__set_thrift_rpc_timeout_ms(config::txn_commit_rpc_timeout_ms);
request.__set_tbls(ctx->table_list);
- VLOG_DEBUG << "commit txn request:" <<
apache::thrift::ThriftDebugString(request);
+ VLOG_DEBUG << "commit txn request:"
+ << apache::thrift::ThriftDebugString(request_for_log(request));
// set attachment if has
TTxnCommitAttachment attachment;
diff --git a/be/src/service/http/http_handler_with_auth.cpp
b/be/src/service/http/http_handler_with_auth.cpp
index 4a30b5640b8..87b0a51fd0a 100644
--- a/be/src/service/http/http_handler_with_auth.cpp
+++ b/be/src/service/http/http_handler_with_auth.cpp
@@ -112,13 +112,15 @@ int HttpHandlerWithAuth::on_header(HttpRequest* req) {
auth_result.status.status_code = TStatusCode::type::OK;
auth_result.status.error_msgs.clear();
} else {
- HttpChannel::send_reply(req, HttpStatus::FORBIDDEN);
- return -1;
+ auth_result.status.status_code = TStatusCode::type::ANALYSIS_ERROR;
+ auth_result.status.error_msgs.clear();
}
#endif
Status status(Status::create(auth_result.status));
if (!status.ok()) {
- LOG(WARNING) << "permission verification failed, request: " <<
auth_request;
+ TCheckAuthRequest request_for_log(auth_request);
+ request_for_log.__set_passwd("***MASKED***");
+ LOG(WARNING) << "permission verification failed, request: " <<
request_for_log;
HttpChannel::send_reply(req, HttpStatus::FORBIDDEN);
return -1;
}
diff --git a/be/src/service/http/http_request.cpp
b/be/src/service/http/http_request.cpp
index 4ae3c7c7f3e..36d5a87a77a 100644
--- a/be/src/service/http/http_request.cpp
+++ b/be/src/service/http/http_request.cpp
@@ -40,7 +40,7 @@ static std::string s_empty = "";
static bool is_sensitive_header(const std::string& header_name) {
return iequal(header_name, HttpHeaders::AUTHORIZATION) ||
iequal(header_name, HttpHeaders::PROXY_AUTHORIZATION) ||
iequal(header_name, "token") ||
- iequal(header_name, HttpHeaders::AUTH_TOKEN);
+ iequal(header_name, HttpHeaders::AUTH_TOKEN) || iequal(header_name,
"auth_code");
}
HttpRequest::HttpRequest(evhttp_request* evhttp_request) :
_ev_req(evhttp_request) {}
diff --git a/be/test/service/http/http_auth_test.cpp
b/be/test/service/http/http_auth_test.cpp
index a738dd7922c..d84de03bd06 100644
--- a/be/test/service/http/http_auth_test.cpp
+++ b/be/test/service/http/http_auth_test.cpp
@@ -15,8 +15,11 @@
// specific language governing permissions and limitations
// under the License.
+#include <glog/logging.h>
#include <gtest/gtest.h>
+#include <string>
+
#include "common/config.h"
#include "service/http/ev_http_server.h"
#include "service/http/http_channel.h"
@@ -40,7 +43,10 @@ public:
private:
bool on_privilege(const HttpRequest& req, TCheckAuthRequest& auth_request)
override {
- return !req.param("table").empty();
+ if (req.param("table").empty()) {
+ return false;
+ }
+ return HttpHandlerWithAuth::on_privilege(req, auth_request);
};
};
@@ -49,6 +55,17 @@ static HttpAuthTestHandler s_auth_handler =
class HttpAuthTest : public testing::Test {};
+class AuthLogSink : public google::LogSink {
+public:
+ void send(google::LogSeverity /*severity*/, const char* /*full_filename*/,
+ const char* /*base_filename*/, int /*line*/, const
google::LogMessageTime& /*time*/,
+ const char* message, std::size_t message_len) override {
+ messages.append(message, message_len);
+ }
+
+ std::string messages;
+};
+
TEST_F(HttpAuthTest, disable_auth) {
EXPECT_FALSE(config::enable_all_http_auth);
@@ -90,6 +107,47 @@ TEST_F(HttpAuthTest, enable_all_http_auth) {
}
}
+TEST_F(HttpAuthTest, failed_auth_does_not_log_password) {
+ Defer restore_auth_config {[]() { config::enable_all_http_auth = false; }};
+ config::enable_all_http_auth = true;
+
+ AuthLogSink log_sink;
+ google::AddLogSink(&log_sink);
+ Defer remove_log_sink {[&log_sink]() { google::RemoveLogSink(&log_sink);
}};
+
+ auto evhttp_req = evhttp_request_new(nullptr, nullptr);
+ HttpRequest req(evhttp_req);
+ req._headers.emplace(HttpHeaders::AUTHORIZATION, "Basic
cm9vdDpwbGFpbl90ZXh0X3NlY3JldA==");
+ req._params.emplace("table", "T");
+
+ EXPECT_EQ(s_auth_handler.on_header(&req), -1);
+ EXPECT_NE(log_sink.messages.find("permission verification failed, request:
TCheckAuthRequest"),
+ std::string::npos);
+ EXPECT_NE(log_sink.messages.find("user=root"), std::string::npos);
+ EXPECT_NE(log_sink.messages.find("passwd=***MASKED***"),
std::string::npos);
+ EXPECT_NE(log_sink.messages.find("priv_hier=GLOBAL"), std::string::npos);
+ EXPECT_EQ(log_sink.messages.find("plain_text_secret"), std::string::npos);
+ EXPECT_EQ(log_sink.messages.find("cm9vdDpwbGFpbl90ZXh0X3NlY3JldA=="),
std::string::npos);
+}
+
+TEST_F(HttpAuthTest, invalid_token_does_not_log_token) {
+ Defer restore_auth_config {[]() { config::enable_all_http_auth = false; }};
+ config::enable_all_http_auth = true;
+
+ AuthLogSink log_sink;
+ google::AddLogSink(&log_sink);
+ Defer remove_log_sink {[&log_sink]() { google::RemoveLogSink(&log_sink);
}};
+
+ auto evhttp_req = evhttp_request_new(nullptr, nullptr);
+ HttpRequest req(evhttp_req);
+ req._headers.emplace(HttpHeaders::AUTH_TOKEN, "plain_text_token");
+
+ EXPECT_EQ(s_auth_handler.on_header(&req), -1);
+ EXPECT_NE(log_sink.messages.find("invalid auth token"), std::string::npos);
+ EXPECT_NE(log_sink.messages.find("value=***MASKED***"), std::string::npos);
+ EXPECT_EQ(log_sink.messages.find("plain_text_token"), std::string::npos);
+}
+
// Test NONE privilege type - when enable_all_http_auth=true, even NONE type
requires auth
TEST_F(HttpAuthTest, privilege_type_none) {
Defer defer {[]() { config::enable_all_http_auth = false; }};
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/common/util/ThriftLogHelper.java
b/fe/fe-core/src/main/java/org/apache/doris/common/util/ThriftLogHelper.java
new file mode 100644
index 00000000000..45faa64c89b
--- /dev/null
+++ b/fe/fe-core/src/main/java/org/apache/doris/common/util/ThriftLogHelper.java
@@ -0,0 +1,57 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.doris.common.util;
+
+import org.apache.thrift.TBase;
+import org.apache.thrift.TFieldIdEnum;
+import org.apache.thrift.meta_data.FieldMetaData;
+
+import java.util.Map;
+
+/** Creates log-only copies of Thrift requests with credential fields masked.
*/
+public final class ThriftLogHelper {
+ private static final String MASKED_CREDENTIAL = "***MASKED***";
+
+ private ThriftLogHelper() {
+ }
+
+ // auth_code is omitted because its numeric field cannot hold the string
mask.
+ public static <T extends TBase<T, F>, F extends TFieldIdEnum> T
requestForLog(T request) {
+ T requestForLog = request.deepCopy();
+ for (Map.Entry<F, FieldMetaData> entry :
fieldMetadata(request).entrySet()) {
+ F field = entry.getKey();
+ if (!requestForLog.isSet(field)) {
+ continue;
+ }
+
+ String fieldName = entry.getValue().fieldName;
+ if ("auth_code".equals(fieldName)) {
+ requestForLog.setFieldValue(field, null);
+ } else if ("passwd".equals(fieldName) || "token".equals(fieldName)
+ || "auth_code_uuid".equals(fieldName)) {
+ requestForLog.setFieldValue(field, MASKED_CREDENTIAL);
+ }
+ }
+ return requestForLog;
+ }
+
+ @SuppressWarnings("unchecked")
+ private static <T extends TBase<T, F>, F extends TFieldIdEnum> Map<F,
FieldMetaData> fieldMetadata(T request) {
+ return (Map<F, FieldMetaData>)
FieldMetaData.getStructMetaDataMap(request.getClass());
+ }
+}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/LoadAction.java
b/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/LoadAction.java
index 336898c0949..b9ec4025d39 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/LoadAction.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/LoadAction.java
@@ -752,7 +752,8 @@ public class LoadAction extends RestBaseController {
|| "Cookie".equalsIgnoreCase(headerName)
|| "Set-Cookie".equalsIgnoreCase(headerName)
|| "token".equalsIgnoreCase(headerName)
- || "Auth-Token".equalsIgnoreCase(headerName);
+ || "Auth-Token".equalsIgnoreCase(headerName)
+ || "auth_code".equalsIgnoreCase(headerName);
}
private Backend selectBackendForGroupCommit(String clusterName,
HttpServletRequest req, long tableId)
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/load/StreamLoadHandler.java
b/fe/fe-core/src/main/java/org/apache/doris/load/StreamLoadHandler.java
index 1d9c7c660f9..99f516f022e 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/load/StreamLoadHandler.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/load/StreamLoadHandler.java
@@ -36,6 +36,7 @@ import org.apache.doris.common.Config;
import org.apache.doris.common.LoadException;
import org.apache.doris.common.MetaNotFoundException;
import org.apache.doris.common.UserException;
+import org.apache.doris.common.util.ThriftLogHelper;
import org.apache.doris.load.routineload.RoutineLoadJob;
import org.apache.doris.nereids.load.NereidsCloudStreamLoadPlanner;
import org.apache.doris.nereids.load.NereidsStreamLoadPlanner;
@@ -119,7 +120,7 @@ public class StreamLoadHandler {
}
if (LOG.isDebugEnabled()) {
- LOG.debug("stream load put request: {}", request);
+ LOG.debug("stream load put request: {}",
ThriftLogHelper.requestForLog(request));
}
// create connect context
ConnectContext ctx = new ConnectContext();
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 19e8376386a..e6470e2074f 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
@@ -85,6 +85,7 @@ import org.apache.doris.common.io.Text;
import org.apache.doris.common.util.DebugPointUtil;
import org.apache.doris.common.util.DebugPointUtil.DebugPoint;
import org.apache.doris.common.util.PropertyAnalyzer;
+import org.apache.doris.common.util.ThriftLogHelper;
import org.apache.doris.common.util.Util;
import org.apache.doris.cooldown.CooldownDelete;
import org.apache.doris.datasource.CatalogIf;
@@ -1339,7 +1340,7 @@ public class FrontendServiceImpl implements
FrontendService.Iface {
public TLoadTxnBeginResult loadTxnBegin(TLoadTxnBeginRequest request)
throws TException {
String clientAddr = getClientAddrAsString();
if (LOG.isDebugEnabled()) {
- LOG.debug("receive txn begin request: {}, backend: {}", request,
clientAddr);
+ LOG.debug("receive txn begin request: {}, backend: {}",
ThriftLogHelper.requestForLog(request), clientAddr);
}
if (request.isSetCertBasedAuth()) {
TCertBasedAuth certAuth = request.getCertBasedAuth();
@@ -1402,7 +1403,7 @@ public class FrontendServiceImpl implements
FrontendService.Iface {
toForwardedCertificateInfo(request.getCertBasedAuth()));
} else {
if (!checkToken(request.getToken())) {
- throw new AuthenticationException("Invalid token: " +
request.getToken());
+ throw new AuthenticationException("Invalid token");
}
}
@@ -1568,7 +1569,8 @@ public class FrontendServiceImpl implements
FrontendService.Iface {
public TLoadTxnCommitResult loadTxnPreCommit(TLoadTxnCommitRequest
request) throws TException {
String clientAddr = getClientAddrAsString();
if (LOG.isDebugEnabled()) {
- LOG.debug("receive txn pre-commit request: {}, backend: {}",
request, clientAddr);
+ LOG.debug("receive txn pre-commit request: {}, backend: {}",
+ ThriftLogHelper.requestForLog(request), clientAddr);
}
TLoadTxnCommitResult result = new TLoadTxnCommitResult();
@@ -1668,7 +1670,7 @@ public class FrontendServiceImpl implements
FrontendService.Iface {
// TODO: deprecated, removed in 3.1, use token instead.
} else if (request.isSetToken()) {
if (!checkToken(request.getToken())) {
- throw new AuthenticationException("Invalid token: " +
request.getToken());
+ throw new AuthenticationException("Invalid token");
}
} else {
if (CollectionUtils.isNotEmpty(request.getTbls())) {
@@ -1711,7 +1713,7 @@ public class FrontendServiceImpl implements
FrontendService.Iface {
public TLoadTxn2PCResult loadTxn2PC(TLoadTxn2PCRequest request) throws
TException {
String clientAddr = getClientAddrAsString();
if (LOG.isDebugEnabled()) {
- LOG.debug("receive txn 2PC request: {}, backend: {}", request,
clientAddr);
+ LOG.debug("receive txn 2PC request: {}, backend: {}",
ThriftLogHelper.requestForLog(request), clientAddr);
}
TLoadTxn2PCResult result = new TLoadTxn2PCResult();
@@ -1803,7 +1805,8 @@ public class FrontendServiceImpl implements
FrontendService.Iface {
deleteMultiTableStreamLoadJobIndex(request.getTxnId());
String clientAddr = getClientAddrAsString();
if (LOG.isDebugEnabled()) {
- LOG.debug("receive txn commit request: {}, backend: {}", request,
clientAddr);
+ LOG.debug("receive txn commit request: {}, backend: {}",
+ ThriftLogHelper.requestForLog(request), clientAddr);
}
TLoadTxnCommitResult result = new TLoadTxnCommitResult();
@@ -2045,7 +2048,8 @@ public class FrontendServiceImpl implements
FrontendService.Iface {
public TLoadTxnRollbackResult loadTxnRollback(TLoadTxnRollbackRequest
request) throws TException {
String clientAddr = getClientAddrAsString();
if (LOG.isDebugEnabled()) {
- LOG.debug("receive txn rollback request: {}, backend: {}",
request, clientAddr);
+ LOG.debug("receive txn rollback request: {}, backend: {}",
+ ThriftLogHelper.requestForLog(request), clientAddr);
}
TLoadTxnRollbackResult result = new TLoadTxnRollbackResult();
TStatus status = checkMaster();
@@ -2286,7 +2290,8 @@ public class FrontendServiceImpl implements
FrontendService.Iface {
public TStreamLoadPutResult streamLoadPut(TStreamLoadPutRequest request) {
String clientAddr = getClientAddrAsString();
if (LOG.isDebugEnabled()) {
- LOG.debug("receive stream load put request: {}, backend: {}",
request, clientAddr);
+ LOG.debug("receive stream load put request: {}, backend: {}",
+ ThriftLogHelper.requestForLog(request), clientAddr);
}
String groupCommitMode = request.getGroupCommitMode();
@@ -2439,7 +2444,7 @@ public class FrontendServiceImpl implements
FrontendService.Iface {
private void httpStreamPutImpl(TStreamLoadPutRequest request,
TStreamLoadPutResult result)
throws UserException {
if (LOG.isDebugEnabled()) {
- LOG.debug("receive http stream put request: {}", request);
+ LOG.debug("receive http stream put request: {}",
ThriftLogHelper.requestForLog(request));
}
ConnectContext ctx = ConnectContext.get();
@@ -2762,7 +2767,7 @@ public class FrontendServiceImpl implements
FrontendService.Iface {
public TCheckAuthResult checkAuth(TCheckAuthRequest request) throws
TException {
String clientAddr = getClientAddrAsString();
if (LOG.isDebugEnabled()) {
- LOG.debug("receive auth request: {}, backend: {}", request,
clientAddr);
+ LOG.debug("receive auth request: {}, backend: {}",
ThriftLogHelper.requestForLog(request), clientAddr);
}
TCheckAuthResult result = new TCheckAuthResult();
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/common/util/ThriftLogHelperTest.java
b/fe/fe-core/src/test/java/org/apache/doris/common/util/ThriftLogHelperTest.java
new file mode 100644
index 00000000000..388fe64cd40
--- /dev/null
+++
b/fe/fe-core/src/test/java/org/apache/doris/common/util/ThriftLogHelperTest.java
@@ -0,0 +1,73 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.doris.common.util;
+
+import org.apache.doris.thrift.TLoadTxnBeginRequest;
+import org.apache.doris.thrift.TStreamLoadPutRequest;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class ThriftLogHelperTest {
+ private static final String MASKED_CREDENTIAL = "***MASKED***";
+
+ @Test
+ public void testRequestForLogMasksCredentialsByFieldName() {
+ TLoadTxnBeginRequest beginRequest = new TLoadTxnBeginRequest()
+ .setUser("user")
+ .setPasswd("password")
+ .setDb("db")
+ .setTbl("table")
+ .setLabel("label")
+ .setToken("token")
+ .setAuthCode(123)
+ .setAuthCodeUuid("auth-code-uuid");
+
+ TLoadTxnBeginRequest beginRequestForLog =
ThriftLogHelper.requestForLog(beginRequest);
+
+ Assertions.assertEquals(MASKED_CREDENTIAL,
beginRequestForLog.getPasswd());
+ Assertions.assertEquals(MASKED_CREDENTIAL,
beginRequestForLog.getToken());
+ Assertions.assertEquals(MASKED_CREDENTIAL,
beginRequestForLog.getAuthCodeUuid());
+ Assertions.assertFalse(beginRequestForLog.isSetAuthCode());
+ Assertions.assertEquals("user", beginRequestForLog.getUser());
+ Assertions.assertEquals("label", beginRequestForLog.getLabel());
+ Assertions.assertEquals("password", beginRequest.getPasswd());
+ Assertions.assertEquals("token", beginRequest.getToken());
+ Assertions.assertEquals(123, beginRequest.getAuthCode());
+ Assertions.assertEquals("auth-code-uuid",
beginRequest.getAuthCodeUuid());
+
+ TStreamLoadPutRequest putRequest = new TStreamLoadPutRequest()
+ .setUser("load-user")
+ .setPasswd("load-password")
+ .setDb("load-db")
+ .setTbl("load-table")
+ .setToken("load-token")
+ .setAuthCode(456);
+
+ TStreamLoadPutRequest putRequestForLog =
ThriftLogHelper.requestForLog(putRequest);
+
+ Assertions.assertEquals(MASKED_CREDENTIAL,
putRequestForLog.getPasswd());
+ Assertions.assertEquals(MASKED_CREDENTIAL,
putRequestForLog.getToken());
+ Assertions.assertFalse(putRequestForLog.isSetAuthCode());
+ Assertions.assertEquals("load-user", putRequestForLog.getUser());
+ Assertions.assertEquals("load-table", putRequestForLog.getTbl());
+ Assertions.assertEquals("load-password", putRequest.getPasswd());
+ Assertions.assertEquals("load-token", putRequest.getToken());
+ Assertions.assertEquals(456, putRequest.getAuthCode());
+ }
+}
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 eef4db1a7a6..e45bed95a47 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
@@ -33,6 +33,7 @@ import org.apache.doris.common.util.PrintableMap;
import org.apache.doris.datasource.InternalCatalog;
import org.apache.doris.datasource.maxcompute.MCTransaction;
import org.apache.doris.datasource.maxcompute.MaxComputeExternalCatalog;
+import org.apache.doris.mysql.authenticate.TestLogAppender;
import org.apache.doris.nereids.parser.NereidsParser;
import org.apache.doris.nereids.trees.plans.commands.Command;
import org.apache.doris.nereids.trees.plans.commands.CreateDatabaseCommand;
@@ -42,6 +43,8 @@ import org.apache.doris.qe.ConnectContext;
import org.apache.doris.qe.StmtExecutor;
import org.apache.doris.tablefunction.BackendsTableValuedFunction;
import org.apache.doris.thrift.TBackendsMetadataParams;
+import org.apache.doris.thrift.TCheckAuthRequest;
+import org.apache.doris.thrift.TCheckAuthResult;
import org.apache.doris.thrift.TCommitTxnRequest;
import org.apache.doris.thrift.TCreatePartitionRequest;
import org.apache.doris.thrift.TCreatePartitionResult;
@@ -61,6 +64,9 @@ import org.apache.doris.thrift.TMaxComputeBlockIdResult;
import org.apache.doris.thrift.TMetadataTableRequestParams;
import org.apache.doris.thrift.TMetadataType;
import org.apache.doris.thrift.TNullableStringLiteral;
+import org.apache.doris.thrift.TPrivilegeCtrl;
+import org.apache.doris.thrift.TPrivilegeHier;
+import org.apache.doris.thrift.TPrivilegeType;
import org.apache.doris.thrift.TRollbackTxnRequest;
import org.apache.doris.thrift.TSchemaTableName;
import org.apache.doris.thrift.TSchemaTableRequestParams;
@@ -74,6 +80,7 @@ import org.apache.doris.utframe.UtFrameUtils;
import com.google.common.collect.Sets;
import mockit.Mocked;
+import org.apache.logging.log4j.Level;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
@@ -154,6 +161,32 @@ public class FrontendServiceImplTest {
field.set(target, value);
}
+ @Test
+ public void testCheckAuthDoesNotLogPassword() throws Exception {
+ FrontendServiceImpl impl = new FrontendServiceImpl(exeEnv);
+ TPrivilegeCtrl privilegeCtrl = new TPrivilegeCtrl();
+ privilegeCtrl.setPrivHier(TPrivilegeHier.GLOBAL);
+ TCheckAuthRequest request = new TCheckAuthRequest();
+ request.setUser("root");
+ request.setPasswd("plain_text_secret");
+ request.setUserIp("127.0.0.1");
+ request.setPrivCtrl(privilegeCtrl);
+ request.setPrivType(TPrivilegeType.LOAD);
+
+ try (TestLogAppender appender =
TestLogAppender.attach(FrontendServiceImpl.class)) {
+ TCheckAuthResult result = impl.checkAuth(request);
+
+ Assert.assertEquals(TStatusCode.ANALYSIS_ERROR,
result.getStatus().getStatusCode());
+ Assert.assertTrue(appender.contains(Level.DEBUG,
+ "receive auth request: TCheckAuthRequest"));
+ Assert.assertTrue(appender.contains(Level.DEBUG, "user:root"));
+ Assert.assertTrue(appender.contains(Level.DEBUG,
"passwd:***MASKED***"));
+ Assert.assertTrue(appender.contains(Level.DEBUG,
"user_ip:127.0.0.1"));
+ Assert.assertTrue(appender.contains(Level.DEBUG,
"priv_hier:GLOBAL"));
+ Assert.assertFalse(appender.contains(Level.DEBUG,
"plain_text_secret"));
+ }
+ }
+
@Test
public void testGetTableNamesWithSysTablePattern() throws Exception {
FrontendServiceImpl impl = new FrontendServiceImpl(exeEnv);
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]