Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

SQL Server :comment autoriser les schémas ?

Je crains que votre description ou votre conception du chaînage de propriété ne soit pas claire, alors permettez-moi de commencer par cela :

"Chaînage de propriété" fait simplement référence au fait que lors de l'exécution d'une procédure stockée (ou d'une vue) sur SQL Server, le lot en cours d'exécution acquiert temporairement les droits/autorisations du propriétaire de la sProc (ou du propriétaire du schéma de la sProc) lors de l'exécution de ce code SQL. Ainsi, dans le cas d'un sProc, l'utilisateur ne peut pas utiliser ces privilèges pour faire quoi que ce soit que le code sProc n'implémente pas pour eux. Notez surtout qu'il n'acquiert jamais l'Identité du Propriétaire, seuls ses droits, temporairement (cependant, EXECUTE AS... le fait).

Ainsi, l'approche typique pour tirer parti de cela pour la sécurité consiste à :

  1. Mettez toutes les tables de données (ainsi que toutes les vues non liées à la sécurité) dans leur propre schéma, appelons-le [data] (bien que généralement [dbo] soit utilisé car il est déjà là et trop privilégié pour le schéma de l'utilisateur). Assurez-vous qu'aucun utilisateur, schéma ou propriétaire existant n'a accès à ce schéma [de données].

  2. Créez un schéma appelé [exec] pour tous les sProcs (et/ou éventuellement toutes les vues de sécurité). Assurez-vous que le propriétaire de ce schéma a accès au schéma [data] (c'est facile si vous faites de dbo le propriétaire de ce schéma).

  3. Créez un nouveau db-Role appelé "Users" et donnez-lui l'accès EXECUTE au schéma [exec]. Ajoutez maintenant tous les utilisateurs à ce rôle. Assurez-vous que vos utilisateurs ne disposent que des droits de connexion et qu'ils n'ont pas accès à d'autres schémas, y compris [dbo].

Désormais, vos utilisateurs peuvent accéder aux données uniquement en exécutant les sProcs dans [exec]. Ils ne peuvent accéder à aucune autre donnée ou exécuter d'autres objets.

Je ne sais pas si cela répond à votre question (parce que je ne savais pas quelle était exactement la question), alors n'hésitez pas à me rediriger.

En ce qui concerne la sécurité au niveau des lignes, voici comment je procède toujours avec le schéma de sécurité ci-dessus :

  1. J'implémente toujours la sécurité au niveau des lignes sous la forme d'une série de vues qui enveloppent chaque table en miroir et comparent l'identité de l'utilisateur (généralement avec Suser_Sname() ou l'un des autres) à une liste de sécurité saisie à partir d'un code de sécurité dans la ligne elle-même. Ce sont les vues de sécurité.

  2. Créez un nouveau schéma appelé [lignes], donnez à son propriétaire l'accès au schéma [données] et rien d'autre. Mettez toutes les vues de sécurité dans ce schéma.

  3. Révoquez l'accès du propriétaire [exec] au schéma [data] et accordez-lui à la place l'accès aux données du schéma [rows].

Fait. Désormais, la sécurité au niveau des lignes a été implémentée en la glissant de manière transparente entre les sProcs et les tables.

Enfin, voici une source stockée que j'utilise pour m'aider à me souvenir de la quantité de ces éléments de sécurité obscurs qui fonctionnent et interagissent avec eux-mêmes (oups, version corrigée du code ):

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_

[EDIT :version corrigée du code)