共用方式為

手动应用行筛选器和列掩码

本页提供了有关使用行筛选器、列掩码和映射表以筛选表中敏感数据的指导和示例。 这些功能需要 Unity 目录。

在您开始之前

若要向表添加行筛选器和列掩码,必须具有:

  • 为 Unity Catalog 启用的工作区。
  • 在 Unity Catalog 中注册的 SQL UDF。 若要使用 Python 或 Scala 逻辑,请先创建 Python 或 Scala UDF,然后创建调用它的 SQL UDF。 SQL UDF 是作为行筛选器或列掩码应用的内容。 有关示例,请参阅 Python UDF 的列掩码。 有关 UDF 的最佳做法和限制,请参阅 行筛选器和列掩码

此外,还必须满足以下要求:

  • 若要分配向表添加行过滤器或列掩码的函数,必须对该函数具有 EXECUTE 权限、对架构具有 USE SCHEMA 权限、对父目录具有 USE CATALOG 权限。
  • 如果要在创建表时添加筛选器或掩码,还必须具有该架构的 CREATE TABLE 权限。
  • 如果要向 现有 表添加筛选器或掩码,则必须是表所有者或 MANAGE 具有该表的特权。

若要访问具有行筛选器或列掩码的表,计算资源必须满足下列要求之一:

  • SQL 仓库。
  • Databricks Runtime 12.2 LTS 或更高版本上的标准访问模式(以前共享访问模式)。
  • Databricks Runtime 15.4 LTS 或更高版本上的专用访问模式(以前是单用户访问模式)。

不能在 Databricks Runtime 15.3 或更低版本上使用专用计算读取行筛选器或列掩码。

若要利用 Databricks Runtime 15.4 LTS 及更高版本中提供的数据筛选,还必须验证工作区是否启用了无服务器计算,因为支持行筛选器和列掩码的数据筛选功能在无服务器计算上运行。 当你使用配置为专用访问模式的计算资源来读取使用行过滤器或列过滤的表时,可能会被收取无服务器计算资源的费用。 对这些表的写入作仅在 DBR 16.3 及更高版本上受支持,并且必须使用支持的模式,例如 MERGE INTO

注释

替换表时保留行筛选器和列掩码。

如果运行 REPLACE TABLE,则会保留任何现有行筛选器,而不考虑架构更改。 如果新表包含与原始表中具有掩码的列名称相同的列,则也会保留列掩码。 在这两种情况下,即使策略未显式重新定义,也会保留这些策略。 这可以防止意外丢失数据访问策略。

但是,如果保留的策略引用已删除或更改的列,则后续查询可能会失败。 若要解决此问题,请使用 ALTER TABLE..

应用行筛选器

若要创建行筛选器,请编写一个函数 (UDF),以定义筛选器策略,然后将其应用于表。 每个表只能有一个行筛选器。 行筛选器接受零个或多个输入参数,其中每个输入参数绑定到相应表的一列。

可以使用目录资源管理器或 SQL 命令应用行筛选器。 目录资源管理器说明假定你已经创建了一个函数,并在 Unity 目录中注册了它。 SQL 说明包括创建行筛选器函数并将其应用于表的示例。

注释

如果使用 Lakeflow 声明性管道,可以使用 Lakeflow 声明性管道 Python API 创建使用行筛选器和列掩码的流式处理表或具体化视图。 请参阅发布具有行筛选器和列掩码的表

目录资源管理器

  1. 在 Azure Databricks 工作区中,单击 “数据”图标。目录

  2. 浏览或搜索要筛选的表。

  3. 在“ 概述 ”选项卡上的 “行筛选器”下,单击“ 添加筛选器”。

  4. 在“添加行筛选器”对话框中,选择包含筛选器函数的目录和架构,然后选择该函数

  5. 在展开的对话框中,查看函数定义并选择与函数语句中包含的列匹配的表列。

  6. 单击 添加

若要从表中移除筛选器,请单击“fx 行筛选器”,然后单击“删除”

SQL

若要创建行筛选器,然后将其添加到现有表,请使用 CREATE FUNCTION 并使用 ALTER TABLE应用函数。 还可以在使用 CREATE TABLE 创建表时应用函数。

  1. 创建行筛选器:

    CREATE FUNCTION <function_name> (<parameter_name> <parameter_type>, ...)
    RETURN {filter clause whose output must be a boolean};
    
  2. 使用列名将行筛选器应用于表:

    ALTER TABLE <table_name> SET ROW FILTER <function_name> ON (<column_name>, ...);
    

其他语法示例

  • 使用与函数参数匹配的常量文本将行筛选器应用于表:

    ALTER TABLE <table_name> SET ROW FILTER <function_name> ON (<constant_literal>, ...);
    
  • 从表中删除行筛选器:

    ALTER TABLE <table_name> DROP ROW FILTER;
    
  • 修改行筛选器:

    Run a DROP FUNCTION statement to drop the existing function, or use CREATE OR REPLACE FUNCTION to replace it.
    
  • 删除行筛选器:

    ALTER TABLE <table_name> DROP ROW FILTER;
    DROP FUNCTION <function_name>;
    

    注释

    在删除函数之前,必须执行 ALTER TABLE ... DROP ROW FILTER 命令。 如果你不这样做,表将处于无法访问的状态。

    如果因此无法访问表,可使用 ALTER TABLE <table_name> DROP ROW FILTER; 更改表并删除孤立的行筛选器引用。

另请参阅 ROW FILTER 条款

行筛选器示例

此示例创建一个适用于国家/地区 adminUS 组成员的 SQL 用户定义函数。

当为 sales 表应用此示例函数时,admin 组的成员可以访问表中的所有记录。 如果函数由非管理员调用,则 RETURN_IF 条件将失败,并计算 region='US' 表达式,从而筛选表以仅显示 US 区域中的记录。

CREATE FUNCTION us_filter(region STRING)
RETURN IF(IS_ACCOUNT_GROUP_MEMBER('admin'), true, region='US');

将函数作为行筛选器应用于表。 sales 表中的后续查询则会返回行子集。

CREATE TABLE sales (region STRING, id INT);
ALTER TABLE sales SET ROW FILTER us_filter ON (region);

禁用行筛选器。 sales 表中的未来用户查询则会返回表中的所有行。

ALTER TABLE sales DROP ROW FILTER;

创建一个表,将该表的函数作为 CREATE TABLE 语句的一部分应用为行筛选器。 sales 表中的每个未来查询则会返回行子集。

CREATE TABLE sales (region STRING, id INT)
WITH ROW FILTER us_filter ON (region);

应用列掩码

若要应用列掩码,请创建一个函数(UDF),并将其应用于表列。

可以使用目录资源管理器或 SQL 命令应用列掩码。 目录资源管理器说明假定你已经创建了一个函数,并在 Unity 目录中注册了它。 SQL 说明包括创建列掩码函数并将其应用于表列的示例。

注释

如果使用 Lakeflow 声明性管道,可以使用 Lakeflow 声明性管道 Python API 创建使用行筛选器和列掩码的流式处理表或具体化视图。 请参阅发布具有行筛选器和列掩码的表

目录资源管理器

  1. 在 Azure Databricks 工作区中,单击 “数据”图标。目录

  2. 浏览或搜索表。

  3. 在“概述”选项卡上,找到要应用列掩码的行,然后单击编辑图标掩码图标。

  4. 在“添加列掩码”对话框中,选择包含筛选器函数的目录和架构,然后选择该函数

  5. 在展开的对话框中,查看函数定义。 如果函数包含除要屏蔽的列之外的任何参数,请选择要用于转换这些附加函数参数的表列。

  6. 单击 添加

要从表中删除列掩码,请单击表行中的“fx 列掩码”,然后单击“移除”

SQL

若要创建列掩码并将其添加到现有表列,请使用 CREATE FUNCTION 并使用 ALTER TABLE 应用掩码函数。 还可以在使用 CREATE TABLE 创建表时应用函数。

使用 SET MASK 应用掩码函数。 在 MASK 子句中,可以使用任何 Azure Databricks 内置运行时函数或调用其他用户定义函数。 常见用例包括通过使用 current_user( ) 检查运行该函数的调用用户的身份或使用 is_account_group_member( ) 获取他们所属的组。 有关详细信息,请参阅 Column mask 子句内置函数

  1. 创建列掩码:

    CREATE FUNCTION <function_name> (<parameter_name> <parameter_type>, ...)
    RETURN {expression with the same type as the first parameter};
    
  2. 将列掩码应用于现有表中的列:

    ALTER TABLE <table_name> ALTER COLUMN <col_name> SET MASK <mask_func_name> USING COLUMNS <additional_columns>;
    

其他语法示例

  • 使用与函数参数匹配的常量文本将列掩码应用于现有表中的列:

    ALTER TABLE <table_name> ALTER COLUMN <col_name> SET MASK <mask_func_name> USING COLUMNS (<constant_name>, ...);
    
  • 从表中的列中删除列掩码:

    ALTER TABLE <table_name> ALTER COLUMN <column where mask is applied> DROP MASK;
    
  • 修改列掩码,DROP 现有函数或使用 CREATE OR REPLACE TABLE

  • 删除列掩码:

    ALTER TABLE <table_name> ALTER COLUMN <column where mask is applied> DROP MASK;
    DROP FUNCTION <function_name>;
    

    注释

    在删除函数前必须执行 ALTER TABLE 命令,否则表将处于不可访问状态。

    如果表因此变得无法访问,可使用 ALTER TABLE <table_name> ALTER COLUMN <column where mask is applied> DROP MASK; 更改表并删除孤立的掩码引用。

列过滤示例

在此示例中,你将创建一个用户定义的函数来屏蔽 ssn 列,以便只有属于 HumanResourceDept 组成员的用户才能查看该列中的值。

CREATE FUNCTION ssn_mask(ssn STRING)
  RETURN CASE WHEN is_account_group_member('HumanResourceDept') THEN ssn ELSE '***-**-****' END;

将新函数作为列过滤应用于表。 可以在创建表时或之后添加列掩码。

--Create the `users` table and apply the column mask in a single step:

CREATE TABLE users (
  name STRING,
  ssn STRING MASK ssn_mask);
--Create the `users` table and apply the column mask after:

CREATE TABLE users
  (name STRING, ssn STRING);

ALTER TABLE users ALTER COLUMN ssn SET MASK ssn_mask;

当查询用户不是 ssn 组的成员时,对该表的查询现在会返回屏蔽的 HumanResourceDept 列值:

SELECT * FROM users;
  James  ***-**-****

若要禁用列掩码,以便查询返回 ssn 列中的原始值,请执行以下操作:

ALTER TABLE users ALTER COLUMN ssn DROP MASK;

带有 Python UDF 的列掩码

若要在列掩码中使用 Python 或 Scala 逻辑,必须创建 Python 或 Scala UDF,然后将其包装在 SQL UDF 中。 SQL 包装器函数是作为列掩码应用的内容。

此示例创建 Python UDF 来屏蔽电子邮件地址,然后将其包装在 SQL UDF 中:

-- Step 1: Create the Python UDF with masking logic
CREATE OR REPLACE FUNCTION email_mask_python(email STRING)
RETURNS STRING
LANGUAGE PYTHON
AS $$
import re
return re.sub(r'^[^@]+', lambda m: '*' * len(m.group()), email)
$$;

-- Step 2: Create a SQL wrapper function that calls the Python UDF
CREATE OR REPLACE FUNCTION email_mask_sql(email STRING)
RETURN email_mask_python(email);

然后,将 SQL 包装器作为列掩码应用于表:

-- Create the `contacts` table and apply the SQL wrapper as the column mask
CREATE TABLE contacts (
  name STRING,
  email STRING MASK email_mask_sql);

重要

必须将 SQL 包装器函数 (email_mask_sql) 应用为列掩码,而不是直接应用 Python UDF。 如果尝试将 Python UDF (email_mask_python) 直接用作列掩码,将收到错误 [ROUTINE_NOT_FOUND]

使用映射表创建访问控制列表

若要实现行级别安全性,请考虑定义映射表(或访问控制列表)。 一个全面的映射表会对原始表中哪些数据行可供某些用户或组访问进行编码。 映射表非常有用,因为它们通过直接联接提供与事实数据表的简单集成。

此方法解决了许多包含自定义要求的用例。 示例包括:

  • 根据登录用户施加限制,同时顾及特定用户组的不同规则。
  • 创建复杂的层次结构(如组织结构),这些层次结构需要不同的规则集。
  • 从外部源系统复制复杂的安全模型。

通过采用映射表,可以成功处理这些具有挑战性的场景,并确保可靠的行级和列级安全实现。

映射表示例

使用映射表检查当前用户是否在列表中:

USE CATALOG main;

创建新的映射表:

DROP TABLE IF EXISTS valid_users;

CREATE TABLE valid_users(username string);
INSERT INTO valid_users
VALUES
  ('fred@databricks.com'),
  ('barney@databricks.com');

创建新筛选器:

注释

除了作为调用方运行的检查用户上下文的函数(例如 CURRENT_USERIS_ACCOUNT_GROUP_MEMBER 函数)外,所有筛选器都以定义者的权限运行。

在此示例中,该函数检查当前用户是否位于 valid_users 表中。 如果找到用户,该函数将返回 true。

DROP FUNCTION IF EXISTS row_filter;

CREATE FUNCTION row_filter()
  RETURN EXISTS(
    SELECT 1 FROM valid_users v
    WHERE v.username = CURRENT_USER()
);

以下示例在创建表期间应用行筛选器。 以后还可以使用 ALTER TABLE 语句添加筛选器。 将筛选器应用于未指定的列时,请使用 ON () 语法。 对于特定列,请使用 ON (column);。 有关详细信息,请参阅 “参数”。

DROP TABLE IF EXISTS data_table;

CREATE TABLE data_table
  (x INT, y INT, z INT)
  WITH ROW FILTER row_filter ON ();

INSERT INTO data_table VALUES
  (1, 2, 3),
  (4, 5, 6),
  (7, 8, 9);

从表中选择数据。 只有当用户位于 valid_users 表中时,才会返回数据。

SELECT * FROM data_table;

创建一个映射表,其中包含应始终有权查看表中所有行的帐户,而不考虑列值:

CREATE TABLE valid_accounts(account string);
INSERT INTO valid_accounts
VALUES
  ('admin'),
  ('cstaff');

现在,创建一个 SQL UDF,如果行中所有列的值小于 5,或者调用用户是上述映射表的成员,则该 SQL UDF 返回 true

CREATE FUNCTION row_filter_small_values (x INT, y INT, z INT)
  RETURN (x < 5 AND y < 5 AND z < 5)
  OR EXISTS(
    SELECT 1 FROM valid_accounts v
    WHERE IS_ACCOUNT_GROUP_MEMBER(v.account));

最后,将 SQL UDF 作为行筛选器应用于表:

ALTER TABLE data_table SET ROW FILTER row_filter_small_values ON (x, y, z);