[BUG] Postgresql permission checking is incorrect
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 15.7k
- Forks
- 5.6k
- Avg merge
- 2d 44m
- Merged PRs (30d)
- 80
Description
Description
There are several issues that arise out of this problem.
- #58035
- #57690
- #51450 (probably)
- #44681 (maybe)
Setup
According to https://www.postgresql.org/docs/13/ddl-priv.html there are several privilege abbreviations, and applicable object types.
| Privilege | Abbreviation | Applicable Object Types |
|---|---|---|
| SELECT | r (“read”) | LARGE OBJECT, SEQUENCE, TABLE (and table-like objects), table column |
| INSERT | a (“append”) | TABLE, table column |
| UPDATE | w (“write”) | LARGE OBJECT, SEQUENCE, TABLE, table column |
| DELETE | d | TABLE |
| TRUNCATE | D | TABLE |
| REFERENCES | x | TABLE, table column |
| TRIGGER | t | TABLE |
| CREATE | C | DATABASE, SCHEMA, TABLESPACE |
| CONNECT | c | DATABASE |
| TEMPORARY | T | DATABASE |
| EXECUTE | X | FUNCTION, PROCEDURE |
| USAGE | U | DOMAIN, FOREIGN DATA WRAPPER, FOREIGN SERVER, LANGUAGE, SCHEMA, SEQUENCE, TYPE |
Currently the tests codifies incorrect parsing that only treats privileges as granted if they have the grant privilege.
For example, this query:
create user user_one;
create user user_two;
create database user_one;
grant all on user_one to user_one;
\c user_one user_one
create table fnord (name text, age int, primary key(name));
SELECT relacl AS name FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE nspname = 'public' AND relname = 'fnord' AND relkind = 'r' ORDER BY relname;
This will produce zero permissions (empty relacl)
Follow up with
grant all on fnord to user_two;
SELECT relacl AS name FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE nspname = 'public' AND relname = 'fnord' AND relkind = 'r' ORDER BY relname;
Produces:
name
-------------------------------------------------------
{user_one=arwdDxt/user_one,user_two=arwdDxt/user_one}
(1 row)
According to the current code that means that neither user has permissions to the table. Oops. To get the permissions to show up:
grant select on fnord to user_two with grant option;
SELECT relacl AS name FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE nspname = 'public' AND relname = 'fnord' AND relkind = 'r' ORDER BY relname;
name
--------------------------------------------------------
{user_one=arwdDxt/user_one,user_two=ar*wdDxt/user_one}
From what I can tell, the tests are expecting grant privileges before they report that permissions have been added. That means any code that's using this path to check permissions are going to have to re-apply the state when they don't need to.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the privilege-related tests in tests/unit/modules/test_postgres.py#L1439-L1464 and the parsing logic in salt/modules/postgres.py#L3051-L3067. Compare the existing expectations with PostgreSQL's privilege abbreviations and the examples in the issue. Done means permissions granted without the grant option are recognized correctly and the affected tests reflect that behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- postgresql, python
- Domain
- authorization, databases
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 35/100