sql >> Base de Datos >  >> RDS >> Sqlserver

SQL Server:¿Cómo otorgar permisos a los esquemas?

Me temo que su descripción o su concepción del encadenamiento de propiedad no está clara, así que permítanme comenzar con eso:

"Encadenamiento de propiedad" simplemente se refiere al hecho de que al ejecutar un procedimiento almacenado (o una vista) en SQL Server, el lote que se está ejecutando actualmente adquiere temporalmente los derechos/permisos del propietario del sProc (o del propietario del esquema del sProc) mientras ejecuta ese código SQL. Entonces, en el caso de un sProc, el usuario no puede usar esos privilegios para hacer nada que el código sProc no implemente para ellos. Tenga en cuenta especialmente que nunca adquiere la Identidad del Propietario, solo sus derechos, temporalmente (sin embargo, EJECUTAR COMO... hace esto).

Entonces, el enfoque típico para aprovechar esto por seguridad es:

  1. Coloque todas las tablas de datos (y también todas las vistas que no sean de seguridad) en su propio esquema, llamémoslo [datos] (aunque normalmente se usa [dbo] porque ya está allí y es demasiado privilegiado para el esquema del usuario). Asegúrese de que ningún Usuario, Esquema o Propietario existente tenga acceso a este esquema de [datos].

  2. Cree un esquema llamado [exec] para todos los sProcs (y/o posiblemente cualquier vista de seguridad). Asegúrese de que el propietario de este esquema tenga acceso al esquema [datos] (esto es fácil si hace que dbo sea el propietario de este esquema).

  3. Cree un nuevo db-Role llamado "Usuarios" y déle acceso de EJECUCIÓN al esquema [exec]. Ahora agregue todos los usuarios a este rol. Asegúrese de que sus usuarios solo tengan derechos de conexión y no tengan acceso otorgado a ningún otro esquema, incluido [dbo].

Ahora sus usuarios pueden acceder a los datos solo ejecutando sProcs en [exec]. No pueden acceder a ningún otro dato ni ejecutar ningún otro objeto.

No estoy seguro de si esto responde a su pregunta (porque no estaba seguro de cuál era exactamente la pregunta), así que no dude en redirigirme.

En cuanto a la seguridad a nivel de fila, así es como siempre lo hago con el esquema de seguridad anterior:

  1. Siempre implemento la seguridad a nivel de fila como una serie de Vistas que reflejan cada tabla y comparan la identidad del Usuario (generalmente con Suser_Sname() o uno de los otros) con una lista de seguridad ingresada a partir de un código de seguridad en la fila misma. Estas son las Vistas de Seguridad.

  2. Cree un nuevo esquema llamado [filas], otorgue a su propietario acceso al esquema [datos] y nada más. Coloque todas las vistas de seguridad en este esquema.

  3. Revoque el acceso del propietario [exec] al esquema [datos] y, en su lugar, concédale acceso a los datos al esquema [filas].

Hecho. Ahora se implementó la seguridad a nivel de fila deslizándola de forma transparente entre los sProcs y las tablas.

Finalmente, aquí hay una compra almacenada que utilizo para ayudarme a recordar cuánto de este oscuro material de seguridad funciona e interactúa consigo mismo (ups, versión corregida del código ):

CREATE proc [TestCnxOnly].[spShowProc_Security_NoEX]  as
--no "With Execute as Owner" for this version
--create User [UserNoLogin] without login
--Grant connect on database :: TestSecurity to Guest
--alter database TestSecurity set trustworthy on

--Show current user context:
select current_user as current_
, session_user as session
, user_name() as _name
, suser_name() as [suser (sproc)]
, suser_sname() as sname
, system_user as system_


--Execute As Login = 'UserNoLogin'
select current_user as current_
, session_user as session
, user_name() as _name
, suser_name() as [suser (after exec as)]
, suser_sname() as sname
, system_user as system_

EXEC('select current_user as current_
, session_user as session
, user_name() as _name
, suser_name() as [suser (in Exec(sql))]
, suser_sname() as sname
, system_user as system_')

EXEC sp_ExecuteSQL N'select current_user as current_
, session_user as session
, user_name() as _name
, suser_name() as [suser (in sp_Executesql)]
, suser_sname() as sname
, system_user as system_'

--Revert
select current_user as current_
, session_user as session
, user_name() as _name
, suser_name() as [suser (aftr revert)]
, suser_sname() as sname
, system_user as system_

[EDITAR:versión corregida del código)