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 83aa06dc61dce..547d7e37bef00 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 @@ -196,6 +196,7 @@ public static void closeConnectionCompletely(Connection connection) throws Inter "DROP DATABASE IF EXISTS test", "REVOKE SELECT,ALTER,INSERT,DELETE ON TEST.TABLE1 FROM USER user1", "REVOKE SELECT ON ANY FROM ROLE role1", + "REVOKE ROLE role1 FROM user2", "DROP USER user1", "DROP USER user2", "DROP ROLE role1"); @@ -634,7 +635,33 @@ public static void closeConnectionCompletely(Connection connection) throws Inter "true", "null", "GRANT ROLE role1 TO user2", - "User root (ID=0) requests authority on object user: user2, role: role1 with result true")), + "User root (ID=0) requests authority on object user: user2, role: role1 with result true"), + Arrays.asList( + "node_1", + "u_0", + "root", + "127.0.0.1", + "MODIFY_SECURITY_FUNCTION", + "CONTROL", + "[SECURITY]", + "GLOBAL", + "true", + "test", + "GRANT ROLE role1 TO user2", + "security function: user-role membership, user: user2, role: role1"), + Arrays.asList( + "node_1", + "u_0", + "root", + "127.0.0.1", + "MODIFY_ROLE_MEMBERSHIP", + "CONTROL", + "[SECURITY]", + "GLOBAL", + "true", + "test", + "GRANT ROLE role1 TO user2", + "user: user2, role: role1")), // List user/role, the authentication object is null since the root can list all new AuditLogSet( Arrays.asList( @@ -1192,7 +1219,46 @@ public static void closeConnectionCompletely(Connection connection) throws Inter "true", "null", "REVOKE SELECT ON ANY FROM ROLE role1", - "User root (ID=0) requests authority on object role1 with result true")), + "User root (ID=0) requests authority on object role1 with result true"), + Arrays.asList( + "node_1", + "u_0", + "root", + "127.0.0.1", + "OBJECT_AUTHENTICATION", + "DDL", + "[SECURITY]", + "GLOBAL", + "true", + "null", + "REVOKE ROLE role1 FROM user2", + "User root (ID=0) requests authority on object user: user2, role: role1 with result true"), + Arrays.asList( + "node_1", + "u_0", + "root", + "127.0.0.1", + "MODIFY_SECURITY_FUNCTION", + "CONTROL", + "[SECURITY]", + "GLOBAL", + "true", + "null", + "REVOKE ROLE role1 FROM user2", + "security function: user-role membership, user: user2, role: role1"), + Arrays.asList( + "node_1", + "u_0", + "root", + "127.0.0.1", + "MODIFY_ROLE_MEMBERSHIP", + "CONTROL", + "[SECURITY]", + "GLOBAL", + "true", + "null", + "REVOKE ROLE role1 FROM user2", + "user: user2, role: role1")), // Drop user, role new AuditLogSet( Arrays.asList( @@ -1352,6 +1418,7 @@ public void basicAuditLogTestForTableModel() throws SQLException, InterruptedExc "drop timeseries root.test.d1.*", "REVOKE READ_DATA, WRITE_DATA ON root.test.** FROM USER user1", "REVOKE READ ON root.test.** FROM ROLE role1", + "REVOKE ROLE role1 FROM user2", "DROP USER user1", "DROP USER user2", "DROP ROLE role1", @@ -1784,6 +1851,30 @@ public void basicAuditLogTestForTableModel() throws SQLException, InterruptedExc "GRANT ROLE role1 TO user2", "OBJECT_AUTHENTICATION", "127.0.0.1", + "root"), + Arrays.asList( + "root.__audit.log.node_1.u_0", + "true", + "GLOBAL", + "[SECURITY]", + "null", + "CONTROL", + "security function: user-role membership, user: user2, role: role1", + "GRANT ROLE role1 TO user2", + "MODIFY_SECURITY_FUNCTION", + "127.0.0.1", + "root"), + Arrays.asList( + "root.__audit.log.node_1.u_0", + "true", + "GLOBAL", + "[SECURITY]", + "null", + "CONTROL", + "user: user2, role: role1", + "GRANT ROLE role1 TO user2", + "MODIFY_ROLE_MEMBERSHIP", + "127.0.0.1", "root")), // List user/role, the target object is null since the root can list all, new AuditLogSet( @@ -2318,6 +2409,42 @@ public void basicAuditLogTestForTableModel() throws SQLException, InterruptedExc "REVOKE READ ON root.test.** FROM ROLE role1", "OBJECT_AUTHENTICATION", "127.0.0.1", + "root"), + Arrays.asList( + "root.__audit.log.node_1.u_0", + "true", + "GLOBAL", + "[MANAGE_ROLE]", + "null", + "DDL", + "User root (ID=0) requests authority on object user: user2, role: role1 with result true", + "REVOKE ROLE role1 FROM user2", + "OBJECT_AUTHENTICATION", + "127.0.0.1", + "root"), + Arrays.asList( + "root.__audit.log.node_1.u_0", + "true", + "GLOBAL", + "[SECURITY]", + "null", + "CONTROL", + "security function: user-role membership, user: user2, role: role1", + "REVOKE ROLE role1 FROM user2", + "MODIFY_SECURITY_FUNCTION", + "127.0.0.1", + "root"), + Arrays.asList( + "root.__audit.log.node_1.u_0", + "true", + "GLOBAL", + "[SECURITY]", + "null", + "CONTROL", + "user: user2, role: role1", + "REVOKE ROLE role1 FROM user2", + "MODIFY_ROLE_MEMBERSHIP", + "127.0.0.1", "root")), // Drop user/role new AuditLogSet( diff --git a/iotdb-core/datanode/src/main/i18n/en/org/apache/iotdb/db/i18n/DataNodeMiscMessages.java b/iotdb-core/datanode/src/main/i18n/en/org/apache/iotdb/db/i18n/DataNodeMiscMessages.java index b43037206ccdc..97947b140971f 100644 --- a/iotdb-core/datanode/src/main/i18n/en/org/apache/iotdb/db/i18n/DataNodeMiscMessages.java +++ b/iotdb-core/datanode/src/main/i18n/en/org/apache/iotdb/db/i18n/DataNodeMiscMessages.java @@ -121,6 +121,11 @@ public final class DataNodeMiscMessages { public static final String CREATE_NEW_REGION_ERROR_FMT = "create new region %s error, exception:%s"; public static final String CREATE_NEW_REGION_SUCCEED_FMT = "create new region %s succeed"; + public static final String LOG_USER_ARG_ROLE_ARG_422D48D3 = "user: %s, role: %s"; + public static final String + LOG_SECURITY_FUNCTION_USER_ROLE_MEMBERSHIP_USER_ARG_ROLE_ARG_0D500C5D = + "security function: user-role membership, user: %s, role: %s"; + private DataNodeMiscMessages() {} // --------------------------------------------------------------------------- diff --git a/iotdb-core/datanode/src/main/i18n/zh/org/apache/iotdb/db/i18n/DataNodeMiscMessages.java b/iotdb-core/datanode/src/main/i18n/zh/org/apache/iotdb/db/i18n/DataNodeMiscMessages.java index a319bce5000e6..0b105feab8c1f 100644 --- a/iotdb-core/datanode/src/main/i18n/zh/org/apache/iotdb/db/i18n/DataNodeMiscMessages.java +++ b/iotdb-core/datanode/src/main/i18n/zh/org/apache/iotdb/db/i18n/DataNodeMiscMessages.java @@ -121,6 +121,11 @@ public final class DataNodeMiscMessages { public static final String CREATE_NEW_REGION_ERROR_FMT = "创建新 region %s 错误,异常:%s"; public static final String CREATE_NEW_REGION_SUCCEED_FMT = "创建新 region %s 成功"; + public static final String LOG_USER_ARG_ROLE_ARG_422D48D3 = "用户:%s,角色:%s"; + public static final String + LOG_SECURITY_FUNCTION_USER_ROLE_MEMBERSHIP_USER_ARG_ROLE_ARG_0D500C5D = + "安全功能:用户角色成员关系,用户:%s,角色:%s"; + private DataNodeMiscMessages() {} // --------------------------------------------------------------------------- diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/audit/UserRoleModificationAuditContext.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/audit/UserRoleModificationAuditContext.java new file mode 100644 index 0000000000000..f4da86e655464 --- /dev/null +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/audit/UserRoleModificationAuditContext.java @@ -0,0 +1,132 @@ +/* + * 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.audit; + +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.auth.entity.PrivilegeType; +import org.apache.iotdb.commons.queryengine.common.SessionInfo; +import org.apache.iotdb.db.i18n.DataNodeMiscMessages; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.RelationalAuthorStatement; +import org.apache.iotdb.db.queryengine.plan.relational.type.AuthorRType; +import org.apache.iotdb.db.queryengine.plan.statement.AuthorType; +import org.apache.iotdb.db.queryengine.plan.statement.sys.AuthorStatement; +import org.apache.iotdb.rpc.TSStatusCode; + +import java.util.function.Supplier; + +/** Tracks one user-role membership statement and logs its successful security changes. */ +public class UserRoleModificationAuditContext { + + private final DNAuditLogger auditLogger; + private final String sqlString; + + private Long userId; + private String username; + private String clientAddress; + private String database; + private String targetUsername; + private String targetRoleName; + + public UserRoleModificationAuditContext(String sqlString) { + this(DNAuditLogger.getInstance(), sqlString); + } + + UserRoleModificationAuditContext(DNAuditLogger auditLogger, String sqlString) { + this.auditLogger = auditLogger; + this.sqlString = sqlString; + } + + public void setSessionInfo(SessionInfo sessionInfo) { + if (sessionInfo == null) { + return; + } + setActor( + sessionInfo.getUserId(), + sessionInfo.getUserName(), + sessionInfo.getCliHostname(), + sessionInfo.getDatabaseName().orElse(null)); + } + + private void setActor(long userId, String username, String clientAddress, String database) { + this.userId = userId; + this.username = username; + this.clientAddress = clientAddress; + this.database = database; + } + + public void track(AuthorStatement statement) { + if (statement.getAuthorType() == AuthorType.GRANT_USER_ROLE + || statement.getAuthorType() == AuthorType.REVOKE_USER_ROLE) { + targetUsername = statement.getUserName(); + targetRoleName = statement.getRoleName(); + } + } + + public void track(RelationalAuthorStatement statement) { + if (statement.getAuthorType() == AuthorRType.GRANT_USER_ROLE + || statement.getAuthorType() == AuthorRType.REVOKE_USER_ROLE) { + targetUsername = statement.getUserName(); + targetRoleName = statement.getRoleName(); + } + } + + public void log(TSStatus status) { + if (targetUsername == null || userId == null || !isSuccessful(status)) { + return; + } + logEvent( + AuditEventType.MODIFY_SECURITY_FUNCTION, + () -> + String.format( + DataNodeMiscMessages + .LOG_SECURITY_FUNCTION_USER_ROLE_MEMBERSHIP_USER_ARG_ROLE_ARG_0D500C5D, + targetUsername, + targetRoleName)); + logEvent( + AuditEventType.MODIFY_ROLE_MEMBERSHIP, + () -> + String.format( + DataNodeMiscMessages.LOG_USER_ARG_ROLE_ARG_422D48D3, + targetUsername, + targetRoleName)); + } + + private void logEvent(AuditEventType eventType, Supplier log) { + auditLogger.log( + new AuditLogFields( + userId, + username, + clientAddress, + eventType, + AuditLogOperation.CONTROL, + PrivilegeType.SECURITY, + true, + database, + sqlString), + log); + } + + private static boolean isSuccessful(TSStatus status) { + return status != null && status.getCode() == TSStatusCode.SUCCESS_STATUS.getStatusCode(); + } +} diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/Coordinator.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/Coordinator.java index 8919182c7ce93..9245402b68161 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/Coordinator.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/Coordinator.java @@ -43,6 +43,7 @@ import org.apache.iotdb.commons.queryengine.plan.relational.type.InternalTypeManager; import org.apache.iotdb.commons.queryengine.plan.relational.type.TypeManager; import org.apache.iotdb.db.audit.DNAuditLogger; +import org.apache.iotdb.db.audit.UserRoleModificationAuditContext; import org.apache.iotdb.db.auth.AuthorityChecker; import org.apache.iotdb.db.conf.IoTDBConfig; import org.apache.iotdb.db.conf.IoTDBDescriptor; @@ -157,6 +158,7 @@ import org.apache.iotdb.db.queryengine.plan.statement.IConfigStatement; import org.apache.iotdb.db.queryengine.plan.statement.Statement; import org.apache.iotdb.db.queryengine.plan.statement.pipe.PipeEnrichedStatement; +import org.apache.iotdb.db.queryengine.plan.statement.sys.AuthorStatement; import org.apache.iotdb.db.queryengine.udf.InternalQueryExecutor; import org.apache.iotdb.db.utils.SetThreadName; @@ -415,6 +417,13 @@ public ExecutionResult executeForTreeModel( } finally { DNAuditLogger.getInstance() .logRevokeFailure(statement, session, sql, result == null ? null : result.status); + if (statement instanceof AuthorStatement) { + final UserRoleModificationAuditContext auditContext = + new UserRoleModificationAuditContext(sql); + auditContext.setSessionInfo(session); + auditContext.track((AuthorStatement) statement); + auditContext.log(result == null ? null : result.status); + } } } @@ -563,6 +572,13 @@ public ExecutionResult executeForTableModel( } finally { DNAuditLogger.getInstance() .logRevokeFailure(statement, session, sql, result == null ? null : result.status); + if (statement instanceof RelationalAuthorStatement) { + final UserRoleModificationAuditContext auditContext = + new UserRoleModificationAuditContext(sql); + auditContext.setSessionInfo(session); + auditContext.track((RelationalAuthorStatement) statement); + auditContext.log(result == null ? null : result.status); + } } } diff --git a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/audit/UserRoleModificationAuditContextTest.java b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/audit/UserRoleModificationAuditContextTest.java new file mode 100644 index 0000000000000..350ce38c76061 --- /dev/null +++ b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/audit/UserRoleModificationAuditContextTest.java @@ -0,0 +1,206 @@ +/* + * 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.audit; + +import org.apache.iotdb.commons.audit.AuditEventType; +import org.apache.iotdb.commons.audit.AuditLogOperation; +import org.apache.iotdb.commons.audit.IAuditEntity; +import org.apache.iotdb.commons.auth.entity.PrivilegeType; +import org.apache.iotdb.commons.queryengine.common.SessionInfo; +import org.apache.iotdb.db.i18n.DataNodeMiscMessages; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.RelationalAuthorStatement; +import org.apache.iotdb.db.queryengine.plan.relational.type.AuthorRType; +import org.apache.iotdb.db.queryengine.plan.statement.AuthorType; +import org.apache.iotdb.db.queryengine.plan.statement.sys.AuthorStatement; +import org.apache.iotdb.rpc.RpcUtils; +import org.apache.iotdb.rpc.TSStatusCode; + +import org.junit.Test; +import org.mockito.ArgumentCaptor; + +import java.util.List; +import java.util.Optional; +import java.util.function.Supplier; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class UserRoleModificationAuditContextTest { + + @Test + public void testTreeGrantRoleSuccess() { + DNAuditLogger auditLogger = mock(DNAuditLogger.class); + UserRoleModificationAuditContext context = + new UserRoleModificationAuditContext(auditLogger, "GRANT ROLE role1 TO user1"); + context.setSessionInfo(mockSessionInfo()); + AuthorStatement statement = new AuthorStatement(AuthorType.GRANT_USER_ROLE); + statement.setUserName("user1"); + statement.setRoleName("role1"); + + context.track(statement); + context.log(RpcUtils.SUCCESS_STATUS); + + assertAuditLogs(auditLogger, "GRANT ROLE role1 TO user1"); + } + + @Test + public void testTableRevokeRoleSuccess() { + DNAuditLogger auditLogger = mock(DNAuditLogger.class); + UserRoleModificationAuditContext context = + new UserRoleModificationAuditContext(auditLogger, "REVOKE ROLE role1 FROM user1"); + context.setSessionInfo(mockSessionInfo()); + RelationalAuthorStatement statement = + new RelationalAuthorStatement(AuthorRType.REVOKE_USER_ROLE); + statement.setUserName("user1"); + statement.setRoleName("role1"); + + context.track(statement); + context.log(RpcUtils.SUCCESS_STATUS); + + assertAuditLogs(auditLogger, "REVOKE ROLE role1 FROM user1"); + } + + @Test + public void testTreeRevokeRoleSuccess() { + DNAuditLogger auditLogger = mock(DNAuditLogger.class); + UserRoleModificationAuditContext context = + new UserRoleModificationAuditContext(auditLogger, "REVOKE ROLE role1 FROM user1"); + context.setSessionInfo(mockSessionInfo()); + AuthorStatement statement = new AuthorStatement(AuthorType.REVOKE_USER_ROLE); + statement.setUserName("user1"); + statement.setRoleName("role1"); + + context.track(statement); + context.log(RpcUtils.SUCCESS_STATUS); + + assertAuditLogs(auditLogger, "REVOKE ROLE role1 FROM user1"); + } + + @Test + public void testTableGrantRoleSuccess() { + DNAuditLogger auditLogger = mock(DNAuditLogger.class); + UserRoleModificationAuditContext context = + new UserRoleModificationAuditContext(auditLogger, "GRANT ROLE role1 TO user1"); + context.setSessionInfo(mockSessionInfo()); + RelationalAuthorStatement statement = + new RelationalAuthorStatement(AuthorRType.GRANT_USER_ROLE); + statement.setUserName("user1"); + statement.setRoleName("role1"); + + context.track(statement); + context.log(RpcUtils.SUCCESS_STATUS); + + assertAuditLogs(auditLogger, "GRANT ROLE role1 TO user1"); + } + + @Test + public void testFailedModificationIsIgnored() { + DNAuditLogger auditLogger = mock(DNAuditLogger.class); + UserRoleModificationAuditContext context = + new UserRoleModificationAuditContext(auditLogger, "grant role"); + context.setSessionInfo(mockSessionInfo()); + AuthorStatement statement = new AuthorStatement(AuthorType.GRANT_USER_ROLE); + statement.setUserName("user1"); + statement.setRoleName("role1"); + context.track(statement); + + context.log(RpcUtils.getStatus(TSStatusCode.NO_PERMISSION)); + + verify(auditLogger, never()).log(any(), any()); + } + + @Test + public void testRedirectedModificationIsIgnored() { + DNAuditLogger auditLogger = mock(DNAuditLogger.class); + UserRoleModificationAuditContext context = + new UserRoleModificationAuditContext(auditLogger, "grant role"); + context.setSessionInfo(mockSessionInfo()); + AuthorStatement statement = new AuthorStatement(AuthorType.GRANT_USER_ROLE); + statement.setUserName("user1"); + statement.setRoleName("role1"); + context.track(statement); + + context.log(RpcUtils.getStatus(TSStatusCode.REDIRECTION_RECOMMEND)); + + verify(auditLogger, never()).log(any(), any()); + } + + @Test + public void testPrivilegeGrantIsIgnored() { + DNAuditLogger auditLogger = mock(DNAuditLogger.class); + UserRoleModificationAuditContext context = + new UserRoleModificationAuditContext(auditLogger, "grant privilege"); + context.setSessionInfo(mockSessionInfo()); + context.track(new AuthorStatement(AuthorType.GRANT_USER)); + + context.log(RpcUtils.SUCCESS_STATUS); + + verify(auditLogger, never()).log(any(), any()); + } + + private static SessionInfo mockSessionInfo() { + SessionInfo session = mock(SessionInfo.class); + when(session.getUserId()).thenReturn(7L); + when(session.getUserName()).thenReturn("operator"); + when(session.getCliHostname()).thenReturn("127.0.0.1"); + when(session.getDatabaseName()).thenReturn(Optional.of("database")); + return session; + } + + @SuppressWarnings("unchecked") + private static void assertAuditLogs(DNAuditLogger auditLogger, String sql) { + ArgumentCaptor entityCaptor = ArgumentCaptor.forClass(IAuditEntity.class); + ArgumentCaptor> logCaptor = ArgumentCaptor.forClass(Supplier.class); + verify(auditLogger, times(2)).log(entityCaptor.capture(), logCaptor.capture()); + + List entities = entityCaptor.getAllValues(); + List> logs = logCaptor.getAllValues(); + assertAuditLog(entities.get(0), sql, AuditEventType.MODIFY_SECURITY_FUNCTION); + assertAuditLog(entities.get(1), sql, AuditEventType.MODIFY_ROLE_MEMBERSHIP); + assertEquals( + String.format( + DataNodeMiscMessages + .LOG_SECURITY_FUNCTION_USER_ROLE_MEMBERSHIP_USER_ARG_ROLE_ARG_0D500C5D, + "user1", + "role1"), + logs.get(0).get()); + assertEquals( + String.format(DataNodeMiscMessages.LOG_USER_ARG_ROLE_ARG_422D48D3, "user1", "role1"), + logs.get(1).get()); + } + + private static void assertAuditLog(IAuditEntity entity, String sql, AuditEventType eventType) { + assertEquals(7L, entity.getUserId()); + assertEquals("operator", entity.getUsername()); + assertEquals("127.0.0.1", entity.getCliHostname()); + assertEquals(eventType, entity.getAuditEventType()); + assertEquals(AuditLogOperation.CONTROL, entity.getAuditLogOperation()); + assertEquals(PrivilegeType.SECURITY, entity.getPrivilegeTypes().get(0)); + assertTrue(entity.getResult()); + assertEquals("database", entity.getDatabase()); + assertEquals(sql, entity.getSqlString()); + } +} 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 510912a302fdc..47eea37169ac1 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 @@ -37,6 +37,8 @@ public enum AuditEventType { LOGIN_FINAL, MODIFY_SECURITY_OPTIONS, MODIFY_DEFAULT_SECURITY_VALUES, + MODIFY_SECURITY_FUNCTION, + MODIFY_ROLE_MEMBERSHIP, REVOKE_FAILED, GRANT_ROLE_FAILED, LOGIN_RESOURCE_RESTRICT,