Перегляд доступу на основі таблиці в іншій базі даних без облікового запису в цій іншій базі даних


11

Я створив представлення у database1 на основі таблиць у database2. Я дав SELECTдозвіл користувачеві, який має доступ лише до бази даних1. Користувач не може змусити цей погляд працювати, оскільки у нього немає облікового запису в базі даних2. Як я можу вирішити це питання? Я не хочу створювати обліковий запис у базі даних2.


1
@mustaccio Ні, це не дублікат іншого питання / відповіді, оскільки ця ситуація була всередині однієї бази даних, і це питання стосується баз даних. За замовчуванням це заборонено. Для такої вузької потреби необхідно відкрити ланцюжок власності міжбаздовим базами даних, і це величезна діра у захисті.
Соломон Руцький

1
@SolomonRutzky, я б не назвав DB_CHAINING "величезною діркою безпеки". У типових виробничих середовищах, де лише учасники ролей системи можуть створювати об'єкти, це не проблема. З огляду на це, його слід обережно застосовувати у випадках, коли члени ролі, які не належать до системи sysadmin, мають дозволи на керування іншими схемами, ніж ті, якими вони володіють.
Дан Гузман

@DanGuzman "Повірте, все буде завжди за планом", не є ефективною стратегією. За цією логікою майже немає ризику встановлювати TRUSTWORTHY ONабо мати вхід у програму як sa. Ланцюжки власності на БД і TRUSTWORTHYіснують в основному завдяки тому, що вони були єдиним рішенням на той час. Але тепер, навіть якщо це не великий ризик, ланцюжок БД, безумовно, є зайвим ризиком, оскільки підписання модуля не так вже й складно. І якщо хтось покладається на ланцюжок БД, а потім використовує Dynamic SQL, вони швидше налаштовують TRUSTWORTHY ONйого виправити, тоді як при підписанні модуля він би не зламався.
Соломон Руцький

@SolomonRutzky, я б запропонував підписати модуль, якби питання стосувалося модуля замість перегляду. Я думаю, що DB_CHAININGце не є більш ризикованим, ніж внутрішнє базування власності на базу даних, коли об'єкти в будь-якому випадку повинні були знаходитися в одній базі даних.
Дан Гузман

@DanGuzman Чому припускати, що "об’єкти все-таки повинні були знаходитися в одній базі даних"? ОП вказала лише навпаки, оскільки вони хочуть розділити доступ до БД. Те, що ОП використовує View, тому я запропонував TVF замість збереженої процедури, але це не означає, що продовження використання View - це найкращий спосіб дії. Як правило, пропонують змінити структуру та / або підхід, коли це має сенс робити, як це відбувається у нас. Тим не менш, я додав додаткову обгортку Перегляд у свою відповідь. І, враховуючи, що найчастіше "dbo" володіти всім, так, DB_CHAININGце досить ризиковано.
Соломон Руцький

Відповіді:


9

Це легко зробити дуже безпечним способом за допомогою підпису модуля. Це буде схоже на два мої відповіді, також тут, на DBA.StackExchange, які дають приклади робити саме це:

Захищена безпека процедури з виконанням як, перехресні запити бази даних та підписання модуля

Дозволи в тригерах при використанні сертифікатів крос-бази даних

Відмінність цього конкретного питання полягає в тому, що він стосується представлення даних, а перегляди не підписуються. Отже, Вам потрібно буде змінити Погляд на функцію багатозначних таблиць з оцінкою (TVF), оскільки вони можуть бути підписані та доступні для них так само, як і Вигляд (ну для SELECTдоступу).

Наступний приклад коду показує виконання саме того, про що йдеться у запитанні, оскільки "Вхід / користувач" RestrictedUser "має доступ лише до" DatabaseA "і ще не може отримати дані з" DatabaseB ". Це працює лише шляхом вибору з цього телевізора і лише завдяки його підписанню.

Досягнення цього типу міждоступних баз даних під час використання представлення даних та не надавання Користувачу додаткових дозволів вимагатиме включення ланцюжка власності на міжбаза даних. Це набагато менш безпечно, оскільки він є повністю відкритим для всіх об'єктів між обома базами даних (він не може бути обмежений певними об'єктами та / або користувачами). Підписання модуля дозволяє лише цьому одному TVF мати міждоступний доступ до БД (користувач не має дозволу, це робить TVF), а користувачі, які не можуть SELECTз TVF взагалі не мають доступу до "DatabaseB".

USE [master];

CREATE LOGIN [RestrictedUser] WITH PASSWORD = 'No way? Yes way!';
GO

---

USE [DatabaseA];

CREATE USER [RestrictedUser] FOR LOGIN [RestrictedUser];

GO
CREATE FUNCTION dbo.DataFromOtherDB()
RETURNS @Results TABLE ([SomeValue] INT)
AS
BEGIN
    INSERT INTO @Results ([SomeValue])
        SELECT [SomeValue]
        FROM   DatabaseB.dbo.LotsOfValues;

    RETURN;
END;
GO

GRANT SELECT ON dbo.[DataFromOtherDB] TO [RestrictedUser];
GO
---

USE [DatabaseB];

CREATE TABLE dbo.[LotsOfValues]
(
    [LotsOfValuesID] INT IDENTITY(1, 1) NOT NULL
        CONSTRAINT [PK_LotsOfValues] PRIMARY KEY,
    [SomeValue] INT
);

INSERT INTO dbo.[LotsOfValues] VALUES
    (1), (10), (100), (1000);
GO

---

USE [DatabaseA];

SELECT * FROM dbo.[DataFromOtherDB]();


EXECUTE AS LOGIN = 'RestrictedUser';

SELECT * FROM dbo.[DataFromOtherDB]();
/*
Msg 916, Level 14, State 1, Line XXXXX
The server principal "RestrictedUser" is not able to access
the database "DatabaseB" under the current security context.
*/

REVERT;

Усі описані вище кроки відтворюють поточну ситуацію: Користувач має доступ до DatabaseA, має дозвіл на взаємодію з об’єктом у DatabaseA, але отримує помилку через те, що цей об’єкт у DatabaseA отримує доступ до чогось у DatabaseB, де користувач не має доступу.

Наведені нижче кроки налаштовують Модульний спів. Він робить наступне:

  1. створює сертифікат у DatabaseA
  2. Підписує TVF Сертифікатом
  3. Копіює сертифікат (без приватного ключа) на базу даних B
  4. Створює користувача в DatabaseB із Сертифіката
  5. Надає SELECTдозвіл на таблицю в DatabaseB користувачеві, що базується на сертифікаті

Налаштування підпису модуля:

CREATE CERTIFICATE [AccessOtherDB]
    ENCRYPTION BY PASSWORD = 'SomePassword'
    WITH SUBJECT = 'Used for accessing other DB',
    EXPIRY_DATE = '2099-12-31';

ADD SIGNATURE
    TO dbo.[DataFromOtherDB]
    BY CERTIFICATE [AccessOtherDB]
    WITH PASSWORD = 'SomePassword';

---
DECLARE @CertificatePublicKey NVARCHAR(MAX) =
            CONVERT(NVARCHAR(MAX), CERTENCODED(CERT_ID(N'AccessOtherDB')), 1);

SELECT @CertificatePublicKey AS [Cert / PublicKey]; -- debug

EXEC (N'USE [DatabaseB];
CREATE CERTIFICATE [AccessOtherDB] FROM BINARY = ' + @CertificatePublicKey + N';');
---


EXEC (N'
USE [DatabaseB];
CREATE USER [AccessOtherDbUser] FROM CERTIFICATE [AccessOtherDB];

GRANT SELECT ON dbo.[LotsOfValues] TO [AccessOtherDbUser];
');

---



EXECUTE AS LOGIN = 'RestrictedUser';

SELECT * FROM dbo.[DataFromOtherDB]();
-- Success!!

SELECT * FROM [DatabaseB].[dbo].[LotsOfValues];
/*
Msg 916, Level 14, State 1, Line XXXXX
The server principal "RestrictedUser" is not able to access
the database "DatabaseB" under the current security context.
*/

REVERT;

ЯКЩО ДОКУМЕНТ НЕОБХІДНИЙ ДЛЯ ОГЛЯДУ З ОГЛЯДУ з будь-якої причини, ви можете просто створити Вигляд, який вибирається з показаного вище TVF. І в цій ситуації SELECTдоступ не повинен надаватись TVF, а лише Перегляду, як показано нижче:

GO
CREATE VIEW dbo.[DataFromTVF]
AS
SELECT [SomeValue]
FROM   dbo.DataFromOtherDB();
GO

-- Remove direct access to the TVF as it is no longer needed:
REVOKE SELECT ON dbo.[DataFromOtherDB] FROM [RestrictedUser];

GRANT SELECT ON dbo.[DataFromTVF] TO [RestrictedUser];

А тепер для тестування:

EXECUTE AS LOGIN = 'RestrictedUser';


SELECT * FROM dbo.[DataFromOtherDB]();
/*
Msg 229, Level 14, State 5, Line XXXXX
The SELECT permission was denied on the object 'DataFromOtherDB',
database 'DatabaseA', schema 'dbo'.
*/


SELECT * FROM [OwnershipChaining].[dbo].[LotsOfValues];
/*
Msg 916, Level 14, State 1, Line XXXXX
The server principal "RestrictedUser" is not able to access
the database "DatabaseB" under the current security context.
*/


SELECT * FROM dbo.[DataFromTVF];
-- Success!!


REVERT;

Для отримання додаткової інформації про підписання модуля, відвідайте: https://ModuleSigning.Info/


Чи є резервні копії резервних копій як частина регулярних резервних копій? Або вони зберігаються в іншому місці і вимагають також резервної копії файлової системи? А що станеться, якщо ви відновитесь до нижчого середовища, яке може використовувати різні паролі тощо?
Кріс Олдріч

@ChrisAldrich У використанні, показаному тут, воно резервне копіювання з БД, оскільки він повністю зберігається в базі даних. Якщо ви використовуєте, ALTER CERTIFICATE ... DROP PRIVATE KEYтоді приватний ключ не буде втрачено, якщо ви спершу не створили його назад у файл за допомогою BACKUP CERTIFICATE . Але відкритий ключ все ще є sys.certificates. І відкритий ключ не потребує пароля. Тільки для використання приватного ключа для підписання модуля потрібен пароль (який однаковий на серверах, на відміну від захисту за допомогою головного ключа).
Соломон Руцький
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.