

 从补丁 198 开始，Amazon Redshift 将不再支持创建新的 Python UDF。现有的 Python UDF 将继续正常运行至 2026 年 6 月 30 日。有关更多信息，请参阅[博客文章](https://aws.amazon.com/blogs/big-data/amazon-redshift-python-user-defined-functions-will-reach-end-of-support-after-june-30-2026/)。

# 动态数据掩蔽
<a name="t_ddm"></a>

**注意**  
在记录有关对 Data Catalog 视图执行的查询的信息时，Amazon Redshift 会自动屏蔽某些系统表列，以防止泄露敏感元数据。有关更多信息，请参阅《Amazon Redshift Management Guide》**中的 [Secure logging](https://docs.aws.amazon.com/redshift/latest/mgmt/db-auditing-secure-logging.html)。

使用 Amazon Redshift 中的动态数据掩蔽 (DDM)，您可以保护数据仓库中的敏感数据。您可以操纵 Amazon Redshift 在查询时如何向用户显示敏感数据，而无需在数据库中对其进行转换。您可以通过将自定义模糊处理规则应用于给定用户或角色的屏蔽策略来控制对数据的访问。这样，您无需更改底层数据或编辑 SQL 查询即可响应不断变化的隐私要求。

动态数据掩蔽策略会隐藏、模糊处理或假名化与给定格式匹配的数据。附加到表时，对表的一个或多个列应用屏蔽表达式。您可以进一步修改屏蔽策略，使其仅应用于某些用户，或者应用于您可以使用 [基于角色的访问控制 (RBAC)](t_Roles.md) 创建的用户定义角色。此外，在创建屏蔽策略时，您可以使用条件列在单元格级别应用 DDM。有关条件屏蔽的更多信息，请参阅[条件动态数据掩蔽](t_ddm-conditional.md)。

您可以将具有不同模糊处理级别的多个屏蔽策略应用于表中的同一列，并将它们分配给不同的角色。为避免在不同角色对一列应用不同策略时发生冲突，可以为每个应用程序设置优先级。通过这种方式，您可以控制给定用户或角色可以访问哪些数据。DDM 策略可以部分或完全编辑数据，也可以使用以 SQL、Python 或 AWS Lambda 编写的用户定义函数对其进行哈希处理。通过使用哈希屏蔽数据，您可以对这些数据应用联接，而无需访问潜在的敏感信息。

# 用于管理动态数据掩蔽策略的 SQL 命令
<a name="r_ddm-procedures"></a>

您可以执行以下操作来创建、附加、分离和删除动态数据掩蔽策略：
+ 要创建 DDM 策略，请使用 [CREATE MASKING POLICY](r_CREATE_MASKING_POLICY.md) 命令。

  以下是使用 SHA-2 哈希函数创建屏蔽策略的示例。

  ```
  CREATE MASKING POLICY hash_credit 
  WITH (credit_card varchar(256)) 
  USING (sha2(credit_card + 'testSalt', 256));
  ```
+ 要更改现有 DDM 政策，请使用 [ALTER MASKING POLICY](r_ALTER_MASKING_POLICY.md) 命令。

  以下是更改现有掩蔽政策的示例。

  ```
  ALTER MASKING POLICY hash_credit
  USING (sha2(credit_card + 'otherTestSalt', 256));
  ```
+ 要将表上的 DDM 策略附加到一个或多个用户或角色，请使用 [ATTACH MASKING POLICY](r_ATTACH_MASKING_POLICY.md) 命令。

  下面是将屏蔽策略附加到列/角色对的示例。

  ```
   ATTACH MASKING POLICY hash_credit 
  ON credit_cards (credit_card) 
  TO ROLE science_role 
  PRIORITY 30;
  ```

  PRIORITY 子句确定当多个策略附加到同一列时，哪个屏蔽策略适用于用户会话。例如，如果前面示例中的用户在同一信用卡列附加了另一个屏蔽策略，该策略的优先级为 20，则 science\$1role 的策略是适用的策略，因为它具有更高的优先级，即 30。
+ 要将表上的 DDM 策略与一个或多个用户或角色分离，请使用 [DETACH MASKING POLICY](r_DETACH_MASKING_POLICY.md) 命令。

  下面是从列/角色对分离屏蔽策略的示例。

  ```
  DETACH MASKING POLICY hash_credit 
  ON credit_cards(credit_card) 
  FROM ROLE science_role;
  ```
+ 要从所有数据库删除 DDM 策略，请使用 [DROP MASKING POLICY](r_DROP_MASKING_POLICY.md) 命令。

  以下是从所有数据库删除屏蔽策略的示例。

  ```
  DROP MASKING POLICY hash_credit;  
  ```

# 动态数据掩蔽策略层次结构
<a name="t_ddm-hierarchy"></a>

在附加多个掩蔽策略时，请注意以下事项：
+ 您可以将多个屏蔽策略附加到单个列。
+ 当多个屏蔽策略适用于一个查询时，附加到每个相应列的最高优先级策略适用。考虑以下示例。

  ```
  ATTACH MASKING POLICY partial_hash
  ON credit_cards(address, credit_card)
  TO ROLE analytics_role 
  PRIORITY 20;
  
  ATTACH MASKING POLICY full_hash
  ON credit_cards(credit_card, ssn)
  TO ROLE auditor_role 
  PRIORITY 30;
  
  SELECT address, credit_card, ssn
  FROM credit_cards;
  ```

  运行 SELECT 语句时，同时具有分析和审计角色的用户会看到应用了 `partial_hash` 屏蔽策略的地址列。他们会看到应用了 `full_hash` 掩蔽策略的信用卡和 SSN 列，因为 `full_hash` 策略在信用卡列上的优先级更高。
+  如果在附加屏蔽策略时未指定优先级，则默认为优先级为 0。
+ 您不能将两个具有相同优先级的策略附加到同一列。
+ 您不能将两个策略附加到用户和列或角色和列的相同组合。
+ 当多个掩蔽策略适用于同一 SUPER 路径，同时附加到同一用户或角色时，只有优先级最高的掩蔽策略才会生效。考虑以下示例。

  第一个示例显示两个掩蔽策略附加在同一路径上，优先级较高的策略生效。

  ```
  ATTACH MASKING POLICY hide_name
  ON employees(col_person.name)
  TO PUBLIC
  PRIORITY 20;
  
  ATTACH MASKING POLICY hide_last_name
  ON employees(col_person.name.last)
  TO PUBLIC
  PRIORITY 30;
  
  --Only the hide_last_name policy takes effect.
  SELECT employees.col_person.name FROM employees;
  ```

  第二个示例显示两个掩蔽策略附加到同一 SUPER 对象中的不同路径，这两个策略之间没有冲突。这两个掩蔽策略将同时适用。

  ```
  ATTACH MASKING POLICY hide_first_name
  ON employees(col_person.name.first)
  TO PUBLIC
  PRIORITY 20;
  
  ATTACH MASKING POLICY hide_last_name
  ON employees(col_person.name.last)
  TO PUBLIC
  PRIORITY 20;
  
  --Both col_person.name.first and col_person.name.last are masked.
  SELECT employees.col_person.name FROM employees;
  ```

要确认哪个掩蔽策略适用于给定的用户和列或角色和列组合，具有 [https://docs.aws.amazon.com/redshift/latest/dg/r_roles-default.html](https://docs.aws.amazon.com/redshift/latest/dg/r_roles-default.html) 角色的用户可以在 [SVV\$1ATTACHED\$1MASKING\$1POLICY](r_SVV_ATTACHED_MASKING_POLICY.md) 系统视图中查找列/角色或列/用户对。有关更多信息，请参阅 [动态数据掩蔽系统视图](r_ddm-svv.md)。

# 对 SUPER 数据类型路径使用动态数据掩蔽
<a name="t_ddm-super"></a>

 Amazon Redshift 支持将动态数据掩蔽策略附加到 SUPER 类型列的路径。有关 SUPER 数据类型的更多信息，请参阅[Amazon Redshift 中的半结构化数据](super-overview.md)。

将掩蔽策略附加到 SUPER 类型列的路径时，请考虑以下几点。
+ 将掩蔽策略附加到列上的路径时，必须将该列定义为 SUPER 数据类型。只能对 SUPER 路径上的*标量*值应用掩蔽策略。不能将掩蔽策略应用于复杂的结构或数组。
+ 只要 SUPER 路径不冲突，就可以对单个 SUPER 列上的多个标量值应用不同的掩蔽策略。例如，SUPER 路径 `a.b` 和 `a.b.c` 冲突，因为它们在同一路径上，`a.b` 是 `a.b.c` 的父路径。SUPER 路径 `a.b.c` 和 `a.b.d` 不冲突。
+ 在用户查询运行时应用策略之前，Amazon Redshift 无法检查数据中是否存在掩蔽策略所附加的路径，也无法检查这些路径是否属于预期类型。例如，当您将掩蔽 TEXT 值的掩蔽策略附加到包含 INT 值的 SUPER 路径时，Amazon Redshift 会尝试在路径上转换值的类型。

  在这种情况下，Amazon Redshift 在运行时的行为取决于您用于查询 SUPER 对象的配置设置。默认情况下，Amazon Redshift 采用宽松模式，对于给定的 SUPER 路径，会将缺失的路径和无效的转换解析为 `NULL`。有关 SUPER 相关配置设置的更多信息，请参阅[SUPER 配置](super-configurations.md)。
+ SUPER 是一种无架构类型，这意味着 Amazon Redshift 无法确认给定 SUPER 路径上的值是否存在。如果您将掩蔽策略附加到不存在的 SUPER 路径并且 Amazon Redshift 采用宽松模式，则 Amazon Redshift 会将该路径解析为 `NULL` 值。我们建议您在将掩蔽策略附加到 SUPER 列的路径时，考虑 SUPER 对象的预期格式以及它们具有意外属性的可能性。如果您认为 SUPER 列中可能存在意外架构，请考虑将掩蔽策略直接附加到 SUPER 列。您可以使用 SUPER 类型信息函数来检查属性和类型，并使用 `OBJECT_TRANSFORM` 来掩蔽这些值。有关 SUPER 类型信息函数的更多信息，请参阅[SUPER 类型信息函数](c_Type_Info_Functions.md)。

## 示例
<a name="t_ddm-super-examples"></a>

**将掩蔽策略附加到 SUPER 路径**  
以下示例在一列中将多个掩蔽策略附加到多个 SUPER 类型路径上。

```
CREATE TABLE employees (
    col_person SUPER
);

INSERT INTO employees
VALUES
    (
        json_parse('
            {
                "name": {
                    "first": "John",
                    "last": "Doe"
                },
                "age": 25,
                "ssn": "111-22-3333",
                "company": "Company Inc."
            }
        ')
    ),
    (
        json_parse('
            {
                "name": {
                    "first": "Jane",
                    "last": "Appleseed"
                },
                "age": 34,
                "ssn": "444-55-7777",
                "company": "Organization Org."
            }
        ')
    )
;
GRANT ALL ON ALL TABLES IN SCHEMA "public" TO PUBLIC;

-- Create the masking policies.

-- This policy converts the given name to all uppercase letters.
CREATE MASKING POLICY mask_first_name
WITH(first_name TEXT)
USING ( UPPER(first_name) );

-- This policy replaces the given name with the fixed string 'XXXX'.
CREATE MASKING POLICY mask_last_name
WITH(last_name TEXT)
USING ( 'XXXX'::TEXT );

-- This policy rounds down the given age to the nearest 10.
CREATE MASKING POLICY mask_age
WITH(age INT)
USING ( (FLOOR(age::FLOAT / 10) * 10)::INT );

-- This policy converts the first five digits of the given SSN to 'XXX-XX'.
CREATE MASKING POLICY mask_ssn
WITH(ssn TEXT)
USING ( 'XXX-XX-'::TEXT || SUBSTRING(ssn::TEXT FROM 8 FOR 4) );

-- Attach the masking policies to the employees table.
ATTACH MASKING POLICY mask_first_name
ON employees(col_person.name.first)
TO PUBLIC;

ATTACH MASKING POLICY mask_last_name
ON employees(col_person.name.last)
TO PUBLIC;

ATTACH MASKING POLICY mask_age
ON employees(col_person.age)
TO PUBLIC;

ATTACH MASKING POLICY mask_ssn
ON employees(col_person.ssn)
TO PUBLIC;

-- Verify that your masking policies are attached.
SELECT
    policy_name,
    TABLE_NAME,
    priority,
    input_columns,
    output_columns
FROM
    svv_attached_masking_policy;

   policy_name   | table_name | priority |           input_columns           |          output_columns
-----------------+------------+----------+-----------------------------------+-----------------------------------
 mask_age        | employees  |        0 | ["col_person.\"age\""]            | ["col_person.\"age\""]
 mask_first_name | employees  |        0 | ["col_person.\"name\".\"first\""] | ["col_person.\"name\".\"first\""]
 mask_last_name  | employees  |        0 | ["col_person.\"name\".\"last\""]  | ["col_person.\"name\".\"last\""]
 mask_ssn        | employees  |        0 | ["col_person.\"ssn\""]            | ["col_person.\"ssn\""]
(4 rows)

-- Observe the masking policies taking effect.
SELECT col_person FROM employees ORDER BY col_person.age;

-- This result is formatted for ease of reading.
         col_person
--------------------------------
{
    "name": {
        "first": "JOHN",
        "last": "XXXX"
    },
    "age": 20,
    "ssn": "XXX-XX-3333",
    "company": "Company Inc."
}
{
    "name": {
        "first": "JANE",
        "last": "XXXX"
    },
    "age": 30,
    "ssn": "XXX-XX-7777",
    "company": "Organization Org."
}
```

以下是附加到 SUPER 路径的无效掩蔽策略的一些示例。

```
-- This attachment fails because there is already a policy
-- with equal priority attached to employees.name.last, which is
-- on the same SUPER path as employees.name.
ATTACH MASKING POLICY mask_ssn
ON employees(col_person.name)
TO PUBLIC;
ERROR:  DDM policy "mask_last_name" is already attached on relation "employees" column "col_person."name"."last"" with same priority
               
-- Create a masking policy that masks DATETIME objects.
CREATE MASKING POLICY mask_date
WITH(INPUT DATETIME)
USING ( INPUT );
               
-- This attachment fails because SUPER type columns can't contain DATETIME objects.
ATTACH MASKING POLICY mask_date
ON employees(col_person.company)
TO PUBLIC;
ERROR:  cannot attach masking policy for output of type "timestamp without time zone" to column "col_person."company"" of type "super
```

以下是将掩蔽策略附加到不存在的 SUPER 路径的示例。默认情况下，Amazon Redshift 将路径解析为 `NULL`。

```
ATTACH MASKING POLICY mask_first_name
ON employees(col_person.not_exists)
TO PUBLIC;

SELECT col_person FROM employees LIMIT 1;

-- This result is formatted for ease of reading.
         col_person
-----------------------------------
{
    "name": {
        "first": "JOHN",
        "last": "XXXX"
    },
    "age": 20,
    "ssn": "XXX-XX-3333",
    "company": "Company Inc.",
    "not_exists": null
}
```

# 条件动态数据掩蔽
<a name="t_ddm-conditional"></a>

通过在屏蔽表达式中使用条件表达式创建掩蔽策略，可以在单元格级别掩蔽数据。例如，您可以创建一个掩蔽策略，根据该行中另一列的值对值应用不同的掩蔽。

以下是使用条件数据掩蔽来创建和附加掩蔽策略的示例，该策略会部分编辑涉及欺诈的信用卡号，同时完全隐藏所有其他信用卡号。您必须是超级用户或具有 [https://docs.aws.amazon.com/redshift/latest/dg/r_roles-default.html](https://docs.aws.amazon.com/redshift/latest/dg/r_roles-default.html) 角色才能运行此示例。

```
--Create an analyst role.
CREATE ROLE analyst;

--Create a credit card table. The table contains an is_fraud boolean column,
--which is TRUE if the credit card number in that row was involved in a fraudulent transaction.
CREATE TABLE credit_cards (id INT, is_fraud BOOLEAN, credit_card_number VARCHAR(16));

--Create a function that partially redacts credit card numbers.
CREATE FUNCTION REDACT_CREDIT_CARD (credit_card VARCHAR(16))
RETURNS VARCHAR(16) IMMUTABLE
AS $$
    import re
    regexp = re.compile("^([0-9]{6})[0-9]{5,6}([0-9]{4})")
 
    match = regexp.search(credit_card)
    if match != None:
        first = match.group(1)
        last = match.group(2)
    else:
        first = "000000"
        last = "0000"
    
    return "{}XXXXX{}".format(first, last)
$$ LANGUAGE plpythonu;

--Create a masking policy that partially redacts credit card numbers if the is_fraud value for that row is TRUE,
--and otherwise blanks out the credit card number completely.
CREATE MASKING POLICY card_number_conditional_mask
    WITH (fraudulent BOOLEAN, pan varchar(16)) 
    USING (CASE WHEN fraudulent THEN REDACT_CREDIT_CARD(pan)
                ELSE Null
           END);

--Attach the masking policy to the credit_cards/analyst table/role pair. 
ATTACH MASKING POLICY card_number_conditional_mask ON credit_cards (credit_card_number)
 USING (is_fraud, credit_card_number)
 TO ROLE analyst PRIORITY 100;
```

# 动态数据掩蔽系统视图
<a name="r_ddm-svv"></a>

超级用户、具有 `sys:operator` 角色的用户和具有 ACCESS SYSTEM TABLE 权限的用户可以访问以下与 DDM 相关的系统视图。
+  [SVV\$1MASKING\$1POLICY](r_SVV_MASKING_POLICY.md) 

   使用 SVV\$1MASKING\$1POLICY 可查看在集群或工作组上创建的所有屏蔽策略。
+  [SVV\$1ATTACHED\$1MASKING\$1POLICY](r_SVV_ATTACHED_MASKING_POLICY.md) 

  使用 SVV\$1ATTACHED\$1MASKING\$1POLICY 可查看已在当前连接的数据库上附加了策略的所有关系和角色或用户。
+  [SYS\$1APPLIED\$1MASKING\$1POLICY\$1LOG](SYS_APPLIED_MASKING_POLICY_LOG.md) 

  使用 SYS\$1APPLIED\$1MASKING\$1POLICY\$1LOG 可跟踪屏蔽策略在引用受 DDM 保护关系的查询上的应用情况。

下面是使用系统视图可以找到的一些信息示例。

```
--Select all policies associated with specific users, as opposed to roles
SELECT policy_name,
       schema_name,
       table_name,
       grantee
FROM svv_attached_masking_policy
WHERE grantee_type = 'user';     

--Select all policies attached to a specific user
SELECT policy_name,
       schema_name,
       table_name,
       grantee
FROM svv_attached_masking_policy
WHERE grantee = 'target_grantee_name'            
            
--Select all policies attached to a given table
SELECT policy_name,
       schema_name,
       table_name,
       grantee
FROM svv_attached_masking_policy
WHERE table_name = 'target_table_name'
      AND schema_name = 'target_schema_name';            
            
--Select the highest priority policy attachment for a given role
SELECT samp.policy_name,
       samp.priority,
       samp.grantee,
       smp.policy_expression
FROM svv_masking_policy AS smp
JOIN svv_attached_masking_policy AS samp
    ON samp.policy_name = smp.policy_name
WHERE
    samp.grantee_type = 'role' AND
    samp.policy_name = mask_get_policy_for_role_on_column(
        'target_schema_name', 
        'target_table_name', 
        'target_column_name', 
        'target_role_name')
ORDER BY samp.priority desc
LIMIT 1;         

--See which policy a specific user will see on a specific column in a given relation
SELECT samp.policy_name,
       samp.priority,
       samp.grantee,
       smp.policy_expression
FROM svv_masking_policy AS smp
JOIN svv_attached_masking_policy AS samp
    ON samp.policy_name = smp.policy_name
WHERE
    samp.grantee_type = 'role' AND
    samp.policy_name = mask_get_policy_for_user_on_column(
        'target_schema_name',
        'target_table_name',
        'target_column_name',
        'target_user_name')
ORDER BY samp.priority desc; 
         
 --Select all policies attached to a given relation.
SELECT policy_name,
schema_name,
relation_name,
database_name
FROM sys_applied_masking_policy_log
WHERE relation_name = 'relation_name'
AND schema_name = 'schema_name';
```

# 使用动态数据掩蔽时的注意事项
<a name="t_ddm-considerations"></a>

使用动态数据掩蔽时，请考虑以下事项：
+  在查询通过表创建的对象（例如视图）时，用户将看到基于他们自己的屏蔽策略的结果，而不是创建对象的用户的策略。例如，具有分析师角色的用户查询 secadmin 创建的视图时，他将看到附加到分析师角色的屏蔽策略的结果。
+  为防止 EXPLAIN 命令可能暴露敏感的屏蔽策略筛选条件，只有拥有 SYS\$1EXPLAIN\$1DDM 权限的用户才能看到在 EXPLAIN 输出中应用的屏蔽策略。默认情况下，用户没有 SYS\$1EXPLAIN\$1DDM 权限。

  向角色授予权限的语法如下。

  ```
  GRANT EXPLAIN MASKING TO ROLE rolename
  ```

   有关 EXPLAIN 命令的更多信息，请参阅 [EXPLAIN](r_EXPLAIN.md)。
+  根据所使用的筛选条件或联接条件，具有不同角色的用户会看到不同的结果。例如，如果运行命令的用户应用了会模糊处理特定列的屏蔽策略，则在使用该列值的表上运行 SELECT 命令将失败。
+  必须在任何谓词操作或预测之前应用 DDM 策略。掩蔽策略可以包括：
  + 低成本常量操作，例如将值转换为 null
  + 中等成本操作，例如 HMAC 哈希
  + 高成本操作，例如调用外部 Lambda 用户定义函数

  因此，如果可能，我们建议您使用简单屏蔽表达式。
+  您可以对具有行级安全策略的角色使用 DDM 策略，但请注意，RLS 策略在 DDM 之前应用。动态数据掩蔽表达式将无法读取受 RLS 保护的行。有关 RLS 的更多信息，请参阅 [行级别安全性](t_rls.md)。
+  使用 [COPY](r_COPY.md) 命令从 parquet 复制到受保护的目标表时，您应在 COPY 语句中明确指定列。有关使用 COPY 映射列的更多信息，请参阅[列映射选项](copy-parameters-column-mapping.md)。
+  DDM 策略不能附加到以下关系：
  +  系统表和目录 
  +  外部表 
  +  数据共享表
  +  跨数据库关系 
  +  临时表 
  +  关联的查询 
+  DDM 策略可以包括查找表。查找表可以存在于 USING 子句中。以下关系类型不能用作查找表：
  +  系统表和目录 
  +  外部表 
  +  数据共享表 
  +  视图、实体化视图和后期绑定视图 
  +  跨数据库关系 
  +  临时表 
  +  关联的查询 

  以下是将掩蔽政策附加到查找表的示例。

  ```
  --Create a masking policy referencing a lookup table
  CREATE MASKING POLICY lookup_mask_credit_card WITH (credit_card TEXT) USING (
    CASE
      WHEN
        credit_card IN (SELECT credit_card_lookup FROM credit_cards_lookup)      
      THEN '000000XXXX0000'
      ELSE REDACT_CREDIT_CARD(credit_card)
      END
    ); 
    
  --Provides access to the lookup table via a policy attached to a role
  GRANT SELECT ON TABLE credit_cards_lookup TO MASKING POLICY lookup_mask_credit_card;
  ```
+  您不能附加所产生的输出与目标列的类型和大小不兼容的屏蔽策略。例如，您不能附加将 12 个字符长的字符串输出到 VARCHAR(10) 列的屏蔽策略。Amazon Redshift 支持以下例外情况：
  +  只要 M < N，输入类型为 INTN 的屏蔽策略就可以附加到大小为 INTM 的策略上。例如，BIGINT (INT8) 输入策略可以附加到 smallint (INT4) 列。
  +  输入类型为 NUMERIC 或 DECIMAL 的屏蔽策略始终可以附加到 FLOAT 列。
+ 您不能将 DDM 策略与数据共享结合使用。如果数据共享的数据创建者将 DDM 策略附加到数据共享中的表，则尝试查询该表的数据使用者用户将无法访问该表。在生产者端集群或命名空间上尝试将关系添加到数据共享将失败，并出现以下错误：

  ```
  <ddm_protected_relation> or a relation dependent on it is protected by a masking policy and cannot be added to a datashare
  ```

  如果您将掩蔽策略附加到生产者端的关系，并且该关系已包含在数据共享中，则尝试在使用者端查询该关系会失败，并显示以下错误：

  ```
  cross-cluster query of the masked relation <ddm_protected_relation> is not supported.
  ```

  可以使用带有 MASKING OFF FOR DATASHARES 参数的 ALTER TABLE 命令关闭数据共享的 DDM。有关更多信息，请参阅 [ALTER TABLE](r_ALTER_TABLE.md)。
+ 如果以下任一配置选项的值与会话的默认值不匹配，则无法查询附加了 DDM 策略的关系：
  +  `enable_case_sensitive_super_attribute` 
  +  `enable_case_sensitive_identifier` 
  +  `downcase_delimited_identifier` 

  如果您试图查询附加了 DDM 策略的关系，并看到消息“DDM 保护的关系不支持会话级别配置，因为区分大小写不同于其默认值”，请考虑重置会话的配置选项。
+  当您的预调配集群或无服务器命名空间具有任何动态数据掩蔽策略时，普通用户将无法使用以下命令：

  ```
  ALTER <current_user> SET enable_case_sensitive_super_attribute/enable_case_sensitive_identifier/downcase_delimited_identifier
  ```

  创建 DDM 策略时，我们建议您更改普通用户的默认配置选项设置，使其与创建策略时会话的配置选项设置相匹配。超级用户和具有 ALTER USER 权限的用户可以使用参数组设置或 ALTER USER 命令来执行此操作。有关参数组的信息，请参阅《Amazon Redshift 管理指南》**中的 [Amazon Redshift 参数组](https://docs.aws.amazon.com/redshift/latest/mgmt/working-with-parameter-groups.html)。有关 ALTER USER 命令的信息，请参阅 [ALTER USER](r_ALTER_USER.md)。
+ 普通用户无法使用 [CREATE VIEW](r_CREATE_VIEW.md) 命令替换已附加 DDM 策略的视图和后期绑定视图。要替换具有 DDM 策略的视图或 LBV，请先分离附加到这些视图的所有 DDM 策略，替换视图或 LBV，然后重新附加策略。具有 `sys:secadmin` 权限的超级用户和用户可以在具有 DDM 策略的视图或 LBV 上使用 CREATE VIEW，而无需分离策略。
+ 附加了 DDM 策略的视图无法引用系统表和视图。后期绑定视图可以引用系统表和视图。
+ 附加了 DDM 策略的后期绑定视图无法引用数据湖中的嵌套数据，例如 JSON 文档。
+  如果任何视图引用了后期绑定视图，则后期绑定视图不能附加 DDM 策略。
+  附加到后期绑定视图的 DDM 策略按列名附加。在查询时，Amazon Redshift 会验证是否已成功应用附加到后期绑定视图的所有掩蔽策略，以及后期绑定视图的输出列类型是否与附加掩蔽策略中的类型相匹配。如果验证失败，Amazon Redshift 将返回查询错误。
+ 创建 DDM 策略时，可以使用自定义的会话上下文变量。以下示例设置 DDM 策略的会话上下文变量。

  ```
  -- Set a customized context variable.
  SELECT set_config('app.city', 'XXXX', FALSE);
  
  -- Create a MASKING policy using current_setting() to get the value of a customized context variable.
  CREATE MASKING POLICY city_mask
  WITH (city VARCHAR(30))
  USING (current_setting('app.city')::VARCHAR(30));
  
  -- Attach the policy on the target table to one or more roles.
  ATTACH MASKING POLICY city_mask 
  ON tickit_users_redshift(city) 
  TO ROLE analyst, ROLE dbadmin;
  ```

  有关如何设置和检索自定义会话上下文变量的详细信息，请转至 [SET](r_SET.md)、[SET\$1CONFIG](r_SET_CONFIG.md)、[SHOW](r_SHOW.md)、[CURRENT\$1SETTING](r_CURRENT_SETTING.md) 和 [RESET](r_RESET.md)。有关在一般情况下修改服务器配置的更多信息，请访问[修改服务器配置](cm_chap_ConfigurationRef.md#t_Modifying_the_default_settings)。
**重要**  
 在 DDM 策略中使用会话上下文变量时，安全策略依赖于调用该策略的用户或角色。在 DDM 策略中使用会话上下文变量时，请注意避免安全漏洞。

# 动态数据掩蔽端到端示例
<a name="ddm-example"></a>

下面是一个端到端的示例，显示了如何创建屏蔽策略并将其附加到列。这些策略让用户可以访问列并查看不同的值，具体取决于与其角色相关的策略的混淆程度。您必须是超级用户或具有 [https://docs.aws.amazon.com/redshift/latest/dg/r_roles-default.html](https://docs.aws.amazon.com/redshift/latest/dg/r_roles-default.html) 角色才能运行此示例。

## 创建屏蔽策略
<a name="ddm-example-create"></a>

首先，创建一个表并填入信用卡值。

```
--create the table         
CREATE TABLE credit_cards (
  customer_id INT,
  credit_card TEXT
);

--populate the table with sample values
INSERT INTO credit_cards
VALUES
  (100, '4532993817514842'),
  (100, '4716002041425888'),
  (102, '5243112427642649'),
  (102, '6011720771834675'),
  (102, '6011378662059710'),
  (103, '373611968625635')
;

--run GRANT to grant permission to use the SELECT statement on the table
GRANT SELECT ON credit_cards TO PUBLIC;

--create two users
CREATE USER regular_user WITH PASSWORD '1234Test!';

CREATE USER analytics_user WITH PASSWORD '1234Test!';

--create the analytics_role role and grant it to analytics_user
--regular_user does not have a role
CREATE ROLE analytics_role;

GRANT ROLE analytics_role TO analytics_user;
```

接下来，创建应用于分析角色的屏蔽策略。

```
--create a masking policy that fully masks the credit card number
CREATE MASKING POLICY mask_credit_card_full
WITH (credit_card VARCHAR(256))
USING ('000000XXXX0000'::TEXT);

--create a user-defined function that partially obfuscates credit card data
CREATE FUNCTION REDACT_CREDIT_CARD (credit_card TEXT)
RETURNS TEXT IMMUTABLE
AS $$
    import re
    regexp = re.compile("^([0-9]{6})[0-9]{5,6}([0-9]{4})")
 
    match = regexp.search(credit_card)
    if match != None:
        first = match.group(1)
        last = match.group(2)
    else:
        first = "000000"
        last = "0000"
    
    return "{}XXXXX{}".format(first, last)
$$ LANGUAGE plpythonu;

--create a masking policy that applies the REDACT_CREDIT_CARD function
CREATE MASKING POLICY mask_credit_card_partial
WITH (credit_card VARCHAR(256))
USING (REDACT_CREDIT_CARD(credit_card));

--confirm the masking policies using the associated system views
SELECT * FROM svv_masking_policy;

SELECT * FROM svv_attached_masking_policy;
```

## 附加屏蔽政策
<a name="ddm-example-attach"></a>

将屏蔽政策附加到信用卡表中。

```
--attach mask_credit_card_full to the credit card table as the default policy
--all users will see this masking policy unless a higher priority masking policy is attached to them or their role
ATTACH MASKING POLICY mask_credit_card_full
ON credit_cards(credit_card)
TO PUBLIC;

--attach mask_credit_card_partial to the analytics role
--users with the analytics role can see partial credit card information
ATTACH MASKING POLICY mask_credit_card_partial
ON credit_cards(credit_card)
TO ROLE analytics_role
PRIORITY 10;

--confirm the masking policies are applied to the table and role in the associated system view
SELECT * FROM svv_attached_masking_policy;

--confirm the full masking policy is in place for normal users by selecting from the credit card table as regular_user
SET SESSION AUTHORIZATION regular_user;

SELECT * FROM credit_cards;

--confirm the partial masking policy is in place for users with the analytics role by selecting from the credit card table as analytics_user
SET SESSION AUTHORIZATION analytics_user;

SELECT * FROM credit_cards;
```

## 修改掩蔽政策
<a name="ddm-example-alter"></a>

以下部分介绍了如何修改动态数据掩蔽政策。

```
--reset session authorization to the default
RESET SESSION AUTHORIZATION;

--alter the mask_credit_card_full policy
ALTER MASKING POLICY mask_credit_card_full
USING ('00000000000000'::TEXT);	
	
--confirm the full masking policy is in place after altering the policy, and that results are altered from '000000XXXX0000' to '00000000000000'
SELECT * FROM credit_cards;
```

## 分离和删除屏蔽策略
<a name="ddm-example-detach"></a>

以下部分显示如何通过从表中删除所有动态数据掩蔽策略来分离和删除屏蔽策略。

```
--reset session authorization to the default
RESET SESSION AUTHORIZATION;

--detach both masking policies from the credit_cards table
DETACH MASKING POLICY mask_credit_card_full 
ON credit_cards(credit_card) 
FROM PUBLIC;

DETACH MASKING POLICY mask_credit_card_partial 
ON credit_cards(credit_card) 
FROM ROLE analytics_role;

--drop both masking policies
DROP MASKING POLICY mask_credit_card_full;

DROP MASKING POLICY mask_credit_card_partial;
```