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

morningman 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 5efc6c4233a [fix](auth)Fix can not insert overwrite who have load priv 
(#25711)
5efc6c4233a is described below

commit 5efc6c4233a2b2f0bbad7aaa405ade0a8b9a16bb
Author: zhangdong <[email protected]>
AuthorDate: Wed Nov 1 15:21:16 2023 +0800

    [fix](auth)Fix can not insert overwrite who have load priv (#25711)
    
    Fix can not insert overwrite who have load priv
---
 .../doris/analysis/InsertOverwriteTableStmt.java   | 11 +++
 .../mysql/privilege/AccessControllerManager.java   |  3 +
 .../plans/commands/InsertIntoTableCommand.java     | 37 +++++++---
 .../java/org/apache/doris/qe/ConnectContext.java   | 14 ++++
 .../java/org/apache/doris/qe/StmtExecutor.java     | 20 ++++--
 .../insert_into_table/insert_auth.groovy           | 79 ++++++++++++++++++++++
 6 files changed, 147 insertions(+), 17 deletions(-)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/analysis/InsertOverwriteTableStmt.java
 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/InsertOverwriteTableStmt.java
index a34c2cab0b9..04e28c7fa6c 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/analysis/InsertOverwriteTableStmt.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/InsertOverwriteTableStmt.java
@@ -17,7 +17,12 @@
 
 package org.apache.doris.analysis;
 
+import org.apache.doris.catalog.Env;
+import org.apache.doris.common.ErrorCode;
+import org.apache.doris.common.ErrorReport;
 import org.apache.doris.common.UserException;
+import org.apache.doris.mysql.privilege.PrivPredicate;
+import org.apache.doris.qe.ConnectContext;
 
 import lombok.Getter;
 
@@ -69,5 +74,11 @@ public class InsertOverwriteTableStmt extends DdlStmt {
 
     @Override
     public void analyze(Analyzer analyzer) throws UserException {
+        if (!Env.getCurrentEnv().getAccessManager()
+                .checkTblPriv(ConnectContext.get(), getDb(), getTbl(), 
PrivPredicate.LOAD)) {
+            
ErrorReport.reportAnalysisException(ErrorCode.ERR_TABLEACCESS_DENIED_ERROR, 
"LOAD",
+                    ConnectContext.get().getQualifiedUser(), 
ConnectContext.get().getRemoteIP(),
+                    getDb() + ": " + getTbl());
+        }
     }
 }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/AccessControllerManager.java
 
b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/AccessControllerManager.java
index 257a6e88bc5..db88ee34b7d 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/AccessControllerManager.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/AccessControllerManager.java
@@ -170,6 +170,9 @@ public class AccessControllerManager {
 
     public boolean checkTblPriv(ConnectContext ctx, String qualifiedCtl,
             String qualifiedDb, String tbl, PrivPredicate wanted) {
+        if (ctx.isSkipAuth()) {
+            return true;
+        }
         return checkTblPriv(ctx.getCurrentUserIdentity(), qualifiedCtl, 
qualifiedDb, tbl, wanted);
     }
 
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/InsertIntoTableCommand.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/InsertIntoTableCommand.java
index 780ba178f09..83273dc6961 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/InsertIntoTableCommand.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/InsertIntoTableCommand.java
@@ -29,9 +29,11 @@ import org.apache.doris.catalog.Env;
 import org.apache.doris.catalog.OlapTable;
 import org.apache.doris.common.DdlException;
 import org.apache.doris.common.ErrorCode;
+import org.apache.doris.common.ErrorReport;
 import org.apache.doris.common.UserException;
 import org.apache.doris.common.util.ProfileManager.ProfileType;
 import org.apache.doris.datasource.InternalCatalog;
+import org.apache.doris.mysql.privilege.PrivPredicate;
 import org.apache.doris.nereids.NereidsPlanner;
 import org.apache.doris.nereids.analyzer.UnboundOlapTableSink;
 import org.apache.doris.nereids.exceptions.AnalysisException;
@@ -134,6 +136,16 @@ public class InsertIntoTableCommand extends Command 
implements ForwardWithSync,
         Preconditions.checkArgument(plan.isPresent(), "insert into command 
must contain OlapTableSinkNode");
         PhysicalOlapTableSink<?> physicalOlapTableSink = 
((PhysicalOlapTableSink<?>) plan.get());
 
+        OlapTable targetTable = physicalOlapTableSink.getTargetTable();
+        // check auth
+        if (!Env.getCurrentEnv().getAccessManager()
+                .checkTblPriv(ConnectContext.get(), 
targetTable.getQualifiedDbName(), targetTable.getName(),
+                        PrivPredicate.LOAD)) {
+            
ErrorReport.reportAnalysisException(ErrorCode.ERR_TABLEACCESS_DENIED_ERROR, 
"LOAD",
+                    ConnectContext.get().getQualifiedUser(), 
ConnectContext.get().getRemoteIP(),
+                    targetTable.getQualifiedDbName() + ": " + 
targetTable.getName());
+        }
+
         if (isOverwrite) {
             dealOverwrite(ctx, executor, physicalOlapTableSink);
             return;
@@ -189,7 +201,6 @@ public class InsertIntoTableCommand extends Command 
implements ForwardWithSync,
      * @param ctx ctx
      * @param executor executor
      * @param physicalOlapTableSink physicalOlapTableSink
-     *
      * @throws Exception Exception
      */
     public void dealOverwrite(ConnectContext ctx, StmtExecutor executor,
@@ -197,16 +208,22 @@ public class InsertIntoTableCommand extends Command 
implements ForwardWithSync,
         OlapTable targetTable = physicalOlapTableSink.getTargetTable();
         TableName tableName = new 
TableName(InternalCatalog.INTERNAL_CATALOG_NAME, 
targetTable.getQualifiedDbName(),
                 targetTable.getName());
-        List<String> partitionNames = ((UnboundOlapTableSink<?>) 
logicalQuery).getPartitions();
-        if (CollectionUtils.isEmpty(partitionNames)) {
-            partitionNames = 
Lists.newArrayList(targetTable.getPartitionNames());
-        }
-        List<String> tempPartitionNames = addTempPartition(ctx, tableName, 
partitionNames);
-        boolean insertRes = insertInto(ctx, executor, tempPartitionNames, 
tableName);
-        if (!insertRes) {
-            return;
+        ConnectContext.get().setSkipAuth(true);
+        try {
+            List<String> partitionNames = ((UnboundOlapTableSink<?>) 
logicalQuery).getPartitions();
+            if (CollectionUtils.isEmpty(partitionNames)) {
+                partitionNames = 
Lists.newArrayList(targetTable.getPartitionNames());
+            }
+            List<String> tempPartitionNames = addTempPartition(ctx, tableName, 
partitionNames);
+            boolean insertRes = insertInto(ctx, executor, tempPartitionNames, 
tableName);
+            if (!insertRes) {
+                return;
+            }
+            replacePartition(ctx, tableName, partitionNames, 
tempPartitionNames);
+        } finally {
+            ConnectContext.get().setSkipAuth(false);
         }
-        replacePartition(ctx, tableName, partitionNames, tempPartitionNames);
+
     }
 
     /**
diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/ConnectContext.java 
b/fe/fe-core/src/main/java/org/apache/doris/qe/ConnectContext.java
index 56d098cc6b9..15359faacaf 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/qe/ConnectContext.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/qe/ConnectContext.java
@@ -190,6 +190,12 @@ public class ConnectContext {
 
     private TResultSinkType resultSinkType = TResultSinkType.MYSQL_PROTOCAL;
 
+    //internal call like `insert overwrite` need skipAuth
+    // For example, `insert overwrite` only requires load permission,
+    // but the internal implementation will call the logic of `AlterTable`.
+    // In this case, `skipAuth` needs to be set to `true` to skip the 
permission check of `AlterTable`
+    private boolean skipAuth = false;
+
     public void setUserQueryTimeout(int queryTimeout) {
         if (queryTimeout > 0) {
             sessionVariable.setQueryTimeoutS(queryTimeout);
@@ -903,5 +909,13 @@ public class ConnectContext {
     public Backend getInsertGroupCommit(long tableId) {
         return insertGroupCommitTableToBeMap.get(tableId);
     }
+
+    public boolean isSkipAuth() {
+        return skipAuth;
+    }
+
+    public void setSkipAuth(boolean skipAuth) {
+        this.skipAuth = skipAuth;
+    }
 }
 
diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java 
b/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java
index 56f3cd84a2b..09afe499435 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java
@@ -994,6 +994,7 @@ public class StmtExecutor {
                 queryStmt.getTables(analyzer, false, tableMap, 
parentViewNameSet);
             } else if (parsedStmt instanceof InsertOverwriteTableStmt) {
                 InsertOverwriteTableStmt parsedStmt = 
(InsertOverwriteTableStmt) this.parsedStmt;
+                parsedStmt.analyze(analyzer);
                 queryStmt = parsedStmt.getQueryStmt();
                 queryStmt.getTables(analyzer, false, tableMap, 
parentViewNameSet);
             } else if (parsedStmt instanceof CreateTableAsSelectStmt) {
@@ -2390,13 +2391,18 @@ public class StmtExecutor {
     }
 
     private void handleIotStmt() {
-        InsertOverwriteTableStmt iotStmt = (InsertOverwriteTableStmt) 
this.parsedStmt;
-        if (iotStmt.getPartitionNames().size() == 0) {
-            // insert overwrite table
-            handleOverwriteTable(iotStmt);
-        } else {
-            // insert overwrite table with partition
-            handleOverwritePartition(iotStmt);
+        ConnectContext.get().setSkipAuth(true);
+        try {
+            InsertOverwriteTableStmt iotStmt = (InsertOverwriteTableStmt) 
this.parsedStmt;
+            if (iotStmt.getPartitionNames().size() == 0) {
+                // insert overwrite table
+                handleOverwriteTable(iotStmt);
+            } else {
+                // insert overwrite table with partition
+                handleOverwritePartition(iotStmt);
+            }
+        } finally {
+            ConnectContext.get().setSkipAuth(false);
         }
     }
 
diff --git 
a/regression-test/suites/nereids_p0/insert_into_table/insert_auth.groovy 
b/regression-test/suites/nereids_p0/insert_into_table/insert_auth.groovy
new file mode 100644
index 00000000000..1a333d41d32
--- /dev/null
+++ b/regression-test/suites/nereids_p0/insert_into_table/insert_auth.groovy
@@ -0,0 +1,79 @@
+// 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('nereids_insert_auth') {
+    sql 'set enable_nereids_planner=true'
+    sql 'set enable_fallback_to_original_planner=false'
+    sql 'set enable_nereids_dml=true'
+    sql 'set enable_strict_consistency_dml=true'
+
+    def db = 'nereids_insert_auth_db'
+    sql "drop database if exists ${db}"
+    sql "create database ${db}"
+    sql "use ${db}"
+
+    def t1 = 't1'
+
+    sql "drop table if exists ${t1}"
+
+    sql """
+        create table ${t1} (
+            id int,
+            c1 bigint
+        )
+        distributed by hash(id) buckets 2
+        properties(
+            'replication_num'='1'
+        );
+    """
+
+    String user = "nereids_insert_auth_user";
+    String pwd = '123456';
+    def tokens = context.config.jdbcUrl.split('/')
+    def url = tokens[0] + "//" + tokens[2] + "/" + "information_schema" + "?"
+    try_sql("DROP USER ${user}")
+    sql """CREATE USER '${user}' IDENTIFIED BY '${pwd}'"""
+
+    connect(user=user, password="${pwd}", url=url) {
+        try {
+            sql """ insert into ${db}.${t1} values (1, 1) """
+            fail()
+        } catch (Exception e) {
+            log.info(e.getMessage())
+        }
+    }
+
+    sql """GRANT LOAD_PRIV ON ${db}.${t1} TO ${user}"""
+
+    connect(user=user, password="${pwd}", url=url) {
+        try {
+            sql """ insert into ${db}.${t1} values (1, 1) """
+        } catch (Exception e) {
+            log.info(e.getMessage())
+            fail()
+        }
+    }
+
+    connect(user=user, password="${pwd}", url=url) {
+        try {
+            sql """ insert overwrite table ${db}.${t1} values (2, 2) """
+        } catch (Exception e) {
+            log.info(e.getMessage())
+            fail()
+        }
+    }
+}
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to