Normal şartlarda, bir SQL Server kullanıcısının başka bir veritabanındaki tabloya erişmesi için o veritabanında açıkça yetkilendirilmesi gerekir. Ancak Veritabanları Arası Sahiplik Zinciri (Cross-Database Ownership Chaining), bu süreci kolaylaştıran bir güvenlik istisnasıdır.
Bu özellik sayesinde, eğer iki farklı veritabanındaki nesneler (örneğin bir View ve o View’ın beslendiği Tablo) aynı sahibi (Owner) paylaşıyorsa, kullanıcıya ikinci veritabanında ayrıca bir izin verilmesine gerek kalmadan erişim sağlanabilir.
Nasıl Çalışır?
- Sahiplik Bağlantısı: SQL Server, bir nesne üzerinden başka bir nesneye erişildiğinde aradaki “sahibi kim?” kontrolünü yapar. Eğer iki nesnenin sahibi de aynıysa, sistem izin kontrolünü atlar.
- Sınırları Aşmak: Normal sahiplik zinciri sadece tek bir veritabanı içinde çalışırken; bu özellik aktif edildiğinde, bu “güven zinciri” veritabanı sınırlarını aşarak tüm SQL Server örneğine (instance) yayılır.
- Kullanım Amacı: Birden fazla veritabanına yayılmış karmaşık sistemlerde, her kullanıcıya her veritabanı için tek tek ayrıntılı izinler tanımlama zahmetini ortadan kaldırır.
Aynı veritabanındaki Tablo A ve Tablo B’nin sahibi aynıysa, birine yetkisi olan diğerine de erişebilir. Veritabanı 1’deki Tablo ile Veritabanı 2’deki Prosedürün sahibi aynıysa, kullanıcıya Veritabanı 2’de yetki vermesem de işlem yapmasına izin verir.
Veritabanları arası zincirlemeyi sunucu ve veritabanı düzeyinde açmak mümkündür.
ALTER DATABASE [MY_DATABASE_NAME] SET DB_CHAINING ON
Elimizde birden fazla veritabanı varsa onlardada bu özelliği aktif edebiliriz.
Sunucu düzeyinde açarsanız, tek tek veritabanı ayarlarından bağımsız olarak bu sunucudaki tüm veritabanları için veritabanları arası zincirleme etkinleştirilir.
Veritabanları arası zincirlemeyi sunucu ve veritabanı düzeyinde açmak mümkündür. Veritabanları arası sahiplik zinciri, sunucu düzeyinde kapalı olarak önceden ayarlanmıştır ve ayrıca master, msdb ve tempdb veritabanları dışındaki tüm veritabanlarında kapalı olarak ayarlanır. Bu sistem veritabanlarının düzgün çalışması için veritabanları arası sahiplik zincirinin açık olması gerekir.
Güvenlik nedenleriyle, veritabanları arası sahiplik zinciri genellikle sunucu düzeyinde açılmamalıdır. Aynı şekilde, zincirleme yalnızca genel bir kural olarak bunu gerektiren belirli veritabanları için açılmalıdır.
Bir View, yalnızca kendi veritabanındaki tablolara erişiyorsa, kullanıcıya yalnızca View üzerinde SELECT yetkisi verilmesi yeterlidir. Kullanıcı, ilgili tablolara doğrudan yetki almadan View üzerinden sorgu çalıştırabilir. Kendi veritabanı üzerinde oluşturduğu veya kendi veritabanı üzerinde bulunan tablolardaki şema yapısına takılmaz select çekilebilmektedir. Aşağıdaki resim B veritabanında bulunan tablo

B veritabanı altında oluşturulan viewler dikkat ederseniz dbo.ProductView – ProductSchema.ProductsView yukarıdaki resimde dikkat ederseniz schema ismi viewlerle aynı veya farklı.

Farklı bir kullanıcı oluşturup viewlerin bulunduğu Veritabanına public yetkisi verildikten sonra ilgili viewlere sağ tıklayıp properties ekranında permission bölümünde kullanıcı seçilip viewlere select yetkisi verilir. Sonuç olarak kullanıcıya tablo üzerinde yetki vermeden sadece viewe yetki vererek sonuçlarımızı görebiliriz. Bu işlem oluşturulan viewin içerisinde farklı bir veritabanına ait olmayan tablolarda geçerli bir işlemdir.


Sonuç olarak yukarıdaki açıklamalardan anladığımız aynı veritabanı tabanı üzerinde schema yapısı fark etmeksizin bir view oluşturup kullanıcıya yetki verildikten sonra select çektiğinde herhangi bir sıkıntı ile karşılaşmamış olur. Tabloya yetki verilmez son kullanıcı view içerisinde tabloları görmemiş olur.
Ancak View’in içinde başka bir veritabanındaki tablolar kullanılıyorsa, kullanıcının bu tablolara doğrudan erişim yetkisi olması gerekir. Aksi takdirde “The SELECT permission was denied on the object” veya “Could not find server” gibi bir yetki hatası alınır. Bunun sebebi, SQL Server’ın farklı veritabanları arasındaki güvenlik politikasıdır. Aşağıdaki hatayı alabilmemiz için öncelikle Select çeken kullanıcının view’in bağlantı sağladığı veritabanında public yetkisinin olması gerekmektedir. Yoksa aşağıdaki hata mesajı alınmaktadır.
The server principal “B1” is not able to access the database “A” under the current security context.
İlgili veritabanına public yetkisi verilince hata mesajı aşağıdaki şekilde gelmektedir.
Msg 229, Level 14, State 5, Line 2
The SELECT permission was denied on the object ‘Table_1’, database ‘A’, schema ‘dbo’.
Kullanıcı farklı veritabanındaki view veya tablodan verileri alabilmesi için A veritabanına public yetkisi daha sonra yetki verilen veritabanından hangi tablo veya viewden yetki veri alınacaksa ilgili ifadelere yetki verilir. Buda şu soruna sebep olur. Kullanıcı view haricinde view’in verileri almış olduğu veritabanı altında tablo veya viewıda görebilir. Buda tüm tabloya veya view’e erişmesi demektir. Resimde dikkat ederseniz viewın verileri almış olduğu veritabanı altında tabloda görülmektedir.

Not: Oluşturulan view’e son kullanıcının sorun yaşamaması için view ve tablo schema isimleri farklı olabilir sadece schema ownerlarının aynı olması gerekmektedir. İlgili veritabanının security sekmesi altında Schema owner aynı kullanıcı olması gerekmektedir.

Yukarıdaki sorundan dolayı db_chaining yapısı kullanılmaktadır. Yada kullanıcı view üzerinden direkt olarak tabloya değil de tablodan çekilecek kolanlar üzerinden bir view oluşturup bu view’e yeki verilebilir.
NOT: DROP, DELETE, INSERT, UPDATE gibi komutlar view tanımının içinde kullanılamaz. Eğer tabloyu silmek istiyorsan bu işlemi doğrudan yapman gerekir, view üzerinden dolaylı yoldan bu mümkün değil.
Server Seviyesinde de bu özellik aktif hale getirilebilir. Ama yukarıda bahsettiğim güvenlik sebebiyle bu özelliği aktif hale getirmemenizde fayda var. Yine de bazı durumlarda ihtiyaç olabileceğini düşünerek aşağıda script’ini paylaşıyorum.
USE master;
GO
EXECUTE sp_configure 'show advanced', 1;
RECONFIGURE;
EXECUTE sp_configure 'cross db ownership chaining', 1;
RECONFIGURE;
SELECT is_db_chaining_on, name FROM sys.databases;

Bu komut ile ownership Chains komutunun aktif edilip edilmediğini görebiliriz.
A ve B veritabanımda DB_CHAINING özelliğini aktif ediyorum.
ALTER DATABASE A SET DB_CHAINING ON
ALTER DATABASE B SET DB_CHAINING ON

Daha sonra B veritabanı altında A veritabanındaki tabloya bağlı olan view’e select çekiyorum.

Başarılı bir şekilde sonucumuz geldi. Resimde dikkat ederseniz A veritabanı altında tablo görülmemektedir. Veritabanları üzerinde kullanıcıya tablo veya view üzerinden yetki vermeden DB_CHAINING özelliğini aktif ederek tablodan verilerimizin son kullanıcının başka veritabanıdaki tabloları görmiyecek şekilde çekmiş oluyoruz.
Dikkat edersek A veritabanındaki tabloya select çekmemize rağmen tabloyu göremedik.

Tekrardan bu özelliği kapatmak isterseniz aşağıdaki komutlar kullanılmaktadır.
ALTER DATABASE A SET DB_CHAINING OFF
ALTER DATABASE B SET DB_CHAINING OFF
Tekrar bu özelliği kapattıktan sonra ilgili view’e select çektiğimizde hata mesajını almış oluyoruz.

Başka bir makalede görüşmek dileğiyle..
“Kıyamet saati hakkındaki bilgi yalnız Allah’ın katındadır; O, yağmuru yağdırmakta; rahimlerdekini bilmektedir. Hiç kimse yarın ne elde edeceğini bilemez; hiç kimse nerede öleceğini bilemez; ama Allah her şeyi bilir, her şeyden haberdardır.”Lokman-34
