Soy un programador, no un dba ... Sé lo suficiente como para ser peligroso.
Heredé una base de datos con un usuario heredado que es un db_owner para la base de datos. No podemos ajustar el permiso de este usuario para tablas, esquemas, etc. existentes, por razones comerciales, pero se están creando algunas tablas nuevas, y solo quiero que este usuario tenga acceso SELECCIONAR sobre ellas.
Se han establecido permisos para este usuario para estas tablas, de modo que todo está DENEGADO, excepto SELECT, que está establecido en GRANT.
Sin embargo, cuando este usuario (dbadmin) intenta realizar una SELECCIÓN en una de estas tablas (Auditoría de contabilidad), se produce este error:
The SELECT permission was denied on the object 'AccountingAudit', database 'billing', schema 'dbo'.
Ejecuté este SQL para probar y ver qué permisos están establecidos para esta tabla / usuario:
select object_name(major_id) as object,
user_name(grantee_principal_id) as grantee,
user_name(grantor_principal_id) as grantor,
permission_name,
state_desc
from sys.database_permissions
Y esto es lo que regreso:
AccountingAudit dbadmin dbo ALTER DENY
AccountingAudit dbadmin dbo CONTROL DENY
AccountingAudit dbadmin dbo DELETE DENY
AccountingAudit dbadmin dbo INSERT DENY
AccountingAudit dbadmin dbo REFERENCES DENY
AccountingAudit dbadmin dbo SELECT GRANT
AccountingAudit dbadmin dbo TAKE OWNERSHIP DENY
AccountingAudit dbadmin dbo UPDATE DENY
AccountingAudit dbadmin dbo VIEW DEFINITION DENY
AccountingAudit dbadmin dbo VIEW CHANGE TRACKING DENY
Parece que debería estar funcionando ¿verdad?
La llamada SELECT que estoy haciendo es una SELECT * FROM AccountingAudit muy básica, desde SSMS. No estoy haciendo ningún sp_executesql especial ni nada de eso.
He intentado explícitamente otorgar permiso:
GRANT SELECT ON [dbo].AccountingAudit TO dbadmin
Esto no tiene ningún efecto (¿por qué lo haría, la consulta anterior ya muestra que se ha concedido! ;-)
He buscado en stackoverflow.com y en otros lugares, y no puedo encontrar nada que aún no haya probado. Me pregunto si tiene algo que ver con cómo se configuran los esquemas. (En este punto, sé muy poco sobre esquemas).
¿Algunas ideas? ¡Gracias!
fuente
Use el
sp_DBPermissions
procedimiento almacenado de Ken Fisher para ver los permisos.DENY CONTROL
no se aplica a la mesa, además de la habitualDENY SELECT
,DENY INSERT
,DENY UPDATE
,DENY DELETE
yDENY REFERENCES
.SELECT
instrucción contiene funciones con valores de tabla, asegúrese de que haya unaEXECUTE AS OWNER
en la función con valores de tabla o unaGRANT EXECUTE
en ella (¡y noDENY EXECUTE
!). Si este es el caso, lea el mensaje de error con más cuidado, ya que probablemente no dirá que el permiso SELECT fue denegado en la tabla, sino algo sobre la denegación de EJECUTAR.Si el usuario es un usuario o grupo de AD, use el siguiente script para determinar los usuarios
login_token
:Mira el plan de ejecución real. Si el error está dentro de un procedimiento almacenado con
SET NOCOUNT ON;
, entonces el plan de ejecución real le dará una idea a la que podría no prestarle atención simplemente mirando la pestaña Mensajes en SSMS, ya que "Filas afectadas" pueden estar fuera de su control.Puede compilar la declaración como un procedimiento almacenado y "Ver dependencias de objetos" de SSMS, así como los trucos descritos por Svetlana Golovko en diferentes formas para encontrar dependencias de objetos de SQL Server
Use el evento de seguridad de SQL Server Profiler "Evento de acceso a objetos de esquema de auditoría" y las columnas "TextData" y "Success" para rastrear en qué objetos SQL Server está evaluando los permisos. - He visto situaciones en las que se emiten dos filas para este evento, y un valor dice Éxito = 1 y el otro dice Éxito = 0. En este escenario, la única solución que he encontrado que funciona es reiniciar el servidor. Incluso la ejecución
repadmin /syncall
no solucionó el problema, tampoco lo hizo iniciar y detener la aplicación (y, por lo tanto, el grupo de conexiones).Determine los permisos efectivos para el inicio de sesión:
Si el usuario está vinculado a un usuario o grupo de AD, considere ejecutar
repadmin /syncall
para forzar que los cambios realizados en el directorio activo se sincronicen entre sus controladores de dominio. - Si alguien conoce una buena manera de comparar los valores actuales de dos controladores de dominio, hágamelo saber.Antes de considerar un reinicio completo de todo el sistema, intente eliminar todas las conexiones activas para ese usuario. La razón es que el usuario obtiene su token de Windows del DC que incluye sus grupos. El token no se actualizará hasta que el usuario obtenga un nuevo token, generalmente cerrando la sesión y volviendo a iniciarla.
Hard reiniciar el sistema. Esto ha funcionado para mí. Todavía no estoy 100% seguro de por qué todavía. ¡SOLO HAGA ESTO SI PUEDE SOBREVIVIR EL TIEMPO ABAJO! ¡TENGA CUIDADO DE HACER ESTO MIENTRAS TIENE GRANDES OPERACIONES EXCEPCIONALES!
fuente