Skip to content

Commit b0d2d17

Browse files
Add permissions audit script to assess roles and privileges
1 parent 8eac57a commit b0d2d17

1 file changed

Lines changed: 46 additions & 0 deletions

File tree

permissions.sql

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Script: sql/admin/permissions.sql
3+
*
4+
* Purpose: Provides a high-level audit of roles, their privileges, and memberships.
5+
*
6+
* Description:
7+
* This query gives a quick overview of all non-system roles in the database.
8+
* It's the first place to look when a customer reports a "permission denied"
9+
* error or when auditing for over-privileged accounts.
10+
*
11+
* Red Flags:
12+
* - `is_superuser = 't'`: Ensure only expected administrative roles have superuser status.
13+
* - `can_login = 't'` with `password_status = 'NO PASSWORD SET'`: A significant security risk.
14+
* - `can_create_roles = 't'`: This privilege can be used for privilege escalation.
15+
* - Unexpected roles in `member_of_roles`: A role may be inheriting dangerous privileges.
16+
*
17+
* Interpretation:
18+
* - `rolname`: The name of the role being audited.
19+
* - `is_superuser`, `can_create_roles`, `can_login`: Critical boolean flags indicating a role's power.
20+
* - `member_of_roles`: Shows which other roles this role inherits privileges from.
21+
*
22+
* Safety:
23+
* This script is read-only and queries standard `pg_catalog` views (`pg_roles`,
24+
* `pg_auth_members`) which are designed for fast diagnostic access. The
25+
* `statement_timeout` set by `pgtools.sh` provides a safety guarantee.
26+
*/
27+
SELECT
28+
r.rolname,
29+
r.rolsuper AS is_superuser,
30+
r.rolcreaterole AS can_create_roles,
31+
r.rolcreatedb AS can_create_databases,
32+
r.rolcanlogin AS can_login,
33+
r.rolreplication AS is_replication_role,
34+
CASE
35+
WHEN r.rolpassword IS NOT NULL THEN 'PASSWORD SET'
36+
ELSE 'NO PASSWORD SET'
37+
END AS password_status,
38+
ARRAY(
39+
SELECT g.rolname
40+
FROM pg_auth_members am
41+
JOIN pg_roles g ON am.roleid = g.oid
42+
WHERE am.member = r.oid
43+
) AS member_of_roles
44+
FROM pg_roles r
45+
WHERE r.rolname NOT LIKE 'pg_%' -- Exclude system roles
46+
ORDER BY r.rolsuper DESC, r.rolcreaterole DESC, r.rolcanlogin DESC, r.rolname;

0 commit comments

Comments
 (0)