Diğer veritabanında hesabı olmayan başka bir veritabanındaki tabloya dayalı erişim görünümü


11

Database2'deki tablolara dayanarak database1'de görünüm oluşturdum. SELECTYalnızca database1'e erişimi olan bir kullanıcıya izin verdim . Kullanıcı, veritabanı2'de bir hesabı olmadığından bu görünümün çalışmasını sağlayamaz. Bu sorunu nasıl çözebilirim? Database2'de bir hesap oluşturmak istemiyorum.


1
@mustaccio Hayır, bu durum aynı veritabanında olduğu için bu diğer soru / cevabın kopyası değil ve bu soru veritabanlarını yaymakla ilgili. Varsayılan olarak buna izin verilmez. Biri, veritabanları arası sahiplik zincirini etkinleştirmek zorunda kalacaktı ve bu, bu kadar dar bir ihtiyaç için açılacak büyük bir güvenlik deliğidir.
Solomon Rutzky

1
@SolomonRutzky, DB_CHAINING'e "büyük güvenlik açığı" demezdim. Yalnızca sysadmin rol üyelerinin nesne oluşturabildiği tipik üretim ortamlarında bu bir sorun değildir. Bununla birlikte, sysadmin olmayan rol üyelerinin sahip oldukları şemalar üzerinde şemalar üzerinde kontrol izinlerine sahip olduğu durumlarda dikkatle kullanılmalıdır.
Dan Guzman

@DanGuzman "Güven bana, her şey her zaman plana göre gidecek" etkili bir strateji değildir. Bu mantıkla, TRUSTWORTHY ONuygulamanın şu şekilde ayarlanmasına veya oturum açılmasına ilişkin neredeyse hiçbir risk yoktur sa. DB Mülkiyet Zinciri ve TRUSTWORTHYo zaman tek çözüm olması nedeniyle var. Ancak şimdi, büyük bir risk olmasa bile, DB Zinciri kesinlikle gereksiz bir risktir çünkü Modül İmzalama o kadar da zor değildir. Biri DB zincirine güveniyor ve ardından Dinamik SQL kullanıyorsa, TRUSTWORTHY ONbunu düzeltmek için daha olasıdır , ancak Modül İmzalama ile kırılmazdı.
Solomon Rutzky

@SolomonRutzky, soru görünüm yerine bir modül hakkında olsaydı modül imzalama öneririm. Benim düşüncem, DB_CHAININGnesnelerin yine de aynı veritabanında olması gerektiğinde veritabanı içi sahiplik zincirinden daha riskli olmadığıdır.
Dan Guzman

@DanGuzman Neden "nesnelerin yine de aynı veritabanında olması gerekir?" OP, DB erişimini ayrı tutmak istedikleri için bunun tersini gösterdi. OP'nin bir Görünüm kullandığından, Saklı Yordam yerine bir TVF önerdim, ancak bu bir Görünümü kullanmaya devam etmek en iyi eylem yolu değil. Burada olduğu gibi, yapması mantıklı olduğunda yapıyı ve / veya yaklaşımı değiştirmeyi önermek yaygındır. Yine de cevabıma isteğe bağlı bir sarıcı Görünümü ekledim. Ve "dbo" nun her şeye sahip olması en yaygın olduğu göz önüne alındığında, evet, DB_CHAININGoldukça risklidir.
Solomon Rutzky

Yanıtlar:


9

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 ( SELECTeriş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:

  1. DatabaseA'da Sertifika oluşturur
  2. TVF'yi Sertifika ile İmzalar
  3. Sertifikayı (Özel Anahtar olmadan) Veritabanı B'ye kopyalar
  4. DatabaseB içinde Sertifikadan bir Kullanıcı oluşturur
  5. SELECTDatabaseB'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, SELECTeriş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/


Sertifikalar düzenli yedeklemelerin bir parçası olarak yedekleniyor mu? Yoksa başka bir yerde mi saklanıyor ve bir dosya sistemi yedeklemesi mi gerekiyor? Farklı şifreler vb. Kullanabilen daha düşük bir ortama geri yüklerseniz ne olur?
Chris Aldrich

@ChrisAldrich Burada gösterilen kullanımda, tamamen Veritabanı içinde tutulduğu için DB ile yedeklenir. Eğer kullanırsanız ALTER CERTIFICATE ... DROP PRIVATE KEYo zaman ilk kullanarak bir dosyaya yedeklemek olmasaydı özel anahtar gitmiş olurdu YEDEK BELGESİ . Ancak, ortak anahtar hala içeride sys.certificates. Ve ortak anahtarın parolaya ihtiyacı yoktur. Bir modülü imzalamak için yalnızca özel anahtarı kullanmak için parola gerekir (ana anahtarla korunduğunuzdan farklı olarak, sunucular arasında aynıdır).
Solomon Rutzky
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.