Ricezione di "L'autorizzazione SELECT è stata negata sull'oggetto" anche se è stata concessa


11

Sono un programmatore, non un dba ... so quanto basta per essere pericoloso.

Ho ereditato un database con un utente legacy che è un db_owner per il database. Non possiamo regolare l'autorizzazione di questo utente per tabelle, schemi, ecc. Esistenti, per motivi di lavoro, ma alcune nuove tabelle vengono create e voglio solo che questo utente abbia accesso a SELECT su di esse.

Le autorizzazioni sono state impostate per questo utente per queste tabelle in modo che tutto sia DENIED, tranne SELECT, che è impostato su GRANT.

Tuttavia, quando questo utente (dbadmin) tenta di eseguire un SELECT su una di queste tabelle (AccountingAudit), si verifica questo errore:

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

Ho eseguito questo SQL per provare e vedere quali autorizzazioni sono impostate per questa tabella / utente:

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

E questo è quello che torno:

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

Sembra che dovrebbe funzionare bene?

La chiamata SELECT che sto effettuando è un SELECT * FROM AccountingAudit molto semplice, all'interno di SSMS. Non sto facendo alcun sp_executesql speciale o qualcosa del genere.

Ho provato a concedere esplicitamente l'autorizzazione:

GRANT SELECT ON [dbo].AccountingAudit TO dbadmin

Questo non ha alcun effetto (perché dovrebbe, la query sopra mostra già che è stata concessa! ;-)

Ho cercato attraverso stackoverflow.com e altrove e non riesco a trovare nulla che non abbia ancora provato. Mi chiedo se abbia qualcosa a che fare con il modo in cui gli schemi sono impostati. (A questo punto so ben poco sugli schemi.)

Qualche idea? Grazie!

Risposte:


10

Non sono sicuro qui, ma sto per uscire su un arto. Penso che il tuo problema potrebbe riguardare il tuo DENY CONTROLrecord. Vedi qui a metà della pagina:

Negare l'autorizzazione CONTROL su un database nega implicitamente l'autorizzazione CONNECT sul database. Un'entità a cui viene negata l'autorizzazione CONTROL su un database non sarà in grado di connettersi a quel database.

Mi rendo conto che l'esempio è per un database, ma prendo un livello più granuale. A DENY CONTROLsu un tavolo negherà tutti i privilegi su di esso, immagino. Fai uno REVOKE CONTROLper sbarazzartene e vedi se questo risolve il tuo problema.

In tal caso, dovrai posizionare l'utente in un ruolo di database o negare loro i privilegi espliciti rispetto alla tabella.


1
Grazie! Inizialmente, durante i miei esperimenti, ho scoperto che se CONTROL non fosse stato negato, avrebbero potuto SELEZIONARE. Ma leggendo BOL l'avevo interpretato erroneamente nel senso che stavo dando all'utente il pieno controllo sul tavolo. Ora vedo che fino a quando non li negherò CONTROL, posso ancora mantenere le altre autorizzazioni (INSERT, DELETE, ecc.) A livello DENY e raggiungere i livelli di autorizzazione che desidero. Grazie!
Mason G. Zhwiti,

Questa è una sottigliezza che ho votato, nonostante non abbia risolto il mio problema, che penso che la maggior parte potrebbe trascurare. Separatamente, ho scoperto che usando i gruppi di Active Directory, se hai cambiato l'appartenenza al gruppo, repadmin / syncall non risolve necessariamente i problemi e ho riscontrato che il riavvio del server ha risolto il problema. Tuttavia, sto ancora cercando un approccio meno efficace.
John Zabroski,

0
  1. Utilizzare la sp_DBPermissionsprocedura memorizzata di Ken Fisher per esaminare le autorizzazioni.

    1. Assicurarsi che DENY CONTROLnon si applica al tavolo, oltre al comune DENY SELECT, DENY INSERT, DENY UPDATE, DENY DELETEe DENY REFERENCES.
    2. Se l' SELECTistruzione contiene funzioni con valori di tabella, assicurati che sia presente una EXECUTE AS OWNERfunzione con valori di tabella o una GRANT EXECUTE(e no DENY EXECUTE!). In questo caso, leggi il messaggio di errore più attentamente poiché probabilmente non dirà che l'autorizzazione SELECT è stata negata sulla tabella, ma invece è stato negato qualcosa riguardo a EXECUTE.
  2. Se l'utente è un utente o gruppo AD, utilizzare il seguente script per determinare l'utente login_token(i):

EXECUTE AS LOGIN = 'EXAMPLEDOMAIN\JOHN.DOE';
SELECT * FROM sys.login_token;
REVERT;
  1. Guarda il piano di esecuzione attuale. Se l'errore si trova all'interno di una procedura memorizzata con SET NOCOUNT ON;, il piano di esecuzione effettivo ti fornirà informazioni sulle quali potresti non prestare attenzione semplicemente guardando la scheda Messaggi in SSMS, poiché "Righe interessate" potrebbe essere al di fuori del tuo controllo.

    1. Cerca trigger o tabelle temporali.
  2. È possibile compilare l'istruzione come procedura memorizzata e "Visualizza dipendenze oggetti" di SSMS, nonché i trucchi descritti da Svetlana Golovko in diversi modi per trovare le dipendenze degli oggetti di SQL Server

  3. Utilizzare l'evento di sicurezza di SQL Server Profiler "Evento di accesso agli oggetti dello schema di controllo" e le colonne "TextData" e "Operazione riuscita" per tenere traccia degli oggetti su cui SQL Server sta valutando le autorizzazioni. - Ho visto situazioni in cui sono state emesse due righe per questo evento e un valore indica Success = 1 e l'altro indica Success = 0. In questo scenario, l'unica soluzione che ho trovato funzionare è riavviare il server. Anche l'esecuzione repadmin /syncallnon ha risolto il problema, né l'avvio e l'arresto dell'applicazione (e quindi del pool di connessioni).

  4. Determinare le autorizzazioni effettive per l'accesso:

-- '<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. Se l'utente è legato a un utente o gruppo AD, prendere in considerazione l'esecuzione repadmin /syncallper forzare la sincronizzazione di tutte le modifiche apportate in active directory tra i controller di dominio. - Se qualcuno conosce un buon modo per confrontare i valori correnti di due controller di dominio, per favore fatemi sapere.

  2. Prima di prendere in considerazione un riavvio forzato dell'intero sistema, prova a eliminare tutte le connessioni attive per quell'utente. Il motivo è che l'utente ottiene il token di Windows dal controller di dominio che include i propri gruppi. Il token non verrà aggiornato fino a quando l'utente non riceverà un nuovo token, in genere disconnettendosi e quindi riconnettendosi.

  3. Hard reboot the system. Ha funzionato per me. Ancora non sicuro al 100% perché ancora. FARE SOLO QUESTO SE PUOI SOPRAVVIVERE I TEMPI! ATTENZIONE A FARE QUESTO MENTRE AVETE GRANDI OPERAZIONI ECCEZIONALI!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.