25

Inspiré par diverses questions liées au schéma que j'ai vu ...SQL Server: comment autoriser les schémas?

Ownership chaining me permet d'accorder Executer sur une procédure stockée sans autorisations explicites sur les tables que j'utilise, si les deux procédures stockées et les tables sont dans le même schéma.

Si nous utilisons des schémas séparés, je devrais explicitement attribuer GRANT XXX sur les tables du schéma différent. L'exemple de chaînage de propriété le démontre. Cela signifie que l'utilisateur proc en cours d'enregistrement peut lire/écrire vos tables directement. Cela équivaudrait à avoir un accès direct à vos variables d'instance dans une classe, en contournant getter/setters, en rompant l'encapsulation.

Nous utilisons également la sécurité de niveau ligne pour restreindre ce que quelqu'un voit et nous l'appliquons dans les procédures stockées. Alors, comment pouvons-nous maintenir la séparation du schéma et empêcher l'accès direct à la table?

Bien sûr, la question ne s'applique pas si vous utilisez un ORM ou n'utilisez pas de procs stockés. Mais je ne suis pas demander si je devrais utiliser un ORM ou quelqu'un proc dans le cas où stocké ressent le besoin de me éclairer ...

Modifier, par exemple

CREATE USER OwnsMultiSchema WITHOUT LOGIN 
GO 
CREATE SCHEMA MultiSchema1 AUTHORIZATION OwnsMultiSchema 
GO 
CREATE SCHEMA MultiSchema2 AUTHORIZATION OwnsMultiSchema 
GO 

CREATE USER OwnsOtherSchema WITHOUT LOGIN 
GO 
CREATE SCHEMA OtherSchema AUTHORIZATION OwnsOtherSchema 
GO 

CREATE TABLE MultiSchema1.T1 (foo int) 
GO 
CREATE TABLE MultiSchema2.T2 (foo int) 
GO 
CREATE TABLE OtherSchema.TA (foo int) 
GO 

CREATE PROC MultiSchema1.P1 
AS 
SELECT * FROM MultiSchema1.T1 
SELECT * FROM MultiSchema2.T2 
SELECT * FROM OtherSchema.TA 
Go 
EXEC AS USER = 'OwnsMultiSchema' 
GO 
--gives error on OtherSchema 
EXEC MultiSchema1.P1 
GO 
REVERT 
GO 

CREATE PROC OtherSchema.PA 
AS 
SELECT * FROM MultiSchema1.T1 
SELECT * FROM MultiSchema2.T2 
SELECT * FROM OtherSchema.TA 
Go 
GRANT EXEC ON OtherSchema.PA TO OwnsMultiSchema 
GO 
EXEC AS USER = 'OwnsMultiSchema' 
GO 
--works 
EXEC OtherSchema.PA 
GO 
REVERT 
GO 

Edit 2:

    nous
  • ne pas utiliser « la propriété de chaînage de base de données croisée »
  • sécurité au niveau de la ligne est un hareng saur et hors de propos: nous ne l'utilisez pas partout
+2

Serait-il possible de fournir un exemple codé du scénario de schéma séparé que vous décrivez pour plus de clarté? Dans votre scénario, les deux schémas séparés ont-ils le même propriétaire? –

+0

Pourquoi voter ferme pour serverfault? C'est pour les singes de code, pas les administrateurs système ... – gbn

+0

@John Sansom: oui je le ferai. – gbn

Répondre

21

Je crains que ce soit votre description ou votre conception de propriété Enchaînement n'est pas clair, alors laissez-moi commencer par cela:

« Ownership Chaining » désigne simplement le fait que lors de l'exécution d'une procédure stockée (ou View) sur SQL Server, le lot en cours d'exécution acquiert temporairement les droits/autorisations du propriétaire de sProc (ou du propriétaire du schéma de 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 quelque chose que le code sProc ne met pas en œuvre pour eux. Notez en particulier qu'il n'acquiert jamais le Identité du propriétaire, seulement ses droits, temporairement (cependant, EXECUTE AS ... fait cela).

donc l'approche typique de tirer parti de cette sécurité est de:

  1. Mettez tous les tableaux de données (et toutes les vues non sécurité ainsi) dans leur propre schéma, nous allons l'appeler [les données ] (bien que typiquement [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 [data].

  2. Créez un schéma appelé [exec] pour tous les sProcs (et/ou éventuellement 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 rôle db appelé "Utilisateurs" et donnez-lui un accès EXECUTE au schéma [exec]. Maintenant, ajoutez tous les utilisateurs à ce rôle. Assurez-vous que vos utilisateurs n'ont que des droits Connect et qu'ils n'ont pas accès à un autre schéma, y ​​compris [dbo].

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

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


En ce qui concerne la sécurité au niveau de la ligne, voici comment je le fais toujours avec le régime de sécurité ci-dessus:

  1. je mets en œuvre toujours la sécurité au niveau de la ligne comme une série de vues ce miroir-wrap chaque table et comparez 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 Security-Views.

  2. Créez un nouveau schéma appelé [rows], donnez son accès propriétaire au schéma [data] et rien d'autre. Placez toutes les vues de sécurité dans ce schéma.

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

Terminé. La sécurité au niveau des lignes a maintenant été implémentée en la glissant de manière transparente entre les sProcs et les tables.


Enfin, voici une Procure stockée que je l'utilise pour me aider souviens combien de ces œuvres de trucs de sécurité obscures et interagit avec lui-même (oops, 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)

+0

Je comprends généralement la propriété chaînage par cet exemple: Un proc stocké dans schema1 accéder à des tables dans schema1 = droits de table (y compris DENY) pas vérifié. Les tables dans, disons, schema2 sont vérifiées. Mon exemple montre qu'avec EXEC MultiSchema1.P1 – gbn

+0

Mon propre exemple qui s'est croisé avec votre réponse. Le bit qui me manquait est que si le * propriétaire * des schémas concernés est le même, les droits ne sont pas vérifiés. C'est donc la signification de la séparation utilisateur/schéma que je devrais vraiment lire. Cependant, nous avons le surplomb pré SQL 2005 et nous n'y avons pas réfléchi – gbn

+0

Cet exemple fonctionne parce que c'est dans le même schéma, donc le proc stocké et la table ont le même propriétaire, donc l'accès est autorisé car un propriétaire a toujours * default * droits d'accès à leurs propres choses. Notez cependant que ce n'est pas exclusif de DENY, etc. tout ce qui pourrait arrêter le propriétaire du schéma arrêtera certainement les procs stockés qu'ils possèdent aussi. – RBarryYoung

4

Vous pouvez:

Grant Execute On Schema::[schema_name] To [user_name] 

pour permettre à l'utilisateur d'exécuter des procédures dans le schéma. Si vous ne voulez pas qu'il soit en mesure d'exécuter chacun d'eux, vous pouvez refuser explicitement d'exécuter sur une procédure particulière à l'utilisateur. Deny aura préséance dans ce cas.

+0

Correct, mais qu'en est-il des tables dans les différents schémas utilisés par les procédures stockées? Je ne veux pas Dénier tous les droits – gbn

8

Mon 2c: Le chaînage de propriété est hérité. Il date des jours où il n'y avait pas d'alternatives, et comparé avec les alternatives d'aujourd'hui est non sécurisé et grossier.

Je dis que l'alternative n'est pas des autorisations de schéma, l'alternative est la signature de code. Avec la signature de code, vous pouvez accorder les autorisations nécessaires sur la signature de la procédure, et accorder un accès d'exécution étendu sur la procédure pendant que l'accès aux données est étroitement contrôlé. La signature de code offre un contrôle plus granulaire et plus précis, et il ne peut pas être abusé de la façon dont le chaînage de propriété peut. Il fonctionne à l'intérieur du schéma, il fonctionne à travers le schéma, il fonctionne à travers la base de données et ne nécessite pas l'énorme trou de sécurité de la chaîne de propriété de la base de données croisée pour être ouvert. Et il ne nécessite pas le piratage de la propriété de l'objet à des fins d'accès: le propriétaire de la procédure peut être n'importe quel utilisateur.En ce qui concerne votre deuxième question sur la sécurité au niveau de la ligne: la sécurité au niveau de la ligne n'existe pas réellement dans les versions de SQL Server 2014 et antérieures, en tant que fonctionnalité offerte par le moteur. Vous avez diverses solutions de contournement, et ces solutions de contournement fonctionnent réellement mieux avec la signature de code qu'avec le chaînage de propriété. Étant donné que sys.login_token contient les signatures de contexte et les contre-signatures, vous pouvez effectuer des vérifications plus complexes que vous ne le pourriez dans un contexte de chaînage de propriété.

Depuis la version 2016, SQL Server prend entièrement en charge row level security.

+0

La sécurité au niveau de la ligne est en fait un harcèlement rouge .. nous utilisons aussi SUSER_SNAME via JOINs à partir des tables de sécurité pour contrôler l'accès. – gbn

+0

C'est le bit «héritage» et puis le temps/effort/paresse pourquoi je n'ai pas suivi. + 1 de toute façon. Merci – gbn

Questions connexes