it-swarm.com.de

Empfangen von "Die SELECT-Berechtigung wurde für das Objekt verweigert", obwohl sie erteilt wurde

Ich bin ein Programmierer, kein dba ... Ich weiß gerade genug, um gefährlich zu sein.

Ich habe eine Datenbank mit einem älteren Benutzer geerbt, der ein Datenbankbesitzer für die Datenbank ist. Wir können die Berechtigung dieses Benutzers für vorhandene Tabellen, Schemas usw. aus geschäftlichen Gründen nicht anpassen, aber einige neue Tabellen werden erstellt, und ich möchte nur, dass dieser Benutzer SELECT-Zugriff darauf hat.

Für diesen Benutzer wurden Berechtigungen für diese Tabellen festgelegt, sodass alles VERWEIGERT wird, mit Ausnahme von SELECT, das auf GRANT festgelegt ist.

Wenn dieser Benutzer (dbadmin) jedoch versucht, ein SELECT für eine dieser Tabellen (AccountingAudit) auszuführen, tritt folgender Fehler auf:

The SELECT permission was denied on the object 'AccountingAudit', database 'billing', schema 'dbo'.

Ich habe diese SQL ausgeführt, um zu sehen, welche Berechtigungen für diese Tabelle/diesen Benutzer festgelegt sind:

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

Und das bekomme ich zurück:

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

Scheint, als sollte es funktionieren, oder?

Der SELECT-Aufruf, den ich mache, ist ein sehr einfaches SELECT * FROM AccountingAudit aus SSMS. Ich mache kein spezielles sp_executesql oder ähnliches.

Ich habe versucht, die Erlaubnis explizit zu erteilen:

GRANT SELECT ON [dbo].AccountingAudit TO dbadmin

Dies hat keine Auswirkung (warum sollte es so sein, die obige Abfrage zeigt bereits, dass es gewährt wird! ;-)

Ich habe durch stackoverflow.com und anderswo gesucht und kann nichts finden, was ich noch nicht ausprobiert habe. Ich frage mich, ob es etwas damit zu tun hat, wie die Schemas eingerichtet sind. (Zu diesem Zeitpunkt weiß ich sehr wenig über Schemata.)

Irgendwelche Ideen? Vielen Dank!

11
Mason G. Zhwiti

Ich bin mir hier nicht sicher, aber ich werde auf einem Ast ausgehen. Ich denke, Ihr Problem könnte in Ihrem DENY CONTROL Datensatz liegen. Siehe hier ungefähr auf halber Höhe der Seite:

Das Verweigern der CONTROL-Berechtigung für eine Datenbank verweigert implizit die CONNECT-Berechtigung für die Datenbank. Ein Principal, dem die CONTROL-Berechtigung für eine Datenbank verweigert wurde, kann keine Verbindung zu dieser Datenbank herstellen.

Mir ist klar, dass dieses Beispiel für eine Datenbank gilt, aber nehmen Sie es noch eine granulare Ebene. Ein DENY CONTROL Auf einem Tisch wird all Berechtigungen verweigern, vermute ich. Führen Sie einen REVOKE CONTROL Aus, um dies zu beseitigen und festzustellen, ob das Problem dadurch behoben wird.

In diesem Fall müssen Sie den Benutzer in eine Datenbankrolle einfügen oder ihm die expliziten Berechtigungen für die Tabelle verweigern.

10
Thomas Stringer
  1. Verwenden Sie die gespeicherte Prozedur sp_DBPermissions von Ken Fisher, um die Berechtigungen anzuzeigen.

    1. Stellen Sie sicher, dass DENY CONTROL nicht auf die Tabelle angewendet wird, zusätzlich zu den allgemeinen DENY SELECT, DENY INSERT, DENY UPDATE, DENY DELETE und DENY REFERENCES.
    2. Wenn die Anweisung SELECT Tabellenwertfunktionen enthält, stellen Sie sicher, dass entweder ein EXECUTE AS OWNER in der Tabellenwertfunktion oder ein GRANT EXECUTE darauf enthalten ist (und kein DENY EXECUTE!). Wenn dies der Fall ist, lesen Sie die Fehlermeldung genauer durch, da sie wahrscheinlich nicht besagt, dass die SELECT-Berechtigung für die Tabelle verweigert wurde, sondern dass etwas über EXECUTE verweigert wird.
  2. Wenn der Benutzer ein AD-Benutzer oder eine AD-Gruppe ist, verwenden Sie das folgende Skript, um die login_token (s) des Benutzers zu bestimmen:

EXECUTE AS LOGIN = 'EXAMPLEDOMAIN\JOHN.DOE';
SELECT * FROM sys.login_token;
REVERT;
  1. Schauen Sie sich den tatsächlichen Ausführungsplan an. Wenn sich der Fehler in einer gespeicherten Prozedur mit SET NOCOUNT ON; befindet, gibt Ihnen der tatsächliche Ausführungsplan einen Einblick, den Sie möglicherweise nicht beachten, wenn Sie nur auf die Registerkarte Nachrichten in SSMS schauen, da sich "Betroffene Zeilen" möglicherweise außerhalb befinden Ihre Kontrolle.

    1. Suchen Sie nach Triggern oder Zeittabellen.
  2. Sie können die Anweisung als gespeicherte Prozedur und SSMS "View Object Dependencies" sowie die von Svetlana Golovko in Verschiedene Möglichkeiten zum Auffinden von SQL Server-Objektabhängigkeiten beschriebenen Tricks kompilieren

  3. Verwenden Sie das SQL Server Profiler-Sicherheitsereignis "Audit Schema Object Access Event" und die Spalten "TextData" und "Success", um zu verfolgen, für welche Objekte SQL Server Berechtigungen auswertet. - Ich habe Situationen gesehen, in denen zwei Zeilen für dieses Ereignis ausgegeben werden und ein Wert "Erfolg = 1" und der andere "Erfolg = 0" anzeigt. In diesem Szenario besteht die einzige Lösung, die ich gefunden habe, darin, den Server neu zu starten. Selbst das Ausführen von repadmin /syncall hat das Problem nicht behoben, ebenso wenig wie das Starten und Stoppen der Anwendung (und damit des Verbindungspools).

  4. Bestimmen Sie die effektiven Berechtigungen für die Anmeldung:

-- '<domain>\<username>' is a domain user in the group you wish to test
EXECUTE AS LOGIN = '<domain>\<username>';
SELECT * FROM fn_my_permissions('Database.Schema.Table', 'OBJECT');
REVERT;
  1. Wenn der Benutzer an einen AD-Benutzer oder eine AD-Gruppe gebunden ist, sollten Sie repadmin /syncall ausführen, um zu erzwingen, dass in Active Directory vorgenommene Änderungen auf Ihren Domänencontrollern synchronisiert werden. - Wenn jemand eine gute Möglichkeit kennt, die aktuellen Werte von zwei Domänencontrollern zu vergleichen, lassen Sie es mich bitte wissen.

  2. Versuchen Sie, alle aktiven Verbindungen für diesen Benutzer zu beenden, bevor Sie einen harten Neustart des gesamten Systems in Betracht ziehen. Der Grund dafür ist, dass der Benutzer sein Windows-Token von DC, einschließlich seiner Gruppen) erhält. Das Token wird erst aktualisiert, wenn der Benutzer ein neues Token erhält - normalerweise durch Abmelden und anschließendes erneutes Anmelden .

  3. Starten Sie das System hart neu. Es hat bei mir funktioniert. Immer noch nicht 100% sicher warum noch. Tun Sie dies nur, wenn Sie die Zeit überleben können! Seien Sie vorsichtig, wenn Sie dies tun, während Sie große herausragende Transaktionen haben!

0
John Zabroski