it-swarm-eu.dev

Obdržení "Oprávnění SELECT bylo u objektu zamítnuto", přestože bylo uděleno

Jsem programátor, ne dba ... vím, že je dost nebezpečný.

Zdědil jsem databázi se starým uživatelem, který je db_owner pro databázi. Oprávnění tohoto uživatele nemůžeme upravit z existujících tabulek, schémat atd. Z obchodních důvodů, ale vytvářejí se některé nové tabulky a já chci, aby měl tento uživatel k nim pouze SELECT přístup.

Pro tohoto uživatele byla pro tyto tabulky nastavena oprávnění tak, aby bylo všechno DENIED, kromě SELECT, který je nastaven na GRANT.

Přesto, když se tento uživatel (dbadmin) pokusí provést SELECT v jedné z těchto tabulek (AccountingAudit), dojde k této chybě:

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

Spustil jsem tento SQL, abych se pokusil zjistit, jaká oprávnění jsou nastavena pro tuto tabulku/uživatele:

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

A to je to, co se dostanu zpět:

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

Vypadá to, že by to mělo fungovat správně?

Volání SELECT, které dělám, je velmi základní SELECT * FROM AccountingAudit, v rámci SSMS. Nedělám žádné speciální sp_executesql nebo něco podobného.

Snažil jsem se výslovně udělit povolení:

GRANT SELECT ON [dbo].AccountingAudit TO dbadmin

To nemá žádný účinek (proč by to, výše uvedený dotaz již ukazuje, že je uděleno! ;-)

Prohledal jsem stackoverflow.com a jinde a nemohu najít nic, co jsem ještě nezkusil. Zajímalo by mě, jestli to má něco společného s tím, jak jsou schémata nastavena. (V tuto chvíli vím o schématech jen velmi málo.)

Nějaké nápady? Dík!

11
Mason G. Zhwiti

Nejsem si tím jistý, ale budu chodit na končetinu. Myslím, že váš problém může být s vaším DENY CONTROL záznam. Viz zde asi v polovině stránky:

Odepření oprávnění CONTROL v databázi implicitně popírá oprávnění CONNECT v databázi. Ředitel, kterému je odepřeno oprávnění CONTROL v databázi, se nebude moci k této databázi připojit.

Uvědomuji si, že příklad je pro databázi, ale vezměte si ji ještě jednu granulární úroveň. A DENY CONTROL na stole zakáže oprávnění vše, myslím. Proveďte REVOKE CONTROL se toho zbavit a zjistit, zda to váš problém vyřeší.

Pokud ano, budete muset umístit uživatele do databázové role nebo jim odepřít explicitní oprávnění proti tabulce.

10
Thomas Stringer
  1. Použijte Ken Fisher sp_DBPermissions uložená procedura pro zobrazení oprávnění.

    1. Ujisti se DENY CONTROL se nepoužije na tabulku, kromě běžné DENY SELECT, DENY INSERT, DENY UPDATE, DENY DELETE a DENY REFERENCES.
    2. Pokud příkaz SELECT obsahuje funkce s hodnotou tabulky, ujistěte se, že existuje EXECUTE AS OWNER ve funkci s hodnotou tabulky nebo GRANT EXECUTE na to (a ne DENY EXECUTE!). Pokud tomu tak je, přečtěte si chybovou zprávu pečlivě, protože pravděpodobně nepovede, že bylo v tabulce odepřeno oprávnění SELECT, ale místo toho něco o odepření EXECUTE.
  2. Pokud je uživatel uživatelem AD nebo skupinou, pomocí následujícího skriptu určete uživatele login_token (s):

EXECUTE AS LOGIN = 'EXAMPLEDOMAIN\JOHN.DOE';
SELECT * FROM sys.login_token;
REVERT;
  1. Podívejte se na skutečný plán provádění. Pokud je chyba uvnitř uložené procedury s SET NOCOUNT ON;, pak vám skutečný prováděcí plán poskytne informace, kterým možná nemusíte věnovat pozornost, když se podíváte na kartu Zprávy v SSMS, protože „ovlivněné řádky“ mohou být mimo vaši kontrolu.

    1. Hledejte spouštěče nebo časové tabulky.
  2. Můžete zkompilovat příkaz jako uloženou proceduru a SSMS "View Object Dependencies", stejně jako triky naznačené Svetlanou Golovko v Různé způsoby, jak najít SQL Server Object Dependencies

  3. Pomocí události SQL Server Profiler Security "Audit Schema Object Access Event" a sloupců "TextData" a "Success" můžete sledovat, na kterých objektech SQL Server vyhodnocuje oprávnění. - Viděl jsem situace, kdy jsou pro tuto událost emitovány dva řádky a jedna hodnota říká Success = 1 a druhá říká Success = 0. V tomto scénáři je jediným řešením, které jsem našel, fungovat restartování serveru. Dokonce běží repadmin /syncall problém nevyřešil, nespustil ani nespustil aplikaci (a tedy fond připojení).

  4. Určete účinná oprávnění pro přihlášení:

-- '<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. Pokud je uživatel vázán na uživatele nebo skupinu AD, zvažte spuštění repadmin /syncall vynutit všechny změny provedené ve službě Active Directory k synchronizaci mezi řadiči domény. - Pokud někdo ví o dobrém způsobu porovnání současných hodnot dvou řadičů domény, dejte mi prosím vědět.

  2. Před zvážením tvrdého restartování celého systému zkuste zabít všechna aktivní připojení pro daného uživatele. Důvodem je, že uživatel získá svůj token systému Windows z DC, který zahrnuje jejich skupiny). Token nebude aktualizován, dokud uživatel neobdrží nový token - obvykle odhlášením a opětovným přihlášením .

  3. Tvrdý restart systému. Fungovalo to pro mě. Stále si není stoprocentně jistý proč. POUZE DO TÉTO, POKUD MŮŽETE PŘEJÍMAT DOBU! Buďte opatrní, když to uděláte, zatímco máte velké mimo transakce!

0
John Zabroski