List PostgreSQL Roles and Their Privileges
How to List PostgreSQL Roles and Privileges
PostgreSQL uses roles for both users and groups. A role with the LOGIN attribute is a user account. A role without LOGIN is typically a group role used to collect privileges that are then granted to login roles. Understanding which roles exist, what privileges they have, and which roles belong to which groups is a fundamental security audit task.
This article shows SQL queries to list all roles, their key attributes, and role membership.
Sample Code
List all roles with key attributes:
1SELECT
2 rolname AS role_name,
3 rolsuper AS superuser,
4 rolcreaterole AS can_create_roles,
5 rolcreatedb AS can_create_db,
6 rolcanlogin AS can_login,
7 rolreplication AS replication_role,
8 rolbypassrls AS bypass_rls,
9 rolconnlimit AS connection_limit,
10 rolvaliduntil AS password_expiry
11FROM
12 pg_catalog.pg_roles
13ORDER BY
14 rolsuper DESC,
15 rolcanlogin DESC,
16 rolname;
List only login roles (users):
1SELECT
2 rolname AS username,
3 rolsuper AS superuser,
4 rolcreatedb AS can_create_db,
5 rolconnlimit AS connection_limit,
6 rolvaliduntil AS password_expiry
7FROM
8 pg_catalog.pg_roles
9WHERE
10 rolcanlogin = true
11ORDER BY
12 rolname;
List role membership (who belongs to which group):
1SELECT
2 r.rolname AS role,
3 m.rolname AS member_of,
4 am.admin_option AS is_admin
5FROM
6 pg_catalog.pg_auth_members am
7 JOIN pg_catalog.pg_roles r ON r.oid = am.member
8 JOIN pg_catalog.pg_roles m ON m.oid = am.roleid
9ORDER BY
10 m.rolname, r.rolname;
Find all superuser accounts:
1SELECT rolname
2FROM pg_catalog.pg_roles
3WHERE rolsuper = true
4ORDER BY rolname;
Notes: Works on all supported PostgreSQL versions. pg_roles is a view over pg_authid that hides the password hash column, making it safe to query as any role.
Code Breakdown
pg_catalog.pg_roles— A view overpg_authidthat exposes role attributes without the password hash. Safe to query as any user.rolname— The role name as used in SQL (CREATE ROLE,GRANT,SET ROLE).rolsuper— If true, this role is a superuser and bypasses all permission checks. Keep the number of superusers minimal.rolcreaterole— If true, this role can create, alter, and drop other roles.rolcreatedb— If true, this role can create new databases.rolcanlogin— If true, this role can authenticate and open a database session. False means it is a group role.rolreplication— If true, this role can initiate streaming replication and runpg_backup_start()/pg_backup_stop().rolbypassrls— If true, this role bypasses all Row Level Security policies.rolconnlimit— Maximum number of concurrent connections.-1means unlimited.rolvaliduntil— Password expiry timestamp. Null means no expiry.pg_catalog.pg_auth_members— Stores role membership.memberis the OID of the role that belongs to the group,roleidis the OID of the group.admin_option— If true, the member can grant this group membership to other roles.
Key Points
- Every PostgreSQL database cluster has a
postgressuperuser role created atinitdbtime. - Predefined system roles starting with
pg_(e.g.,pg_monitor,pg_read_all_stats,pg_signal_backend) are built-in since PostgreSQL 10. They are not superusers but grant specific elevated privileges. - A role that is a member of a group role inherits its privileges by default. This can be controlled with
NOINHERIT. - Passwords are not visible through
pg_roles. The underlyingpg_authidtable stores the hash, but only superusers can query it.
Insights and Explanations
Superuser sprawl is a security risk:
Every superuser can do anything in the cluster — bypass RLS, read all tables, terminate any connection, run COPY to/from files on the server. Audit the superuser list regularly and revoke superuser from accounts that do not need it.
Demote a superuser to a regular role:
1ALTER ROLE myuser NOSUPERUSER;
Using group roles to manage permissions:
Rather than granting privileges directly to every login role, grant them to a group role, then add users to the group:
1CREATE ROLE readonly NOLOGIN;
2GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly;
3GRANT readonly TO alice;
4GRANT readonly TO bob;
When a new table is added, only the group role needs updating.
Checking effective privileges for a role:
1-- See database-level privileges
2SELECT
3 datname,
4 datacl
5FROM pg_database
6WHERE datname = 'mydb';
7
8-- See table-level privileges
9SELECT
10 grantee,
11 table_name,
12 privilege_type
13FROM information_schema.role_table_grants
14WHERE grantee = 'alice';
Checking which roles have the replication attribute:
1SELECT rolname
2FROM pg_catalog.pg_roles
3WHERE rolreplication = true;
Only replication roles should be used in pg_hba.conf replication entries.
Additional Considerations
- Permissions: Any user can query
pg_roles. Only superusers can querypg_authid(which includes the password hash). - Row Level Security:
rolbypassrlsshould be assigned with caution. Even non-superuser roles withBYPASSRLScan read rows that RLS policies are meant to hide. - Password expiry: Setting
rolvaliduntilenforces password rotation but only for password-based authentication. It does not affect certificate or peer authentication. - \du command: In
psql,\duruns a formatted version of a similar query. The SQL approach used here is more portable and scriptable.
References
Posts in this series
- How Many Connections Can Your PostgreSQL Database Handle?
- PostgreSQL Backend Connections via pg_stat_database
- Identifying Blocking PostgreSQL Queries using pg_stat_activity
- List PostgreSQL Databases by Size with Access Check
- Assess PostgreSQL Database Sizes Quickly and Easily
- Unveiling Your PostgreSQL Server - A Diagnostic Powerhouse
- Keep Your PostgreSQL Database Clean, Identify Idle Connections
- Query the PostgreSQL Configuration
- PostgreSQL Recovery Monitoring: Essential SQL Insights
- Restart All PostgreSQL Sequences with ALTER SEQUENCE
- Monitor Running Queries in PostgreSQL using pg_stat_activity
- Monitor PostgreSQL Active Sessions with pg_stat_activity
- PostgreSQL Error Handling Settings via pg_settings
- PostgreSQL File Location Settings Query via pg_settings
- PostgreSQL Lock Management Settings via pg_settings
- PostgreSQL Logging Configuration Query via pg_settings
- Monitor PostgreSQL Memory Settings with pg_settings
- PostgreSQL Table Row Count Estimates with SQL
- List PostgreSQL Tables by Size with SQL
- PostgreSQL WAL Settings Query Guide
- PostgreSQL SSL Settings Query Guide
- PostgreSQL Statistics Settings Query Guide
- PostgreSQL Resource Settings Query Guide
- PostgreSQL Replication Settings Query Guide
- PostgreSQL Query Planning Settings Query Guide
- PostgreSQL Preset Options Settings Query Guide
- PostgreSQL Miscellaneous Settings Query Guide
- Count PostgreSQL Sessions by State with SQL
- Kill Idle PostgreSQL Sessions with SQL
- Grant SELECT on All Tables in PostgreSQL
- Identify Insert-Only Tables in PostgreSQL
- Detect Soft Delete Patterns in PostgreSQL
- List PostgreSQL Object Comments with SQL
- List Foreign Key Constraints in PostgreSQL
- List PostgreSQL Enum Types and Their Values with SQL
- List All Views in a PostgreSQL Database with SQL
- Find PostgreSQL Tables Without a Primary Key
- List PostgreSQL Partitioned Tables with SQL
- List All Schemas in Your PostgreSQL Database
- PostgreSQL Database Statistics with pg_stat_database
- List PostgreSQL Roles and Their Privileges
- Scrubbing Email PII in PostgreSQL for GDPR Compliance
- List Installed Extensions in PostgreSQL
- List Collations in Your PostgreSQL Database
- PostgreSQL Replica Identity for Logical Replication