Skip to content

Commit 2ed0213

Browse files
authored
Audit log patch for both tree and table models (apache#16497)
1 parent 4b29130 commit 2ed0213

File tree

18 files changed

+926
-157
lines changed

18 files changed

+926
-157
lines changed

integration-test/src/test/java/org/apache/iotdb/db/it/audit/IoTDBAuditLogBasicIT.java

Lines changed: 552 additions & 27 deletions
Large diffs are not rendered by default.

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/audit/DNAuditLogger.java

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@
7777
import java.util.concurrent.TimeUnit;
7878
import java.util.concurrent.atomic.AtomicBoolean;
7979
import java.util.function.Supplier;
80+
import java.util.regex.Matcher;
81+
import java.util.regex.Pattern;
8082

8183
import static org.apache.iotdb.db.pipe.receiver.protocol.legacy.loader.ILoader.SCHEMA_FETCHER;
8284

@@ -159,6 +161,20 @@ private static InsertRowStatement generateInsertStatement(
159161
AUDIT_LOG_LOG
160162
});
161163
insertStatement.setAligned(false);
164+
String sqlString = auditLogFields.getSqlString();
165+
if (sqlString != null) {
166+
if (sqlString.toUpperCase().startsWith("CREATE USER")) {
167+
sqlString = String.join(" ", Arrays.asList(sqlString.split(" ")).subList(0, 3)) + " ...";
168+
}
169+
Pattern pattern = Pattern.compile("(?i)(values)\\([^)]*\\)");
170+
Matcher matcher = pattern.matcher(sqlString);
171+
StringBuffer sb = new StringBuffer();
172+
while (matcher.find()) {
173+
matcher.appendReplacement(sb, matcher.group(1) + "(...)");
174+
}
175+
matcher.appendTail(sb);
176+
sqlString = sb.toString();
177+
}
162178
insertStatement.setValues(
163179
new Object[] {
164180
new Binary(username == null ? "null" : username, TSFileConfig.STRING_CHARSET),
@@ -178,9 +194,7 @@ private static InsertRowStatement generateInsertStatement(
178194
new Binary(
179195
auditLogFields.getDatabase() == null ? "null" : auditLogFields.getDatabase(),
180196
TSFileConfig.STRING_CHARSET),
181-
new Binary(
182-
auditLogFields.getSqlString() == null ? "null" : auditLogFields.getSqlString(),
183-
TSFileConfig.STRING_CHARSET),
197+
new Binary(sqlString == null ? "null" : sqlString, TSFileConfig.STRING_CHARSET),
184198
new Binary(log == null ? "null" : log, TSFileConfig.STRING_CHARSET)
185199
});
186200
insertStatement.setDataTypes(

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/auth/AuthorityChecker.java

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import org.apache.iotdb.db.queryengine.plan.relational.security.AccessControl;
4646
import org.apache.iotdb.db.queryengine.plan.relational.security.AccessControlImpl;
4747
import org.apache.iotdb.db.queryengine.plan.relational.security.ITableAuthCheckerImpl;
48+
import org.apache.iotdb.db.queryengine.plan.relational.security.TreeAccessCheckContext;
4849
import org.apache.iotdb.db.queryengine.plan.relational.security.TreeAccessCheckVisitor;
4950
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.RelationalAuthorStatement;
5051
import org.apache.iotdb.db.queryengine.plan.statement.Statement;
@@ -176,22 +177,21 @@ public static IAuditEntity createIAuditEntity(String userName, IClientSession cl
176177
}
177178
}
178179

179-
/** Check whether specific Session has the authorization to given plan. */
180-
public static TSStatus checkAuthority(Statement statement, IClientSession session) {
180+
public static TSStatus checkAuthority(Statement statement, IAuditEntity auditEntity) {
181181
long startTime = System.nanoTime();
182182
try {
183+
if (auditEntity instanceof TreeAccessCheckContext) {
184+
return accessControl.checkPermissionBeforeProcess(
185+
statement, (TreeAccessCheckContext) auditEntity);
186+
}
183187
return accessControl.checkPermissionBeforeProcess(
184188
statement,
185-
new UserEntity(session.getUserId(), session.getUsername(), session.getClientAddress()));
186-
} finally {
187-
PERFORMANCE_OVERVIEW_METRICS.recordAuthCost(System.nanoTime() - startTime);
188-
}
189-
}
190-
191-
public static TSStatus checkAuthority(Statement statement, UserEntity userEntity) {
192-
long startTime = System.nanoTime();
193-
try {
194-
return accessControl.checkPermissionBeforeProcess(statement, userEntity);
189+
(TreeAccessCheckContext)
190+
new TreeAccessCheckContext(
191+
auditEntity.getUserId(),
192+
auditEntity.getUsername(),
193+
auditEntity.getCliHostname())
194+
.setSqlString(auditEntity.getSqlString()));
195195
} finally {
196196
PERFORMANCE_OVERVIEW_METRICS.recordAuthCost(System.nanoTime() - startTime);
197197
}

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/receiver/protocol/thrift/IoTDBDataNodeReceiver.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@
8686
import org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.CreateDBTask;
8787
import org.apache.iotdb.db.queryengine.plan.planner.LocalExecutionPlanner;
8888
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.metadata.write.view.AlterLogicalViewNode;
89+
import org.apache.iotdb.db.queryengine.plan.relational.security.TreeAccessCheckContext;
8990
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.PipeEnriched;
9091
import org.apache.iotdb.db.queryengine.plan.relational.sql.parser.SqlParser;
9192
import org.apache.iotdb.db.queryengine.plan.statement.Statement;
@@ -880,7 +881,12 @@ private TSStatus executeStatementWithPermissionCheckAndRetryOnDataTypeMismatch(
880881
// For table model, the authority check is done in inner execution. No need to check here
881882
if (!isTableModelStatement) {
882883
final TSStatus permissionCheckStatus =
883-
AuthorityChecker.checkAuthority(statement, clientSession);
884+
AuthorityChecker.checkAuthority(
885+
statement,
886+
new TreeAccessCheckContext(
887+
clientSession.getUserId(),
888+
clientSession.getUsername(),
889+
clientSession.getClientAddress()));
884890
if (permissionCheckStatus.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
885891
PipeLogger.log(
886892
LOGGER::warn,

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/sink/protocol/writeback/WriteBackSink.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.CreateDBTask;
4646
import org.apache.iotdb.db.queryengine.plan.planner.LocalExecutionPlanner;
4747
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.write.InsertNode;
48+
import org.apache.iotdb.db.queryengine.plan.relational.security.TreeAccessCheckContext;
4849
import org.apache.iotdb.db.queryengine.plan.relational.sql.parser.SqlParser;
4950
import org.apache.iotdb.db.queryengine.plan.statement.Statement;
5051
import org.apache.iotdb.db.queryengine.plan.statement.crud.InsertBaseStatement;
@@ -481,7 +482,11 @@ private TSStatus executeStatementForTreeModel(final Statement statement, final S
481482
if (useEventUserName && userName != null) {
482483
session.setUsername(userName);
483484
}
484-
final TSStatus permissionCheckStatus = AuthorityChecker.checkAuthority(statement, session);
485+
final TSStatus permissionCheckStatus =
486+
AuthorityChecker.checkAuthority(
487+
statement,
488+
new TreeAccessCheckContext(
489+
session.getUserId(), session.getUsername(), session.getClientAddress()));
485490
if (permissionCheckStatus.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
486491
PipeLogger.log(
487492
LOGGER::warn,

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/source/schemaregion/PipePlanTreePrivilegeParseVisitor.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
package org.apache.iotdb.db.pipe.source.schemaregion;
2121

2222
import org.apache.iotdb.commons.audit.IAuditEntity;
23-
import org.apache.iotdb.commons.audit.UserEntity;
2423
import org.apache.iotdb.commons.auth.entity.PrivilegeType;
2524
import org.apache.iotdb.commons.exception.auth.AccessDeniedException;
2625
import org.apache.iotdb.commons.path.MeasurementPath;
@@ -328,7 +327,9 @@ public Optional<PlanNode> visitDeleteData(
328327
final DeleteDataNode node, final IAuditEntity auditEntity) {
329328
final List<MeasurementPath> intersectedPaths =
330329
TreeAccessCheckVisitor.getIntersectedPaths4Pipe(
331-
node.getPathList(), new TreeAccessCheckContext((UserEntity) auditEntity));
330+
node.getPathList(),
331+
new TreeAccessCheckContext(
332+
auditEntity.getUserId(), auditEntity.getUsername(), auditEntity.getCliHostname()));
332333
if (!skip && !intersectedPaths.equals(node.getPathList())) {
333334
throw new AccessDeniedException("Not has privilege to transfer plan: " + node);
334335
}

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/client/DataNodeInternalClient.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import org.apache.iotdb.db.queryengine.plan.execution.ExecutionResult;
3939
import org.apache.iotdb.db.queryengine.plan.planner.LocalExecutionPlanner;
4040
import org.apache.iotdb.db.queryengine.plan.relational.metadata.Metadata;
41+
import org.apache.iotdb.db.queryengine.plan.relational.security.TreeAccessCheckContext;
4142
import org.apache.iotdb.db.queryengine.plan.relational.sql.parser.SqlParser;
4243
import org.apache.iotdb.db.queryengine.plan.statement.StatementType;
4344
import org.apache.iotdb.db.queryengine.plan.statement.crud.InsertMultiTabletsStatement;
@@ -98,7 +99,11 @@ public DataNodeInternalClient(SessionInfo sessionInfo) {
9899
public TSStatus insertTablets(InsertMultiTabletsStatement statement) {
99100
try {
100101
// permission check
101-
TSStatus status = AuthorityChecker.checkAuthority(statement, session);
102+
TSStatus status =
103+
AuthorityChecker.checkAuthority(
104+
statement,
105+
new TreeAccessCheckContext(
106+
session.getUserId(), session.getUsername(), session.getClientAddress()));
102107
if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
103108
return status;
104109
}

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/mqtt/MPPPublishHandler.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import org.apache.iotdb.db.queryengine.plan.execution.ExecutionResult;
3838
import org.apache.iotdb.db.queryengine.plan.planner.LocalExecutionPlanner;
3939
import org.apache.iotdb.db.queryengine.plan.relational.metadata.Metadata;
40+
import org.apache.iotdb.db.queryengine.plan.relational.security.TreeAccessCheckContext;
4041
import org.apache.iotdb.db.queryengine.plan.relational.sql.parser.SqlParser;
4142
import org.apache.iotdb.db.queryengine.plan.statement.crud.InsertRowStatement;
4243
import org.apache.iotdb.db.queryengine.plan.statement.crud.InsertTabletStatement;
@@ -279,7 +280,11 @@ private void insertTree(TreeMessage message, MqttClientSession session) {
279280
}
280281
statement.setAligned(false);
281282

282-
tsStatus = AuthorityChecker.checkAuthority(statement, session);
283+
tsStatus =
284+
AuthorityChecker.checkAuthority(
285+
statement,
286+
new TreeAccessCheckContext(
287+
session.getUserId(), session.getUsername(), session.getClientAddress()));
283288
if (tsStatus.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
284289
LOG.warn(tsStatus.message);
285290
} else {

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/handler/AuthorizationHandler.java

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,29 +19,19 @@
1919

2020
import org.apache.iotdb.common.rpc.thrift.TSStatus;
2121
import org.apache.iotdb.commons.audit.UserEntity;
22-
import org.apache.iotdb.commons.auth.entity.User;
2322
import org.apache.iotdb.db.auth.AuthorityChecker;
24-
import org.apache.iotdb.db.auth.BasicAuthorityCache;
25-
import org.apache.iotdb.db.auth.ClusterAuthorityFetcher;
26-
import org.apache.iotdb.db.auth.IAuthorityFetcher;
2723
import org.apache.iotdb.db.protocol.rest.model.ExecutionStatus;
2824
import org.apache.iotdb.db.queryengine.plan.statement.Statement;
2925
import org.apache.iotdb.rpc.TSStatusCode;
3026

31-
import org.apache.ratis.util.MemoizedSupplier;
32-
3327
import javax.ws.rs.core.Response;
3428
import javax.ws.rs.core.SecurityContext;
3529

3630
public class AuthorizationHandler {
3731

38-
private static final MemoizedSupplier<IAuthorityFetcher> authorityFetcher =
39-
MemoizedSupplier.valueOf(() -> new ClusterAuthorityFetcher(new BasicAuthorityCache()));
40-
4132
public Response checkAuthority(SecurityContext securityContext, Statement statement) {
4233
String userName = securityContext.getUserPrincipal().getName();
43-
User user = authorityFetcher.get().getUser(userName);
44-
long userId = user == null ? -1 : user.getUserId();
34+
long userId = AuthorityChecker.getUserId(userName).orElse(-1L);
4535
TSStatus status =
4636
AuthorityChecker.checkAuthority(statement, new UserEntity(userId, userName, ""));
4737
if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {

0 commit comments

Comments
 (0)