Отримання "В дозволі SELECT було відмовлено в об'єкті", навіть якщо він був наданий


11

Я програміст, а не дба ... Я знаю просто так, щоб бути небезпечним.

Я успадкував базу даних із застарілим користувачем, який є власником db_owner для бази даних. Ми не можемо коригувати дозвіл цього користувача для існуючих таблиць, схем тощо з бізнес-причин, але створюються нові таблиці, і я хочу лише, щоб цей користувач мав доступ до них SELECT.

Для цього користувача встановлено дозволи для цього користувача, щоб усе було DENIED, крім SELECT, для якого встановлено GRANT.

Однак коли цей користувач (dbadmin) намагається виконати SELECT в одній із цих таблиць (AccountingAudit), ця помилка трапляється:

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

Я запустив цей SQL, щоб перевірити, які дозволи встановлені для цієї таблиці / користувача:

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

І ось що я повертаю:

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

Здається, це має працювати так?

Виклик SELECT, який я здійснюю, є дуже базовим SELECT * FROM AccountingAudit, зсередини SSMS. Я не роблю спеціального sp_executesql або чогось подібного.

Я спробував явно надати дозвіл:

GRANT SELECT ON [dbo].AccountingAudit TO dbadmin

Це не впливає (чому б це зробити, вищезазначений запит уже показує, що це надано! ;-)

Я шукав stackoverflow.com та інші місця, і не можу знайти нічого, чого я ще не пробував. Мені цікаво, чи має це щось спільне з налаштуванням схем. (На даний момент я дуже мало знаю про схеми.)

Будь-які ідеї? Дякую!

Відповіді:


10

Я не впевнений тут, але я збираюся вийти на кінцівку. Я думаю, що у вашому питанні може бути ваш DENY CONTROLзапис. Дивіться тут приблизно на півдорозі сторінки:

Заборона дозволу CONTROL на базі даних неявно заперечує дозвіл CONNECT на базі даних. Принцип, якому відмовлено в дозволі CONTROL в базі даних, не зможе підключитися до цієї бази даних.

Я розумію, що приклад - це база даних, але візьміть її ще на один гранульований рівень. DENY CONTROLНа столі буде заперечувати все привілеї на ньому, я припускаю , що . Зробіть це, REVOKE CONTROLщоб позбутися цього і побачити, чи це вирішує вашу проблему.

Якщо це так, вам доведеться розмістити користувача в ролі бази даних або заборонити їм явні привілеї щодо таблиці.


1
Дякую! Спочатку в експерименті я виявив, що якщо CONTROL не буде відмовлено, то вони можуть ВИБІРАТИ. Але читаючи BOL, я неправильно трактував це, що означав, що я даю користувачеві повний контроль над таблицею. Тепер я бачу, що поки я не відмовляю їм у керуванні, я все одно можу зберігати інші дозволи (INSERT, DELETE тощо) на рівні DENY та досягти потрібного рівня дозволів. Дякую!
Мейсон Жвіті

Це тонкість, на яку я закликав, незважаючи на те, що не вирішив свою проблему, на яку я відчуваю, що більшість не помітить уваги. Окремо я виявив, що, використовуючи групи Active Directory, якщо ви змінили членство в групі, repadmin / syncall не обов'язково виправляє проблеми, і я виявив, що перезавантаження сервера вирішило проблему. Все ж шукаю менше підходу кувалди.
Іван Заброський

0
  1. Використовуйте sp_DBPermissionsзбережену процедуру Кена Фішера, щоб переглянути дозволи.

    1. Переконайтеся , що DENY CONTROLне застосовується до таблиці, на додаток до загального DENY SELECT, DENY INSERT, DENY UPDATE, DENY DELETEі DENY REFERENCES.
    2. Якщо SELECTвислів містить функції, визначені EXECUTE AS OWNERза таблицею , переконайтеся, що є або функція на табличну цінність, або a GRANT EXECUTEна ній (і ні DENY EXECUTE!). У такому випадку уважніше прочитайте повідомлення про помилку, оскільки воно, ймовірно, не скаже, що дозвіл SELECT було відхилено на столі, а натомість щось про EXECUTE буде відхилено.
  2. Якщо користувач є користувачем або групою AD, використовуйте наступний сценарій, щоб визначити користувача login_token(ів):

EXECUTE AS LOGIN = 'EXAMPLEDOMAIN\JOHN.DOE';
SELECT * FROM sys.login_token;
REVERT;
  1. Подивіться на фактичний план виконання. Якщо помилка знаходиться в межах збереженої процедури SET NOCOUNT ON;, то фактичний план виконання дасть вам зрозуміти, на що ви, можливо, не звернете уваги, просто подивившись на вкладку Повідомлення в SSMS, оскільки "Зачеплені рядки" можуть бути поза вашим контролем.

    1. Шукайте тригери або тимчасові таблиці.
  2. Ви можете скласти вислів як збережену процедуру та SSMS "Перегляд залежностей об'єкта", а також хитрощі, описані Світланою Головко в " Різні способи" для пошуку об'єктних залежностей SQL Server

  3. Використовуйте подію безпеки SQL Server Profiler "Подія доступу до об’єктів схеми аудиту" та стовпці "TextData" та "Успіх" для відстеження, на які об'єкти SQL Server оцінює дозволи на. - Я бачив ситуації, коли для цієї події випускаються два рядки, і одне значення говорить "Успіх = 1", а інше - "Успіх" = "0". У цьому сценарії єдине рішення, яке я знайшов для роботи, - це перезавантажити сервер. Навіть запуск repadmin /syncallне усунув проблему, не запустив і зупинив додаток (а отже, пул підключень).

  4. Визначте ефективні дозволи для входу:

-- '<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. Якщо користувач прив’язаний до користувача або групи AD, подумайте про запуск, repadmin /syncallщоб змусити будь-які зміни, внесені в активний каталог, синхронізуватися між контролерами вашого домену. - Якщо хтось знає хороший спосіб порівняти поточні значення двох контролерів домену, будь ласка, дайте мені знати.

  2. Перш ніж розглянути можливість жорсткого перезавантаження всієї системи, спробуйте вбити всі активні з'єднання для цього користувача. Причина полягає в тому, що користувач отримує маркер Windows від постійного струму, який включає їх групи. Маркер не оновлюється доти, доки користувач не отримає новий маркер - зазвичай виходить із системи та знову ввійшов у систему.

  3. Важка перезавантаження системи. Це спрацювало на мене. Все ще не на 100% впевнений, чому ще. ТІЛЬКИ РОБИТИ ЦЕ ЯКЩО ВИ МОЖЕТЕ ВІДГОТОВИТИ ЧАС! Будьте уважні щодо того, як робите це, коли у вас є великі зовнішні трансакції!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.