How to enumerate all enabled roles for all users in PostgreSQL?

前端 未结 2 582
我在风中等你
我在风中等你 2021-01-21 03:35

If you want to check the roles that a user has access to, there is no easy way in PostgreSQL. In the information_schema there are relations enabled_roles

相关标签:
2条回答
  • 2021-01-21 04:00

    The trick is to make a recursive query over the system catalog relations pg_roles and pg_auth_members:

    WITH RECURSIVE membership_tree(grpid, userid) AS (
        -- Get all roles and list them as their own group as well
        SELECT pg_roles.oid, pg_roles.oid
        FROM pg_roles
      UNION ALL
        -- Now add all group membership
        SELECT m_1.roleid, t_1.userid
        FROM pg_auth_members m_1, membership_tree t_1
        WHERE m_1.member = t_1.grpid
    )
    SELECT DISTINCT t.userid, r.rolname AS usrname, t.grpid, m.rolname AS grpname
    FROM membership_tree t, pg_roles r, pg_roles m
    WHERE t.grpid = m.oid AND t.userid = r.oid
    ORDER BY r.rolname, m.rolname;
    

    This gives a view of all users in the system with all inherited role memberships. Wrap this in a view to have this utility always handy.

    Cheers, Patrick

    0 讨论(0)
  • 2021-01-21 04:20

    This was very helpful as I was looking for just this sort of information. Adapting the work above to include a level to keep track of the inheritance

    WITH RECURSIVE membership_tree(grpid, userid, lvl) AS (
    -- Get all roles and list them as their own group as well
    SELECT 
        pg_roles.oid
        , pg_roles.oid
        , 0
    FROM
        pg_roles
    
    UNION ALL
    
    -- Now add all group membership
    SELECT 
        m_1.roleid
        , t_1.userid
        , lvl + 1
    FROM
        pg_auth_members m_1
    INNER JOIN
        membership_tree t_1 
    ON
        m_1.member = t_1.grpid
    )
    SELECT DISTINCT
        t.userid
        , r.rolname AS usrname
        , t.grpid
        , m.rolname AS grpname
        , t.lvl
    FROM
        membership_tree t
    INNER JOIN
        pg_roles r
    ON
        t.userid = r.oid
    INNER JOIN
        pg_roles m
    ON
        t.grpid = m.oid
    ORDER BY
        r.rolname
        , t.lvl
        , m.rolname;
    
    0 讨论(0)
提交回复
热议问题