RDS permissions bug report with PostgreSQL 15

0

Database owner does not have (implicit) usage permissions for pg_database_owner unless triggered by "related" query.

First false, then true

initech=> \conninfo
You are connected to database "initech" as user "initech_admin" on host "initech.cthulhu4u2u1.us-east-1.rds.amazonaws.com" (address "10.108.77.201") at port "5432".
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, compression: off)
initech=> SELECT
  pg_catalog.pg_has_role('initech_admin', 'pg_database_owner', 'member') AS member,
  pg_catalog.pg_has_role('initech_admin', 'pg_database_owner', 'usage') AS usage;
 member | usage
--------+-------
 t      | f
(1 row)

initech=> SELECT
  pg_catalog.pg_has_role('initech_admin', 'pg_database_owner', 'member') AS member,
  pg_catalog.pg_has_role('initech_admin', 'pg_database_owner', 'usage') AS usage;
 member | usage
--------+-------
 t      | f
(1 row)

initech=> SELECT
  pg_catalog.pg_has_role('initech_master_user', 'pg_database_owner', 'member') AS member,
  pg_catalog.pg_has_role('initech_master_user', 'pg_database_owner', 'usage') AS usage;
 member | usage
--------+-------
 t      | t
(1 row)

initech=> SELECT
  pg_catalog.pg_has_role('initech_admin', 'pg_database_owner', 'member') AS member,
  pg_catalog.pg_has_role('initech_admin', 'pg_database_owner', 'usage') AS usage;
 member | usage
--------+-------
 t      | t
(1 row)

Note from the \conninfo, the active role in the session is initech_admin. The usage=f is consistent until the initech_master_user query occurs, after which usage=t is consistent. Note the initech_master_user is the RDS master user for this PostgreSQL instance and that role has been granted initech_admin:

initech=> \du initech_master_user
                                    List of roles
      Role name      |          Attributes           |           Member of
---------------------+-------------------------------+-------------------------------
 initech_master_user | Create role, Create DB       +| {initech_admin,rds_superuser}
                     | Password valid until infinity |

initech=> \l initech
                                                 List of databases
   Name  |     Owner     | Encoding |   Collate   |    Ctype    | ICU Locale | Locale Provider | Access privileges
---------+---------------+----------+-------------+-------------+------------+-----------------+-------------------
 initech | initech_admin | UTF8     | en_US.UTF-8 | en_US.UTF-8 |            | libc            |
(1 row)

From non-database owner

If we connect as a different role initech_app (which is neither the database owner nor the RDS master user), the usage=t returns immediately for the initech_admin role:

psql (15.2 (Homebrew))
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, compression: off)
Type "help" for help.

initech=> \conninfo
You are connected to database "initech" as user "initech_app" on host "initech.cthulhu4u2u1.us-east-1.rds.amazonaws.com" (address "10.108.77.201") at port "5432".
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, compression: off)
initech=> SELECT
  pg_catalog.pg_has_role('initech_admin', 'pg_database_owner', 'member') AS member,
  pg_catalog.pg_has_role('initech_admin', 'pg_database_owner', 'usage') AS usage;
 member | usage
--------+-------
 t      | t
(1 row)

Note this role is not a member of any other roles (and from the above, is not the database owner):

initech=> \du initech_app
                      List of roles
  Role name  |          Attributes           | Member of
-------------+-------------------------------+-----------
 initech_app | Password valid until infinity | {}

Comparison to non-RDS PostgreSQL

On the other hand, a Dockerized PostgreSQL does not have this issue:

initech=> \conninfo
You are connected to database "initech" as user "initech_admin" on host "127.0.0.1" at port "16077".
initech=> SELECT
  pg_catalog.pg_has_role('initech_admin', 'pg_database_owner', 'member') AS member,
  pg_catalog.pg_has_role('initech_admin', 'pg_database_owner', 'usage') AS usage;
 member | usage
--------+-------
 t      | t
(1 row)

Note the database is set up in roughly the same way:

initech=> \du initech_master_user
                             List of roles
      Role name      |          Attributes           |    Member of
---------------------+-------------------------------+-----------------
 initech_master_user | Create role, Create DB       +| {initech_admin}
                     | Password valid until infinity |

initech=> \l initech
                                                 List of databases
  Name   |     Owner     | Encoding |   Collate   |    Ctype    | ICU Locale | Locale Provider | Access privileges
---------+---------------+----------+-------------+-------------+------------+-----------------+-------------------
 initech | initech_admin | UTF8     | en_US.UTF-8 | en_US.UTF-8 |            | libc            |
(1 row)
profile picture
asked a year ago77 views
No Answers

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions