Jest to łatwe do osiągnięcia w bardzo bezpieczny sposób przy użyciu podpisywania modułów. Będzie to podobne do poniższych dwóch moich odpowiedzi, również tutaj na DBA.StackExchange, które podają przykłady wykonania tego:
Zabezpieczenia procedur przechowywanych z wykonywaniem jako, zapytania do wielu baz danych i podpisywanie modułów
Uprawnienia w wyzwalaczach podczas korzystania z certyfikatów między bazami danych
Różnica w tym konkretnym pytaniu polega na tym, że dotyczy ono Widoku i Widoku nie można podpisać. Musisz więc zmienić widok na wielowątkową funkcję tabelową (TVF), ponieważ można je podpisać i uzyskać do nich dostęp podobnie jak widok (cóż, SELECT
dostęp).
Poniższy przykładowy kod pokazuje robienie dokładnie tego, co jest wymagane w pytaniu, ponieważ Login / Użytkownik „RestrictedUser” ma dostęp tylko do „DatabaseA” i jest w stanie uzyskać dane z „DatabaseB”. Działa to tylko poprzez wybranie z tego jednego TVF i tylko z powodu jego podpisania.
Realizacji tego typu dostępu cross-bazy danych, jednocześnie korzystając z widoku, a nie dając użytkownikowi żadnych dodatkowych uprawnień, wymagałoby umożliwiając Cross-bazy danych własności łańcuchowym. Jest to o wiele mniej bezpieczne, ponieważ jest całkowicie otwarte dla wszystkich obiektów między obiema bazami danych (nie można go ograniczyć do niektórych obiektów i / lub użytkowników). Podpisywanie modułów pozwala tylko temu jednemu TVF na SELECT
dostęp między bazami danych (użytkownik nie ma pozwolenia, TVF ma), a użytkownicy, którzy nie mogą z TVF, nie mają w ogóle dostępu do „Bazy danychB”.
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;
Wszystkie powyższe kroki odtwarzają bieżącą sytuację: użytkownik ma dostęp do bazy danych A, ma uprawnienia do interakcji z obiektem w bazie danych A, ale dostaje błąd z powodu tego, że obiekt w bazie danych uzyskuje dostęp do czegoś w bazie danych b, do którego użytkownik nie ma dostępu.
Poniższe kroki konfigurują śpiewanie modułów. Wykonuje następujące czynności:
- tworzy certyfikat w bazie danych A.
- Podpisuje TVF certyfikatem
- Kopiuje certyfikat (bez klucza prywatnego) do bazy danych B
- Tworzy użytkownika w bazie danychB na podstawie certyfikatu
- Nadaje
SELECT
uprawnienia do tabeli w bazie danych B użytkownikowi opartemu na certyfikatach
Konfiguracja podpisywania modułów:
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;
JEŚLI DOSTĘP POTRZEBUJE PRZEZ WIDOK, z jakiegokolwiek powodu, możesz po prostu utworzyć Widok, który wybierze z TVF pokazanego powyżej. W tej sytuacji SELECT
dostęp nie musi być przyznany TVF, a jedynie widokowi, jak pokazano poniżej:
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];
A teraz, aby to przetestować:
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;
Aby uzyskać więcej informacji na temat podpisywania modułów, odwiedź: https://ModuleSigning.Info/