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
+}

Reply via email to