This is an automated email from the ASF dual-hosted git repository.

morrysnow pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/master by this push:
     new 57ee5c4a65 [feature](nereids) Support authentication (#13434)
57ee5c4a65 is described below

commit 57ee5c4a657043f1d46f281ff1bb7510215cc6bf
Author: Adonis Ling <adonis0...@gmail.com>
AuthorDate: Thu Nov 3 11:58:14 2022 +0800

    [feature](nereids) Support authentication (#13434)
    
    Add a rule to check the permission of a user who are executing a query. 
Forbid users who don't have SELECT_PRIV on some tables from executing queries 
on these tables.
---
 .../doris/nereids/jobs/batch/AnalyzeRulesJob.java  |  2 +
 .../org/apache/doris/nereids/rules/RuleType.java   |  4 ++
 .../nereids/rules/analysis/UserAuthentication.java | 52 ++++++++++++++
 .../account_p0/test_nereids_authentication.groovy  | 83 ++++++++++++++++++++++
 4 files changed, 141 insertions(+)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/batch/AnalyzeRulesJob.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/batch/AnalyzeRulesJob.java
index bb3f107066..d5bb56e8e7 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/batch/AnalyzeRulesJob.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/batch/AnalyzeRulesJob.java
@@ -25,6 +25,7 @@ import 
org.apache.doris.nereids.rules.analysis.ProjectToGlobalAggregate;
 import org.apache.doris.nereids.rules.analysis.RegisterCTE;
 import org.apache.doris.nereids.rules.analysis.ResolveHaving;
 import org.apache.doris.nereids.rules.analysis.Scope;
+import org.apache.doris.nereids.rules.analysis.UserAuthentication;
 
 import com.google.common.collect.ImmutableList;
 
@@ -48,6 +49,7 @@ public class AnalyzeRulesJob extends BatchRulesJob {
                 )),
                 bottomUpBatch(ImmutableList.of(
                         new BindRelation(),
+                        new UserAuthentication(),
                         new BindSlotReference(scope),
                         new BindFunction(),
                         new ResolveHaving(),
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/RuleType.java 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/RuleType.java
index b81695bfef..a6f4641bb6 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/RuleType.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/RuleType.java
@@ -52,6 +52,8 @@ public enum RuleType {
     PROJECT_TO_GLOBAL_AGGREGATE(RuleTypeClass.REWRITE),
     REGISTER_CTE(RuleTypeClass.REWRITE),
 
+    RELATION_AUTHENTICATION(RuleTypeClass.VALIDATION),
+
     // check analysis rule
     CHECK_ANALYSIS(RuleTypeClass.CHECK),
 
@@ -185,8 +187,10 @@ public enum RuleType {
     enum RuleTypeClass {
         REWRITE,
         EXPLORATION,
+        // This type is used for unit test only.
         CHECK,
         IMPLEMENTATION,
+        VALIDATION,
         SENTINEL,
         ;
     }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/UserAuthentication.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/UserAuthentication.java
new file mode 100644
index 0000000000..e9b4c6d412
--- /dev/null
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/UserAuthentication.java
@@ -0,0 +1,52 @@
+// 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.doris.nereids.rules.analysis;
+
+import org.apache.doris.common.ErrorCode;
+import org.apache.doris.mysql.privilege.PrivPredicate;
+import org.apache.doris.nereids.exceptions.AnalysisException;
+import org.apache.doris.nereids.rules.Rule;
+import org.apache.doris.nereids.rules.RuleType;
+import org.apache.doris.nereids.trees.plans.Plan;
+import org.apache.doris.nereids.trees.plans.logical.LogicalRelation;
+import org.apache.doris.qe.ConnectContext;
+
+/**
+ * Check whether a user is permitted to scan specific tables.
+ */
+public class UserAuthentication extends OneAnalysisRuleFactory {
+
+    @Override
+    public Rule build() {
+        return logicalRelation().thenApply(ctx -> checkPermission(ctx.root, 
ctx.connectContext))
+                .toRule(RuleType.RELATION_AUTHENTICATION);
+    }
+
+    private Plan checkPermission(LogicalRelation relation, ConnectContext 
connectContext) {
+        String dbName = !relation.getQualifier().isEmpty() ? 
relation.getQualifier().get(0) : null;
+        String tableName = relation.getTable().getName();
+        if (!connectContext.getEnv().getAuth().checkTblPriv(connectContext, 
dbName, tableName, PrivPredicate.SELECT)) {
+            String message = 
ErrorCode.ERR_TABLEACCESS_DENIED_ERROR.formatErrorMsg("SELECT",
+                    ConnectContext.get().getQualifiedUser(), 
ConnectContext.get().getRemoteIP(),
+                    dbName + ": " + tableName);
+            throw new AnalysisException(message);
+
+        }
+        return relation;
+    }
+}
diff --git 
a/regression-test/suites/account_p0/test_nereids_authentication.groovy 
b/regression-test/suites/account_p0/test_nereids_authentication.groovy
new file mode 100644
index 0000000000..6a2a980401
--- /dev/null
+++ b/regression-test/suites/account_p0/test_nereids_authentication.groovy
@@ -0,0 +1,83 @@
+// 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.
+
+suite("test_nereids_authentication", "query") {
+    def create_table = { tableName ->
+        sql "DROP TABLE IF EXISTS ${tableName}"
+        sql """
+            CREATE TABLE ${tableName} (
+                `key` INT,
+                value INT
+            ) DUPLICATE KEY (`key`) DISTRIBUTED BY HASH (`key`) BUCKETS 1
+            PROPERTIES ('replication_num' = '1')
+        """
+    }
+
+    sql "set enable_nereids_planner = true"
+
+    def dbName = "nereids_authentication"
+    sql "DROP DATABASE IF EXISTS ${dbName}"
+    sql "CREATE DATABASE ${dbName}"
+    sql "USE ${dbName}"
+
+    def tableName1 = "accessible_table";
+    def tableName2 = "inaccessible_table";
+    create_table.call(tableName1);
+    create_table.call(tableName2);
+
+    def user='nereids_user'
+    try_sql "DROP USER ${user}"
+    sql "CREATE USER ${user} IDENTIFIED BY '123456'"
+    sql "GRANT SELECT_PRIV ON internal.${dbName}.${tableName1} TO ${user}"
+
+    def tokens = context.config.jdbcUrl.split('/')
+    def url=tokens[0] + "//" + tokens[2] + "/" + dbName + "?"
+    def result = connect(user=user, password='123456', url=url) {
+        sql "SELECT * FROM ${tableName1}"
+    }
+    assertEquals(result.size(), 0)
+
+    connect(user=user, password='123456', url=url) {
+        try {
+            sql "SELECT * FROM ${tableName2}"
+            fail()
+        } catch (Exception e) {
+            log.info(e.getMessage())
+            assertTrue(e.getMessage().contains('SELECT command denied to 
user'))
+        }
+    }
+
+    connect(user=user, password='123456', url=url) {
+        try {
+            sql "SELECT * FROM ${tableName1}, ${tableName2} WHERE 
${tableName1}.`key` = ${tableName2}.`key`"
+            fail()
+        } catch (Exception e) {
+            log.info(e.getMessage())
+            assertTrue(e.getMessage().contains('SELECT command denied to 
user'))
+        }
+    }
+
+    sql "GRANT SELECT_PRIV ON internal.${dbName}.${tableName2} TO ${user}"
+    connect(user=user, password='123456', url=url) {
+        sql "SELECT * FROM ${tableName2}"
+    }
+    assertEquals(result.size(), 0)
+    connect(user=user, password='123456', url=url) {
+        sql "SELECT * FROM ${tableName1}, ${tableName2} WHERE 
${tableName1}.`key` = ${tableName2}.`key`"
+    }
+    assertEquals(result.size(), 0)
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org
For additional commands, e-mail: commits-h...@doris.apache.org

Reply via email to