sortkey redshift queries foreign example create commands sql amazon-redshift

queries - redshift sql commands



¿Cómo veo las subvenciones en Redshift? (6)

Algo a lo largo de las líneas de apagado:

select tablename, HAS_TABLE_PRIVILEGE(tablename, ''select'') as select, HAS_TABLE_PRIVILEGE(tablename, ''insert'') as insert, HAS_TABLE_PRIVILEGE(tablename, ''update'') as update, HAS_TABLE_PRIVILEGE(tablename, ''delete'') as delete, HAS_TABLE_PRIVILEGE(tablename, ''references'') as references from pg_tables where schemaname=''public'' order by tablename;

me da todo lo que necesito.

Me gustaría ver las subvenciones en los desplazamientos al rojo.

Encontré esta vista para postgres :

CREATE OR REPLACE VIEW view_all_grants AS SELECT use.usename as subject, nsp.nspname as namespace, c.relname as item, c.relkind as type, use2.usename as owner, c.relacl, (use2.usename != use.usename and c.relacl::text !~ (''({|,)'' || use.usename || ''='')) as public FROM pg_user use cross join pg_class c left join pg_namespace nsp on (c.relnamespace = nsp.oid) left join pg_user use2 on (c.relowner = use2.usesysid) WHERE c.relowner = use.usesysid or c.relacl::text ~ (''({|,)(|'' || use.usename || '')='') ORDER BY subject, namespace, item

Lo que no funciona porque la ::text de ::text de relacl falla con lo siguiente:

ERROR: cannot cast type aclitem[] to character varying [SQL State=42846]

Modificando la consulta para

CREATE OR REPLACE VIEW view_all_grants AS SELECT use.usename as subject, nsp.nspname as namespace, c.relname as item, c.relkind as type, use2.usename as owner, c.relacl -- , (use2.usename != use.usename and c.relacl::text !~ (''({|,)'' || use.usename || ''='')) as public FROM pg_user use cross join pg_class c left join pg_namespace nsp on (c.relnamespace = nsp.oid) left join pg_user use2 on (c.relowner = use2.usesysid) WHERE c.relowner = use.usesysid -- or c.relacl::text ~ (''({|,)(|'' || use.usename || '')='') ORDER BY subject, namespace, item

Permite crear la vista, pero me preocupa que esto no muestre todos los datos relevantes.

¿Cómo puedo modificar la vista para que funcione en el desplazamiento al rojo o hay una manera mejor / alternativa de ver las concesiones en el desplazamiento al rojo?

ACTUALIZACIÓN: Redshift tiene la función HAS_TABLE_PRIVILEGE para verificar las concesiones. (ver here )


Aquí hay otra consulta útil para ver las concesiones en el esquema (uso, creación) por usuario que creé en base a la consulta anterior por :

SELECT * FROM ( SELECT schemaname ,usename ,HAS_SCHEMA_PRIVILEGE(usrs.usename, schemaname, ''usage'') AS usg ,HAS_SCHEMA_PRIVILEGE(usrs.usename, schemaname, ''create'') AS crt FROM ( SELECT distinct(schemaname) FROM pg_tables WHERE schemaname not in (''pg_internal'') UNION SELECT distinct(schemaname) FROM pg_views WHERE schemaname not in (''pg_internal'') ) AS objs ,(SELECT * FROM pg_user) AS usrs ORDER BY schemaname ) WHERE (usg = true or crt = true) --and schemaname=''<opt schemaname>'' --and usename = ''<opt username>'';


La función has_table_privilege es práctica, pero no siempre ayuda en la administración cuando desea administrar grupos. Transformé su consulta original para crear scripts de concesión para usuarios o grupos específicos. Esta consulta de muestra puede modificarse fácilmente para satisfacer sus necesidades

select namespace||''.''||item as tablename , ''grant '' || substring( case when charindex(''r'',split_part(split_part(array_to_string(relacl, ''|''),''group dw_developers='',2 ) ,''/'',1)) > 0 then '',select '' else '''' end ||case when charindex(''w'',split_part(split_part(array_to_string(relacl, ''|''),''group dw_developers='',2 ) ,''/'',1)) > 0 then '',update '' else '''' end ||case when charindex(''a'',split_part(split_part(array_to_string(relacl, ''|''),''group dw_developers='',2 ) ,''/'',1)) > 0 then '',insert '' else '''' end ||case when charindex(''d'',split_part(split_part(array_to_string(relacl, ''|''),''group dw_developers='',2 ) ,''/'',1)) > 0 then '',delete '' else '''' end ||case when charindex(''R'',split_part(split_part(array_to_string(relacl, ''|''),''group dw_developers='',2 ) ,''/'',1)) > 0 then '',rule '' else '''' end ||case when charindex(''x'',split_part(split_part(array_to_string(relacl, ''|''),''group dw_developers='',2 ) ,''/'',1)) > 0 then '',references '' else '''' end ||case when charindex(''t'',split_part(split_part(array_to_string(relacl, ''|''),''group dw_developers='',2 ) ,''/'',1)) > 0 then '',trigger '' else '''' end ||case when charindex(''X'',split_part(split_part(array_to_string(relacl, ''|''),''group dw_developers='',2 ) ,''/'',1)) > 0 then '',execute '' else '''' end ||case when charindex(''U'',split_part(split_part(array_to_string(relacl, ''|''),''group dw_developers='',2 ) ,''/'',1)) > 0 then '',usage '' else '''' end ||case when charindex(''C'',split_part(split_part(array_to_string(relacl, ''|''),''group dw_developers='',2 ) ,''/'',1)) > 0 then '',create '' else '''' end ||case when charindex(''T'',split_part(split_part(array_to_string(relacl, ''|''),''group dw_developers='',2 ) ,''/'',1)) > 0 then '',temporary '' else '''' end , 2,10000) || '' on ''||namespace||''.''||item ||'' to group dw_developers;'' as grantsql from (SELECT use.usename as subject, nsp.nspname as namespace, c.relname as item, c.relkind as type, use2.usename as owner, c.relacl FROM pg_user use cross join pg_class c left join pg_namespace nsp on (c.relnamespace = nsp.oid) left join pg_user use2 on (c.relowner = use2.usesysid) WHERE c.relowner = use.usesysid and nsp.nspname NOT IN (''pg_catalog'', ''pg_toast'', ''information_schema'') ORDER BY subject, namespace, item ) where relacl is not null and array_to_string(relacl, ''|'') like ''%group dw_developers%'' order by 1


Luché mucho con esto y finalmente se me ocurrió una solución que me da justo lo que quiero ver.

WITH tabledef as ( SELECT schemaname, ''t'' AS typename, tablename AS objectname, tableowner as owner, schemaname + ''.'' + tablename AS fullname FROM pg_tables UNION SELECT schemaname, ''v'' AS typename, viewname AS objectname, viewowner as owner, schemaname + ''.'' + viewname AS fullname FROM pg_views ), res AS ( SELECT t.*, CASE HAS_TABLE_PRIVILEGE(u.usename, t.fullname, ''select'') WHEN true THEN u.usename ELSE NULL END AS sel, CASE HAS_TABLE_PRIVILEGE(u.usename, t.fullname, ''insert'') WHEN true THEN u.usename ELSE NULL END AS ins, CASE HAS_TABLE_PRIVILEGE(u.usename, t.fullname, ''update'') WHEN true THEN u.usename ELSE NULL END AS upd, CASE HAS_TABLE_PRIVILEGE(u.usename, t.fullname, ''delete'') WHEN true THEN u.usename ELSE NULL END AS del, CASE HAS_TABLE_PRIVILEGE(u.usename, t.fullname, ''references'') WHEN true THEN u.usename ELSE NULL END AS ref FROM tabledef AS t JOIN pg_user AS u ON HAS_TABLE_PRIVILEGE(u.usename, t.fullname, ''select'') = true OR HAS_TABLE_PRIVILEGE(u.usename, t.fullname, ''insert'') = true OR HAS_TABLE_PRIVILEGE(u.usename, t.fullname, ''update'') = true OR HAS_TABLE_PRIVILEGE(u.usename, t.fullname, ''delete'') = true OR HAS_TABLE_PRIVILEGE(u.usename, t.fullname, ''references'') = true OR t.owner = u.usename WHERE t.schemaname = ''analytics'' ) SELECT schemaname, objectname, owner, sel, ins, upd, del, ref FROM res WHERE sel not in (''rdsdb'', ''<superuser>'') ORDER BY schemaname, objectname;

Las dos líneas importantes: una que señala qué esquema se debe buscar para acceder

WHERE t.schemaname = ''analytics''

Y - Segundo, que descarta los permisos de superusuario (tienen permiso completo de todos modos) de los resultados.

WHERE sel not in (''rdsdb'', ''<superuser>'')


Otra variación será como:

SELECT * FROM ( SELECT schemaname ,objectname ,usename ,HAS_TABLE_PRIVILEGE(usrs.usename, fullobj, ''select'') AND has_schema_privilege(usrs.usename, schemaname, ''usage'') AS sel ,HAS_TABLE_PRIVILEGE(usrs.usename, fullobj, ''insert'') AND has_schema_privilege(usrs.usename, schemaname, ''usage'') AS ins ,HAS_TABLE_PRIVILEGE(usrs.usename, fullobj, ''update'') AND has_schema_privilege(usrs.usename, schemaname, ''usage'') AS upd ,HAS_TABLE_PRIVILEGE(usrs.usename, fullobj, ''delete'') AND has_schema_privilege(usrs.usename, schemaname, ''usage'') AS del ,HAS_TABLE_PRIVILEGE(usrs.usename, fullobj, ''references'') AND has_schema_privilege(usrs.usename, schemaname, ''usage'') AS ref FROM ( SELECT schemaname, ''t'' AS obj_type, tablename AS objectname, schemaname + ''.'' + tablename AS fullobj FROM pg_tables WHERE schemaname not in (''pg_internal'') UNION SELECT schemaname, ''v'' AS obj_type, viewname AS objectname, schemaname + ''.'' + viewname AS fullobj FROM pg_views WHERE schemaname not in (''pg_internal'') ) AS objs ,(SELECT * FROM pg_user) AS usrs ORDER BY fullobj ) WHERE (sel = true or ins = true or upd = true or del = true or ref = true) and schemaname=''<opt schema>'' and usename = ''<opt username>'';


Un desarrollo en la respuesta de mike_pdb se me ocurrió lo siguiente

WITH object_list(schema_name,object_name,permission_info) AS ( SELECT N.nspname, C.relname, array_to_string(relacl,'','') FROM pg_class AS C INNER JOIN pg_namespace AS N ON C.relnamespace = N.oid WHERE C.relkind in (''v'',''r'') AND N.nspname NOT IN (''pg_catalog'', ''pg_toast'', ''information_schema'') AND C.relacl[1] IS NOT NULL ), object_permissions(schema_name,object_name,permission_string) AS ( SELECT schema_name,object_name, SPLIT_PART(permission_info,'','',1) FROM object_list UNION ALL SELECT schema_name,object_name, SPLIT_PART(permission_info,'','',2) FROM object_list UNION ALL SELECT schema_name,object_name, SPLIT_PART(permission_info,'','',3) FROM object_list UNION ALL SELECT schema_name,object_name, SPLIT_PART(permission_info,'','',4) FROM object_list UNION ALL SELECT schema_name,object_name, SPLIT_PART(permission_info,'','',5) FROM object_list UNION ALL SELECT schema_name,object_name, SPLIT_PART(permission_info,'','',6) FROM object_list UNION ALL SELECT schema_name,object_name, SPLIT_PART(permission_info,'','',7) FROM object_list UNION ALL SELECT schema_name,object_name, SPLIT_PART(permission_info,'','',8) FROM object_list UNION ALL SELECT schema_name,object_name, SPLIT_PART(permission_info,'','',9) FROM object_list UNION ALL SELECT schema_name,object_name, SPLIT_PART(permission_info,'','',10) FROM object_list ), permission_parts(schema_name, object_name,security_principal, permission_pattern) AS ( SELECT schema_name, object_name, LEFT(permission_string ,CHARINDEX(''='',permission_string)-1), SPLIT_PART(SPLIT_PART(permission_string,''='',2),''/'',1) FROM object_permissions WHERE permission_string >'''' ) SELECT schema_name, object_name, ''GRANT '' || SUBSTRING( case when charindex(''r'',permission_pattern) > 0 then '',SELECT '' else '''' end ||case when charindex(''w'',permission_pattern) > 0 then '',UPDATE '' else '''' end ||case when charindex(''a'',permission_pattern) > 0 then '',INSERT '' else '''' end ||case when charindex(''d'',permission_pattern) > 0 then '',DELETE '' else '''' end ||case when charindex(''R'',permission_pattern) > 0 then '',RULE '' else '''' end ||case when charindex(''x'',permission_pattern) > 0 then '',REFERENCES '' else '''' end ||case when charindex(''t'',permission_pattern) > 0 then '',TRIGGER '' else '''' end ||case when charindex(''X'',permission_pattern) > 0 then '',EXECUTE '' else '''' end ||case when charindex(''U'',permission_pattern) > 0 then '',USAGE '' else '''' end ||case when charindex(''C'',permission_pattern) > 0 then '',CREATE '' else '''' end ||case when charindex(''T'',permission_pattern) > 0 then '',TEMPORARY '' else '''' end ,2,10000 ) || '' ON '' || schema_name||''.''||object_name || '' TO '' || security_principal || '';'' as grantsql FROM permission_parts ;

Hay 3 expresiones de tabla comunes usadas aquí.

  • object_list: tablas y vistas con su matriz de permisos como una cadena delimitada por comas.
  • object_permissions: esquema / objeto (tabla o vista) y un registro por cadena de permisos. Tenga en cuenta que la función SPLIT_PART no permite una posición dinámica de la pieza, por lo que se supone que no hay más de 10 usuarios o grupos con permisos directos asignados.
  • permission_parts El esquema / objeto, el principal de seguridad a quien se otorgan los permisos y los atributos de seguridad que se establecen.

Según la solución de mike_pdb, los caracteres de permiso individuales se convierten en una lista concatenada de concesiones. Como no sabemos qué subvenciones se utilizarán, usamos SUBSTRING de la posición 2 para descartar la primera coma de la lista.

Puede usar exactamente el mismo enfoque para la creación de scripts fuera de los permisos de esquema

WITH schema_list(schema_name, permission_info) AS ( SELECT nspname, array_to_string(nspacl,'','') FROM pg_namespace WHERE nspacl[1] IS NOT NULL AND nspname NOT LIKE ''pg%'' AND nspname NOT IN (''public'',''information_schema'') ), schema_permissions(schema_name,permission_string) AS ( SELECT schema_name,SPLIT_PART(permission_info,'','',1) FROM schema_list UNION ALL SELECT schema_name,SPLIT_PART(permission_info,'','',2) FROM schema_list UNION ALL SELECT schema_name,SPLIT_PART(permission_info,'','',3) FROM schema_list UNION ALL SELECT schema_name,SPLIT_PART(permission_info,'','',4) FROM schema_list UNION ALL SELECT schema_name,SPLIT_PART(permission_info,'','',5) FROM schema_list UNION ALL SELECT schema_name,SPLIT_PART(permission_info,'','',6) FROM schema_list UNION ALL SELECT schema_name,SPLIT_PART(permission_info,'','',7) FROM schema_list UNION ALL SELECT schema_name,SPLIT_PART(permission_info,'','',8) FROM schema_list UNION ALL SELECT schema_name,SPLIT_PART(permission_info,'','',9) FROM schema_list UNION ALL SELECT schema_name,SPLIT_PART(permission_info,'','',10) FROM schema_list ), permission_parts(schema_name, security_principal, permission_pattern) AS ( SELECT schema_name, LEFT(permission_string ,CHARINDEX(''='',permission_string)-1), SPLIT_PART(SPLIT_PART(permission_string,''='',2),''/'',1) FROM schema_permissions WHERE permission_string >'''' ) SELECT schema_name, ''GRANT '' || SUBSTRING( case when charindex(''r'',permission_pattern) > 0 then '',SELECT '' else '''' end ||case when charindex(''w'',permission_pattern) > 0 then '',UPDATE '' else '''' end ||case when charindex(''a'',permission_pattern) > 0 then '',INSERT '' else '''' end ||case when charindex(''d'',permission_pattern) > 0 then '',DELETE '' else '''' end ||case when charindex(''R'',permission_pattern) > 0 then '',RULE '' else '''' end ||case when charindex(''x'',permission_pattern) > 0 then '',REFERENCES '' else '''' end ||case when charindex(''t'',permission_pattern) > 0 then '',TRIGGER '' else '''' end ||case when charindex(''X'',permission_pattern) > 0 then '',EXECUTE '' else '''' end ||case when charindex(''U'',permission_pattern) > 0 then '',USAGE '' else '''' end ||case when charindex(''C'',permission_pattern) > 0 then '',CREATE '' else '''' end ||case when charindex(''T'',permission_pattern) > 0 then '',TEMPORARY '' else '''' end ,2,10000 ) || '' ON SCHEMA '' || schema_name || '' TO '' || security_principal || '';'' as grantsql FROM permission_parts;