Fabric 数据仓库中的行级别安全性

适用于:SQL 分析终结点和 Microsoft Fabric 中的仓库

借助行级别安全性 (RLS),可以使用组成员资格或执行上下文来控制对数据库表中行的访问权限。 例如,可以确保工作人员仅访问与其部门相关的数据行。 再例如,将客户的数据访问权限限制为,仅访问在多租户体系结构中与其公司相关的数据。 此功能类似于SQL Server中的行级别安全性。

数据级别的行级别安全性

行级别安全性简化了应用程序中的安全性设计和编程。 行级别安全性可帮助实现对数据行访问的限制。

访问限制逻辑位于数据库层中,而不是任何单个应用程序层中。 每次尝试从任何应用程序或报告平台(包括 Power BI)访问数据时,数据库都会应用访问限制。 这样就会通过减少安全系统的外围应用,使安全系统变得更加可靠和稳健。 行级别安全性仅适用于 Fabric 中仓库或 SQL 分析终结点上的查询。 Direct Lake 模式下仓库的 Power BI 查询将回退到 Direct Query 模式,以遵守行级别安全性。

将特定行的访问权限限制为特定用户

使用 CREATE SECURITY POLICY Transact-SQL 语句,以及作为内联表值函数创建的谓词来实现 RLS。

行级别安全性应用于共享仓库或湖屋,因为基础数据源未更改。

基于谓词的行级别安全性

Fabric Synapse 数据仓库中的行级别安全性支持基于谓词的安全性。 筛选谓词以静默方式筛选可用于读取操作的行。

对表中的行级数据的访问将受到定义为内联表值函数的安全谓词的限制。 随后调用该函数,并由安全策略进行实施。 对于筛选谓词,应用程序不知道从结果集中筛选掉的行。 如果所有行都被筛选掉,返回的是空集。

筛选谓词在读取基表中数据时应用。 它们会影响所有 Get 操作:SELECTDELETEUPDATE。 用户无法选择或删除筛选掉的行。 用户无法更新筛选掉的行。 但可以更新以后将要筛选掉的行。

筛选器谓词和安全策略具有以下行为:

  • 可以定义与另一个表联接和/或调用函数的谓词函数。 如果使用 SCHEMABINDING = ON(默认设置)创建安全策略,则该联接或函数可以从查询进行访问并按预期方式工作而无需进行任何其他权限检查。

  • 可以针对已定义但禁用安全谓词的表发出查询。 筛选掉或阻止的任何行都不会受影响。

  • 如果 dbo 用户、db_owner角色的成员或表所有者查询已定义并启用安全策略的表,行按照安全策略所定义被筛选掉或阻止。

  • 尝试更改架构绑定安全策略绑定的表的架构会导致错误。 但是,可以更改谓词未引用的列。

  • 如果表已针对指定操作定义了谓词,尝试向表添加谓词会导致错误出现。 无论是否已启用谓词,都会这样。

  • 如果函数在架构绑定安全策略中用作表中的谓词,尝试修改函数会导致错误出现。

  • 定义包含非重叠谓词的多个活动安全策略会成功。

筛选器谓词具有以下行为:

  • 定义筛选表中的行的安全策略。 应用程序不知道任何针对SELECTUPDATEDELETE操作被筛选掉的行。 包括所有行都被筛选掉的情况。应用程序可以对行执行INSERT操作,即使这些行将在其他任何操作过程中被筛选掉,也不例外。

权限

创建、更改或删除安全策略需要ALTER ANY SECURITY POLICY权限。 创建或删除安全策略需要对架构具有ALTER权限。

另外,每个添加的谓词都需要以下权限:

  • 对用作谓词的函数具有SELECTREFERENCES权限。

  • 对绑定到策略的目标表具有REFERENCES权限。

  • 对目标表中用作参数的每个列具有REFERENCES权限。

安全策略应用于所有用户(包括数据库中的 dbo 用户)。 Dbo 用户可以更改或删除安全策略,但是可以审核他们对安全策略进行的更改。 如果管理员、成员或参与者等角色的成员需要查看所有行以排除故障或验证数据,必须为此编写安全策略。

如果使用SCHEMABINDING = OFF创建安全策略,则若要查询目标表,用户必须具有针对谓词函数及在其中使用的任何其他表、视图或函数的SELECTEXECUTE权限。 如果使用 SCHEMABINDING = ON 创建安全策略(默认值),则当用户查询目标表时,会绕过这些权限检查。

安全注意事项:旁路攻击

请考虑并准备以下两种方案。

恶意安全策略管理员

观察到以下这点十分重要:具有足够权限来基于敏感列创建安全策略并且有权创建或更改内联表值函数的恶意安全策略管理员可以与另一个对表具有选择权限的用户串通,通过恶意创建旨在使用旁路攻击推断数据的内联表值函数来泄漏数据。 此类攻击需要进行串通(或向恶意用户授予过多权限),并且可能需要多次反复修改策略(需要删除谓词以便中断架构绑定的权限)、修改内联表值函数并重复对目标表运行选择语句。 建议根据需要限制权限,并监视是否有任何可疑活动。 应监视不断更改与行级别安全性相关的策略和内联表值函数等活动。

精心设计的查询

使用精心设计的查询(利用错误泄露数据)可能会导致信息泄露。 例如,SELECT 1/(SALARY-100000) FROM PAYROLL WHERE NAME='John Doe';会让恶意用户知道 John Doe 的薪金正好是 10 万美元。 即使采用安全谓词来防止恶意用户直接查询其他人的薪金,用户仍然可以确定查询何时返回被零除异常。

示例

我们可以在 Microsoft Fabric 中演示行级别安全仓库和 SQL 分析终结点。

以下示例创建将用于 Fabric 中的仓库的示例表,但在 SQL 分析终结点中,使用现有表。 在 SQL 分析终结点中,不能CREATE TABLE,但可以CREATE SCHEMACREATE FUNCTIONCREATE SECURITY POLICY

在此示例中,先创建架构sales、表sales.Orders

CREATE SCHEMA sales;
GO

-- Create a table to store sales data
CREATE TABLE sales.Orders (
    SaleID INT,
    SalesRep VARCHAR(100),
    ProductName VARCHAR(50),
    SaleAmount DECIMAL(10, 2),
    SaleDate DATE
);

-- Insert sample data
INSERT INTO sales.Orders (SaleID, SalesRep, ProductName, SaleAmount, SaleDate)
VALUES
    (1, 'Sales1@contoso.com', 'Smartphone', 500.00, '2023-08-01'),
    (2, 'Sales2@contoso.com', 'Laptop', 1000.00, '2023-08-02'),
    (3, 'Sales1@contoso.com', 'Headphones', 120.00, '2023-08-03'),
    (4, 'Sales2@contoso.com', 'Tablet', 800.00, '2023-08-04'),
    (5, 'Sales1@contoso.com', 'Smartwatch', 300.00, '2023-08-05'),
    (6, 'Sales2@contoso.com', 'Gaming Console', 400.00, '2023-08-06'),
    (7, 'Sales1@contoso.com', 'TV', 700.00, '2023-08-07'),
    (8, 'Sales2@contoso.com', 'Wireless Earbuds', 150.00, '2023-08-08'),
    (9, 'Sales1@contoso.com', 'Fitness Tracker', 80.00, '2023-08-09'),
    (10, 'Sales2@contoso.com', 'Camera', 600.00, '2023-08-10');

创建Security架构、函数Security.tvf_securitypredicate和安全策略SalesFilter

-- Creating schema for Security
CREATE SCHEMA Security;
GO
 
-- Creating a function for the SalesRep evaluation
CREATE FUNCTION Security.tvf_securitypredicate(@SalesRep AS nvarchar(50))
    RETURNS TABLE
WITH SCHEMABINDING
AS
    RETURN SELECT 1 AS tvf_securitypredicate_result
WHERE @SalesRep = USER_NAME() OR USER_NAME() = 'manager@contoso.com';
GO
 
-- Using the function to create a Security Policy
CREATE SECURITY POLICY SalesFilter
ADD FILTER PREDICATE Security.tvf_securitypredicate(SalesRep)
ON sales.Orders
WITH (STATE = ON);
GO

后续步骤