Skip to content

Commit 30e585e

Browse files
committed
fix
Signed-off-by: gengjun-git <gengjun@starrocks.com>
1 parent ba2c86a commit 30e585e

File tree

7 files changed

+126
-19
lines changed

7 files changed

+126
-19
lines changed

fe/fe-core/src/main/java/com/starrocks/common/util/SqlCredentialRedactor.java

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,25 @@ public class SqlCredentialRedactor {
119119
Pattern.DOTALL | Pattern.MULTILINE
120120
);
121121

122+
private static final Pattern IDENTIFIED_BY_PATTERN = Pattern.compile(
123+
"(IDENTIFIED\\s+BY\\s+(?:PASSWORD\\s+)?)" +
124+
"(?:'((?:[^'\\\\]|\\\\.)*)'|\"((?:[^\"\\\\]|\\\\.)*)\")",
125+
Pattern.CASE_INSENSITIVE | Pattern.DOTALL | Pattern.MULTILINE
126+
);
127+
128+
private static final Pattern IDENTIFIED_WITH_PATTERN = Pattern.compile(
129+
"(IDENTIFIED\\s+WITH\\s+[^\\s]+\\s+(?:BY|AS)\\s+)" +
130+
"(?:'((?:[^'\\\\]|\\\\.)*)'|\"((?:[^\"\\\\]|\\\\.)*)\")",
131+
Pattern.CASE_INSENSITIVE | Pattern.DOTALL | Pattern.MULTILINE
132+
);
133+
134+
private static final Pattern SET_PASSWORD_PATTERN = Pattern.compile(
135+
"(SET\\s+PASSWORD(?:\\s+FOR\\s+.+?)?\\s*=\\s*PASSWORD\\s*\\()" +
136+
"(?:'((?:[^'\\\\]|\\\\.)*)'|\"((?:[^\"\\\\]|\\\\.)*)\")" +
137+
"(\\s*\\))",
138+
Pattern.CASE_INSENSITIVE | Pattern.DOTALL | Pattern.MULTILINE
139+
);
140+
122141
private static final String REDACTED_VALUE = "***";
123142

124143
/**
@@ -132,6 +151,14 @@ public static String redact(String sql) {
132151
return sql;
133152
}
134153

154+
sql = redactKeyValueCredentials(sql);
155+
sql = redactSqlCredentialClause(sql, IDENTIFIED_BY_PATTERN, 1, 2, 3, 0);
156+
sql = redactSqlCredentialClause(sql, IDENTIFIED_WITH_PATTERN, 1, 2, 3, 0);
157+
sql = redactSqlCredentialClause(sql, SET_PASSWORD_PATTERN, 1, 2, 3, 4);
158+
return sql;
159+
}
160+
161+
private static String redactKeyValueCredentials(String sql) {
135162
Matcher matcher = KEY_VALUE_PATTERN.matcher(sql);
136163
StringBuilder result = new StringBuilder(sql.length() + 100);
137164

@@ -168,4 +195,31 @@ public static String redact(String sql) {
168195
result.append(sql, lastEnd, sql.length());
169196
return result.toString();
170197
}
198+
199+
private static String redactSqlCredentialClause(String sql, Pattern pattern, int prefixGroup,
200+
int singleQuotedGroup, int doubleQuotedGroup, int suffixGroup) {
201+
Matcher matcher = pattern.matcher(sql);
202+
StringBuilder result = new StringBuilder(sql.length() + 32);
203+
int lastEnd = 0;
204+
while (matcher.find()) {
205+
result.append(sql, lastEnd, matcher.start());
206+
207+
result.append(matcher.group(prefixGroup));
208+
if (matcher.group(singleQuotedGroup) != null) {
209+
result.append('\'').append(REDACTED_VALUE).append('\'');
210+
} else if (matcher.group(doubleQuotedGroup) != null) {
211+
result.append('"').append(REDACTED_VALUE).append('"');
212+
} else {
213+
result.append(REDACTED_VALUE);
214+
}
215+
216+
if (suffixGroup > 0) {
217+
result.append(matcher.group(suffixGroup));
218+
}
219+
lastEnd = matcher.end();
220+
}
221+
222+
result.append(sql, lastEnd, sql.length());
223+
return result.toString();
224+
}
171225
}

fe/fe-core/src/main/java/com/starrocks/qe/ConnectProcessor.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -321,15 +321,15 @@ private String formatStmt(String origStmt, StatementBase parsedStmt) {
321321
return "this is a desensitized invalid sql";
322322
}
323323
return SqlCredentialRedactor.redact(origStmt);
324-
} else if (AuditEncryptionChecker.needEncrypt(parsedStmt)) {
325-
return SqlCredentialRedactor.redact(origStmt);
326-
} else if (Config.enable_sql_desensitize_in_log) {
324+
} else if (needEncrypt || Config.enable_sql_desensitize_in_log) {
327325
// Some information like username, password in the stmt should not be printed.
328326
return AstToSQLBuilder.toSQL(parsedStmt, FormatOptions.allEnable()
329327
.setColumnSimplifyTableName(false)
330328
.setHideCredential(needEncrypt)
331329
.setEnableDigest(Config.enable_sql_desensitize_in_log))
332-
.orElse("this is a desensitized sql");
330+
.orElseGet(() -> needEncrypt
331+
? SqlCredentialRedactor.redact(LogUtil.removeLineSeparator(origStmt))
332+
: "this is a desensitized sql");
333333
} else {
334334
// Always redact credentials as defense in depth - raw SQL may contain
335335
// credentials that AuditEncryptionChecker does not yet recognize

fe/fe-core/src/main/java/com/starrocks/sql/formatter/AST2StringVisitor.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,8 @@
147147
import static java.util.stream.Collectors.toList;
148148

149149
public class AST2StringVisitor implements AstVisitorExtendInterface<String, Void> {
150+
private static final String MASKED_AUTH_TEXT = "*XXX";
151+
150152
// use options:
151153
// addFunctionDbName;
152154
// withBackquote;
@@ -191,22 +193,25 @@ public StringBuilder buildAuthOptionSql(UserAuthOption authOption) {
191193
return sb;
192194
}
193195

196+
String authString = authOption.getAuthString();
197+
String printedAuthString = options.isHideCredential() ? MASKED_AUTH_TEXT : authString;
198+
194199
if (!Strings.isNullOrEmpty(authOption.getAuthPlugin())) {
195200
sb.append(" IDENTIFIED WITH ").append(authOption.getAuthPlugin());
196-
if (!Strings.isNullOrEmpty(authOption.getAuthString())) {
201+
if (!Strings.isNullOrEmpty(authString)) {
197202
if (authOption.isPasswordPlain()) {
198203
sb.append(" BY '");
199204
} else {
200205
sb.append(" AS '");
201206
}
202-
sb.append(authOption.getAuthString()).append("'");
207+
sb.append(printedAuthString).append("'");
203208
}
204209
} else {
205-
if (!Strings.isNullOrEmpty(authOption.getAuthString())) {
210+
if (!Strings.isNullOrEmpty(authString)) {
206211
if (authOption.isPasswordPlain()) {
207-
sb.append(" IDENTIFIED BY '").append("*XXX").append("'");
212+
sb.append(" IDENTIFIED BY '").append(printedAuthString).append("'");
208213
} else {
209-
sb.append(" IDENTIFIED BY PASSWORD '").append(authOption.getAuthString()).append("'");
214+
sb.append(" IDENTIFIED BY PASSWORD '").append(printedAuthString).append("'");
210215
}
211216
}
212217
}

fe/fe-core/src/test/java/com/starrocks/analysis/AlterUserStmtTest.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ public void testToString() throws Exception {
6767
sql = "ALTER USER 'user' IDENTIFIED BY PASSWORD '*59c70da2f3e3a5bdf46b68f5c8b8f25762bccef0'";
6868
stmt = (AlterUserStmt) UtFrameUtils.parseStmtWithNewParser(sql, ConnectContext.get());
6969
Assertions.assertEquals("user", stmt.getUser().getUser());
70-
Assertions.assertEquals("ALTER USER 'user'@'%' IDENTIFIED BY PASSWORD '*59c70da2f3e3a5bdf46b68f5c8b8f25762bccef0'",
70+
Assertions.assertEquals("ALTER USER 'user'@'%' IDENTIFIED BY PASSWORD '*XXX'",
7171
AstToSQLBuilder.toSQL(stmt));
7272
Assertions.assertEquals(new String(new UserAuthenticationInfo(stmt.getUser(), stmt.getAuthOption()).getPassword(),
7373
StandardCharsets.UTF_8),
@@ -83,7 +83,7 @@ public void testToString() throws Exception {
8383

8484
sql = "ALTER USER 'user' IDENTIFIED WITH MYSQL_NATIVE_PASSWORD BY 'passwd'";
8585
stmt = (AlterUserStmt) UtFrameUtils.parseStmtWithNewParser(sql, ConnectContext.get());
86-
Assertions.assertEquals("ALTER USER 'user'@'%' IDENTIFIED WITH MYSQL_NATIVE_PASSWORD BY 'passwd'",
86+
Assertions.assertEquals("ALTER USER 'user'@'%' IDENTIFIED WITH MYSQL_NATIVE_PASSWORD BY '*XXX'",
8787
AstToSQLBuilder.toSQL(stmt));
8888
Assertions.assertEquals(new String(new UserAuthenticationInfo(stmt.getUser(), stmt.getAuthOption()).getPassword(),
8989
StandardCharsets.UTF_8),
@@ -93,7 +93,7 @@ public void testToString() throws Exception {
9393
sql = "ALTER USER 'user' IDENTIFIED WITH MYSQL_NATIVE_PASSWORD AS '*59C70DA2F3E3A5BDF46B68F5C8B8F25762BCCEF0'";
9494
stmt = (AlterUserStmt) UtFrameUtils.parseStmtWithNewParser(sql, ConnectContext.get());
9595
Assertions.assertEquals(
96-
"ALTER USER 'user'@'%' IDENTIFIED WITH MYSQL_NATIVE_PASSWORD AS '*59C70DA2F3E3A5BDF46B68F5C8B8F25762BCCEF0'",
96+
"ALTER USER 'user'@'%' IDENTIFIED WITH MYSQL_NATIVE_PASSWORD AS '*XXX'",
9797
AstToSQLBuilder.toSQL(stmt));
9898
Assertions.assertEquals(new String(new UserAuthenticationInfo(stmt.getUser(), stmt.getAuthOption()).getPassword(),
9999
StandardCharsets.UTF_8),
@@ -111,7 +111,7 @@ public void testToString() throws Exception {
111111
sql = "ALTER USER 'user' IDENTIFIED WITH AUTHENTICATION_LDAP_SIMPLE AS 'uid=gengjun,ou=people,dc=example,dc=io'";
112112
stmt = (AlterUserStmt) UtFrameUtils.parseStmtWithNewParser(sql, ConnectContext.get());
113113
Assertions.assertEquals(
114-
"ALTER USER 'user'@'%' IDENTIFIED WITH AUTHENTICATION_LDAP_SIMPLE AS 'uid=gengjun,ou=people,dc=example,dc=io'",
114+
"ALTER USER 'user'@'%' IDENTIFIED WITH AUTHENTICATION_LDAP_SIMPLE AS '*XXX'",
115115
AstToSQLBuilder.toSQL(stmt));
116116
Assertions.assertEquals(new String(new UserAuthenticationInfo(stmt.getUser(), stmt.getAuthOption()).getPassword(),
117117
StandardCharsets.UTF_8), "");
@@ -122,7 +122,7 @@ public void testToString() throws Exception {
122122
sql = "ALTER USER 'user' IDENTIFIED WITH AUTHENTICATION_LDAP_SIMPLE BY 'uid=gengjun,ou=people,dc=example,dc=io'";
123123
stmt = (AlterUserStmt) UtFrameUtils.parseStmtWithNewParser(sql, ConnectContext.get());
124124
Assertions.assertEquals(
125-
"ALTER USER 'user'@'%' IDENTIFIED WITH AUTHENTICATION_LDAP_SIMPLE BY 'uid=gengjun,ou=people,dc=example,dc=io'",
125+
"ALTER USER 'user'@'%' IDENTIFIED WITH AUTHENTICATION_LDAP_SIMPLE BY '*XXX'",
126126
AstToSQLBuilder.toSQL(stmt));
127127
Assertions.assertEquals(new String(new UserAuthenticationInfo(stmt.getUser(), stmt.getAuthOption()).getPassword(),
128128
StandardCharsets.UTF_8), "");

fe/fe-core/src/test/java/com/starrocks/analysis/CreateUserStmtTest.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ public void testToString() throws Exception {
7777
stmt = (CreateUserStmt) UtFrameUtils.parseStmtWithNewParser(sql, ConnectContext.get());
7878
Assertions.assertEquals("user", stmt.getUser().getUser());
7979
Assertions.assertEquals(
80-
"CREATE USER 'user'@'%' IDENTIFIED BY PASSWORD '*59c70da2f3e3a5bdf46b68f5c8b8f25762bccef0'",
80+
"CREATE USER 'user'@'%' IDENTIFIED BY PASSWORD '*XXX'",
8181
AstToSQLBuilder.toSQL(stmt));
8282
Assertions.assertEquals(new String(new UserAuthenticationInfo(stmt.getUser(), stmt.getAuthOption()).getPassword(),
8383
StandardCharsets.UTF_8), "*59C70DA2F3E3A5BDF46B68F5C8B8F25762BCCEF0");
@@ -92,7 +92,7 @@ public void testToString() throws Exception {
9292

9393
sql = "CREATE USER 'user' IDENTIFIED WITH MYSQL_NATIVE_PASSWORD BY 'passwd'";
9494
stmt = (CreateUserStmt) UtFrameUtils.parseStmtWithNewParser(sql, ConnectContext.get());
95-
Assertions.assertEquals("CREATE USER 'user'@'%' IDENTIFIED WITH MYSQL_NATIVE_PASSWORD BY 'passwd'",
95+
Assertions.assertEquals("CREATE USER 'user'@'%' IDENTIFIED WITH MYSQL_NATIVE_PASSWORD BY '*XXX'",
9696
AstToSQLBuilder.toSQL(stmt));
9797
Assertions.assertEquals(new String(new UserAuthenticationInfo(stmt.getUser(), stmt.getAuthOption()).getPassword(),
9898
StandardCharsets.UTF_8), "*59C70DA2F3E3A5BDF46B68F5C8B8F25762BCCEF0");
@@ -101,7 +101,7 @@ public void testToString() throws Exception {
101101
sql = "CREATE USER 'user' IDENTIFIED WITH MYSQL_NATIVE_PASSWORD AS '*59C70DA2F3E3A5BDF46B68F5C8B8F25762BCCEF0'";
102102
stmt = (CreateUserStmt) UtFrameUtils.parseStmtWithNewParser(sql, ConnectContext.get());
103103
Assertions.assertEquals(
104-
"CREATE USER 'user'@'%' IDENTIFIED WITH MYSQL_NATIVE_PASSWORD AS '*59C70DA2F3E3A5BDF46B68F5C8B8F25762BCCEF0'",
104+
"CREATE USER 'user'@'%' IDENTIFIED WITH MYSQL_NATIVE_PASSWORD AS '*XXX'",
105105
AstToSQLBuilder.toSQL(stmt));
106106
Assertions.assertEquals(new String(new UserAuthenticationInfo(stmt.getUser(), stmt.getAuthOption()).getPassword(),
107107
StandardCharsets.UTF_8), "*59C70DA2F3E3A5BDF46B68F5C8B8F25762BCCEF0");
@@ -118,7 +118,7 @@ public void testToString() throws Exception {
118118
sql = "CREATE USER 'user' IDENTIFIED WITH AUTHENTICATION_LDAP_SIMPLE AS 'uid=gengjun,ou=people,dc=example,dc=io'";
119119
stmt = (CreateUserStmt) UtFrameUtils.parseStmtWithNewParser(sql, ConnectContext.get());
120120
Assertions.assertEquals(
121-
"CREATE USER 'user'@'%' IDENTIFIED WITH AUTHENTICATION_LDAP_SIMPLE AS 'uid=gengjun,ou=people,dc=example,dc=io'",
121+
"CREATE USER 'user'@'%' IDENTIFIED WITH AUTHENTICATION_LDAP_SIMPLE AS '*XXX'",
122122
AstToSQLBuilder.toSQL(stmt));
123123
Assertions.assertEquals(new String(new UserAuthenticationInfo(stmt.getUser(), stmt.getAuthOption()).getPassword(),
124124
StandardCharsets.UTF_8), "");
@@ -129,7 +129,7 @@ public void testToString() throws Exception {
129129
sql = "CREATE USER 'user' IDENTIFIED WITH AUTHENTICATION_LDAP_SIMPLE BY 'uid=gengjun,ou=people,dc=example,dc=io'";
130130
stmt = (CreateUserStmt) UtFrameUtils.parseStmtWithNewParser(sql, ConnectContext.get());
131131
Assertions.assertEquals(
132-
"CREATE USER 'user'@'%' IDENTIFIED WITH AUTHENTICATION_LDAP_SIMPLE BY 'uid=gengjun,ou=people,dc=example,dc=io'",
132+
"CREATE USER 'user'@'%' IDENTIFIED WITH AUTHENTICATION_LDAP_SIMPLE BY '*XXX'",
133133
AstToSQLBuilder.toSQL(stmt));
134134
Assertions.assertEquals(new String(new UserAuthenticationInfo(stmt.getUser(), stmt.getAuthOption()).getPassword(),
135135
StandardCharsets.UTF_8), "");

fe/fe-core/src/test/java/com/starrocks/common/util/SqlCredentialRedactorTest.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,29 @@ public void testMultipleCredentials() {
260260
Assertions.assertEquals(2, count, "Should have exactly 2 redacted values");
261261
}
262262

263+
@Test
264+
public void testRedactCreateUserCredentialClauses() {
265+
String plainSql = "CREATE USER 'u1' IDENTIFIED BY 'secret'";
266+
String plainRedacted = SqlCredentialRedactor.redact(plainSql);
267+
Assertions.assertEquals("CREATE USER 'u1' IDENTIFIED BY '***'", plainRedacted);
268+
269+
String hashedSql = "CREATE USER 'u1' IDENTIFIED BY PASSWORD '*59C70DA2'";
270+
String hashedRedacted = SqlCredentialRedactor.redact(hashedSql);
271+
Assertions.assertEquals("CREATE USER 'u1' IDENTIFIED BY PASSWORD '***'", hashedRedacted);
272+
273+
String pluginSql = "CREATE USER 'u1' IDENTIFIED WITH AUTHENTICATION_LDAP_SIMPLE AS 'uid=test,dc=example,dc=io'";
274+
String pluginRedacted = SqlCredentialRedactor.redact(pluginSql);
275+
Assertions.assertEquals("CREATE USER 'u1' IDENTIFIED WITH AUTHENTICATION_LDAP_SIMPLE AS '***'",
276+
pluginRedacted);
277+
}
278+
279+
@Test
280+
public void testRedactSetPasswordClause() {
281+
String sql = "SET PASSWORD FOR 'test'@'%' = PASSWORD('secret')";
282+
String redacted = SqlCredentialRedactor.redact(sql);
283+
Assertions.assertEquals("SET PASSWORD FOR 'test'@'%' = PASSWORD('***')", redacted);
284+
}
285+
263286
/**
264287
* java.regex uses NFA algorithm, it cannot guarantee O(N) complexity, might run into timeout
265288
* when the string is very long.

fe/fe-core/src/test/java/com/starrocks/qe/QueryDetailTest.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,31 @@ public void testInternalQuerySource() throws Exception {
149149
Assertions.assertEquals("INTERNAL", event.querySource);
150150
}
151151

152+
@Test
153+
public void testSensitiveAuditStmtUsesAstDesensitization() throws Exception {
154+
String sql = "CREATE USER 'audit_user' IDENTIFIED WITH AUTHENTICATION_LDAP_SIMPLE "
155+
+ "AS 'uid=gengjun,ou=people,dc=example,dc=io'";
156+
StatementBase statement = SqlParser.parse(sql, connectContext.getSessionVariable()).get(0);
157+
158+
ConnectContext testContext = new ConnectContext();
159+
testContext.setGlobalStateMgr(connectContext.getGlobalStateMgr());
160+
testContext.setCurrentUserIdentity(connectContext.getCurrentUserIdentity());
161+
testContext.setQualifiedUser(connectContext.getQualifiedUser());
162+
testContext.setDatabase("test_db");
163+
testContext.setCurrentCatalog("default_catalog");
164+
testContext.setQueryId(UUIDUtil.genUUID());
165+
testContext.setStartTime();
166+
167+
ConnectProcessor processor = new ConnectProcessor(testContext);
168+
processor.auditAfterExec(sql, statement, null);
169+
170+
AuditEvent event = testContext.getAuditEventBuilder().build();
171+
Assertions.assertEquals(
172+
"CREATE USER 'audit_user'@'%' IDENTIFIED WITH AUTHENTICATION_LDAP_SIMPLE AS '*XXX'",
173+
event.stmt);
174+
Assertions.assertFalse(event.stmt.contains("uid=gengjun"));
175+
}
176+
152177
@Test
153178
public void testImpersonatedUserInQueryDetail() throws Exception {
154179
String sql = "SELECT 1";

0 commit comments

Comments
 (0)