Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,9 @@ public class DNAuditLogger extends AbstractAuditLogger {

// This text matcher is only a fallback. Password-update semantic nodes must clear sql_string
// before any audit entry is generated.
private static final Pattern ALTER_USER_PASSWORD_PATTERN =
private static final Pattern ALTER_USER_PASSWORD_PREFIX_PATTERN =
Pattern.compile(
"^(\\s*ALTER\\s+USER\\s+.+?\\s+SET\\s+PASSWORD\\s+)"
+ "(?:(?:U&)?'(?:''|[^'])*'|\"(?:\"\"|[^\"])*\")"
+ "(\\s*;?\\s*)$",
Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
"^\\s*ALTER\\s+USER\\s+\\S+\\s+SET\\s+PASSWORD\\s+", Pattern.CASE_INSENSITIVE);
private static final Pattern VALUES_PATTERN = Pattern.compile("(?i)(values)\\([^)]*\\)");

private Coordinator coordinator;
Expand All @@ -89,10 +86,10 @@ private static InsertRowStatement generateInsertStatement(
@NotNull
static InsertRowStatement generateInsertStatement(
IAuditEntity auditLogFields, String log, PartialPath logDevice, long logTimestamp) {
String username = auditLogFields.getUsername();
String address = auditLogFields.getCliHostname();
AuditEventType type = auditLogFields.getAuditEventType();
AuditLogOperation operation = auditLogFields.getAuditLogOperation();
final String username = auditLogFields.getUsername();
final String address = auditLogFields.getCliHostname();
final AuditEventType type = auditLogFields.getAuditEventType();
final AuditLogOperation operation = auditLogFields.getAuditLogOperation();
PrivilegeLevel privilegeLevel = PrivilegeLevel.GLOBAL;
if (auditLogFields.getPrivilegeTypes() != null) {
for (PrivilegeType privilegeType : auditLogFields.getPrivilegeTypes()) {
Expand Down Expand Up @@ -164,29 +161,76 @@ static String sanitizeAuditSql(String sqlString) {
if (sqlString.regionMatches(true, 0, "CREATE USER", 0, "CREATE USER".length())) {
sqlString = String.join(" ", Arrays.asList(sqlString.split(" ")).subList(0, 3)) + " ...";
}
Matcher alterUserMatcher = ALTER_USER_PASSWORD_PATTERN.matcher(sqlString);
if (alterUserMatcher.matches()) {
sqlString = alterUserMatcher.replaceFirst("$1...$2");
final Matcher passwordPrefixMatcher = ALTER_USER_PASSWORD_PREFIX_PATTERN.matcher(sqlString);
if (passwordPrefixMatcher.find()) {
final int passwordLiteralStart = passwordPrefixMatcher.end();
final int passwordLiteralEnd = findQuotedTokenEnd(sqlString, passwordLiteralStart);
if (passwordLiteralEnd >= 0 && isStatementSuffix(sqlString, passwordLiteralEnd)) {
sqlString =
sqlString.substring(0, passwordLiteralStart)
+ "..."
+ sqlString.substring(passwordLiteralEnd);
}
}
return VALUES_PATTERN.matcher(sqlString).replaceAll("$1(...)");
}

private static int skipWhitespace(final String value, int index) {
while (index < value.length() && Character.isWhitespace(value.charAt(index))) {
index++;
}
return index;
}

private static int findQuotedTokenEnd(final String value, final int index) {
int quoteIndex = index;
if (value.regionMatches(true, quoteIndex, "U&", 0, 2)) {
quoteIndex += 2;
}
if (quoteIndex >= value.length()) {
return -1;
}
final char quote = value.charAt(quoteIndex);
if (quote != '\'' && quote != '"') {
return -1;
}
for (int cursor = quoteIndex + 1; cursor < value.length(); cursor++) {
if (value.charAt(cursor) != quote) {
continue;
}
if (cursor + 1 < value.length() && value.charAt(cursor + 1) == quote) {
cursor++;
continue;
}
return cursor + 1;
}
return -1;
}

private static boolean isStatementSuffix(final String value, final int index) {
int suffixIndex = skipWhitespace(value, index);
if (suffixIndex < value.length() && value.charAt(suffixIndex) == ';') {
suffixIndex = skipWhitespace(value, suffixIndex + 1);
}
return suffixIndex == value.length();
}

private static PrivilegeLevel judgePrivilegeLevel(PrivilegeType type) {
if (type == null) {
return PrivilegeLevel.GLOBAL;
}
switch (type) {
case READ_DATA:
case DROP:
case ALTER:
case CREATE:
case DELETE:
case INSERT:
case SELECT:
case MANAGE_DATABASE:
case WRITE_DATA:
case READ_SCHEMA:
case WRITE_SCHEMA:
case READ_DATA,
DROP,
ALTER,
CREATE,
DELETE,
INSERT,
SELECT,
MANAGE_DATABASE,
WRITE_DATA,
READ_SCHEMA,
WRITE_SCHEMA:
return PrivilegeLevel.OBJECT;
default:
return PrivilegeLevel.GLOBAL;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,17 +117,17 @@ static PasswordChangeAuditContext forTreeAuthorization(
}

private static String getTreeTargetUsername(Statement statement) {
return statement instanceof AuthorStatement
&& ((AuthorStatement) statement).getAuthorType() == AuthorType.UPDATE_USER
? ((AuthorStatement) statement).getUserName()
return statement instanceof AuthorStatement authorStatement
&& authorStatement.getAuthorType() == AuthorType.UPDATE_USER
? authorStatement.getUserName()
: null;
}

private static String getTableTargetUsername(
org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.Statement statement) {
return statement instanceof RelationalAuthorStatement
&& ((RelationalAuthorStatement) statement).getAuthorType() == AuthorRType.UPDATE_USER
? ((RelationalAuthorStatement) statement).getUserName()
return statement instanceof RelationalAuthorStatement authorStatement
&& authorStatement.getAuthorType() == AuthorRType.UPDATE_USER
? authorStatement.getUserName()
: null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,10 @@ public void onFailure(@NotNull Throwable throwable) {
},
MoreExecutors.directExecutor());
return future;
} catch (InterruptedException | RuntimeException | Error e) {
} catch (InterruptedException e) {
auditContext.log(null);
throw e;
} catch (RuntimeException e) {
auditContext.log(null);
throw e;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ public void checkCanCreateViewFromTreePath(final PartialPath path, IAuditEntity
}

@Override
@SuppressWarnings("java:S6541") // Keep all relational authorization branches together.
public void checkUserCanRunRelationalAuthorStatement(
String userName, RelationalAuthorStatement statement, IAuditEntity auditEntity) {
AuthorRType type = statement.getAuthorType();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -693,9 +693,10 @@ private TSStatus checkCanUpdateUser(AuthorStatement statement, TreeAccessCheckCo
}
}

@SuppressWarnings("checkstyle:LineLength")
private TSStatus checkCanAlterUser(AuthorStatement statement, TreeAccessCheckContext context) {
context.setAuditLogOperation(AuditLogOperation.DDL);
if (statement.getUserName().equals(context.getUsername())) {
if (Objects.equals(statement.getUserName(), context.getUsername())) {
// users can change the username and password of themselves
AUDIT_LOGGER.recordObjectAuthenticationAuditLog(
context.setResult(true), context::getUsername);
Expand Down
Loading