Ich fürchte, dass entweder Ihre Beschreibung oder Ihre Vorstellung von Ownership Chaining unklar ist, also lassen Sie mich damit beginnen:
„Ownership Chaining“ bezieht sich einfach auf die Tatsache, dass beim Ausführen einer gespeicherten Prozedur (oder Ansicht) auf SQL Server der aktuell ausgeführte Batch vorübergehend die Rechte/Berechtigungen des Eigentümers der sProc (oder des Eigentümers des Schemas der sProc) erwirbt, während dieser SQL-Code ausgeführt wird. Im Fall einer sProc kann der Benutzer diese Privilegien also nicht verwenden, um etwas zu tun, was der sProc-Code nicht für ihn implementiert. Beachten Sie besonders, dass es niemals die Identität erwirbt des Besitzers, nur seine Rechte, vorübergehend (jedoch tut EXECUTE AS... dies).
Der typische Ansatz, um dies für die Sicherheit zu nutzen, ist also:
-
Legen Sie alle Datentabellen (und auch alle nicht sicherheitsrelevanten Ansichten) in ihr eigenes Schema, nennen wir es [data] (obwohl normalerweise [dbo] verwendet wird, weil es bereits vorhanden und für das Schema des Benutzers zu privilegiert ist). Stellen Sie sicher, dass keine vorhandenen Benutzer, Schemas oder Eigentümer Zugriff auf dieses [Daten]-Schema haben.
-
Erstellen Sie ein Schema namens [exec] für alle sProcs (und/oder möglicherweise alle Sicherheitsansichten). Stellen Sie sicher, dass der Eigentümer dieses Schemas Zugriff auf das [Daten]-Schema hat (das ist einfach, wenn Sie dbo zum Eigentümer dieses Schemas machen).
-
Erstellen Sie eine neue db-Rolle mit dem Namen "Benutzer" und geben Sie ihr EXECUTE-Zugriff auf das [exec]-Schema. Fügen Sie nun alle Benutzer zu dieser Rolle hinzu. Stellen Sie sicher, dass Ihre Benutzer nur Connect-Rechte haben und keinen gewährten Zugriff auf andere Schemas haben, einschließlich [dbo].
Jetzt können Ihre Benutzer nur noch auf die Daten zugreifen, indem sie die sProcs in [exec] ausführen. Sie können nicht auf andere Daten zugreifen oder andere Objekte ausführen.
Ich bin mir nicht sicher, ob dies Ihre Frage beantwortet (weil ich mir nicht sicher war, was genau die Frage war), also leiten Sie mich gerne weiter.
Was die Sicherheit auf Zeilenebene betrifft, so mache ich es immer mit dem obigen Sicherheitsschema:
-
Ich implementiere die Sicherheit auf Zeilenebene immer als eine Reihe von Views, die jede Tabelle spiegelbildlich umschließen und die Identität des Benutzers (normalerweise mit Suser_Sname() oder einem der anderen) mit einer Sicherheitsliste vergleichen, die aus einem Sicherheitscode in der Zeile selbst verschlüsselt ist. Dies sind die Sicherheitsansichten.
-
Erstellen Sie ein neues Schema namens [Zeilen], geben Sie seinem Besitzer Zugriff auf das Schema [Daten] und sonst nichts. Fügen Sie alle Sicherheitsansichten in dieses Schema ein.
-
Widerrufen Sie den Zugriff des Besitzers [exec] auf das Schema [data] und gewähren Sie ihm stattdessen Datenzugriff auf das Schema [rows].
Fertig. Jetzt wurde die Sicherheit auf Zeilenebene implementiert, indem sie transparent zwischen die sProcs und die Tabellen geschoben wurde.
Schließlich ist hier ein gespeicherter Procure, den ich verwende, um mich daran zu erinnern, wie viel von diesem obskuren Sicherheitszeug funktioniert und mit sich selbst interagiert (oops, korrigierte Version des Codes ):
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_
[BEARBEITEN:korrigierte Version des Codes)