Це легко зробити дуже безпечним способом за допомогою підпису модуля. Це буде схоже на два мої відповіді, також тут, на 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, де користувач не має доступу.
Наведені нижче кроки налаштовують Модульний спів. Він робить наступне:
- створює сертифікат у DatabaseA
- Підписує TVF Сертифікатом
- Копіює сертифікат (без приватного ключа) на базу даних B
- Створює користувача в DatabaseB із Сертифіката
- Надає
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/