saltstack / saltstack/salt

[BUG] Postgresql permission checking is incorrect

Open
#59,979 3 comments 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug Confirmed severity-medium
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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.