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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1659,7 +1659,7 @@ public IConfigTask visitKillQuery(KillQuery node, MPPQueryContext context) {
@Override
public IConfigTask visitCreateFunction(CreateFunction node, MPPQueryContext context) {
context.setQueryType(QueryType.OTHER);
accessControl.checkUserGlobalSysPrivilege(context);
accessControl.checkUserGlobalSysPrivilege(context, AuditLogOperation.DDL, node::getUdfName);
if (node.getUriString().map(ExecutableManager::isUriTrusted).orElse(true)) {
// 1. user specified uri and that uri is trusted
// 2. user doesn't specify uri
Expand All @@ -1679,7 +1679,7 @@ public IConfigTask visitShowFunctions(ShowFunctions node, MPPQueryContext contex
@Override
public IConfigTask visitDropFunction(DropFunction node, MPPQueryContext context) {
context.setQueryType(QueryType.OTHER);
accessControl.checkUserGlobalSysPrivilege(context);
accessControl.checkUserGlobalSysPrivilege(context, AuditLogOperation.DDL, node::getUdfName);
return new DropFunctionTask(Model.TABLE, node.getUdfName());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.auth.entity.PrivilegeType;
import org.apache.iotdb.commons.exception.auth.AccessDeniedException;
Expand Down Expand Up @@ -204,6 +205,18 @@ void checkUserCanRunRelationalAuthorStatement(
*/
void checkUserGlobalSysPrivilege(IAuditEntity auditEntity);

/**
* Check if user has global SYSTEM privilege and record the authentication audit log with the
* specified operation and object.
*
* @param auditEntity records necessary info for audit log
* @param auditLogOperation operation type of the statement being authorized
* @param auditObject object affected by the statement
* @throws AccessDeniedException if not allowed
*/
void checkUserGlobalSysPrivilege(
IAuditEntity auditEntity, AuditLogOperation auditLogOperation, Supplier<String> auditObject);

/**
* Check if user has sepecified global privilege
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@
}

@Override
public void checkUserCanRunRelationalAuthorStatement(

Check warning on line 272 in iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/AccessControlImpl.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

A "Brain Method" was detected. Refactor it to reduce at least one of the following metrics: LOC from 247 to 64, Complexity from 60 to 14, Nesting Level from 3 to 2, Number of Variables from 10 to 6.

See more on https://sonarcloud.io/project/issues?id=apache_iotdb&issues=AZ-tHuAbF5FOG_1H-hIj&open=AZ-tHuAbF5FOG_1H-hIj&pullRequest=18351
String userName, RelationalAuthorStatement statement, IAuditEntity auditEntity) {
AuthorRType type = statement.getAuthorType();
switch (type) {
Expand Down Expand Up @@ -546,6 +546,17 @@
}
}

@Override
public void checkUserGlobalSysPrivilege(
IAuditEntity auditEntity, AuditLogOperation auditLogOperation, Supplier<String> auditObject) {
authChecker.checkGlobalPrivilege(
auditEntity.getUsername(),
TableModelPrivilege.SYSTEM,
auditLogOperation,
auditEntity,
auditObject);
}

@Override
public boolean hasGlobalPrivilege(IAuditEntity entity, PrivilegeType privilegeType) {
return AuthorityChecker.SUPER_USER_ID == entity.getUserId()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.auth.entity.PrivilegeType;
import org.apache.iotdb.commons.path.PartialPath;
Expand Down Expand Up @@ -106,6 +107,12 @@
@Override
public void checkUserGlobalSysPrivilege(IAuditEntity auditEntity) {}

@Override
public void checkUserGlobalSysPrivilege(

Check failure on line 111 in iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/AllowAllAccessControl.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add a nested comment explaining why this method is empty, throw an UnsupportedOperationException or complete the implementation.

See more on https://sonarcloud.io/project/issues?id=apache_iotdb&issues=AZ-tHuB9F5FOG_1H-hIk&open=AZ-tHuB9F5FOG_1H-hIk&pullRequest=18351
IAuditEntity auditEntity,
AuditLogOperation auditLogOperation,
Supplier<String> auditObject) {}

@Override
public boolean hasGlobalPrivilege(IAuditEntity entity, PrivilegeType privilegeType) {
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@

package org.apache.iotdb.db.queryengine.plan.relational.security;

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.exception.auth.AccessDeniedException;
import org.apache.iotdb.commons.queryengine.plan.relational.metadata.QualifiedObjectName;

import java.util.Collection;
import java.util.function.Supplier;

public interface ITableAuthChecker {

Expand Down Expand Up @@ -108,6 +110,17 @@ void checkTableVisibility(
void checkGlobalPrivilege(
String userName, TableModelPrivilege privilege, IAuditEntity auditEntity);

/**
* Check if user has the specified global privilege and record the authentication audit log with
* the operation and object of the statement being authorized.
*/
void checkGlobalPrivilege(
String userName,
TableModelPrivilege privilege,
AuditLogOperation auditLogOperation,
IAuditEntity auditEntity,
Supplier<String> auditObject);

void checkGlobalPrivileges(
String username, Collection<PrivilegeType> privileges, IAuditEntity auditEntity);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,30 @@ public void checkGlobalPrivilege(
recordAuditLogViaAuthenticationResult(() -> userName, privilege, auditEntity, result);
}

@Override
public void checkGlobalPrivilege(
String userName,
TableModelPrivilege privilege,
AuditLogOperation auditLogOperation,
IAuditEntity auditEntity,
Supplier<String> auditObject) {
if (AuthorityChecker.SUPER_USER_ID == auditEntity.getUserId()) {
AUDIT_LOGGER.recordObjectAuthenticationAuditLog(
auditEntity
.setAuditLogOperation(auditLogOperation)
.setPrivilegeType(privilege.getPrivilegeType())
.setResult(true),
auditObject);
return;
}
TSStatus result =
AuthorityChecker.getTSStatus(
AuthorityChecker.checkSystemPermission(userName, privilege.getPrivilegeType()),
privilege.getPrivilegeType());
recordAuditLogViaAuthenticationResult(
auditObject, privilege, auditLogOperation, auditEntity, result);
}

@Override
public void checkGlobalPrivileges(
String username, Collection<PrivilegeType> privileges, IAuditEntity auditEntity) {
Expand Down Expand Up @@ -468,18 +492,28 @@ private void recordAuditLogViaAuthenticationResult(
TableModelPrivilege privilege,
IAuditEntity auditEntity,
TSStatus result) {
recordAuditLogViaAuthenticationResult(
auditObject, privilege, privilege.getAuditLogOperation(), auditEntity, result);
}

private void recordAuditLogViaAuthenticationResult(
Supplier<String> auditObject,
TableModelPrivilege privilege,
AuditLogOperation auditLogOperation,
IAuditEntity auditEntity,
TSStatus result) {
if (result.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
AUDIT_LOGGER.recordObjectAuthenticationAuditLog(
auditEntity
.setAuditLogOperation(privilege.getAuditLogOperation())
.setAuditLogOperation(auditLogOperation)
.setPrivilegeType(privilege.getPrivilegeType())
.setResult(false),
auditObject);
throw new AccessDeniedException(result.getMessage());
}
AUDIT_LOGGER.recordObjectAuthenticationAuditLog(
auditEntity
.setAuditLogOperation(privilege.getAuditLogOperation())
.setAuditLogOperation(auditLogOperation)
.setPrivilegeType(privilege.getPrivilegeType())
.setResult(true),
auditObject);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
package org.apache.iotdb.db.pipe.event;

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.auth.entity.PrivilegeType;
import org.apache.iotdb.commons.conf.IoTDBConstant;
Expand Down Expand Up @@ -374,6 +375,12 @@ public void checkUserIsAdmin(IAuditEntity auditEntity) {}
@Override
public void checkUserGlobalSysPrivilege(IAuditEntity auditEntity) {}

@Override
public void checkUserGlobalSysPrivilege(
IAuditEntity auditEntity,
AuditLogOperation auditLogOperation,
Supplier<String> auditObject) {}

@Override
public boolean hasGlobalPrivilege(IAuditEntity auditEntity, PrivilegeType privilegeType) {
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@

package org.apache.iotdb.db.queryengine.plan.relational.analyzer;

import org.apache.iotdb.commons.audit.AuditLogOperation;
import org.apache.iotdb.commons.audit.UserEntity;
import org.apache.iotdb.commons.auth.entity.PrivilegeType;
import org.apache.iotdb.commons.exception.auth.AccessDeniedException;
import org.apache.iotdb.commons.queryengine.common.SessionInfo;
import org.apache.iotdb.commons.queryengine.common.SqlDialect;
Expand All @@ -30,6 +33,7 @@
import org.apache.iotdb.db.queryengine.plan.execution.config.TableConfigTaskVisitor;
import org.apache.iotdb.db.queryengine.plan.relational.security.AccessControlImpl;
import org.apache.iotdb.db.queryengine.plan.relational.security.ITableAuthChecker;
import org.apache.iotdb.db.queryengine.plan.relational.security.ITableAuthCheckerImpl;
import org.apache.iotdb.db.queryengine.plan.relational.security.TableModelPrivilege;
import org.apache.iotdb.db.queryengine.plan.relational.security.TreeAccessCheckVisitor;
import org.apache.iotdb.db.queryengine.plan.relational.sql.parser.SqlParser;
Expand All @@ -47,9 +51,13 @@
import static org.apache.iotdb.db.queryengine.plan.relational.analyzer.TestUtils.QUERY_ID;
import static org.apache.iotdb.db.queryengine.plan.relational.analyzer.TestUtils.TEST_MATADATA;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

public class AuthTest {

Expand Down Expand Up @@ -206,6 +214,49 @@ public void testDatabaseManagementRelatedAuth() {

}

@Test
public void testFunctionManagementAuditOperation() {
ITableAuthChecker authChecker = Mockito.mock(ITableAuthChecker.class);
String functionName = "test_function";

analyzeConfigTask(
String.format(
"CREATE FUNCTION %s AS 'org.apache.iotdb.db.query.udf.example.relational.AllSum'",
functionName),
user1,
authChecker);
analyzeConfigTask(String.format("DROP FUNCTION %s", functionName), user1, authChecker);

verify(authChecker, times(2))
.checkGlobalPrivilege(
eq(user1),
eq(TableModelPrivilege.SYSTEM),
eq(AuditLogOperation.DDL),
any(),
argThat(auditObject -> functionName.equals(auditObject.get())));
}

@Test
public void testExplicitGlobalPrivilegeAuditOperation() {
ITableAuthCheckerImpl authChecker = new ITableAuthCheckerImpl();
UserEntity auditEntity = new UserEntity(0, userRoot, "127.0.0.1");

authChecker.checkGlobalPrivilege(
userRoot,
TableModelPrivilege.SYSTEM,
AuditLogOperation.DDL,
auditEntity,
() -> "test_function");

assertEquals(AuditLogOperation.DDL, auditEntity.getAuditLogOperation());
assertEquals(Collections.singletonList(PrivilegeType.SYSTEM), auditEntity.getPrivilegeTypes());
assertTrue(auditEntity.getResult());

UserEntity defaultAuditEntity = new UserEntity(0, userRoot, "127.0.0.1");
authChecker.checkGlobalPrivilege(userRoot, TableModelPrivilege.SYSTEM, defaultAuditEntity);
assertEquals(AuditLogOperation.CONTROL, defaultAuditEntity.getAuditLogOperation());
}

private void analyzeSQL(String sql, String userName, ITableAuthChecker authChecker) {
analyzeSQL(sql, userName, authChecker, null);
}
Expand Down
Loading