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!
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.
Použijte Ken Fisher sp_DBPermissions
uložená procedura pro zobrazení oprávnění.
DENY CONTROL
se nepoužije na tabulku, kromě běžné DENY SELECT
, DENY INSERT
, DENY UPDATE
, DENY DELETE
a DENY REFERENCES
.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.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;
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.
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
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í).
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;
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.
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 .
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!