From f0ef604bbb7477fb71dc116353840eeee162a228 Mon Sep 17 00:00:00 2001 From: Calvin Kirs Date: Mon, 11 Nov 2024 15:41:56 +0800 Subject: [PATCH] [feat](authorization)Centralizing Common Authorization Operations in a Common Interface ### Optimize Column-Level Permission Checks Using Table-Level Permissions: Since having column-level permissions does not imply table-level permissions, but having table-level permissions does imply permissions on all columns within the table, we can streamline column permission checks. When checking column-level permissions, we can first check if the user has table-level permissions. If table-level permissions are granted, column-level checks become unnecessary. Only if table-level permissions are absent do we proceed with specific column-level permission checks. ### Global Permissions Shortcut: Global-level permissions typically grant full access across all operations. Therefore, to optimize permission checks, we can add an early check for global permissions. If the user has global permissions, they are authorized, and further permission checks at the database, table, or column levels are unnecessary, allowing us to return immediately. --- .../doris/RangerDorisAccessController.java | 8 ------ .../privilege/CatalogAccessController.java | 28 +++++++++++++------ .../apache/doris/mysql/privilege/Role.java | 2 +- 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/authorizer/ranger/doris/RangerDorisAccessController.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/authorizer/ranger/doris/RangerDorisAccessController.java index 8a7bea57534f6e..48a3aac2f57f99 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/catalog/authorizer/ranger/doris/RangerDorisAccessController.java +++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/authorizer/ranger/doris/RangerDorisAccessController.java @@ -218,14 +218,6 @@ private boolean checkAnyPrivWithinTbl(UserIdentity currentUser, String ctl, Stri public void checkColsPriv(UserIdentity currentUser, String ctl, String db, String tbl, Set cols, PrivPredicate wanted) throws AuthorizationException { PrivBitSet checkedPrivs = PrivBitSet.of(); - boolean hasTablePriv = checkGlobalPrivInternal(currentUser, wanted, checkedPrivs) - || checkCtlPrivInternal(currentUser, ctl, wanted, checkedPrivs) - || checkDbPrivInternal(currentUser, ctl, db, wanted, checkedPrivs) - || checkTblPrivInternal(currentUser, ctl, db, tbl, wanted, checkedPrivs); - if (hasTablePriv) { - return; - } - for (String col : cols) { if (!checkColPrivInternal(currentUser, ctl, db, tbl, col, wanted, checkedPrivs.copy())) { throw new AuthorizationException(String.format( diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/CatalogAccessController.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/CatalogAccessController.java index 74d136c466592f..d367c8ee83c4b7 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/CatalogAccessController.java +++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/CatalogAccessController.java @@ -28,8 +28,10 @@ public interface CatalogAccessController { // ==== Catalog ==== default boolean checkCtlPriv(boolean hasGlobal, UserIdentity currentUser, String ctl, PrivPredicate wanted) { - boolean res = checkCtlPriv(currentUser, ctl, wanted); - return hasGlobal || res; + if (hasGlobal) { + return true; + } + return checkCtlPriv(currentUser, ctl, wanted); } // ==== Global ==== @@ -40,26 +42,34 @@ default boolean checkCtlPriv(boolean hasGlobal, UserIdentity currentUser, String // ==== Database ==== default boolean checkDbPriv(boolean hasGlobal, UserIdentity currentUser, String ctl, String db, - PrivPredicate wanted) { - boolean res = checkDbPriv(currentUser, ctl, db, wanted); - return hasGlobal || res; + PrivPredicate wanted) { + if (hasGlobal) { + return true; + } + return checkDbPriv(currentUser, ctl, db, wanted); } boolean checkDbPriv(UserIdentity currentUser, String ctl, String db, PrivPredicate wanted); // ==== Table ==== default boolean checkTblPriv(boolean hasGlobal, UserIdentity currentUser, String ctl, String db, String tbl, - PrivPredicate wanted) { - boolean res = checkTblPriv(currentUser, ctl, db, tbl, wanted); - return hasGlobal || res; + PrivPredicate wanted) { + if (hasGlobal) { + return true; + } + return checkTblPriv(currentUser, ctl, db, tbl, wanted); } boolean checkTblPriv(UserIdentity currentUser, String ctl, String db, String tbl, PrivPredicate wanted); // ==== Column ==== default void checkColsPriv(boolean hasGlobal, UserIdentity currentUser, String ctl, String db, String tbl, - Set cols, PrivPredicate wanted) throws AuthorizationException { + Set cols, PrivPredicate wanted) throws AuthorizationException { try { + boolean hasTablePriv = checkTblPriv(hasGlobal, currentUser, ctl, db, tbl, wanted); + if (hasTablePriv) { + return; + } checkColsPriv(currentUser, ctl, db, tbl, cols, wanted); } catch (AuthorizationException e) { if (!hasGlobal) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/Role.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/Role.java index 0054579062fcc5..c6abbf049e03d4 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/Role.java +++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/Role.java @@ -473,7 +473,7 @@ public boolean checkColPriv(String ctl, String db, String tbl, String col, PrivP if (!colPrivilege.isPresent()) { throw new IllegalStateException("this privPredicate should not use checkColPriv:" + wanted); } - return checkTblPriv(ctl, db, tbl, wanted) || onlyCheckColPriv(ctl, db, tbl, col, colPrivilege.get()); + return onlyCheckColPriv(ctl, db, tbl, col, colPrivilege.get()); } private boolean onlyCheckColPriv(String ctl, String db, String tbl, String col,