github-actions[bot] commented on code in PR #66218:
URL: https://github.com/apache/doris/pull/66218#discussion_r3679441033


##########
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AddConstraintCommand.java:
##########
@@ -71,6 +74,7 @@ public void run(ConnectContext ctx, StmtExecutor executor) 
throws Exception {
         TableNameInfo tableNameInfo = TableNameInfoUtils.fromCatalogDb(
                 table.getDatabase().getCatalog(), table.getDatabase(), table);
         ImmutableList<String> columns = columnsAndTable.first;
+        checkAlterPriv(ctx, tableNameInfo);

Review Comment:
   The relation and columns have already been bound by 
`extractColumnsAndTable()` before this `ALTER` gate; `ANALYZED_PLAN` returns 
before the rewrite-stage privilege rule. Consequently a caller without ALTER 
can distinguish missing tables/columns from valid protected ones, and the FK 
path similarly probes the referenced side before its second check. Normalize 
both table names and authorize them first, then bind columns; add no-grant 
existing/missing-object tests plus an ALTER-without-SELECT success case.



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/CreateDictionaryCommand.java:
##########
@@ -60,12 +65,20 @@ public StmtType stmtType() {
     }
 
     @Override
-    public void run(ConnectContext ctx, StmtExecutor executor) {
+    public void run(ConnectContext ctx, StmtExecutor executor) throws 
Exception {
         try {
             // 1. Validate the dictionary info. names and existence.
             createDictionaryInfo.validateAndSet(ctx);
+        } catch (Exception e) {
+            LOG.warn("Failed to create dictionary: {}", e.getMessage());
+            throw new AnalysisException("Failed to create dictionary: " + 
e.getMessage());
+        }
+
+        // 2. Check auth. Must run after validateAndSet(), which fills in the 
default catalog/db names.

Review Comment:
   `validateAndSet()` has already resolved the source catalog/DB/table, read 
its full schema, and validated column names/types before either new check runs. 
A user without `SELECT` can therefore distinguish missing objects/columns and 
invalid types from the eventual access denial. Split default-name normalization 
from metadata binding, run the target/source checks on the normalized names, 
and only then resolve and validate the source.



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropConstraintCommand.java:
##########
@@ -75,6 +78,14 @@ public void run(ConnectContext ctx, StmtExecutor executor) 
throws Exception {
                     + "falling back to name-based lookup: {}", name, 
e.getMessage());
             tableNameInfo = extractTableNameFromPlan(ctx);
         }
+        // must be checked on both paths above: table resolution failing 
(which includes an
+        // authorization failure) falls back to a name-only lookup that binds 
nothing.
+        if (!Env.getCurrentEnv().getAccessManager().checkTblPriv(ctx, 
tableNameInfo.getCtl(),

Review Comment:
   This authorizes only the named table, but dropping a primary key calls 
`ConstraintManager.cascadeDropForeignKeys()` and removes the actual FK 
constraints from every table in `foreignTableInfos`. A user with `ALTER` on the 
parent but none on a child can therefore delete the child's constraint. Require 
`ALTER` on every referencing table before the atomic mutation (or reject the 
cascade and require separately authorized FK drops), and cover the cross-table 
PK/FK case rather than only UNIQUE.



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/CreateDictionaryCommand.java:
##########
@@ -75,4 +88,25 @@ public void run(ConnectContext ctx, StmtExecutor executor) {
             throw new AnalysisException("Failed to create dictionary: " + 
e.getMessage());
         }
     }
+
+    /**
+     * A dictionary is created in the internal catalog and its data is loaded 
by an internal task,
+     * so require CREATE on the dictionary itself and SELECT on the source 
table. Without the latter
+     * the dictionary would expose data the creator can not read.
+     */
+    private void checkAuth(ConnectContext ctx) throws 
org.apache.doris.common.AnalysisException {
+        if (!Env.getCurrentEnv().getAccessManager().checkTblPriv(ctx, 
InternalCatalog.INTERNAL_CATALOG_NAME,
+                createDictionaryInfo.getDbName(), 
createDictionaryInfo.getDictName(), PrivPredicate.CREATE)) {
+            
ErrorReport.reportAnalysisException(ErrorCode.ERR_SPECIFIC_ACCESS_DENIED_ERROR, 
"CREATE");
+        }
+
+        String srcCtl = createDictionaryInfo.getSourceCtlName();
+        String srcDb = createDictionaryInfo.getSourceDbName();
+        String srcTbl = createDictionaryInfo.getSourceTableName();
+        if (!Env.getCurrentEnv().getAccessManager().checkTblPriv(ctx, srcCtl, 
srcDb, srcTbl,

Review Comment:
   A plain table-level `SELECT` check does not establish that the creator may 
read the raw source rows. `createDictionary()` schedules `dataLoad(null, ...)`, 
which builds an ADMIN context; `LogicalCheckPolicy` skips row filters and data 
masks for ADMIN, so a policy-restricted user can create a dictionary containing 
rows/unmasked values their own SELECT would hide and read them with `dict_get`. 
Preserve the effective principal/policies for the load (and refresh), or 
otherwise prevent policy-bound sources from being materialized this way.



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/WarmUpClusterCommand.java:
##########
@@ -180,6 +190,13 @@ public void validate(ConnectContext connectContext) throws 
UserException {
             throw new UserException("The sql is just support in cloud mode");
         }
 
+        // check auth. warming up moves data between compute groups, so 
require USAGE on both ends
+        // instead of global ADMIN. Keep it aligned with 
UseCloudClusterCommand.
+        checkComputeGroupUsage(connectContext, dstCluster);

Review Comment:
   This USAGE gate admits non-admin `ON TABLES` jobs, but that mode then scans 
every internal DB/table and stores matching IDs/names without table 
authorization; `refreshAllTableFilters()` adds future matches without an 
effective identity to reauthorize them. A user with USAGE on both compute 
groups can therefore warm protected tables. Either keep pattern jobs 
ADMIN-only, or require SELECT for every initial match and persist the principal 
so future matches are reauthorized.



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/WarmUpClusterCommand.java:
##########
@@ -226,6 +243,12 @@ public void validate(ConnectContext connectContext) throws 
UserException {
                 if (table == null) {
                     
ErrorReport.reportAnalysisException(ErrorCode.ERR_BAD_TABLE_ERROR, 
tableNameInfo.getTbl());
                 }
+                if 
(!Env.getCurrentEnv().getAccessManager().checkTblPriv(connectContext, 
tableNameInfo.getCtl(),

Review Comment:
   The object resolved and later warmed is always `internal.db.table`, but this 
check uses the catalog supplied in SQL and the downstream triple drops the 
catalog. Thus `SELECT` on `ext.db.t` can authorize warming the same-named 
`internal.db.t`. The internal lookup and `OlapTable` cast also happen before 
this check, leaking object/type existence to denied users. Reject non-internal 
catalogs and authorize the internal fully qualified name before lookup/cast, or 
carry one resolved catalog/object consistently end to end.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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

Reply via email to