apache / apache/doris

[Bug] Dictionaries share the table privilege namespace and may collide with a same-name table

Open
#67,345 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
Java
Stars
15.9k
Forks
3.9k
Avg merge
2d 23h
Merged PRs (30d)
520

Description

### Search before asking

- [x] I had searched in the [issues](https://github.com/apache/doris/issues?q=is%3Aissue) and found no similar issues.

### Version

master (4a9956e0a93)

### What's Wrong?

Dictionaries are stored in `DictionaryManager`, outside the `Database` table map, but they are authorized with the table privilege key of the internal catalog: `checkTblPriv(internal, db, , ...)` is used by `CREATE/DROP DICTIONARY` (#66218) and by `SHOW/EXPLAIN/REFRESH DICTIONARY` (#67343).

Two things make that namespace leaky:

1. Name collisions are allowed. `CREATE DICTIONARY db.foo ...` only checks that no dictionary `foo` exists, and `CREATE TABLE db.foo` never checks for a dictionary `foo`, so a table and a dictionary can share a name in the same database.
2. Privileges are matched by name only. With a same-name table, any grant on table `db.foo` (including a column grant, which `Role.checkTblPriv` treats as `SHOW`) also satisfies the dictionary checks: such a user can see the dictionary in `SHOW DICTIONARIES`, describe it, drop it with `DROP` on the table, or refresh it with `LOAD` on the table.

Related: `GRANT ... ON db.` is rejected with `table: ... does not exist` for every privilege except `CREATE` (the existence check in `Auth.grantInternal` is skipped for `CREATE_PRIV`), so today dictionaries can only be authorized at the database level.

### What You Expected?

Either

- reject name collisions between tables and dictionaries in both `CREATE DICTIONARY` and `CREATE TABLE` (internal catalog), so a grant on `db.foo` can only ever refer to one object; or
- give dictionaries their own privilege object so that `GRANT`, the internal access controller and Ranger authorize them independently of tables.

### How to Reproduce?

```sql
CREATE TABLE db.src (id INT, v VARCHAR(32)) DISTRIBUTED BY HASH(id) BUCKETS 1 PROPERTIES("replication_num"="1");
CREATE TABLE db.foo (id INT) DISTRIBUTED BY HASH(id) BUCKETS 1 PROPERTIES("replication_num"="1");
CREATE DICTIONARY db.foo USING db.src (id KEY, v VALUE) LAYOUT(HASH_MAP) PROPERTIES('data_lifetime'='600');

CREATE USER u IDENTIFIED BY 'Pwd_12345';
GRANT SELECT_PRIV ON db.foo TO u; -- grant on the *table* foo

-- as u
USE db;
SHOW DICTIONARIES; -- lists dictionary foo with its source table
EXPLAIN DICTIONARY foo; -- returns the dictionary schema
```

### Anything Else?

Found while adding the missing privilege checks in #67343; that PR keeps the existing table-keyed model on purpose, so the collision handling / dedicated privilege object is tracked here.

### Are you willing to submit PR?

- [x] Yes I am willing to submit a PR!

### Code of Conduct

- [x] I agree to follow this project's [Code of Conduct](https://www.apache.org/foundation/policies/conduct)

Contributor guide

Open the contributing guide

Research direction

Start with DictionaryManager and the named authorization entry points: checkTblPriv, Role.checkTblPriv, and Auth.grantInternal. Reproduce the same-name table and dictionary scenario from the SQL example, then trace CREATE TABLE and CREATE/DROP DICTIONARY handling. Done means table privileges no longer authorize a dictionary, through collision rejection or a separate dictionary privilege object, with the listed dictionary operations covered.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, sql
Domain
authorization, databases
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.