Modül İmzalama'yı kullanarak bunu çok güvenli bir şekilde gerçekleştirmek kolaydır. Bu, DBA.StackExchange'te, sadece bunu yapma örnekleri veren aşağıdaki iki cevabımla benzer olacaktır:
Farklı yürütme, veritabanları arası sorgular ve modül imzalama ile saklı yordam güvenliği
Çapraz veritabanı sertifikaları kullanılırken tetikleyicilerdeki izinler
Bu özel sorunun farkı, bir Görünümle ilgilenmesi ve Görünümlerin imzalanamamasıdır. Bu nedenle, İmzalanabildiği ve tıpkı bir Görünüm ( SELECT
erişim için iyi) gibi erişilebileceği için Görünümü çok ifadeli Tablo Değerli İşlev (TVF) olarak değiştirmeniz gerekir .
Aşağıdaki örnek kod, Oturum Açma / Kullanıcı "RestrictedUser" öğesinin yalnızca "DatabaseA" işlevine erişebildiğini ve "DatabaseB" den veri alabildiğini tam olarak sorulmakta olduğunu gösterir. Bu yalnızca bu TVF'den seçim yaparak ve yalnızca imzalandığı için çalışır.
Hala View kullanıyor ve süre çapraz veritabanı erişimi bu tür gerçekleştirerek değil sağlayan geçici veritabanı sahipliği zincirleme gerektirecektir, kullanıcı herhangi bir ek izin vererek. Bu çok daha az güvenlidir, çünkü her iki Veri Tabanı arasındaki tüm nesneler için tamamen açık uçludur (belirli nesneler ve / veya Kullanıcılar ile sınırlandırılamaz). Modül İmzalama sadece bir TVF'nin çapraz DB erişimine sahip olmasına izin verir (Kullanıcı iznine sahip değildir, TVF sahiptir) ve TVF'den yapamayan Kullanıcıların SELECT
"DatabaseB" ye hiç erişimi yoktur.
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;
Yukarıdaki adımların tümü mevcut durumu yeniden oluşturur: Kullanıcının DatabaseA'ya erişimi vardır, DatabaseA'daki bir nesneyle etkileşimde bulunma izni vardır, ancak DatabaseA'daki bu nesnenin Kullanıcının herhangi bir erişimi olmayan DatabaseB'de bir şeye erişmesi nedeniyle bir hata alır.
Aşağıdaki adımlar Modül Şarkı Söylemesini ayarlar. Aşağıdakileri yapar:
- DatabaseA'da Sertifika oluşturur
- TVF'yi Sertifika ile İmzalar
- Sertifikayı (Özel Anahtar olmadan) Veritabanı B'ye kopyalar
- DatabaseB içinde Sertifikadan bir Kullanıcı oluşturur
SELECT
DatabaseB'deki Tabloya Sertifika Tabanlı Kullanıcıya İzin Verir
Modül İmzalama kurulumu:
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;
ERİŞİM GÖRÜNÜM İLE GEREKİRSE, hangi nedenle olursa olsun, yukarıda gösterilen TVF'den seçilen bir Görünüm oluşturabilirsiniz. Ve bu durumda, SELECT
erişim yok değil aşağıda gösterildiği gibi, sadece Görünüm TVF, verilecek gerekir:
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];
Ve şimdi test etmek için:
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;
Modül İmzalama hakkında daha fazla bilgi için lütfen şu adresi ziyaret edin: https://ModuleSigning.Info/