Bu makalede, SQL Server’da veritabanı genelindeki tüm mevcut ve gelecekte oluşturulacak olan Stored Procedure ile Fonksiyonları çalıştırma (EXECUTE) yetkisini vermenin iki farklı senaryosunu ele alacağız. İster geleceğe yatırım yaparak bir Rol (Role) oluşturun, isterseniz de sadece Tek Bir Kullanıcıya (User) özel bu yetkiyi tanımlayın; her iki yöntemin de tüm detaylarını ve T-SQL kodlarını aşağıda bulabilirsiniz.
Buradaki sihirli kelimemiz SCHEMA::dbo ifadesidir. SQL Server’da objeler şemalar altında toplanır (varsayılan olarak dbo). Biz şema düzeyinde EXECUTE yetkisi verdiğimizde, o şema altında şu an var olan ve ileride oluşturulacak tüm procedure ve fonksiyonlar otomatik olarak bu yetki kapsamına girer.
Aşağıdaki komutlarda özellikle PROCEDURE veya FUNCTION yazmamasının nedeni, SQL Server’ın mimarisindeki “Nesne Ailesi” (Object Family) mantığıdır. SQL Server’da EXECUTE (veya kısaca EXEC) komutuyla çalıştırılabilen nesnelerin tamamı çalıştırılabilir (executable) nesne grubundadır.
SQL Server dünyasında çalıştırılabilir nesneler ise şunlardır:
1. Stored Procedure
2. Scalar-Valued Functions (Tek değer dönen fonksiyonlar)
3. Table-Valued Functions (Tablo dönen fonksiyonlar)
4. CLR Assembly Prosedür ve Fonksiyonları
Yani EXECUTE yetkisini şema düzeyinde verdiğinizde, SQL Server arka planda hem fonksiyonları hem de prosedürleri tek bir çatı altında kabul eder ve ikisine birden bu yetkiyi tanımlar. Ayrı ayrı GRANT EXECUTE ON PROCEDURE::… veya GRANT EXECUTE ON FUNCTION::… diye bir şema genellemesi söz dizimi (syntax) olarak SQL Server’da mevcut değildir.
Rol (Role) Oluşturarak Yetkilendirme:
Eğer veritabanınızda birden fazla kullanıcı varsa veya ileride aynı yetkilere sahip yeni kullanıcıların (yazılımcılar, raporlama hesapları vb.) geleceğini öngörüyorsanız, en sürdürülebilir yöntem bir Veritabanı Rolü (Database Role) oluşturmaktır. Yetkiyi role tanımlar, kullanıcıları bu role üye yaparsınız.
Veritabanı içinde özel bir rol oluşturuyoruz.
CREATE ROLE db_executor;
Oluşturduğumuz role dbo şemasındaki her şeyi EXECUTE etme yetkisi veriyoruz. Bu yetki hem Stored Procedure’leri hem de Scalar/Table-valued fonksiyonları kapsar.
GRANT EXECUTE ON SCHEMA::dbo TO db_executor;
Kullanıcımızı bu role üye yapıyoruz.
ALTER ROLE db_executor ADD MEMBER klnTEST;
Yarın bir gün aynı yetkiye ihtiyaç duyan ikinci bir kullanıcı geldiğinde tek yapmanız gereken ALTER ROLE db_executor ADD MEMBER YeniKullanici; komutunu çalıştırmaktır. Tek tek yetki tanımlamakla uğraşmazsınız.
Doğrudan Tek Bir Kullanıcıya (User) Yetki Verme:
Eğer veritabanınızda sadece tek bir özel entegrasyon kullanıcısı (örneğin bir API veya Mikroservis kullanıcısı) varsa, araya bir rol katmanı sokmadan doğrudan o kullanıcı hesabına şema düzeyinde yetki verebilirsiniz.
Bu yöntem uygulandığında da kullanıcı hem mevcut hem de gelecekte yazılacak olan tüm procedure ve fonksiyonları çalıştırabilir.
GRANT EXECUTE ON SCHEMA::dbo TO klnTEST;
Avantajı: Ekstra bir rol nesnesi oluşturmadan, tek satırlık bir komutla hızlıca çözüme ulaşırsınız.
Dezavantajı: İleride aynı yetkiye sahip başka bir kullanıcı daha gerekirse, onun için de aynı komutu sıfırdan çalıştırmanız gerekir ve zamanla hangi kullanıcının hangi yetkiye sahip olduğunu takip etmek zorlaşabilir.
Fonksiyonlar (Functions) İçin İnce Bir Ayrım
Yukarıda her iki senaryoda da kullandığımız GRANT EXECUTE ON SCHEMA::dbo komutu, T-SQL dünyasındaki iki temel fonksiyon türünü de kapsar:
1. Scalar-Valued Functions (Tek değer dönenler): Bu fonksiyonlar EXECUTE yetkisiyle doğrudan çalıştırılabilir.
2. Table-Valued Functions (Tablo dönenler): Eğer bir fonksiyon geriye bir tablo dönüyorsa, kullanıcı bunu genellikle bir SELECT sorgusunun içinde çağırır: SELECT * FROM dbo.fn_VeriGetir().
Eğer kullanıcı bu fonksiyonu SELECT ile çağıracaksa, sadece EXECUTE yetkisi yeterli olmayabilir; kullanıcının o fonksiyon üzerinde SELECT yetkisinin de olması gerekir. Eğer tüm tablo değerli fonksiyonları da açmak istiyorsanız:
GRANT SELECT ON SCHEMA::dbo TO db_executor;
GRANT SELECT ON SCHEMA::dbo TO klnTEST;
Şema düzeyinde SELECT yetkisi vermek, kullanıcının dbo şemasındaki tüm tablolara da sorgu atabilmesi anlamına gelir. Eğer amacınız kullanıcının tablolara doğrudan erişmesini tamamen engellemekse, GRANT SELECT komutunu kullanmamalısınız. Bu sebepten function bazlı select yetkisinin verilmesi gerekmektedir.
Zamanı geldiğinde verdiğiniz bu geniş yetkileri iptal etmek isterseniz, senaryonuza göre aşağıdaki komutları kullanabilirsiniz
--Kullanıcıyı rolden çıkarır.
ALTER ROLE db_executor DROP MEMBER klnTEST;
--Rolün şema üzerindeki yetkisini tamamen kaldırmak isterseniz:
REVOKE EXECUTE ON SCHEMA::dbo FROM db_executor;
--Kullanıcının şema üzerindeki EXECUTE yetkisini doğrudan iptal eder
REVOKE EXECUTE ON SCHEMA::dbo FROM klnTEST;
SQL Server’da “En Az Yetki İlkesi” (Principle of Least Privilege) esastır. Kullanıcılara doğrudan db_owner gibi veritabanını ele geçirebilecekleri yetkiler vermek yerine, ihtiyaca göre ister Senaryo 1‘deki gibi bir rol havuzu oluşturarak, ister Senaryo 2‘deki gibi doğrudan kullanıcı bazlı GRANT EXECUTE ON SCHEMA::dbo komutunu kullanarak sisteminizi hem güvenli hem de dinamik tutabilirsiniz.
Başka makalede görüşmek dileğiyle..
“Öyle ise emrolunduğun gibi dosdoğru ol.” Hud-112