This is an automated email from the ASF dual-hosted git repository. shuwenwei pushed a commit to branch sync-generic-changes in repository https://gitbox.apache.org/repos/asf/iotdb.git
commit 29c06fb929ca6de4fdf22d07bb49638938ddaf1d Author: shuwenwei <[email protected]> AuthorDate: Thu Sep 17 15:04:37 2026 +0800 [LBAC] Add LBAC access control abstraction with allow-all default implementation --- .../org/apache/iotdb/db/auth/AuthorityChecker.java | 14 ++++ .../iotdb/db/lbac/AllowAllLBACAccessControl.java | 47 ++++++++++++++ .../apache/iotdb/db/lbac/ILBACAccessControl.java | 74 ++++++++++++++++++++++ .../apache/iotdb/commons/i18n/LBACMessages.java | 28 ++++++++ .../apache/iotdb/commons/i18n/LBACMessages.java | 28 ++++++++ .../commons/lbac/LBACAccessDeniedException.java | 56 ++++++++++++++++ .../iotdb/commons/lbac/LBACRuntimeException.java | 33 ++++++++++ .../apache/iotdb/commons/lbac/RequiredLabels.java | 64 +++++++++++++++++++ .../commons/lbac/operation/LabelAccessType.java | 26 ++++++++ 9 files changed, 370 insertions(+) diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/auth/AuthorityChecker.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/auth/AuthorityChecker.java index 0593db10840..9634992f0af 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/auth/AuthorityChecker.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/auth/AuthorityChecker.java @@ -41,6 +41,8 @@ import org.apache.iotdb.confignode.rpc.thrift.TTablePrivilege; import org.apache.iotdb.confignode.rpc.thrift.TUserResp; import org.apache.iotdb.db.audit.DNAuditLogger; import org.apache.iotdb.db.i18n.DataNodeMiscMessages; +import org.apache.iotdb.db.lbac.AllowAllLBACAccessControl; +import org.apache.iotdb.db.lbac.ILBACAccessControl; import org.apache.iotdb.db.pipe.source.dataregion.realtime.listener.PipeInsertionDataNodeListener; import org.apache.iotdb.db.protocol.session.IClientSession; import org.apache.iotdb.db.queryengine.common.header.DatasetHeader; @@ -109,6 +111,8 @@ public class AuthorityChecker { private static volatile AccessControl accessControl = new AccessControlImpl(new ITableAuthCheckerImpl(), new TreeAccessCheckVisitor()); + private static volatile ILBACAccessControl lbacAccessControl = new AllowAllLBACAccessControl(); + private AuthorityChecker() { // empty constructor } @@ -122,6 +126,16 @@ public class AuthorityChecker { AuthorityChecker.accessControl = accessControl; } + @SuppressWarnings("java:S100") + public static ILBACAccessControl getLBACAccessControl() { + return lbacAccessControl; + } + + @SuppressWarnings("java:S100") + public static void setLBACAccessControl(final ILBACAccessControl lbacAccessControl) { + AuthorityChecker.lbacAccessControl = lbacAccessControl; + } + public static void setSuperUser(String superUser) { SUPER_USER = superUser; } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/lbac/AllowAllLBACAccessControl.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/lbac/AllowAllLBACAccessControl.java new file mode 100644 index 00000000000..49e7c0d30ae --- /dev/null +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/lbac/AllowAllLBACAccessControl.java @@ -0,0 +1,47 @@ +/* + * 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.lbac; + +import org.apache.iotdb.commons.audit.IAuditEntity; +import org.apache.iotdb.commons.lbac.RequiredLabels; +import org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.Statement; +import org.apache.iotdb.db.protocol.session.IClientSession; +import org.apache.iotdb.db.queryengine.plan.relational.metadata.Metadata; + +import java.util.Map; + +/** + * Open-source default implementation of {@link ILBACAccessControl} that allows all access. The + * commercial TimechoDB DataNode replaces this with its real LBAC implementation during startup. + */ +@SuppressWarnings("java:S100") +public class AllowAllLBACAccessControl implements ILBACAccessControl { + + @Override + public void checkCanAccess( + final Statement statement, + final Metadata metadata, + final IClientSession clientSession, + final IAuditEntity auditEntity) {} + + @Override + public void checkCanAccess( + final Map<String, RequiredLabels> requiredLabelsByPolicy, final IAuditEntity auditEntity) {} +} diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/lbac/ILBACAccessControl.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/lbac/ILBACAccessControl.java new file mode 100644 index 00000000000..070118a1ab0 --- /dev/null +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/lbac/ILBACAccessControl.java @@ -0,0 +1,74 @@ +/* + * 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.lbac; + +import org.apache.iotdb.commons.audit.IAuditEntity; +import org.apache.iotdb.commons.lbac.LBACAccessDeniedException; +import org.apache.iotdb.commons.lbac.RequiredLabels; +import org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.Statement; +import org.apache.iotdb.db.protocol.session.IClientSession; +import org.apache.iotdb.db.queryengine.plan.relational.metadata.Metadata; + +import java.util.Map; + +/** + * LBAC (Label-Based Access Control) entry point, at the same level as RBAC's {@code AccessControl}. + * Performs label-level access checks on protected columns. + */ +@SuppressWarnings("java:S100") +public interface ILBACAccessControl { + + /** + * Performs a full LBAC access check for the given DDL statement. + * + * <p>Internally extracts the required column labels from the statement, loads user/role grants + * and LBAC metadata from cache, then compares subject labels against required object labels. + * + * @param statement the DDL statement to check + * @param metadata metadata handle for table schema lookups + * @param clientSession the client session for database resolution + * @param auditEntity the audit entity carrying the user identity + * @throws LBACAccessDeniedException if any required label comparison fails + */ + void checkCanAccess( + Statement statement, + Metadata metadata, + IClientSession clientSession, + IAuditEntity auditEntity) + throws LBACAccessDeniedException; + + /** + * Performs a full LBAC access check for explicitly-declared column label requirements, without + * going through the relational StatementAnalyzer (e.g. the tree-model Load TsFile path). + * + * @param requiredLabelsByPolicy required object labels grouped by policy name + * @param auditEntity the audit entity carrying the user identity + * @throws LBACAccessDeniedException + */ + void checkCanAccess(Map<String, RequiredLabels> requiredLabelsByPolicy, IAuditEntity auditEntity) + throws LBACAccessDeniedException; + + /** + * Clears any LBAC-local caches. Invoked when the metadata lease is fenced and the DataNode drops + * its caches, so a recovery forces a fresh re-fetch from the ConfigNode. Defaults to a no-op for + * implementations without a local cache. + */ + default void clearCache() {} +} diff --git a/iotdb-core/node-commons/src/main/i18n/en/org/apache/iotdb/commons/i18n/LBACMessages.java b/iotdb-core/node-commons/src/main/i18n/en/org/apache/iotdb/commons/i18n/LBACMessages.java new file mode 100644 index 00000000000..85453a94678 --- /dev/null +++ b/iotdb-core/node-commons/src/main/i18n/en/org/apache/iotdb/commons/i18n/LBACMessages.java @@ -0,0 +1,28 @@ +/* + * 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.commons.i18n; + +public final class LBACMessages { + + private LBACMessages() {} + + public static final String EXCEPTION_LBAC_CHECK_FAILED_FOR_USER_ARG_ARG_TO_LABEL_ARG_VALUE_ARG_UNDER_POLICY_ARG_USER_S_MERGED_GRANT_ARG_DOES_NOT_DOMINATE_REQUIRED_ARG_C18D4EA7 = "LBAC check failed for user '%s' %s to label '%s' (value: %s) under policy '%s': user's merged grant %s does not dominate required %s"; + public static final String EXCEPTION_LABELNAME_IS_NULL_856ABAE4 = "labelName is null"; +} diff --git a/iotdb-core/node-commons/src/main/i18n/zh/org/apache/iotdb/commons/i18n/LBACMessages.java b/iotdb-core/node-commons/src/main/i18n/zh/org/apache/iotdb/commons/i18n/LBACMessages.java new file mode 100644 index 00000000000..ce7d66b9f17 --- /dev/null +++ b/iotdb-core/node-commons/src/main/i18n/zh/org/apache/iotdb/commons/i18n/LBACMessages.java @@ -0,0 +1,28 @@ +/* + * 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.commons.i18n; + +public final class LBACMessages { + + private LBACMessages() {} + + public static final String EXCEPTION_LBAC_CHECK_FAILED_FOR_USER_ARG_ARG_TO_LABEL_ARG_VALUE_ARG_UNDER_POLICY_ARG_USER_S_MERGED_GRANT_ARG_DOES_NOT_DOMINATE_REQUIRED_ARG_C18D4EA7 = "用户 '%s' 的 %s 访问失败:标签 '%s'(值:%s)位于策略 '%s' 下,用户合并后的授权 %s 不支配所需值 %s"; + public static final String EXCEPTION_LABELNAME_IS_NULL_856ABAE4 = "labelName 为 null"; +} diff --git a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/lbac/LBACAccessDeniedException.java b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/lbac/LBACAccessDeniedException.java new file mode 100644 index 00000000000..c025e4333fa --- /dev/null +++ b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/lbac/LBACAccessDeniedException.java @@ -0,0 +1,56 @@ +/* + * 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.commons.lbac; + +import org.apache.iotdb.commons.audit.IAuditEntity; +import org.apache.iotdb.commons.i18n.LBACMessages; +import org.apache.iotdb.commons.lbac.operation.LabelAccessType; +import org.apache.iotdb.rpc.TSStatusCode; + +import java.io.Serial; +import java.util.Set; + +/** Thrown when an LBAC label comparison denies access to a protected object. */ +@SuppressWarnings("java:S100") +public class LBACAccessDeniedException extends LBACRuntimeException { + + @Serial private static final long serialVersionUID = 1L; + + public LBACAccessDeniedException( + final IAuditEntity auditEntity, + final String policyName, + final String subjectValue, + final Set<String> objectComponentValues, + final String objectLabelName, + final LabelAccessType accessType) { + super( + String.format( + LBACMessages + .EXCEPTION_LBAC_CHECK_FAILED_FOR_USER_ARG_ARG_TO_LABEL_ARG_VALUE_ARG_UNDER_POLICY_ARG_USER_S_MERGED_GRANT_ARG_DOES_NOT_DOMINATE_REQUIRED_ARG_C18D4EA7, + auditEntity.getUsername(), + accessType, + objectLabelName, + objectComponentValues, + policyName, + subjectValue, + objectComponentValues), + TSStatusCode.LBAC_ACCESS_DENIED); + } +} diff --git a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/lbac/LBACRuntimeException.java b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/lbac/LBACRuntimeException.java new file mode 100644 index 00000000000..04235886f7d --- /dev/null +++ b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/lbac/LBACRuntimeException.java @@ -0,0 +1,33 @@ +/* + * 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.commons.lbac; + +import org.apache.iotdb.commons.exception.IoTDBRuntimeException; +import org.apache.iotdb.rpc.TSStatusCode; + +@SuppressWarnings("java:S100") +public class LBACRuntimeException extends IoTDBRuntimeException { + + private static final long serialVersionUID = 1L; + + public LBACRuntimeException(final String message, final TSStatusCode statusCode) { + super(message, statusCode.getStatusCode()); + } +} diff --git a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/lbac/RequiredLabels.java b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/lbac/RequiredLabels.java new file mode 100644 index 00000000000..13d63559765 --- /dev/null +++ b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/lbac/RequiredLabels.java @@ -0,0 +1,64 @@ +/* + * 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.commons.lbac; + +import org.apache.iotdb.commons.i18n.LBACMessages; + +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; + +/** The object-side LBAC requirement: protected column labels grouped by READ and WRITE. */ +public final class RequiredLabels { + + private final Set<String> readLabels = new HashSet<>(); + private final Set<String> writeLabels = new HashSet<>(); + + public RequiredLabels requireLabelWithReadAccess(final String labelName) { + Objects.requireNonNull(labelName, LBACMessages.EXCEPTION_LABELNAME_IS_NULL_856ABAE4); + readLabels.add(labelName); + return this; + } + + public RequiredLabels requireLabelWithWriteAccess(final String labelName) { + Objects.requireNonNull(labelName, LBACMessages.EXCEPTION_LABELNAME_IS_NULL_856ABAE4); + writeLabels.add(labelName); + return this; + } + + public RequiredLabels requireLabelWithAllAccess(final String labelName) { + Objects.requireNonNull(labelName, LBACMessages.EXCEPTION_LABELNAME_IS_NULL_856ABAE4); + readLabels.add(labelName); + writeLabels.add(labelName); + return this; + } + + public Set<String> getReadLabels() { + return readLabels; + } + + public Set<String> getWriteLabels() { + return writeLabels; + } + + public boolean isEmpty() { + return readLabels.isEmpty() && writeLabels.isEmpty(); + } +} diff --git a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/lbac/operation/LabelAccessType.java b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/lbac/operation/LabelAccessType.java new file mode 100644 index 00000000000..fd8ce0fdbf6 --- /dev/null +++ b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/lbac/operation/LabelAccessType.java @@ -0,0 +1,26 @@ +/* + * 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.commons.lbac.operation; + +public enum LabelAccessType { + READ, + WRITE, + ALL +}
