This is an automated email from the ASF dual-hosted git repository.
yongzao pushed a commit to branch fix-table-audit-log
in repository https://gitbox.apache.org/repos/asf/iotdb.git
The following commit(s) were added to refs/heads/fix-table-audit-log by this
push:
new 7f4bb0b1ed2 Audit CI 4 table
7f4bb0b1ed2 is described below
commit 7f4bb0b1ed2061dfb89ccd858bf1b6aa8ff620c3
Author: Yongzao <[email protected]>
AuthorDate: Thu Sep 25 22:01:29 2025 +0800
Audit CI 4 table
---
.../it/env/cluster/config/MppCommonConfig.java | 24 ++
.../env/cluster/config/MppSharedCommonConfig.java | 28 ++
.../it/env/remote/config/RemoteCommonConfig.java | 20 +
.../org/apache/iotdb/itbase/env/CommonConfig.java | 8 +
.../iotdb/db/it/audit/IoTDBAuditLogBasicIT.java | 430 +++++++++++++++++++++
.../org/apache/iotdb/db/audit/DNAuditLogger.java | 75 ++--
.../impl/DataNodeInternalRPCServiceImpl.java | 2 +-
.../db/queryengine/common/MPPQueryContext.java | 6 +-
.../execution/config/TableConfigTaskVisitor.java | 2 +-
.../relational/security/AccessControlImpl.java | 16 +-
.../relational/security/ITableAuthCheckerImpl.java | 4 +-
.../security/TreeAccessCheckVisitor.java | 9 +-
.../java/org/apache/iotdb/db/service/DataNode.java | 2 +-
.../iotdb/db/service/DataNodeShutdownHook.java | 2 +-
.../apache/iotdb/db/utils/DataNodeAuthUtils.java | 12 +-
.../iotdb/commons/audit/AbstractAuditLogger.java | 17 +-
.../apache/iotdb/commons/audit/AuditLogFields.java | 28 +-
17 files changed, 626 insertions(+), 59 deletions(-)
diff --git
a/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/config/MppCommonConfig.java
b/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/config/MppCommonConfig.java
index b84414eba8c..f9120ddb131 100644
---
a/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/config/MppCommonConfig.java
+++
b/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/config/MppCommonConfig.java
@@ -627,6 +627,30 @@ public class MppCommonConfig extends MppBaseConfig
implements CommonConfig {
return this;
}
+ @Override
+ public CommonConfig setEnableAuditLog(boolean enableAuditLog) {
+ setProperty("enable_audit_log", String.valueOf(enableAuditLog));
+ return this;
+ }
+
+ @Override
+ public CommonConfig setAuditableOperationType(String auditableOperationType)
{
+ setProperty("auditable_operation_type", auditableOperationType);
+ return this;
+ }
+
+ @Override
+ public CommonConfig setAuditableOperationLevel(String
auditableOperationLevel) {
+ setProperty("auditable_operation_level", auditableOperationLevel);
+ return this;
+ }
+
+ @Override
+ public CommonConfig setAuditableOperationResult(String
auditableOperationResult) {
+ setProperty("auditable_operation_result", auditableOperationResult);
+ return this;
+ }
+
// For part of the log directory
public String getClusterConfigStr() {
return
fromConsensusFullNameToAbbr(properties.getProperty(CONFIG_NODE_CONSENSUS_PROTOCOL_CLASS))
diff --git
a/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/config/MppSharedCommonConfig.java
b/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/config/MppSharedCommonConfig.java
index 2599aa3854a..504b1ae60e2 100644
---
a/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/config/MppSharedCommonConfig.java
+++
b/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/config/MppSharedCommonConfig.java
@@ -656,4 +656,32 @@ public class MppSharedCommonConfig implements CommonConfig
{
cnConfig.setDatanodeMemoryProportion(datanodeMemoryProportion);
return this;
}
+
+ @Override
+ public CommonConfig setEnableAuditLog(boolean enableAuditLog) {
+ dnConfig.setEnableAuditLog(enableAuditLog);
+ cnConfig.setEnableAuditLog(enableAuditLog);
+ return this;
+ }
+
+ @Override
+ public CommonConfig setAuditableOperationType(String auditableOperationType)
{
+ dnConfig.setAuditableOperationType(auditableOperationType);
+ cnConfig.setAuditableOperationType(auditableOperationType);
+ return this;
+ }
+
+ @Override
+ public CommonConfig setAuditableOperationLevel(String
auditableOperationLevel) {
+ dnConfig.setAuditableOperationLevel(auditableOperationLevel);
+ cnConfig.setAuditableOperationLevel(auditableOperationLevel);
+ return this;
+ }
+
+ @Override
+ public CommonConfig setAuditableOperationResult(String
auditableOperationResult) {
+ dnConfig.setAuditableOperationResult(auditableOperationResult);
+ cnConfig.setAuditableOperationResult(auditableOperationResult);
+ return this;
+ }
}
diff --git
a/integration-test/src/main/java/org/apache/iotdb/it/env/remote/config/RemoteCommonConfig.java
b/integration-test/src/main/java/org/apache/iotdb/it/env/remote/config/RemoteCommonConfig.java
index 7b093f4804e..fdcff20dbc8 100644
---
a/integration-test/src/main/java/org/apache/iotdb/it/env/remote/config/RemoteCommonConfig.java
+++
b/integration-test/src/main/java/org/apache/iotdb/it/env/remote/config/RemoteCommonConfig.java
@@ -457,4 +457,24 @@ public class RemoteCommonConfig implements CommonConfig {
public CommonConfig setDatanodeMemoryProportion(String
datanodeMemoryProportion) {
return this;
}
+
+ @Override
+ public CommonConfig setEnableAuditLog(boolean enableAuditLog) {
+ return this;
+ }
+
+ @Override
+ public CommonConfig setAuditableOperationType(String auditableOperationType)
{
+ return this;
+ }
+
+ @Override
+ public CommonConfig setAuditableOperationLevel(String
auditableOperationLevel) {
+ return this;
+ }
+
+ @Override
+ public CommonConfig setAuditableOperationResult(String
auditableOperationResult) {
+ return this;
+ }
}
diff --git
a/integration-test/src/main/java/org/apache/iotdb/itbase/env/CommonConfig.java
b/integration-test/src/main/java/org/apache/iotdb/itbase/env/CommonConfig.java
index 0d11b05b0bf..9767e1c089e 100644
---
a/integration-test/src/main/java/org/apache/iotdb/itbase/env/CommonConfig.java
+++
b/integration-test/src/main/java/org/apache/iotdb/itbase/env/CommonConfig.java
@@ -203,4 +203,12 @@ public interface CommonConfig {
CommonConfig setTrustStorePwd(String trustStorePwd);
CommonConfig setDatanodeMemoryProportion(String datanodeMemoryProportion);
+
+ CommonConfig setEnableAuditLog(boolean enableAuditLog);
+
+ CommonConfig setAuditableOperationType(String auditableOperationType);
+
+ CommonConfig setAuditableOperationLevel(String auditableOperationLevel);
+
+ CommonConfig setAuditableOperationResult(String auditableOperationResult);
}
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
new file mode 100644
index 00000000000..0f831ad8a74
--- /dev/null
+++
b/integration-test/src/test/java/org/apache/iotdb/db/it/audit/IoTDBAuditLogBasicIT.java
@@ -0,0 +1,430 @@
+/*
+ * 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.iotdb.db.it.audit;
+
+import org.apache.iotdb.commons.audit.AbstractAuditLogger;
+import org.apache.iotdb.commons.audit.AuditLogOperation;
+import org.apache.iotdb.commons.audit.PrivilegeLevel;
+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.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.StringJoiner;
+
+@RunWith(IoTDBTestRunner.class)
+@Category({LocalStandaloneIT.class})
+public class IoTDBAuditLogBasicIT {
+
+ private static final Logger LOGGER =
LoggerFactory.getLogger(IoTDBAuditLogBasicIT.class);
+
+ /**
+ * Ensure the Audit log behave exactly the same as we expected, including
number, sequence and
+ * content.
+ */
+ private static final List<String> AUDIT_TABLE_COLUMNS =
+ Arrays.asList(
+ AbstractAuditLogger.AUDIT_LOG_NODE_ID,
+ AbstractAuditLogger.AUDIT_LOG_USER_ID,
+ AbstractAuditLogger.AUDIT_LOG_USERNAME,
+ AbstractAuditLogger.AUDIT_LOG_CLI_HOSTNAME,
+ AbstractAuditLogger.AUDIT_LOG_AUDIT_EVENT_TYPE,
+ AbstractAuditLogger.AUDIT_LOG_OPERATION_TYPE,
+ AbstractAuditLogger.AUDIT_LOG_PRIVILEGE_TYPE,
+ AbstractAuditLogger.AUDIT_LOG_PRIVILEGE_LEVEL,
+ AbstractAuditLogger.AUDIT_LOG_RESULT,
+ AbstractAuditLogger.AUDIT_LOG_DATABASE,
+ AbstractAuditLogger.AUDIT_LOG_SQL_STRING,
+ AbstractAuditLogger.AUDIT_LOG_LOG);
+
+ private static final List<String> AUDIT_TABLE_DATA_TYPES =
+ Arrays.asList(
+ "STRING", "STRING", "STRING", "STRING", "STRING", "STRING",
"STRING", "STRING", "BOOLEAN",
+ "STRING", "STRING", "STRING");
+
+ private static final List<String> AUDIT_TABLE_CATEGORIES =
+ Arrays.asList(
+ "TAG", "TAG", "FIELD", "FIELD", "FIELD", "FIELD", "FIELD", "FIELD",
"FIELD", "FIELD",
+ "FIELD", "FIELD");
+
+ private static final boolean ENABLE_AUDIT_LOG = true;
+ private static final String AUDITABLE_OPERATION_TYPE =
+ new StringJoiner(",")
+ .add(AuditLogOperation.DDL.toString())
+ .add(AuditLogOperation.DML.toString())
+ .add(AuditLogOperation.QUERY.toString())
+ .add(AuditLogOperation.CONTROL.toString())
+ .toString();
+
+ private static final String AUDITABLE_OPERATION_LEVEL =
PrivilegeLevel.GLOBAL.toString();
+
+ private static final String AUDITABLE_OPERATION_RESULT = "SUCCESS,FAIL";
+
+ @BeforeClass
+ public static void setUp() throws SQLException {
+ EnvFactory.getEnv()
+ .getConfig()
+ .getCommonConfig()
+ .setEnableAuditLog(ENABLE_AUDIT_LOG)
+ .setAuditableOperationType(AUDITABLE_OPERATION_TYPE)
+ .setAuditableOperationLevel(AUDITABLE_OPERATION_LEVEL)
+ .setAuditableOperationResult(AUDITABLE_OPERATION_RESULT);
+
+ // 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));
+ }
+
+ 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);
+ }
+ }
+
+ @AfterClass
+ public static void tearDown() {
+ EnvFactory.getEnv().cleanClusterEnvironment();
+ }
+
+ private static final List<String> TABLE_MODEL_AUDIT_SQLS =
+ Arrays.asList(
+ "CREATE DATABASE test",
+ // "SHOW DATABASES",
+ "ALTER DATABASE test SET PROPERTIES TTL='INF'",
+ "USE test",
+ "CREATE TABLE table1(t1 STRING TAG, a1 STRING ATTRIBUTE, s1 TEXT
FIELD)",
+ "SHOW TABLES",
+ "DESC table1",
+ "ALTER TABLE table1 set properties TTL='INF'",
+ "INSERT INTO table1(time, t1, a1, s1) values(1, 't1', 'a1', 's1')",
+ "DELETE FROM table1",
+ "DROP TABLE table1",
+ "DROP DATABASE IF EXISTS test");
+ private static final List<List<String>> TABLE_MODEL_AUDIT_FIELDS =
+ Arrays.asList(
+ // Start DataNode
+ Arrays.asList(
+ "node_1",
+ "u_none",
+ "null",
+ "null",
+ "CHANGE_AUDIT_OPTION",
+ "CONTROL",
+ "[AUDIT]",
+ "GLOBAL",
+ "true",
+ "null",
+ "null",
+ "Successfully start the Audit service with configurations
(auditableOperationType [DDL, DML, QUERY, CONTROL], auditableOperationLevel
GLOBAL, auditableOperationResult SUCCESS,FAIL)"),
+ // Show audit database TODO: Fix typo in tree model
+ Arrays.asList(
+ "node_1",
+ "u_0",
+ "root",
+ "127.0.0.1",
+ "OBJECT_AUTHENTICATION",
+ "QUERY",
+ "[MANAGE_DATABASE]",
+ "GLOBAL",
+ "true",
+ "[root.__audit]",
+ "null",
+ "User root (ID=0) requests authority on object root.__audit with
result true"),
+ // Desc audit table
+ Arrays.asList(
+ "node_1",
+ "u_0",
+ "root",
+ "127.0.0.1",
+ "OBJECT_AUTHENTICATION",
+ "QUERY",
+ "[READ_SCHEMA]",
+ "OBJECT",
+ "true",
+ "__audit",
+ "DESC __audit.audit_log",
+ "User root (ID=0) requests authority on object audit_log with
result true"),
+ // Create database
+ Arrays.asList(
+ "node_1",
+ "u_0",
+ "root",
+ "127.0.0.1",
+ "OBJECT_AUTHENTICATION",
+ "DDL",
+ "[CREATE]",
+ "OBJECT",
+ "true",
+ "test",
+ "CREATE DATABASE test",
+ "User root (ID=0) requests authority on object test with result
true"),
+ // Show database TODO: Enable only when the order of show databases
authentication fixed
+ // Arrays.asList(
+ // "node_1",
+ // "u_0",
+ // "root",
+ // "127.0.0.1",
+ // "OBJECT_AUTHENTICATION",
+ // "QUERY",
+ // "[READ_SCHEMA]",
+ // "OBJECT",
+ // "true",
+ // "test",
+ // "SHOW DATABASES",
+ // "User root (ID=0) requests authority on object test with
result true"),
+ // Arrays.asList(
+ // "node_1",
+ // "u_0",
+ // "root",
+ // "127.0.0.1",
+ // "OBJECT_AUTHENTICATION",
+ // "QUERY",
+ // "[READ_SCHEMA]",
+ // "OBJECT",
+ // "true",
+ // "information_schema",
+ // "SHOW DATABASES",
+ // "User root (ID=0) requests authority on object
information_schema with
+ // result true"),
+ // Arrays.asList(
+ // "node_1",
+ // "u_0",
+ // "root",
+ // "127.0.0.1",
+ // "OBJECT_AUTHENTICATION",
+ // "QUERY",
+ // "[READ_SCHEMA]",
+ // "OBJECT",
+ // "true",
+ // "__audit",
+ // "SHOW DATABASES",
+ // "User root (ID=0) requests authority on object test
with result true"),
+ // Alter database
+ Arrays.asList(
+ "node_1",
+ "u_0",
+ "root",
+ "127.0.0.1",
+ "OBJECT_AUTHENTICATION",
+ "DDL",
+ "[ALTER]",
+ "OBJECT",
+ "true",
+ "test",
+ "ALTER DATABASE test SET PROPERTIES TTL='INF'",
+ "User root (ID=0) requests authority on object test with result
true"),
+ // Use database TODO: Find out why twice
+ Arrays.asList(
+ "node_1",
+ "u_0",
+ "root",
+ "127.0.0.1",
+ "OBJECT_AUTHENTICATION",
+ "QUERY",
+ "[READ_SCHEMA]",
+ "OBJECT",
+ "true",
+ "test",
+ "USE test",
+ "User root (ID=0) requests authority on object test with result
true"),
+ Arrays.asList(
+ "node_1",
+ "u_0",
+ "root",
+ "127.0.0.1",
+ "OBJECT_AUTHENTICATION",
+ "QUERY",
+ "[READ_SCHEMA]",
+ "OBJECT",
+ "true",
+ "test",
+ "USE test",
+ "User root (ID=0) requests authority on object test with result
true"),
+ // Create table
+ Arrays.asList(
+ "node_1",
+ "u_0",
+ "root",
+ "127.0.0.1",
+ "OBJECT_AUTHENTICATION",
+ "DDL",
+ "[SYSTEM]",
+ "GLOBAL",
+ "true",
+ "test",
+ "CREATE TABLE table1(t1 STRING TAG, a1 STRING ATTRIBUTE, s1 TEXT
FIELD)",
+ "User root (ID=0) requests authority on object table1 with
result true"),
+ // Show table
+ Arrays.asList(
+ "node_1",
+ "u_0",
+ "root",
+ "127.0.0.1",
+ "OBJECT_AUTHENTICATION",
+ "QUERY",
+ "[READ_SCHEMA]",
+ "OBJECT",
+ "true",
+ "test",
+ "SHOW TABLES",
+ "User root (ID=0) requests authority on object table1 with
result true"),
+ // Desc table
+ Arrays.asList(
+ "node_1",
+ "u_0",
+ "root",
+ "127.0.0.1",
+ "OBJECT_AUTHENTICATION",
+ "QUERY",
+ "[READ_SCHEMA]",
+ "OBJECT",
+ "true",
+ "test",
+ "DESC table1",
+ "User root (ID=0) requests authority on object table1 with
result true"),
+ // Insert into table
+ Arrays.asList(
+ "node_1",
+ "u_0",
+ "root",
+ "127.0.0.1",
+ "OBJECT_AUTHENTICATION",
+ "DML",
+ "[INSERT]",
+ "OBJECT",
+ "true",
+ "test",
+ "INSERT INTO table1(time, t1, a1, s1) values(1, 't1', 'a1',
's1')",
+ "User root (ID=0) requests authority on object table1 with
result true"),
+ // Delete table TODO: find the delete SQL
+ Arrays.asList(
+ "node_1",
+ "u_0",
+ "root",
+ "127.0.0.1",
+ "OBJECT_AUTHENTICATION",
+ "DML",
+ "[DELETE]",
+ "OBJECT",
+ "true",
+ "test",
+ "null",
+ "User root (ID=0) requests authority on object table1 with
result true"),
+ // Drop database
+ Arrays.asList(
+ "node_1",
+ "u_0",
+ "root",
+ "127.0.0.1",
+ "OBJECT_AUTHENTICATION",
+ "DDL",
+ "[DROP]",
+ "OBJECT",
+ "true",
+ "test",
+ "DROP DATABASE IF EXISTS test",
+ "User root (ID=0) requests authority on object test with result
true"),
+ // Select audit log TODO: find out why twice
+ Arrays.asList(
+ "node_1",
+ "u_0",
+ "root",
+ "127.0.0.1",
+ "OBJECT_AUTHENTICATION",
+ "QUERY",
+ "[SELECT]",
+ "OBJECT",
+ "true",
+ "__audit",
+ "null",
+ "User root (ID=0) requests authority on object __audit with
result true"),
+ Arrays.asList(
+ "node_1",
+ "u_0",
+ "root",
+ "127.0.0.1",
+ "OBJECT_AUTHENTICATION",
+ "QUERY",
+ "[SELECT]",
+ "OBJECT",
+ "true",
+ "__audit",
+ "null",
+ "User root (ID=0) requests authority on object __audit with
result true"));
+
+ @Test
+ public void basicAuditLogTestForTableModel() throws SQLException {
+ try (Connection connection =
EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ Statement statement = connection.createStatement()) {
+ for (String sql : TABLE_MODEL_AUDIT_SQLS) {
+ statement.execute(sql);
+ }
+ int count = 0;
+ ResultSet resultSet = statement.executeQuery("SELECT * FROM
__audit.audit_log");
+ while (resultSet.next()) {
+ LOGGER.info("Expected audit log: {}",
TABLE_MODEL_AUDIT_FIELDS.get(count));
+ List<String> actualFields = new ArrayList<>();
+ for (int i = 1; i <= 12; i++) {
+ actualFields.add(resultSet.getString(i + 1));
+ }
+ LOGGER.info("Actual audit log: {}", actualFields);
+ List<String> expectedFields = TABLE_MODEL_AUDIT_FIELDS.get(count);
+ for (int i = 1; i <= 11; i++) {
+ Assert.assertEquals(expectedFields.get(i - 1), resultSet.getString(i
+ 1));
+ }
+
Assert.assertTrue(resultSet.getString(13).contains(expectedFields.get(11)));
+ count++;
+ }
+ Assert.assertEquals(TABLE_MODEL_AUDIT_FIELDS.size(), count);
+ }
+ }
+}
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 ef69a5c8403..39df9137f4f 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
@@ -88,17 +88,6 @@ public class DNAuditLogger extends AbstractAuditLogger {
private static final int INSERT_RETRY_INTERVAL_MS = 2000;
private static final IoTDBConfig config =
IoTDBDescriptor.getInstance().getConfig();
- private static final String LOG = "log";
- private static final String USERNAME = "username";
- private static final String USER_ID = "user_id";
- private static final String CLI_HOSTNAME = "cli_hostname";
- private static final String RESULT = "result";
- private static final String AUDIT_EVENT_TYPE = "audit_event_type";
- private static final String OPERATION_TYPE = "operation_type";
- private static final String PRIVILEGE_TYPE = "privilege_type";
- private static final String PRIVILEGE_LEVEL = "privilege_level";
- private static final String DATABASE = "database";
- private static final String SQL_STRING = "sql_string";
private static final String AUDIT_LOG_DEVICE =
"root.__audit.log.node_%s.u_%s";
private static final String AUDIT_LOGIN_LOG_DEVICE =
"root.__audit.login.node_%s.u_%s";
@@ -155,16 +144,16 @@ public class DNAuditLogger extends AbstractAuditLogger {
insertStatement.setTime(CommonDateTimeUtils.currentTime());
insertStatement.setMeasurements(
new String[] {
- USERNAME,
- CLI_HOSTNAME,
- AUDIT_EVENT_TYPE,
- OPERATION_TYPE,
- PRIVILEGE_TYPE,
- PRIVILEGE_LEVEL,
- RESULT,
- DATABASE,
- SQL_STRING,
- LOG
+ AUDIT_LOG_USERNAME,
+ AUDIT_LOG_CLI_HOSTNAME,
+ AUDIT_LOG_AUDIT_EVENT_TYPE,
+ AUDIT_LOG_OPERATION_TYPE,
+ AUDIT_LOG_PRIVILEGE_TYPE,
+ AUDIT_LOG_PRIVILEGE_LEVEL,
+ AUDIT_LOG_RESULT,
+ AUDIT_LOG_DATABASE,
+ AUDIT_LOG_SQL_STRING,
+ AUDIT_LOG_LOG
});
insertStatement.setAligned(false);
insertStatement.setValues(
@@ -285,20 +274,33 @@ public class DNAuditLogger extends AbstractAuditLogger {
}
stmt =
relationSqlParser.createStatement(
- "CREATE VIEW __audit.audit_log (\n"
- + " node_id STRING TAG,\n"
- + " user_id STRING TAG,\n"
- + " username STRING FIELD,\n"
- + " cli_hostname STRING FIELD,\n"
- + " audit_event_type STRING FIELD,\n"
- + " operation_type STRING FIELD,\n"
- + " privilege_type STRING FIELD,\n"
- + " privilege_level STRING FIELD,\n"
- + " result BOOLEAN FIELD,\n"
- + " database STRING FIELD,\n"
- + " sql_string STRING FIELD,\n"
- + " log STRING FIELD\n"
- + ") AS root.__audit.log.**",
+ String.format(
+ "CREATE VIEW __audit.audit_log (\n"
+ + " %s STRING TAG,\n"
+ + " %s STRING TAG,\n"
+ + " %s STRING FIELD,\n"
+ + " %s STRING FIELD,\n"
+ + " %s STRING FIELD,\n"
+ + " %s STRING FIELD,\n"
+ + " %s STRING FIELD,\n"
+ + " %s STRING FIELD,\n"
+ + " %s BOOLEAN FIELD,\n"
+ + " %s STRING FIELD,\n"
+ + " %s STRING FIELD,\n"
+ + " %s STRING FIELD\n"
+ + ") AS root.__audit.log.**",
+ AUDIT_LOG_NODE_ID,
+ AUDIT_LOG_USER_ID,
+ AUDIT_LOG_USERNAME,
+ AUDIT_LOG_CLI_HOSTNAME,
+ AUDIT_LOG_AUDIT_EVENT_TYPE,
+ AUDIT_LOG_OPERATION_TYPE,
+ AUDIT_LOG_PRIVILEGE_TYPE,
+ AUDIT_LOG_PRIVILEGE_LEVEL,
+ AUDIT_LOG_RESULT,
+ AUDIT_LOG_DATABASE,
+ AUDIT_LOG_SQL_STRING,
+ AUDIT_LOG_LOG),
ZoneId.systemDefault(),
session);
status =
@@ -395,6 +397,9 @@ public class DNAuditLogger extends AbstractAuditLogger {
public void logFromCN(AuditLogFields auditLogFields, String log, int nodeId)
throws IllegalPathException {
+ if (!IS_AUDIT_LOG_ENABLED) {
+ return;
+ }
createViewIfNecessary();
if (noNeedInsertAuditLog(auditLogFields)) {
return;
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/DataNodeInternalRPCServiceImpl.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/DataNodeInternalRPCServiceImpl.java
index b5b6d919d5e..433497657e7 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/DataNodeInternalRPCServiceImpl.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/DataNodeInternalRPCServiceImpl.java
@@ -2994,8 +2994,8 @@ public class DataNodeInternalRPCServiceImpl implements
IDataNodeRPCService.Iface
public TSStatus writeAuditLog(TAuditLogReq req) {
AuditLogFields fields =
new AuditLogFields(
- req.getUsername(),
req.getUserId(),
+ req.getUsername(),
req.getCliHostname(),
AuditEventType.valueOf(req.getAuditEventType()),
AuditLogOperation.valueOf(req.getOperationType()),
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/MPPQueryContext.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/MPPQueryContext.java
index 8ab0347b626..27a1beba195 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/MPPQueryContext.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/MPPQueryContext.java
@@ -443,6 +443,8 @@ public class MPPQueryContext implements IAuditEntity {
private List<PrivilegeType> privilegeTypeList;
+ private String databaseName;
+
private boolean result;
@Override
@@ -517,12 +519,12 @@ public class MPPQueryContext implements IAuditEntity {
@Override
public String getDatabase() {
- return session.getDatabaseName().orElse("");
+ return databaseName;
}
@Override
public IAuditEntity setDatabase(String database) {
- // Do nothing
+ this.databaseName = database;
return this;
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/TableConfigTaskVisitor.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/TableConfigTaskVisitor.java
index 8020ffab1bb..7b80d20d1b7 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/TableConfigTaskVisitor.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/TableConfigTaskVisitor.java
@@ -535,7 +535,7 @@ public class TableConfigTaskVisitor extends
AstVisitor<IConfigTask, MPPQueryCont
final Pair<String, String> databaseTablePair =
splitQualifiedName(node.getName());
final String database = databaseTablePair.getLeft();
final String tableName = databaseTablePair.getRight();
-
+ context.setDatabase(database);
accessControl.checkCanCreateTable(
context.getSession().getUserName(), new QualifiedObjectName(database,
tableName), context);
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/AccessControlImpl.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/AccessControlImpl.java
index a121b905abd..3395f8f6f2a 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/AccessControlImpl.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/AccessControlImpl.java
@@ -20,6 +20,7 @@
package org.apache.iotdb.db.queryengine.plan.relational.security;
import org.apache.iotdb.common.rpc.thrift.TSStatus;
+import org.apache.iotdb.commons.audit.AuditLogOperation;
import org.apache.iotdb.commons.audit.IAuditEntity;
import org.apache.iotdb.commons.audit.UserEntity;
import org.apache.iotdb.commons.auth.entity.PrivilegeType;
@@ -76,14 +77,14 @@ public class AccessControlImpl implements AccessControl {
String userName, String databaseName, IAuditEntity auditEntity) {
InformationSchemaUtils.checkDBNameInWrite(databaseName);
authChecker.checkDatabasePrivilege(
- userName, databaseName, TableModelPrivilege.CREATE, auditEntity);
+ userName, databaseName, TableModelPrivilege.CREATE,
auditEntity.setDatabase(databaseName));
}
@Override
public void checkCanDropDatabase(String userName, String databaseName,
IAuditEntity auditEntity) {
InformationSchemaUtils.checkDBNameInWrite(databaseName);
authChecker.checkDatabasePrivilege(
- userName, databaseName, TableModelPrivilege.DROP, auditEntity);
+ userName, databaseName, TableModelPrivilege.DROP,
auditEntity.setDatabase(databaseName));
}
@Override
@@ -91,18 +92,20 @@ public class AccessControlImpl implements AccessControl {
String userName, String databaseName, IAuditEntity auditEntity) {
InformationSchemaUtils.checkDBNameInWrite(databaseName);
authChecker.checkDatabasePrivilege(
- userName, databaseName, TableModelPrivilege.ALTER, auditEntity);
+ userName, databaseName, TableModelPrivilege.ALTER,
auditEntity.setDatabase(databaseName));
}
@Override
public void checkCanShowOrUseDatabase(
String userName, String databaseName, IAuditEntity auditEntity) {
- authChecker.checkDatabaseVisibility(userName, databaseName, auditEntity);
+ authChecker.checkDatabaseVisibility(
+ userName, databaseName, auditEntity.setDatabase(databaseName));
}
@Override
public void checkCanCreateTable(
String userName, QualifiedObjectName tableName, IAuditEntity
auditEntity) {
+ auditEntity.setAuditLogOperation(AuditLogOperation.DDL);
InformationSchemaUtils.checkDBNameInWrite(tableName.getDatabaseName());
if (userName.equals(AuthorityChecker.INTERNAL_AUDIT_USER)
&& tableName.getDatabaseName().equals(TABLE_MODEL_AUDIT_DATABASE)) {
@@ -111,6 +114,9 @@ public class AccessControlImpl implements AccessControl {
}
checkAuditDatabase(tableName.getDatabaseName());
if (hasGlobalPrivilege(auditEntity, PrivilegeType.SYSTEM)) {
+ ITableAuthCheckerImpl.recordAuditLog(
+ auditEntity.setPrivilegeType(PrivilegeType.SYSTEM).setResult(true),
+ tableName.getObjectName());
return;
}
authChecker.checkTablePrivilege(userName, tableName,
TableModelPrivilege.CREATE, auditEntity);
@@ -122,6 +128,7 @@ public class AccessControlImpl implements AccessControl {
InformationSchemaUtils.checkDBNameInWrite(tableName.getDatabaseName());
checkAuditDatabase(tableName.getDatabaseName());
if (hasGlobalPrivilege(auditEntity, PrivilegeType.SYSTEM)) {
+ ITableAuthCheckerImpl.recordAuditLog(auditEntity,
tableName.getObjectName());
return;
}
authChecker.checkTablePrivilege(userName, tableName,
TableModelPrivilege.DROP, auditEntity);
@@ -133,6 +140,7 @@ public class AccessControlImpl implements AccessControl {
InformationSchemaUtils.checkDBNameInWrite(tableName.getDatabaseName());
checkAuditDatabase(tableName.getDatabaseName());
if (hasGlobalPrivilege(auditEntity, PrivilegeType.SYSTEM)) {
+ ITableAuthCheckerImpl.recordAuditLog(auditEntity,
tableName.getObjectName());
return;
}
authChecker.checkTablePrivilege(userName, tableName,
TableModelPrivilege.ALTER, auditEntity);
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/ITableAuthCheckerImpl.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/ITableAuthCheckerImpl.java
index 56ccdcb1744..af648895320 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/ITableAuthCheckerImpl.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/ITableAuthCheckerImpl.java
@@ -242,6 +242,7 @@ public class ITableAuthCheckerImpl implements
ITableAuthChecker {
QualifiedObjectName tableName,
TableModelPrivilege privilege,
IAuditEntity auditEntity) {
+ auditEntity.setDatabase(tableName.getDatabaseName());
if (AuthorityChecker.SUPER_USER_ID == auditEntity.getUserId()) {
recordAuditLog(
auditEntity
@@ -329,6 +330,7 @@ public class ITableAuthCheckerImpl implements
ITableAuthChecker {
@Override
public void checkTableVisibility(
String userName, QualifiedObjectName tableName, IAuditEntity
auditEntity) {
+ auditEntity.setDatabase(tableName.getDatabaseName());
if (AuthorityChecker.SUPER_USER_ID == auditEntity.getUserId()) {
recordAuditLog(
auditEntity
@@ -477,7 +479,7 @@ public class ITableAuthCheckerImpl implements
ITableAuthChecker {
auditObject);
}
- private static void recordAuditLog(IAuditEntity auditEntity, String
auditObject) {
+ public static void recordAuditLog(IAuditEntity auditEntity, String
auditObject) {
AUDIT_LOGGER.log(
auditEntity.setAuditEventType(AuditEventType.OBJECT_AUTHENTICATION),
() ->
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/TreeAccessCheckVisitor.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/TreeAccessCheckVisitor.java
index dc485c00e23..65a2ebc1ea7 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/TreeAccessCheckVisitor.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/TreeAccessCheckVisitor.java
@@ -915,7 +915,14 @@ public class TreeAccessCheckVisitor extends
StatementVisitor<TSStatus, TreeAcces
@Override
public TSStatus visitShowDatabase(
ShowDatabaseStatement showDatabaseStatement, TreeAccessCheckContext
context) {
- context.setAuditLogOperation(AuditLogOperation.QUERY);
+ context
+ .setAuditLogOperation(AuditLogOperation.QUERY)
+ .setDatabase(
+ showDatabaseStatement.getPaths().stream()
+ .distinct()
+ .collect(Collectors.toList())
+ .toString())
+ .setPrivilegeType(PrivilegeType.MANAGE_DATABASE);
if (AuthorityChecker.SUPER_USER.equals(context.getUsername())) {
recordObjectAuthenticationAuditLog(
context.setResult(true), () ->
showDatabaseStatement.getPathPattern().toString());
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/service/DataNode.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/service/DataNode.java
index 1964b19bb1e..4760efe7dbd 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/service/DataNode.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/service/DataNode.java
@@ -276,9 +276,9 @@ public class DataNode extends ServerCommandLine implements
DataNodeMBean {
DNAuditLogger.getInstance().setCoordinator(Coordinator.getInstance());
AuditLogFields fields =
new AuditLogFields(
- null,
-1,
null,
+ null,
AuditEventType.CHANGE_AUDIT_OPTION,
AuditLogOperation.CONTROL,
PrivilegeType.AUDIT,
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/service/DataNodeShutdownHook.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/service/DataNodeShutdownHook.java
index a2d91eb1f32..be9ef315dd9 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/service/DataNodeShutdownHook.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/service/DataNodeShutdownHook.java
@@ -97,9 +97,9 @@ public class DataNodeShutdownHook extends Thread {
logger.info("DataNode exiting...");
AuditLogFields fields =
new AuditLogFields(
- null,
-1,
null,
+ null,
AuditEventType.DN_SHUTDOWN,
AuditLogOperation.CONTROL,
PrivilegeType.SYSTEM,
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/DataNodeAuthUtils.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/DataNodeAuthUtils.java
index 05ab37a696c..b487c0d78f8 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/DataNodeAuthUtils.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/DataNodeAuthUtils.java
@@ -86,8 +86,8 @@ public class DataNodeAuthUtils {
new SessionInfo(
0,
new UserEntity(
- AuthorityChecker.SUPER_USER_ID,
- AuthorityChecker.SUPER_USER,
+ AuthorityChecker.INTERNAL_AUDIT_USER_ID,
+ AuthorityChecker.INTERNAL_AUDIT_USER,
IoTDBDescriptor.getInstance().getConfig().getInternalAddress()),
ZoneId.systemDefault());
@@ -183,8 +183,8 @@ public class DataNodeAuthUtils {
new SessionInfo(
0,
new UserEntity(
- AuthorityChecker.SUPER_USER_ID,
- AuthorityChecker.SUPER_USER,
+ AuthorityChecker.INTERNAL_AUDIT_USER_ID,
+ AuthorityChecker.INTERNAL_AUDIT_USER,
IoTDBDescriptor.getInstance().getConfig().getInternalAddress()),
ZoneId.systemDefault());
@@ -236,8 +236,8 @@ public class DataNodeAuthUtils {
new SessionInfo(
0,
new UserEntity(
- AuthorityChecker.SUPER_USER_ID,
- AuthorityChecker.SUPER_USER,
+ AuthorityChecker.INTERNAL_AUDIT_USER_ID,
+ AuthorityChecker.INTERNAL_AUDIT_USER,
IoTDBDescriptor.getInstance().getConfig().getInternalAddress()),
ZoneId.systemDefault());
diff --git
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/audit/AbstractAuditLogger.java
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/audit/AbstractAuditLogger.java
index e89726e8b2d..59554ed5133 100644
---
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/audit/AbstractAuditLogger.java
+++
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/audit/AbstractAuditLogger.java
@@ -27,15 +27,26 @@ import java.util.List;
import java.util.function.Supplier;
public abstract class AbstractAuditLogger {
+
+ public static final String AUDIT_LOG_NODE_ID = "node_id";
+ public static final String AUDIT_LOG_USER_ID = "user_id";
+ public static final String AUDIT_LOG_USERNAME = "username";
+ public static final String AUDIT_LOG_CLI_HOSTNAME = "cli_hostname";
+ public static final String AUDIT_LOG_AUDIT_EVENT_TYPE = "audit_event_type";
+ public static final String AUDIT_LOG_OPERATION_TYPE = "operation_type";
+ public static final String AUDIT_LOG_PRIVILEGE_TYPE = "privilege_type";
+ public static final String AUDIT_LOG_PRIVILEGE_LEVEL = "privilege_level";
+ public static final String AUDIT_LOG_RESULT = "result";
+ public static final String AUDIT_LOG_DATABASE = "database";
+ public static final String AUDIT_LOG_SQL_STRING = "sql_string";
+ public static final String AUDIT_LOG_LOG = "log";
+
private static final CommonConfig CONFIG =
CommonDescriptor.getInstance().getConfig();
protected static final boolean IS_AUDIT_LOG_ENABLED =
CONFIG.isEnableAuditLog();
-
private static final List<AuditLogOperation> AUDITABLE_OPERATION_TYPE =
CONFIG.getAuditableOperationType();
-
private static final PrivilegeLevel AUDITABLE_OPERATION_LEVEL =
CONFIG.getAuditableOperationLevel();
-
private static final String AUDITABLE_OPERATION_RESULT =
CONFIG.getAuditableOperationResult();
public abstract void log(IAuditEntity auditLogFields, Supplier<String> log);
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 06a0545a310..98af46e30fd 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
@@ -37,12 +37,12 @@ public class AuditLogFields implements IAuditEntity {
private final String sqlString;
public AuditLogFields(
- String username,
long userId,
+ String username,
String cliHostname,
AuditEventType auditType,
AuditLogOperation operationType,
- PrivilegeType privilegeType,
+ List<PrivilegeType> privilegeTypes,
boolean result,
String database,
String sqlString) {
@@ -51,12 +51,34 @@ public class AuditLogFields implements IAuditEntity {
this.cliHostname = cliHostname;
this.auditType = auditType;
this.operationType = operationType;
- this.privilegeTypes = Collections.singletonList(privilegeType);
+ this.privilegeTypes = privilegeTypes;
this.result = result;
this.database = database;
this.sqlString = sqlString;
}
+ public AuditLogFields(
+ long userId,
+ String username,
+ String cliHostname,
+ AuditEventType auditType,
+ AuditLogOperation operationType,
+ PrivilegeType privilegeType,
+ boolean result,
+ String database,
+ String sqlString) {
+ this(
+ userId,
+ username,
+ cliHostname,
+ auditType,
+ operationType,
+ Collections.singletonList(privilegeType),
+ result,
+ database,
+ sqlString);
+ }
+
public String getUsername() {
return username;
}