Satır Düzeyi güvenliği uygulama
Satır düzeyi güvenlik (RLS) şifreleme kullanmaz ve grup üyeliği veya yetkilendirme bağlamını temel alan bir güvenlik ilkesi kullanarak tabloya erişimi kısıtlamak için veritabanı düzeyinde çalışır. Bu işlev olarak bir WHERE yan tümceye eşdeğerdir.
Güvenlik ilkesi, tablodaki satırlara erişimi korumak için satır içi tablo değerli bir işlev çağırır.
Bir kullanıcının özniteliğine bağlı olarak koşul, kullanıcının ilgili bilgilere erişimi olup olmadığını belirler. Bir tabloda sorgu çalıştırdığınızda, güvenlik ilkesi koşul işlevini uygular. İş gereksinimlerine bağlı olarak, RLS gerektiği kadar WHERE CustomerId = 29 basit veya karmaşık olabilir.
Satır düzeyi güvenlik tarafından desteklenen iki tür güvenlik ilkesi vardır:
Filtre önkoşulları - koşulu ihlal eden veri erişimini kısıtlayın.
Access Tanım SELECT Filtrelenen satırlar görüntülenemez. UPDATE Filtrelenen satırlar güncelleştirilemez. DELETE Filtrelenen satırlar silinemez. INSERT Uygulanamaz. Önkoşulları engelle - koşulu ihlal eden veri değişikliklerini kısıtlayın.
Access Tanım EKLENDIKTEN SONRA Kullanıcıların koşulu ihlal eden değerlerle satır eklemesini engeller. GÜNCELLEŞTIRMEDEN SONRA Kullanıcıların koşulu ihlal eden değerlere satırları güncelleştirmesini engeller. GÜNCELLEŞTIRMEDEN ÖNCE Kullanıcıların şu anda koşulu ihlal eden satırları güncelleştirmesini engeller. SİlMEDEN ÖNCE Satır koşulu ihlal ederse silme işlemlerini engeller.
Erişim denetimi veritabanı düzeyinde yapılandırıldığından ve uygulandığından, varsa uygulama değişiklikleri çok azdır. Ayrıca kullanıcılar tablolara doğrudan erişebilir ve kendi verilerini sorgulayabilir.
Satır düzeyi güvenlik üç ana adımda uygulanır:
- Erişimi yalıtmak istediğiniz kullanıcıları veya grupları oluşturun.
- Sonuçları tanımlanan koşula göre filtreleyen satır içi tablo değerli işlevi oluşturun.
- Daha önce oluşturulan işlevi atayarak tablo için bir güvenlik ilkesi oluşturun.
Aşağıdaki T-SQL komutları, kullanıcı erişiminin kiracı tarafından ayrıştırıldığı bir senaryoda RLS'nin nasıl kullanılacağını gösterir:
-- Create supporting objects for this example
CREATE TABLE [Sales] (SalesID INT,
ProductID INT,
TenantName NVARCHAR(10),
OrderQtd INT,
UnitPrice MONEY)
GO
INSERT INTO [Sales] VALUES (1, 3, 'Tenant1', 5, 10.00);
INSERT INTO [Sales] VALUES (2, 4, 'Tenant1', 2, 57.00);
INSERT INTO [Sales] VALUES (3, 7, 'Tenant1', 4, 23.00);
INSERT INTO [Sales] VALUES (4, 2, 'Tenant2', 2, 91.00);
INSERT INTO [Sales] VALUES (5, 9, 'Tenant3', 5, 80.00);
INSERT INTO [Sales] VALUES (6, 1, 'Tenant3', 5, 35.00);
INSERT INTO [Sales] VALUES (7, 3, 'Tenant4', 8, 11.00);
-- View all the rows in the table
SELECT * FROM Sales;
Ardından, kullanıcıları oluşturun ve Satış tablosuna erişim verin. Bu örnekte, her kullanıcı belirli bir kiracıdan sorumludur. TenantAdmin kullanıcısının tüm kiracılardan gelen verileri görme erişimi vardır.
CREATE USER [TenantAdmin] WITH PASSWORD = '<strong password>'
GO
CREATE USER [Tenant1] WITH PASSWORD = '<strong password>'
GO
CREATE USER [Tenant2] WITH PASSWORD = '<strong password>'
GO
CREATE USER [Tenant3] WITH PASSWORD = '<strong password>'
GO
CREATE USER [Tenant4] WITH PASSWORD = '<strong password>'
GO
GRANT SELECT ON [Sales] TO [TenantAdmin]
GO
GRANT SELECT ON [Sales] TO [Tenant1]
GO
GRANT SELECT ON [Sales] TO [Tenant2]
GO
GRANT SELECT ON [Sales] TO [Tenant3]
GO
GRANT SELECT ON [Sales] TO [Tenant4]
GO
Ardından yeni bir şema, satır içi tablo değerli bir işlev oluşturacak ve kullanıcıya yeni işleve erişim izni yeceğiz. Koşul, WHERE @TenantName = USER_NAME() OR USER_NAME() = 'TenantAdmin' sorguyu yürüten kullanıcı adının TenantName sütun değerleriyle eşleşip eşleşmediğini değerlendirir.
CREATE SCHEMA sec;
GO
--Create the filter predicate
CREATE FUNCTION sec.tvf_SecurityPredicatebyTenant(@TenantName AS NVARCHAR(10))
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN SELECT 1 AS result
WHERE @TenantName = USER_NAME() OR USER_NAME() = 'TenantAdmin';
GO
--Grant users access to inline table-valued function
GRANT SELECT ON sec.tvf_SecurityPredicatebyTenant TO [TenantAdmin]
GO
GRANT SELECT ON sec.tvf_SecurityPredicatebyTenant TO [Tenant1]
GO
GRANT SELECT ON sec.tvf_SecurityPredicatebyTenant TO [Tenant2]
GO
GRANT SELECT ON sec.tvf_SecurityPredicatebyTenant TO [Tenant3]
GO
GRANT SELECT ON sec.tvf_SecurityPredicatebyTenant TO [Tenant4]
GO
--Create security policy and add the filter predicate
CREATE SECURITY POLICY sec.SalesPolicy
ADD FILTER PREDICATE sec.tvf_SecurityPredicatebyTenant(TenantName) ON [dbo].[Sales]
WITH (STATE = ON);
GO
Bu noktada, erişimi test etmeye hazırız:
EXECUTE AS USER = 'TenantAdmin';
SELECT * FROM dbo.Sales;
REVERT;
EXECUTE AS USER = 'Tenant1';
SELECT * FROM dbo.Sales;
REVERT;
EXECUTE AS USER = 'Tenant2';
SELECT * FROM dbo.Sales;
REVERT;
EXECUTE AS USER = 'Tenant3';
SELECT * FROM dbo.Sales;
REVERT;
EXECUTE AS USER = 'Tenant4';
SELECT * FROM dbo.Sales;
REVERT;
TenantAdmin kullanıcısı tüm satırları görmelidir. Tenant1, Tenant2, Tenant3 ve Tenant4 kullanıcıları yalnızca kendi satırlarını görmelidir.
ile güvenlik ilkesini WITH (STATE = OFF);değiştirirseniz, kullanıcıların tüm satırları gördüğünü fark edeceksiniz.
Not
Bir saldırgan özel olarak hazırlanmış WHERE bir yan tümceyle bir sorgu yazarsa ve örneğin, koşul doğruysa WHERE bir özel durumu zorlamak için sıfıra bölme hatasıyla bilgi sızıntısı riski vardır. Bu, yan kanal saldırısı olarak bilinir. Satır düzeyi güvenlik kullanırken kullanıcıların planlanmamış sorgular çalıştırma becerisini sınırlamak akıllıca olacaktır.
Kullanım örneği
Satır düzeyi güvenlik, aşağıdakiler de dahil olmak üzere birçok senaryo için idealdir:
- Bölüm erişimini satır düzeyinde yalıtmanız gerektiğinde.
- Müşterilerin veri erişimini yalnızca şirketleriyle ilgili verilerde kısıtlamanız gerektiğinde.
- Uyumluluk amacıyla erişimi kısıtlamanız gerektiğinde.
En iyi yöntemler
RLS'yi uygularken göz önünde bulundurmanız gereken en iyi birkaç yöntem şunlardır:
- Koşul işlevleri ve güvenlik ilkeleri için ayrı bir şema oluşturun.
- Koşul işlevlerinde tür dönüştürmelerinden kaçının.
- Koşul işlevlerinde aşırı tablo birleşimleri ve özyineleme kullanmaktan kaçının.