This is an automated email from the ASF dual-hosted git repository.
yongzao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git
The following commit(s) were added to refs/heads/master by this push:
new c2696b33ae4 Add audit logic for login and logout event (#16520)
c2696b33ae4 is described below
commit c2696b33ae49a070e27a701988091d5cca4b9ff3
Author: wenyanshi-123 <[email protected]>
AuthorDate: Wed Oct 1 11:01:00 2025 +0800
Add audit logic for login and logout event (#16520)
---
.../iotdb/it/env/cluster/env/AbstractEnv.java | 2 +-
.../itbase/runtime/ClusterTestConnection.java | 10 +-
.../iotdb/itbase/runtime/ClusterTestStatement.java | 4 +-
.../iotdb/itbase/runtime/NodeConnection.java | 12 +-
.../iotdb/db/it/audit/IoTDBAuditLogBasicIT.java | 361 +++++++++++++++++++--
.../persistence/auth/AuthorPlanExecutor.java | 5 +-
.../org/apache/iotdb/db/audit/DNAuditLogger.java | 2 +
.../iotdb/db/protocol/session/SessionManager.java | 66 ++--
.../protocol/thrift/impl/ClientRPCServiceImpl.java | 17 +
.../auth/authorizer/LocalFileAuthorizerTest.java | 2 +-
.../apache/iotdb/commons/audit/AuditEventType.java | 1 +
.../apache/iotdb/commons/audit/AuditLogFields.java | 19 ++
.../commons/auth/authorizer/BasicAuthorizer.java | 5 +-
13 files changed, 444 insertions(+), 62 deletions(-)
diff --git
a/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/env/AbstractEnv.java
b/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/env/AbstractEnv.java
index c207ca8ac4c..8308225a9af 100644
---
a/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/env/AbstractEnv.java
+++
b/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/env/AbstractEnv.java
@@ -679,7 +679,7 @@ public abstract class AbstractEnv implements BaseEnv {
? new ClusterTestConnection(
getWriteConnection(version, username, password, sqlDialect),
getReadConnections(version, username, password, sqlDialect))
- : getWriteConnection(version, username, password,
sqlDialect).getUnderlyingConnecton();
+ : getWriteConnection(version, username, password,
sqlDialect).getUnderlyingConnection();
}
@Override
diff --git
a/integration-test/src/main/java/org/apache/iotdb/itbase/runtime/ClusterTestConnection.java
b/integration-test/src/main/java/org/apache/iotdb/itbase/runtime/ClusterTestConnection.java
index 77a5136e696..e272583b08a 100644
---
a/integration-test/src/main/java/org/apache/iotdb/itbase/runtime/ClusterTestConnection.java
+++
b/integration-test/src/main/java/org/apache/iotdb/itbase/runtime/ClusterTestConnection.java
@@ -43,8 +43,8 @@ import java.util.concurrent.Executor;
/** The implementation of {@link Connection} in cluster test. */
public class ClusterTestConnection implements Connection {
- private final NodeConnection writeConnection;
- private final List<NodeConnection> readConnections;
+ public final NodeConnection writeConnection;
+ public final List<NodeConnection> readConnections;
private boolean isClosed;
public ClusterTestConnection(
@@ -110,7 +110,7 @@ public class ClusterTestConnection implements Connection {
@Override
public DatabaseMetaData getMetaData() throws SQLException {
- return writeConnection.getUnderlyingConnecton().getMetaData();
+ return writeConnection.getUnderlyingConnection().getMetaData();
}
@Override
@@ -269,9 +269,9 @@ public class ClusterTestConnection implements Connection {
@Override
public void setClientInfo(String name, String value) throws
SQLClientInfoException {
- writeConnection.getUnderlyingConnecton().setClientInfo(name, value);
+ writeConnection.getUnderlyingConnection().setClientInfo(name, value);
for (NodeConnection conn : readConnections) {
- conn.getUnderlyingConnecton().setClientInfo(name, value);
+ conn.getUnderlyingConnection().setClientInfo(name, value);
}
}
diff --git
a/integration-test/src/main/java/org/apache/iotdb/itbase/runtime/ClusterTestStatement.java
b/integration-test/src/main/java/org/apache/iotdb/itbase/runtime/ClusterTestStatement.java
index f5dc5289d12..3f96fdf1372 100644
---
a/integration-test/src/main/java/org/apache/iotdb/itbase/runtime/ClusterTestStatement.java
+++
b/integration-test/src/main/java/org/apache/iotdb/itbase/runtime/ClusterTestStatement.java
@@ -51,7 +51,7 @@ public class ClusterTestStatement implements Statement {
public ClusterTestStatement(
NodeConnection writeConnection, List<NodeConnection> readConnections) {
try {
- this.writeStatement =
writeConnection.getUnderlyingConnecton().createStatement();
+ this.writeStatement =
writeConnection.getUnderlyingConnection().createStatement();
updateConfig(writeStatement, 0);
writEndpoint = writeConnection.toString();
} catch (SQLException e) {
@@ -60,7 +60,7 @@ public class ClusterTestStatement implements Statement {
for (NodeConnection readConnection : readConnections) {
try {
- Statement readStatement =
readConnection.getUnderlyingConnecton().createStatement();
+ Statement readStatement =
readConnection.getUnderlyingConnection().createStatement();
this.readStatements.add(readStatement);
this.readEndpoints.add(readConnection.toString());
updateConfig(readStatement, queryTimeout);
diff --git
a/integration-test/src/main/java/org/apache/iotdb/itbase/runtime/NodeConnection.java
b/integration-test/src/main/java/org/apache/iotdb/itbase/runtime/NodeConnection.java
index e3508422aa8..8f9eddcf3f4 100644
---
a/integration-test/src/main/java/org/apache/iotdb/itbase/runtime/NodeConnection.java
+++
b/integration-test/src/main/java/org/apache/iotdb/itbase/runtime/NodeConnection.java
@@ -33,17 +33,17 @@ public class NodeConnection {
private final String endpoint;
private final NodeRole nodeRole;
private final ConnectionRole connectionRole;
- private final Connection underlyingConnecton;
+ private final Connection underlyingConnection;
public NodeConnection(
String endpoint,
NodeRole nodeRole,
ConnectionRole connectionRole,
- Connection underlyingConnecton) {
+ Connection underlyingConnection) {
this.endpoint = endpoint;
this.nodeRole = nodeRole;
this.connectionRole = connectionRole;
- this.underlyingConnecton = underlyingConnecton;
+ this.underlyingConnection = underlyingConnection;
}
public String getEndpoint() {
@@ -58,13 +58,13 @@ public class NodeConnection {
return connectionRole;
}
- public Connection getUnderlyingConnecton() {
- return underlyingConnecton;
+ public Connection getUnderlyingConnection() {
+ return underlyingConnection;
}
public void close() {
try {
- underlyingConnecton.close();
+ underlyingConnection.close();
} catch (SQLException e) {
logger.error("Close connection {} error", this, e);
}
diff --git
a/integration-test/src/test/java/org/apache/iotdb/db/it/audit/IoTDBAuditLogBasicIT.java
b/integration-test/src/test/java/org/apache/iotdb/db/it/audit/IoTDBAuditLogBasicIT.java
index 4d96a41406c..39a51468082 100644
---
a/integration-test/src/test/java/org/apache/iotdb/db/it/audit/IoTDBAuditLogBasicIT.java
+++
b/integration-test/src/test/java/org/apache/iotdb/db/it/audit/IoTDBAuditLogBasicIT.java
@@ -26,6 +26,8 @@ import org.apache.iotdb.it.env.EnvFactory;
import org.apache.iotdb.it.framework.IoTDBTestRunner;
import org.apache.iotdb.itbase.category.LocalStandaloneIT;
import org.apache.iotdb.itbase.env.BaseEnv;
+import org.apache.iotdb.itbase.runtime.ClusterTestConnection;
+import org.apache.iotdb.itbase.runtime.NodeConnection;
import org.junit.After;
import org.junit.Assert;
@@ -96,7 +98,7 @@ public class IoTDBAuditLogBasicIT {
private static final String AUDITABLE_OPERATION_RESULT = "SUCCESS,FAIL";
@Before
- public void setUp() throws SQLException {
+ public void setUp() throws SQLException, InterruptedException {
EnvFactory.getEnv()
.getConfig()
.getCommonConfig()
@@ -108,27 +110,38 @@ public class IoTDBAuditLogBasicIT {
// Init 1C1D cluster environment
EnvFactory.getEnv().initClusterEnvironment(1, 1);
- try (Connection connection =
EnvFactory.getEnv().getConnection(BaseEnv.TREE_SQL_DIALECT);
- Statement statement = connection.createStatement()) {
- // Ensure there exists audit database in tree model
- ResultSet resultSet = statement.executeQuery("SHOW DATABASES
root.__audit");
- Assert.assertTrue(resultSet.next());
- Assert.assertEquals("root.__audit", resultSet.getString(1));
+ Connection connection =
EnvFactory.getEnv().getConnection(BaseEnv.TREE_SQL_DIALECT);
+ Statement statement = connection.createStatement();
+ ResultSet resultSet = statement.executeQuery("SHOW DATABASES
root.__audit");
+ Assert.assertTrue(resultSet.next());
+ Assert.assertEquals("root.__audit", resultSet.getString(1));
+ Thread.sleep(1000);
+ ((ClusterTestConnection) connection).writeConnection.close();
+ Thread.sleep(1000);
+ for (NodeConnection conn : ((ClusterTestConnection)
connection).readConnections) {
+ Thread.sleep(1000);
+ conn.close();
+ Thread.sleep(1000);
}
-
- try (Connection connection =
EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
- Statement statement = connection.createStatement()) {
- // Ensure there exists audit table
- ResultSet resultSet = statement.executeQuery("DESC __audit.audit_log");
- resultSet.next(); // Skip time column
- int cnt = 0;
- while (resultSet.next()) {
- Assert.assertEquals(AUDIT_TABLE_COLUMNS.get(cnt),
resultSet.getString(1));
- Assert.assertEquals(AUDIT_TABLE_DATA_TYPES.get(cnt),
resultSet.getString(2));
- Assert.assertEquals(AUDIT_TABLE_CATEGORIES.get(cnt),
resultSet.getString(3));
- cnt++;
- }
- Assert.assertEquals(AUDIT_TABLE_COLUMNS.size(), cnt);
+ connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ statement = connection.createStatement();
+ resultSet = statement.executeQuery("DESC __audit.audit_log");
+ resultSet.next(); // Skip time column
+ int cnt = 0;
+ while (resultSet.next()) {
+ Assert.assertEquals(AUDIT_TABLE_COLUMNS.get(cnt),
resultSet.getString(1));
+ Assert.assertEquals(AUDIT_TABLE_DATA_TYPES.get(cnt),
resultSet.getString(2));
+ Assert.assertEquals(AUDIT_TABLE_CATEGORIES.get(cnt),
resultSet.getString(3));
+ cnt++;
+ }
+ Assert.assertEquals(AUDIT_TABLE_COLUMNS.size(), cnt);
+ Thread.sleep(1000);
+ ((ClusterTestConnection) connection).writeConnection.close();
+ Thread.sleep(1000);
+ for (NodeConnection conn : ((ClusterTestConnection)
connection).readConnections) {
+ Thread.sleep(1000);
+ conn.close();
+ Thread.sleep(1000);
}
}
@@ -176,7 +189,60 @@ public class IoTDBAuditLogBasicIT {
"null",
"null",
"Successfully start the Audit service with configurations
(auditableOperationType [DDL, DML, QUERY, CONTROL], auditableOperationLevel
GLOBAL, auditableOperationResult SUCCESS,FAIL)"),
- // Show audit database
+
+ // Environment init login/logout
+ Arrays.asList(
+ "node_1",
+ "u_0",
+ "root",
+ "127.0.0.1",
+ "LOGIN",
+ "CONTROL",
+ "null",
+ "GLOBAL",
+ "true",
+ "",
+ "",
+ "IoTDB: Login status: Login successfully. User root (ID=0),
opens Session"),
+ Arrays.asList(
+ "node_1",
+ "u_0",
+ "root",
+ "127.0.0.1",
+ "LOGOUT",
+ "CONTROL",
+ "null",
+ "GLOBAL",
+ "true",
+ "",
+ "",
+ "is closing"),
+ Arrays.asList(
+ "node_1",
+ "u_0",
+ "root",
+ "127.0.0.1",
+ "LOGIN",
+ "CONTROL",
+ "null",
+ "GLOBAL",
+ "true",
+ "",
+ "",
+ "IoTDB: Login status: Login successfully. User root (ID=0),
opens Session"),
+ Arrays.asList(
+ "node_1",
+ "u_0",
+ "root",
+ "127.0.0.1",
+ "LOGIN",
+ "CONTROL",
+ "null",
+ "GLOBAL",
+ "true",
+ "",
+ "",
+ "IoTDB: Login status: Login successfully. User root (ID=0),
opens Session"),
Arrays.asList(
"node_1",
"u_0",
@@ -190,6 +256,60 @@ public class IoTDBAuditLogBasicIT {
"[root.__audit]",
"SHOW DATABASES root.__audit",
"User root (ID=0) requests authority on object root.__audit with
result true"),
+ // Setup logout through tree model dialect, twice for both read and
write connections
+ Arrays.asList(
+ "node_1",
+ "u_0",
+ "root",
+ "127.0.0.1",
+ "LOGOUT",
+ "CONTROL",
+ "null",
+ "GLOBAL",
+ "true",
+ "",
+ "",
+ "is closing"),
+ Arrays.asList(
+ "node_1",
+ "u_0",
+ "root",
+ "127.0.0.1",
+ "LOGOUT",
+ "CONTROL",
+ "null",
+ "GLOBAL",
+ "true",
+ "",
+ "",
+ "is closing"),
+ // Setup login through table model dialect, twice for both read and
write connections
+ Arrays.asList(
+ "node_1",
+ "u_0",
+ "root",
+ "127.0.0.1",
+ "LOGIN",
+ "CONTROL",
+ "null",
+ "GLOBAL",
+ "true",
+ "",
+ "",
+ "IoTDB: Login status: Login successfully. User root (ID=0),
opens Session"),
+ Arrays.asList(
+ "node_1",
+ "u_0",
+ "root",
+ "127.0.0.1",
+ "LOGIN",
+ "CONTROL",
+ "null",
+ "GLOBAL",
+ "true",
+ "",
+ "",
+ "IoTDB: Login status: Login successfully. User root (ID=0),
opens Session"),
// Desc audit table
Arrays.asList(
"node_1",
@@ -204,6 +324,58 @@ public class IoTDBAuditLogBasicIT {
"__audit",
"DESC __audit.audit_log",
"User root (ID=0) requests authority on object audit_log with
result true"),
+ Arrays.asList(
+ "node_1",
+ "u_0",
+ "root",
+ "127.0.0.1",
+ "LOGOUT",
+ "CONTROL",
+ "null",
+ "GLOBAL",
+ "true",
+ "",
+ "",
+ "is closing"),
+ Arrays.asList(
+ "node_1",
+ "u_0",
+ "root",
+ "127.0.0.1",
+ "LOGOUT",
+ "CONTROL",
+ "null",
+ "GLOBAL",
+ "true",
+ "",
+ "",
+ "is closing"),
+ Arrays.asList(
+ "node_1",
+ "u_0",
+ "root",
+ "127.0.0.1",
+ "LOGIN",
+ "CONTROL",
+ "null",
+ "GLOBAL",
+ "true",
+ "",
+ "",
+ "IoTDB: Login status: Login successfully. User root (ID=0),
opens Session"),
+ Arrays.asList(
+ "node_1",
+ "u_0",
+ "root",
+ "127.0.0.1",
+ "LOGIN",
+ "CONTROL",
+ "null",
+ "GLOBAL",
+ "true",
+ "",
+ "",
+ "IoTDB: Login status: Login successfully. User root (ID=0),
opens Session"),
// Create database
Arrays.asList(
"node_1",
@@ -634,6 +806,54 @@ public class IoTDBAuditLogBasicIT {
"CHANGE_AUDIT_OPTION",
"null",
"null"),
+ Arrays.asList(
+ "root.__audit.log.node_1.u_0",
+ "true",
+ "GLOBAL",
+ "null",
+ "",
+ "CONTROL",
+ "IoTDB: Login status: Login successfully. User root (ID=0),
opens Session",
+ "",
+ "LOGIN",
+ "127.0.0.1",
+ "root"),
+ Arrays.asList(
+ "root.__audit.log.node_1.u_0",
+ "true",
+ "GLOBAL",
+ "null",
+ "",
+ "CONTROL",
+ "is closing",
+ "",
+ "LOGOUT",
+ "127.0.0.1",
+ "root"),
+ Arrays.asList(
+ "root.__audit.log.node_1.u_0",
+ "true",
+ "GLOBAL",
+ "null",
+ "",
+ "CONTROL",
+ "IoTDB: Login status: Login successfully. User root (ID=0),
opens Session",
+ "",
+ "LOGIN",
+ "127.0.0.1",
+ "root"),
+ Arrays.asList(
+ "root.__audit.log.node_1.u_0",
+ "true",
+ "GLOBAL",
+ "null",
+ "",
+ "CONTROL",
+ "IoTDB: Login status: Login successfully. User root (ID=0),
opens Session",
+ "",
+ "LOGIN",
+ "127.0.0.1",
+ "root"),
// Show audit database
Arrays.asList(
"root.__audit.log.node_1.u_0",
@@ -647,6 +867,55 @@ public class IoTDBAuditLogBasicIT {
"OBJECT_AUTHENTICATION",
"127.0.0.1",
"root"),
+ Arrays.asList(
+ "root.__audit.log.node_1.u_0",
+ "true",
+ "GLOBAL",
+ "null",
+ "",
+ "CONTROL",
+ "is closing",
+ "",
+ "LOGOUT",
+ "127.0.0.1",
+ "root"),
+ Arrays.asList(
+ "root.__audit.log.node_1.u_0",
+ "true",
+ "GLOBAL",
+ "null",
+ "",
+ "CONTROL",
+ "is closing",
+ "",
+ "LOGOUT",
+ "127.0.0.1",
+ "root"),
+ Arrays.asList(
+ "root.__audit.log.node_1.u_0",
+ "true",
+ "GLOBAL",
+ "null",
+ "",
+ "CONTROL",
+ "IoTDB: Login status: Login successfully. User root (ID=0),
opens Session",
+ "",
+ "LOGIN",
+ "127.0.0.1",
+ "root"),
+ Arrays.asList(
+ "root.__audit.log.node_1.u_0",
+ "true",
+ "GLOBAL",
+ "null",
+ "",
+ "CONTROL",
+ "IoTDB: Login status: Login successfully. User root (ID=0),
opens Session",
+ "",
+ "LOGIN",
+ "127.0.0.1",
+ "root"),
+
// Desc audit table
Arrays.asList(
"root.__audit.log.node_1.u_0",
@@ -660,6 +929,54 @@ public class IoTDBAuditLogBasicIT {
"OBJECT_AUTHENTICATION",
"127.0.0.1",
"root"),
+ Arrays.asList(
+ "root.__audit.log.node_1.u_0",
+ "true",
+ "GLOBAL",
+ "null",
+ "",
+ "CONTROL",
+ "is closing",
+ "",
+ "LOGOUT",
+ "127.0.0.1",
+ "root"),
+ Arrays.asList(
+ "root.__audit.log.node_1.u_0",
+ "true",
+ "GLOBAL",
+ "null",
+ "",
+ "CONTROL",
+ "is closing",
+ "",
+ "LOGOUT",
+ "127.0.0.1",
+ "root"),
+ Arrays.asList(
+ "root.__audit.log.node_1.u_0",
+ "true",
+ "GLOBAL",
+ "null",
+ "",
+ "CONTROL",
+ "IoTDB: Login status: Login successfully. User root (ID=0),
opens Session",
+ "",
+ "LOGIN",
+ "127.0.0.1",
+ "root"),
+ Arrays.asList(
+ "root.__audit.log.node_1.u_0",
+ "true",
+ "GLOBAL",
+ "null",
+ "",
+ "CONTROL",
+ "IoTDB: Login status: Login successfully. User root (ID=0),
opens Session",
+ "",
+ "LOGIN",
+ "127.0.0.1",
+ "root"),
// Create database
Arrays.asList(
"root.__audit.log.node_1.u_0",
diff --git
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/auth/AuthorPlanExecutor.java
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/auth/AuthorPlanExecutor.java
index 694f37325c4..6eee2481d5b 100644
---
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/auth/AuthorPlanExecutor.java
+++
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/auth/AuthorPlanExecutor.java
@@ -97,12 +97,9 @@ public class AuthorPlanExecutor implements
IAuthorPlanExecutor {
}
} catch (AuthException e) {
LOGGER.error("meet error while logging in.", e);
- status = false;
loginMessage = e.getMessage();
- }
- if (!status) {
+ tsStatus.setCode(e.getCode().getStatusCode());
tsStatus.setMessage(loginMessage != null ? loginMessage :
"Authentication failed.");
- tsStatus.setCode(TSStatusCode.WRONG_LOGIN_PASSWORD.getStatusCode());
result.setStatus(tsStatus);
}
return result;
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/audit/DNAuditLogger.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/audit/DNAuditLogger.java
index 9043361fea0..a8a5280b444 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/audit/DNAuditLogger.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/audit/DNAuditLogger.java
@@ -141,6 +141,8 @@ public class DNAuditLogger extends AbstractAuditLogger {
break;
}
}
+ } else {
+ privilegeLevel = PrivilegeLevel.GLOBAL;
}
InsertRowStatement insertStatement = new InsertRowStatement();
insertStatement.setDevicePath(logDevice);
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/session/SessionManager.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/session/SessionManager.java
index bae81487f4f..bebc93b7e6b 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/session/SessionManager.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/session/SessionManager.java
@@ -20,8 +20,10 @@
package org.apache.iotdb.db.protocol.session;
import org.apache.iotdb.common.rpc.thrift.TSStatus;
+import org.apache.iotdb.commons.audit.AuditEventType;
+import org.apache.iotdb.commons.audit.AuditLogFields;
+import org.apache.iotdb.commons.audit.AuditLogOperation;
import org.apache.iotdb.commons.audit.UserEntity;
-import org.apache.iotdb.commons.auth.entity.User;
import org.apache.iotdb.commons.conf.CommonDescriptor;
import org.apache.iotdb.commons.conf.IoTDBConstant;
import org.apache.iotdb.commons.exception.IoTDBRuntimeException;
@@ -34,9 +36,6 @@ import org.apache.iotdb.commons.utils.AuthUtils;
import org.apache.iotdb.commons.utils.CommonDateTimeUtils;
import org.apache.iotdb.db.audit.DNAuditLogger;
import org.apache.iotdb.db.auth.AuthorityChecker;
-import org.apache.iotdb.db.auth.BasicAuthorityCache;
-import org.apache.iotdb.db.auth.ClusterAuthorityFetcher;
-import org.apache.iotdb.db.auth.IAuthorityFetcher;
import org.apache.iotdb.db.auth.LoginLockManager;
import org.apache.iotdb.db.conf.IoTDBDescriptor;
import org.apache.iotdb.db.protocol.basic.BasicOpenSessionResp;
@@ -61,7 +60,6 @@ import org.apache.iotdb.service.rpc.thrift.TSLastDataQueryReq;
import org.apache.iotdb.service.rpc.thrift.TSProtocolVersion;
import org.apache.commons.lang3.StringUtils;
-import org.apache.ratis.util.MemoizedSupplier;
import org.apache.tsfile.read.common.block.TsBlock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -85,6 +83,7 @@ import static
org.apache.iotdb.db.utils.ErrorHandlingUtils.onNpeOrUnexpectedExce
public class SessionManager implements SessionManagerMBean {
private static final Logger LOGGER =
LoggerFactory.getLogger(SessionManager.class);
+ private static final DNAuditLogger AUDIT_LOGGER =
DNAuditLogger.getInstance();
// When the client abnormally exits, we can still know who to disconnect
/** currSession can be only used in client-thread model services. */
@@ -105,9 +104,6 @@ public class SessionManager implements SessionManagerMBean {
public static final TSProtocolVersion CURRENT_RPC_VERSION =
TSProtocolVersion.IOTDB_SERVICE_PROTOCOL_V3;
- private static final MemoizedSupplier<IAuthorityFetcher> authorityFetcher =
- MemoizedSupplier.valueOf(() -> new ClusterAuthorityFetcher(new
BasicAuthorityCache()));
-
protected SessionManager() {
// singleton
String mbeanName =
@@ -248,11 +244,10 @@ public class SessionManager implements
SessionManagerMBean {
return openSessionResp;
}
- User user = authorityFetcher.get().getUser(username);
- boolean enableLoginLock = user != null;
+ long userId = AuthorityChecker.getUserId(username).orElse(-1L);
+ boolean enableLoginLock = userId != -1;
LoginLockManager loginLockManager = LoginLockManager.getInstance();
- if (enableLoginLock
- && loginLockManager.checkLock(user.getUserId(),
session.getClientAddress())) {
+ if (enableLoginLock && loginLockManager.checkLock(userId,
session.getClientAddress())) {
// Generic authentication error
openSessionResp
.sessionId(-1)
@@ -270,8 +265,6 @@ public class SessionManager implements SessionManagerMBean {
.setCode(TSStatusCode.INCOMPATIBLE_VERSION.getStatusCode())
.setMessage("The version is incompatible, please upgrade to " +
IoTDBConstant.VERSION);
} else {
- User tmpUser = AuthorityChecker.getUser(username);
- long userId = tmpUser == null ? -1 : tmpUser.getUserId();
session.setSqlDialect(sqlDialect);
supplySession(session, userId, username, ZoneId.of(zoneId),
clientVersion);
String logInMessage = "Login successfully";
@@ -314,7 +307,22 @@ public class SessionManager implements SessionManagerMBean
{
.sessionId(session.getId())
.setCode(TSStatusCode.SUCCESS_STATUS.getStatusCode())
.setMessage(logInMessage);
-
+ AUDIT_LOGGER.log(
+ new AuditLogFields(
+ userId,
+ username,
+ session.getClientAddress(),
+ AuditEventType.LOGIN,
+ AuditLogOperation.CONTROL,
+ true),
+ () ->
+ String.format(
+ "%s: Login status: %s. User %s (ID=%d), opens Session-%s",
+ IoTDBConstant.GLOBAL_DB_NAME,
+ openSessionResp.getMessage(),
+ username,
+ userId,
+ session));
LOGGER.info(
"{}: Login status: {}. User : {}, opens Session-{}",
IoTDBConstant.GLOBAL_DB_NAME,
@@ -322,16 +330,27 @@ public class SessionManager implements
SessionManagerMBean {
username,
session);
if (enableLoginLock) {
- loginLockManager.clearFailure(tmpUser.getUserId(),
session.getClientAddress());
+ loginLockManager.clearFailure(userId, session.getClientAddress());
}
}
} else {
openSessionResp.sessionId(-1).setMessage(loginStatus.message).setCode(loginStatus.code);
if (enableLoginLock) {
- loginLockManager.recordFailure(user.getUserId(),
session.getClientAddress());
+ loginLockManager.recordFailure(userId, session.getClientAddress());
}
+ AUDIT_LOGGER.log(
+ new AuditLogFields(
+ userId,
+ username,
+ session.getClientAddress(),
+ AuditEventType.LOGIN,
+ AuditLogOperation.CONTROL,
+ false),
+ () ->
+ String.format(
+ "User %s (ID=%d) login failed with code: %d, %s",
+ username, userId, loginStatus.getCode(),
loginStatus.getMessage()));
}
-
return openSessionResp;
}
@@ -345,7 +364,16 @@ public class SessionManager implements SessionManagerMBean
{
String.valueOf(session.getId()));
// TODO we only need to do so when query is killed by time out close the
socket.
IClientSession session1 = currSession.get();
- return session1 == null || session == session1;
+ if (session1 != null && session != session1) {
+ LOGGER.info(
+ String.format(
+ "The client-%s is trying to close another session %s, pls check
if it's a bug",
+ session, session1));
+ return false;
+ } else {
+ LOGGER.info(String.format("Session-%s is closing", session));
+ return true;
+ }
}
private void releaseSessionResource(IClientSession session, LongConsumer
releaseQueryResource) {
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/ClientRPCServiceImpl.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/ClientRPCServiceImpl.java
index 74c2f6eda6b..9c514979e4b 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/ClientRPCServiceImpl.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/ClientRPCServiceImpl.java
@@ -26,6 +26,9 @@ import org.apache.iotdb.common.rpc.thrift.TSStatus;
import org.apache.iotdb.common.rpc.thrift.TShowConfigurationResp;
import org.apache.iotdb.common.rpc.thrift.TShowConfigurationTemplateResp;
import org.apache.iotdb.common.rpc.thrift.TTimePartitionSlot;
+import org.apache.iotdb.commons.audit.AuditEventType;
+import org.apache.iotdb.commons.audit.AuditLogFields;
+import org.apache.iotdb.commons.audit.AuditLogOperation;
import org.apache.iotdb.commons.client.exception.ClientManagerException;
import org.apache.iotdb.commons.conf.CommonConfig;
import org.apache.iotdb.commons.conf.CommonDescriptor;
@@ -44,6 +47,7 @@ import org.apache.iotdb.commons.path.PartialPath;
import org.apache.iotdb.commons.schema.column.ColumnHeader;
import org.apache.iotdb.commons.utils.PathUtils;
import org.apache.iotdb.commons.utils.TimePartitionUtils;
+import org.apache.iotdb.db.audit.DNAuditLogger;
import org.apache.iotdb.db.auth.AuthorityChecker;
import org.apache.iotdb.db.conf.IoTDBConfig;
import org.apache.iotdb.db.conf.IoTDBDescriptor;
@@ -235,6 +239,8 @@ public class ClientRPCServiceImpl implements
IClientRPCServiceWithHandler {
private static final Logger LOGGER =
LoggerFactory.getLogger(ClientRPCServiceImpl.class);
+ private static final DNAuditLogger AUDIT_LOGGER =
DNAuditLogger.getInstance();
+
private static final IoTDBConfig config =
IoTDBDescriptor.getInstance().getConfig();
private static final CommonConfig COMMON_CONFIG =
CommonDescriptor.getInstance().getConfig();
@@ -3240,6 +3246,17 @@ public class ClientRPCServiceImpl implements
IClientRPCServiceWithHandler {
IClientSession session = SESSION_MANAGER.getCurrSession();
if (session != null) {
TSCloseSessionReq req = new TSCloseSessionReq();
+ if (!session.getUsername().contains("null")) {
+ AUDIT_LOGGER.log(
+ new AuditLogFields(
+ session.getUserId(),
+ session.getUsername(),
+ session.getClientAddress(),
+ AuditEventType.LOGOUT,
+ AuditLogOperation.CONTROL,
+ true),
+ () -> String.format("Session-%s is closing", session));
+ }
closeSession(req);
}
PipeDataNodeAgent.receiver().thrift().handleClientExit();
diff --git
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/auth/authorizer/LocalFileAuthorizerTest.java
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/auth/authorizer/LocalFileAuthorizerTest.java
index 300a7c0646d..96a40d0c90d 100644
---
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/auth/authorizer/LocalFileAuthorizerTest.java
+++
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/auth/authorizer/LocalFileAuthorizerTest.java
@@ -65,7 +65,7 @@ public class LocalFileAuthorizerTest {
@Test
public void testLogin() throws AuthException {
Assert.assertTrue(authorizer.login("root", "root"));
- Assert.assertFalse(authorizer.login("root", "error"));
+ Assert.assertThrows(AuthException.class, () -> authorizer.login("root",
"error"));
}
@Test
diff --git
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/audit/AuditEventType.java
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/audit/AuditEventType.java
index 39b13835481..510912a302f 100644
---
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/audit/AuditEventType.java
+++
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/audit/AuditEventType.java
@@ -33,6 +33,7 @@ public enum AuditEventType {
LOGIN_FAIL_MAX_TIMES,
MODIFY_PASSWD,
LOGIN,
+ LOGOUT,
LOGIN_FINAL,
MODIFY_SECURITY_OPTIONS,
MODIFY_DEFAULT_SECURITY_VALUES,
diff --git
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/audit/AuditLogFields.java
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/audit/AuditLogFields.java
index 98af46e30fd..bf167c743ce 100644
---
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/audit/AuditLogFields.java
+++
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/audit/AuditLogFields.java
@@ -79,6 +79,25 @@ public class AuditLogFields implements IAuditEntity {
sqlString);
}
+ public AuditLogFields(
+ long userId,
+ String username,
+ String cliHostname,
+ AuditEventType auditEventType,
+ AuditLogOperation operationType,
+ boolean result) {
+ this(
+ userId,
+ username,
+ cliHostname,
+ auditEventType,
+ operationType,
+ (List<PrivilegeType>) null,
+ result,
+ "",
+ "");
+ }
+
public String getUsername() {
return username;
}
diff --git
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/authorizer/BasicAuthorizer.java
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/authorizer/BasicAuthorizer.java
index ac86ae8d9fc..5d61b9e5e38 100644
---
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/authorizer/BasicAuthorizer.java
+++
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/authorizer/BasicAuthorizer.java
@@ -109,7 +109,8 @@ public abstract class BasicAuthorizer implements
IAuthorizer, IService {
public boolean login(String username, String password) throws AuthException {
User user = userManager.getEntity(username);
if (user == null || password == null) {
- return false;
+ throw new AuthException(
+ TSStatusCode.USER_NOT_EXIST, String.format("The user %s does not
exist.", username));
}
if (AuthUtils.validatePassword(
password, user.getPassword(),
AsymmetricEncrypt.DigestAlgorithm.SHA_256)) {
@@ -123,7 +124,7 @@ public abstract class BasicAuthorizer implements
IAuthorizer, IService {
}
return true;
}
- return false;
+ throw new AuthException(TSStatusCode.WRONG_LOGIN_PASSWORD, "Incorrect
password.");
}
@Override