This is an automated email from the ASF dual-hosted git repository.
bobhan1 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push:
new 7b3d0ea41af [fix](auth) Mask credentials in authentication and Stream
Load logs (#66618)
7b3d0ea41af is described below
commit 7b3d0ea41af890d20a98d2e7781bf5c93b54c8b1
Author: bobhan1 <[email protected]>
AuthorDate: Tue Aug 18 14:54:27 2026 +0800
[fix](auth) Mask credentials in authentication and Stream Load logs (#66618)
### What problem does this PR solve?
Problem Summary: Authentication credentials could be exposed by HTTP
authentication and Stream Load diagnostic logs. In addition to the
original HTTP authentication request logging, several FE and BE Stream
Load paths formatted complete Thrift requests containing `passwd`,
`token`, `auth_code`, or `auth_code_uuid`. The deprecated `auth_code`
HTTP header was also missing from the sensitive-header filter, and two
Stream Load authentication errors included the invalid token value.
This PR logs sanitized copies of authentication-related requests.
Credential values are masked or omitted while non-sensitive request
fields remain available for diagnostics.
### Release note
Mask authentication credentials in HTTP authentication and Stream Load
logs while retaining non-sensitive request context.
### Check List (For Author)
- Test
- [ ] Regression test
- [x] Unit Test
- `./run-be-ut.sh --run --filter=HttpAuthTest.* -j100` (7 tests passed)
- `./run-fe-ut.sh --run
org.apache.doris.common.util.ThriftLogHelperTest,org.apache.doris.service.FrontendServiceImplTest,org.apache.doris.load.StreamLoadHandlerTest`
(24 tests passed)
- `clang-format --dry-run --Werror
be/src/load/stream_load/stream_load_executor.cpp
be/src/service/http/http_request.cpp`
- `git diff --check`
- [ ] Manual test (add detailed scripts or steps below)
- [ ] No need to test or manual test. Explain why:
- [ ] This is a refactor/code format and no logic has been changed.
- [ ] Previous test can cover this change.
- [ ] No code files have been changed.
- [ ] Other reason
- Behavior changed:
- [ ] No.
- [x] Yes. Credential values are no longer emitted by the affected logs
and invalid-token errors; other request fields are unchanged.
- Does this need documentation?
- [x] No.
- [ ] Yes.
### Implementation notes
- FE uses one Thrift-metadata-based helper to deep-copy requests and
sanitize credential fields by field name, so request structs with
different field IDs share the same logic.
- String credentials (`passwd`, `token`, and `auth_code_uuid`) are
replaced with `***MASKED***`; the numeric deprecated `auth_code` is
omitted from log-only copies.
- BE uses a dedicated helper to sanitize the Stream Load commit request
before formatting it.
- FE and BE HTTP request formatters also treat the deprecated
`auth_code` header as sensitive.
- The helper unit test covers two different Thrift request types,
preservation of non-sensitive fields, and immutability of the original
requests.
---
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 7ea6f8147b8..fc636db2eb9 100644
--- a/be/src/load/stream_load/stream_load_executor.cpp
+++ b/be/src/load/stream_load/stream_load_executor.cpp
@@ -58,6 +58,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;
@@ -328,7 +347,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 23be67c654c..d00734b7b74 100644
--- a/be/src/service/http/http_handler_with_auth.cpp
+++ b/be/src/service/http/http_handler_with_auth.cpp
@@ -113,13 +113,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 7c38d5b9e30..e002e5986cb 100644
--- a/be/src/service/http/http_request.cpp
+++ b/be/src/service/http/http_request.cpp
@@ -41,7 +41,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 09815ad068c..065fac754b7 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
@@ -765,7 +765,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 1be1a500397..f2002c011eb 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
@@ -35,6 +35,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;
@@ -118,7 +119,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 aa6e26ca63e..486b27b6a43 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
@@ -86,6 +86,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;
@@ -1411,7 +1412,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();
@@ -1474,7 +1475,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");
}
}
@@ -1640,7 +1641,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();
@@ -1740,7 +1742,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())) {
@@ -1783,7 +1785,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();
@@ -1875,7 +1877,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();
@@ -2117,7 +2120,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();
@@ -3034,7 +3038,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();
@@ -3187,7 +3192,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();
@@ -3512,7 +3517,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 3114b87e7e3..03fde60682b 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
@@ -31,6 +31,7 @@ import org.apache.doris.common.ErrorCode;
import org.apache.doris.common.FeConstants;
import org.apache.doris.common.util.DatasourcePrintableMap;
import org.apache.doris.datasource.InternalCatalog;
+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;
@@ -38,6 +39,8 @@ import
org.apache.doris.nereids.trees.plans.logical.LogicalPlan;
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;
@@ -55,6 +58,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;
@@ -69,6 +75,7 @@ import
org.apache.doris.transaction.WriteBlockAllocatingTransaction;
import org.apache.doris.utframe.TestWithFeService;
import com.google.common.collect.Sets;
+import org.apache.logging.log4j.Level;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
@@ -120,6 +127,32 @@ public class FrontendServiceImplTest extends
TestWithFeService {
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);
+
+ Assertions.assertEquals(TStatusCode.ANALYSIS_ERROR,
result.getStatus().getStatusCode());
+ Assertions.assertTrue(appender.contains(Level.DEBUG,
+ "receive auth request: TCheckAuthRequest"));
+ Assertions.assertTrue(appender.contains(Level.DEBUG, "user:root"));
+ Assertions.assertTrue(appender.contains(Level.DEBUG,
"passwd:***MASKED***"));
+ Assertions.assertTrue(appender.contains(Level.DEBUG,
"user_ip:127.0.0.1"));
+ Assertions.assertTrue(appender.contains(Level.DEBUG,
"priv_hier:GLOBAL"));
+ Assertions.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]