Retrieving all object privileges for specific role

前端 未结 2 1287
Happy的楠姐
Happy的楠姐 2020-12-14 11:02

Is there an easy way to enumerate all objects that a specific role has some access privilege to? I know of the set of has_*_privilege functions in pg_catalog bu

相关标签:
2条回答
  • 2020-12-14 11:25

    There's no such view out of the box, but the data needed to create it is in the system catalogs:

    http://www.postgresql.org/docs/current/static/catalogs.html

    For instance, there's a relacl field in pg_class:

    select oid::regclass, relacl from pg_class;
    

    There are similar fields in other catalogs, namely typacl in pg_type and proacl in pg_proc.

    You'll presumably want to use two more catalogs, namely pg_authid to know which roles are have superuser privileges, and pg_auth_members to know who has what role.

    (The pg_default_acl is only used during object creation, so is not useful.)

    There are a couple of aclitem-related internal functions that may come in handy in creating the view. You can list them in psql like so:

    \df+ *acl*
    

    In particular aclexplode(). The following example will hopefully be enough to get you started:

    select oid::regclass,
           (aclexplode(relacl)).grantor,
           (aclexplode(relacl)).grantee,
           (aclexplode(relacl)).privilege_type,
           (aclexplode(relacl)).is_grantable
    from pg_class
    where relacl is not null;
    

    It can be optimized by expanding the acl rows first, e.g.:

    select oid::regclass,
           aclitem.grantee
    from (select oid, aclexplode(relacl) as aclitem from pg_class) sub
    

    It will lead you straight to the desired result.

    Insofar as I'm aware, that's about as good as it'll get using the built-in tools. (Naturally, you could write your own set of operators in C if you'd like to try to optimize this further.)

    With respect to your extra questions, I'm afraid they can only be answered by a handful of people in the world, aka the core devs themselves. They hang out on the pg hackers list more often than they do here.

    0 讨论(0)
  • 2020-12-14 11:39

    Probably not the best / efficient way, but it helps me a lot! I needed it while having problems dropping roles and having the error.

    ERROR:  role ROLE_NAME cannot be dropped because some objects depend on it
    

    You can use it as

    SELECT * FROM upg_roles_privs WHERE grantee = 'testuser'
    

    The code is below. I'm not including "system" objects (from pg_catalog and information_schema), you can take the conditions out of the query if you wish to enumerate them.

    CREATE VIEW upg_roles_privs AS
    
        /* Databases */
        select type, objname, r1.rolname grantor, r2.rolname grantee, privilege_type
        from
        (select 
          'database'::text as type, datname as objname, datistemplate, datallowconn, 
          (aclexplode(datacl)).grantor as grantorI, 
          (aclexplode(datacl)).grantee as granteeI,
          (aclexplode(datacl)).privilege_type,
          (aclexplode(datacl)).is_grantable
        from pg_database) as db
        join pg_roles r1 on db.grantorI = r1.oid
        join pg_roles r2 on db.granteeI = r2.oid
        where r2.rolname not in ('postgres')
    
        union all
    
        /* Schemas / Namespaces */
        select type, objname, r1.rolname grantor, r2.rolname grantee, privilege_type from 
        (select
          'schema'::text as type, nspname as objname, 
          (aclexplode(nspacl)).grantor as grantorI, 
          (aclexplode(nspacl)).grantee as granteeI,
          (aclexplode(nspacl)).privilege_type,
          (aclexplode(nspacl)).is_grantable
        from pg_catalog.pg_namespace) as ns
        join pg_roles r1 on ns.grantorI = r1.oid
        join pg_roles r2 on ns.granteeI = r2.oid
        where r2.rolname not in ('postgres')
    
        union all
    
        /* Tabelas */
        select 'tables'::text as type, table_name||' ('||table_schema||')' as objname, grantor, grantee, privilege_type  
        from information_schema.role_table_grants 
        where grantee not in ('postgres')
        and table_schema not in ('information_schema', 'pg_catalog')
        and grantor <> grantee
    
        union all
    
        /* Colunas (TODO: se o revoke on table from x retirar acesso das colunas, nao precisa desse bloco) */
        select 
          'columns'::text as type, column_name||' ('||table_name||')' as objname,
          grantor, grantee, privilege_type
        from information_schema.role_column_grants
        where 
        table_schema not in ('information_schema', 'pg_catalog')
        and grantor <> grantee
    
        union all
    
        /* Funcoes / Procedures */
        select 'routine'::text as type, routine_name as objname, grantor, grantee, privilege_type
        from information_schema.role_routine_grants
        where grantor <> grantee
        and routine_schema not in ('information_schema', 'pg_catalog')
    
        --union all information_schema.role_udt_grants
    
        union all
    
        /* Outros objetos */
        select 'object'::text as type, object_name||'( '||object_type||')' as objname, grantor, grantee, privilege_type
        from information_schema.role_usage_grants
        where object_type <> 'COLLATION' and object_type <> 'DOMAIN'
    
    0 讨论(0)
提交回复
热议问题