

 从补丁 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="r_Database_objects"></a>

您可以通过控制哪些用户可以访问哪些数据库对象来管理数据库安全。可以为用户分配角色或组，授予给用户、角色或组的权限决定了他们可以访问哪些数据库对象。

**Topics**
+ [Amazon Redshift 安全性概览](c_security-overview.md)
+ [默认数据库用户权限](r_Privileges.md)
+ [superuser](r_superusers.md)
+ [用户](r_Users.md)
+ [组](r_Groups.md)
+ [Schemas](r_Schemas_and_tables.md)
+ [基于角色的访问控制 (RBAC)](t_Roles.md)
+ [行级别安全性](t_rls.md)
+ [元数据安全性](t_metadata_security.md)
+ [动态数据掩蔽](t_ddm.md)
+ [限定范围权限](t_scoped-permissions.md)

对数据库对象的访问权限取决于您向用户或角色授予的权限。以下指南概括了数据库安全的工作方式：
+ 默认情况下，仅向对象拥有者授予权限。
+ Amazon Redshift 数据库用户是可连接到数据库的指定用户。可通过两种方式向用户授予权限：显式（直接将这些权限分配给账户），或隐式（成为被授予权限的组的成员）。
+ 组是可集体分配权限的用户集合，更简化安全维护。
+ Schemas 是数据库表和其他数据库对象的集合。架构类似于文件系统目录，但架构不能嵌套。可以向用户授予对单个 schema 或多个 schemas 的访问权限。

此外，Amazon Redshift 还采用了以下功能，让您可以更好地控制哪些用户可以访问哪些数据库对象：
+  通过基于角色的访问控制 (RBAC)，您可以向角色分配权限，然后将角色应用到用户，这样就可以控制大批用户的权限。与组不同，角色可以继承其他角色的权限。

  通过行级别安全性 (RLS)，您可以定义策略来限制对所选行的访问，然后将这些策略应用于用户或组。

   动态数据掩蔽 (DDM) 会在查询运行时转换数据，这样您就可以允许用户访问数据而不暴露敏感的详细信息，从而进一步保护您的数据。

有关安全实现的示例，请参阅[控制用户和组访问的示例](t_user_group_examples.md)。

有关保护数据的更多信息，请参阅《Amazon Redshift 管理指南》**中的 [Amazon Redshift 中的安全性](https://docs.aws.amazon.com/redshift/latest/mgmt/iam-redshift-user-mgmt.html)。

# Amazon Redshift 安全性概览
<a name="c_security-overview"></a>



Amazon Redshift 数据库安全不同于其他类型的 Amazon Redshift 安全。除此部分介绍的数据库安全之外，Amazon Redshift 还提供下面的功能来管理安全：
+  **登录凭证** – 对 Amazon Redshift AWS 管理控制台的访问 AWS 受账户权限控制。有关更多信息，请参阅[登录凭证](https://docs.aws.amazon.com/general/latest/gr/aws-security-credentials.html)。
+  **访问管理** — 要控制对特定 Amazon Redshift 资源的访问权限，您可以定义 AWS Identity and Access Management (IAM) 账户。有关更多信息，请参阅[控制对 Amazon Redshift 资源的访问](https://docs.aws.amazon.com/redshift/latest/mgmt/iam-redshift-user-mgmt.html)。
+  **集群安全组** — 要向其他用户授予对 Amazon Redshift 集群的入站访问权限，可定义一个集群安全组并将其与集群相关联。有关更多信息，请参阅[ Amazon Redshift 集群安全组](https://docs.aws.amazon.com/redshift/latest/mgmt/working-with-security-groups.html)。
+  **VPC** — 要通过使用虚拟联网环境保护对集群的访问，可在 Amazon Virtual Private Cloud (VPC) 中启动集群。有关更多信息，请参阅[在 Virtual Private Cloud (VPC) 中管理集群](https://docs.aws.amazon.com/redshift/latest/mgmt/managing-clusters-vpc.html)。
+  **集群加密** – 要对用户创建的所有表中的数据进行加密，可以在启动集群时开启集群加密。有关更多信息，请参阅 [Amazon Redshift 集群](https://docs.aws.amazon.com/redshift/latest/mgmt/working-with-clusters.html)。
+  **SSL 连接** — 要对 SQL 客户端与集群之间的连接进行加密，可以使用安全套接字层 (SSL) 加密。有关更多信息，请参阅[使用 SSL 连接到集群](https://docs.aws.amazon.com/redshift/latest/mgmt/connecting-ssl-support.html)。
+  **加载数据加密** — 要在将表加载数据文件上载到 Amazon S3 时对这些文件进行加密，可以使用服务器端加密或客户端加密。从服务器端加密的数据进行加载时，Amazon S3 将以透明方式处理解密。从客户端加密的数据进行加载时，Amazon Redshift COPY 命令将在加载表时解密数据。有关更多信息，请参阅 [将加密的数据上载到 Amazon S3](t_uploading-encrypted-data.md)。
+ **传输中的数据** – 为保护 AWS 云中的传输中数据，Amazon Redshift 使用硬件加速的 SSL 与 Amazon S3 或 Amazon DynamoDB 通信以执行复制、卸载、备份和还原操作。
+ **列级访问控制** – 要在 Amazon Redshift 中对数据进行列级访问控制，请使用列级授予和撤销语句，而无需实施基于视图的访问控制或使用其他系统。
+ **行级安全控制** — 要对 Amazon Redshift 中的数据实施行级安全控制，请创建在策略中定义了限制对行的访问权限的策略，并将其附加到角色或用户。

# 默认数据库用户权限
<a name="r_Privileges"></a>

当您创建数据库对象时，您便是该对象的所有者。默认情况下，只有超级用户或对象的拥有者可以查询、修改或授予该对象上的权限。为使用户能够使用对象，您必须向该用户或包含该用户的组授予必要的权限。数据库超级用户具有与数据库拥有者相同的权限。

Amazon Redshift 支持以下权限：SELECT、INSERT、UPDATE、DELETE、REFERENCES、CREATE、TEMPORARY 和 USAGE。不同的权限与不同的对象类型关联。有关 Amazon Redshift 支持的数据库对象权限的信息，请参阅 [GRANT](r_GRANT.md) 命令。

仅所有者有权修改或销毁对象。

默认情况下，所有用户都对数据库的 PUBLIC Schema 具有 CREATE 和 USAGE 权限。要禁止用户在数据库的 PUBLIC 架构中创建对象，请使用 REVOKE 命令删除该权限。

要撤消以前授予的权限，可以使用 [REVOKE](r_REVOKE.md) 命令。对象拥有者的权限（例如 DROP、GRANT 和 REVOKE 权限）是隐式的，无法授予或撤消。对象拥有者可以撤消自己的普通权限，例如，使表对自己以及其他人只读。超级用户将保留所有权限，而不考虑 GRANT 和 REVOKE 命令。

# 超级用户
<a name="r_superusers"></a>

<a name="def_superusers"></a>数据库超级用户具有与所有数据库的数据库拥有者相同的权限。

您在启动集群时创建的用户 *admin* 即是超级用户。

您必须是超级用户才能创建超级用户。

Amazon Redshift 系统表和系统视图要么只对超级用户可见，要么对所有用户可见。只有超级用户可以查询指定为“对超级用户可见”的系统表和系统视图。有关信息，请参阅[SYS 监控视图](serverless_views-monitoring.md)。

超级用户可以查看所有目录表。有关信息，请参阅[系统目录表](c_intro_catalog_views.md)。

数据库超级用户会绕过所有权限检查。超级用户将保留所有权限，而不考虑 GRANT 和 REVOKE 命令。请谨慎使用超级用户角色。建议您使用不是超级用户的角色执行多数工作。您可以创建具有更多限制权限的管理员角色。有关创建角色的更多信息，请参阅[基于角色的访问控制 (RBAC)](t_Roles.md)。

要创建新的数据库超级用户，请以超级用户身份登录到数据库，并使用 CREATEUSER 权限发送 CREATE USER 命令或 ALTER USER 命令。

```
CREATE USER adminuser CREATEUSER PASSWORD '1234Admin';
ALTER USER adminuser CREATEUSER;
```

要创建、更改或删除超级用户，请使用相同的命令来管理用户。有关更多信息，请参阅 [创建、修改和删除用户](r_Users-creatingaltering-and-deleting-users.md)。

# 用户
<a name="r_Users"></a>

您可以使用 Amazon Redshift SQL 的 CREATE USER 和 ALTER USER 命令来创建和管理数据库用户。您还可以使用 Amazon Redshift JDBC 或 ODBC 驱动程序配置 SQL 客户端。这些驱动程序在数据库登录过程中管理创建数据库用户和临时密码的过程。

这些驱动程序将基于 AWS Identity and Access Management (IAM) 身份验证来验证数据库用户的身份。如果您已在 AWS 外部管理用户身份，则可以使用符合 SAML 2.0 标准的身份提供者 (IdP) 来管理对 Amazon Redshift 资源的访问。您使用 IAM 角色将 IdP 和 AWS 配置为允许联合身份用户生成临时数据库凭证并登录 Amazon Redshift 数据库。有关更多信息，请参阅[使用 IAM 身份验证生成数据库用户凭证](https://docs.aws.amazon.com/redshift/latest/mgmt/generating-user-credentials.html)。

Amazon Redshift 用户只能由数据库超级用户创建和删除。在用户登录 Amazon Redshift 时会对其进行身份验证。用户可以拥有数据库和数据库对象（例如，表）。他们还可以向用户、组和 Schema 授予对这些对象的权限，以控制谁可以访问哪个对象。具有 CREATE DATABASE 权限的用户可以创建数据库并授予对这些数据库的权限。超级用户具有所有数据库的数据库所有权。

# 创建、修改和删除用户
<a name="r_Users-creatingaltering-and-deleting-users"></a>

数据库用户在数据仓库集群中具有全局性（不针对单个数据库）。
+  要创建用户，请使用 [CREATE USER](r_CREATE_USER.md) 命令。
+  要创建超级用户，请使用 [CREATE USER](r_CREATE_USER.md) 命令和 CREATEUSER 选项。
+ 要删除现有用户，请使用 [DROP USER](r_DROP_USER.md) 命令。
+ 要更改用户（例如更改密码），请使用 [ALTER USER](r_ALTER_USER.md) 命令。
+ 要查看用户列表，请查询 PG\$1USER 目录表。

  ```
  select * from pg_user;
  
    usename   | usesysid | usecreatedb | usesuper | usecatupd |  passwd  | valuntil | useconfig
  ------------+----------+-------------+----------+-----------+----------+----------+-----------
   rdsdb      |        1 | t           | t        | t         | ******** |          |
   masteruser |      100 | t           | t        | f         | ******** |          |
   dwuser     |      101 | f           | f        | f         | ******** |          |
   simpleuser |      102 | f           | f        | f         | ******** |          |
   poweruser  |      103 | f           | t        | f         | ******** |          |
   dbuser     |      104 | t           | f        | f         | ******** |          |
  (6 rows)
  ```

# 组
<a name="r_Groups"></a>

组是一些用户的集合，这些用户全部被授予与组关联的所有权限。您可以使用组分配权限。例如，您可以为销售、管理和支持创建不同的组，并向每组中的用户授予对其工作所需数据的适当访问权限。您可以在组级别授予或撤消权限，而这些更改将应用于组的所有成员，但超级用户除外。

要查看所有用户组，请查询 PG\$1GROUP 系统目录表：

```
select * from pg_group;
```

例如，要按组列出所有数据库用户，请运行以下 SQL。

```
SELECT u.usesysid
,g.groname
,u.usename
FROM pg_user u
LEFT JOIN pg_group g ON u.usesysid = ANY (g.grolist)
```

# 创建、修改和删除组
<a name="r_Groups-creating-altering-and-deleting-groups"></a>

只有超级用户才能创建、修改或删除组。

您可以执行以下操作：
+ 要创建组，请使用 [CREATE GROUP](r_CREATE_GROUP.md) 命令。
+ 要在现有组中添加或删除用户，请使用 [ALTER GROUP](r_ALTER_GROUP.md) 命令。
+ 要删除组，请使用 [DROP GROUP](r_DROP_GROUP.md) 命令。此命令仅删除组，而不删除组成员用户。

# 控制用户和组访问的示例
<a name="t_user_group_examples"></a>

此示例创建了用户组和用户，然后向其授予对连接到 Web 应用程序客户端的 Amazon Redshift 数据库的各种权限。此示例假设三组用户：Web 应用程序的常规用户、Web 应用程序的超级用户和 Web 开发人员。

有关如何从组中移除用户的信息，请参阅 [ALTER GROUP](r_ALTER_GROUP.md)。

1. 创建将在其中分配用户的组。下面一组命令创建三个不同的用户组：

   ```
   create group webappusers;
   
   create group webpowerusers;
   
   create group webdevusers;
   ```

1.  创建多个具有不同权限的数据库用户并将其添加到组。

   1.  创建两个用户并将其添加到 WEBAPPUSERS 组：

      ```
      create user webappuser1 password 'webAppuser1pass'
      in group webappusers;
      
      create user webappuser2 password 'webAppuser2pass'
      in group webappusers;
      ```

   1.  创建 Web 开发人员用户并将其添加到 WEBDEVUSERS 组：

      ```
      create user webdevuser1 password 'webDevuser2pass'
      in group webdevusers;
      ```

   1.  创建超级用户。此用户将具有管理权限，可以创建其他用户：

      ```
      create user webappadmin  password 'webAppadminpass1'
      createuser;
      ```

1.  创建要与 Web 应用程序所使用的数据库表关联的 schema，并授予对此 schema 的各种用户组访问权限：

   1.  创建 WEBAPP schema：

      ```
      create schema webapp;
      ```

   1.  向 WEBAPPUSERS 组授予 USAGE 权限：

      ```
      grant usage on schema webapp to group webappusers;
      ```

   1.  向 WEBPOWERUSERS 组授予 USAGE 权限：

      ```
      grant usage on schema webapp to group webpowerusers;
      ```

   1.  向 WEBDEVUSERS 组授予 ALL 权限：

      ```
      grant all on schema webapp to group webdevusers;
      ```

   基本用户和组现已设置。您现在可以修改用户和组。

1.  例如，以下命令会修改 WEBAPPUSER1 的 search\$1path 参数。

   ```
   alter user webappuser1 set search_path to webapp, public;
   ```

   SEARCH\$1PATH 指定在通过未指定 schema 的简单名称引用数据库对象（例如，表和函数）时，对象的 schema 搜索顺序。

1.  您还可以在创建组之后向组中添加用户，例如，将 WEBAPPUSER2 添加到 WEBPOWERUSERS 组：

   ```
   alter group webpowerusers add user webappuser2;
   ```

# Schemas
<a name="r_Schemas_and_tables"></a>

数据库包含一个或多个命名 schemas。数据库中的每个 schema 包含表和其他类型的命名对象。默认情况下，数据库具有单个 schema（名为 PUBLIC）。您可以通过 schemas 使用公用名称分组数据库对象。架构类似于文件系统目录，但架构不能嵌套。

相同的数据库对象名称可以用在同一数据库的不同 schemas 中，没有冲突。例如，MY\$1SCHEMA 和 YOUR\$1SCHEMA 都可以包含名为 MYTABLE 的表。具有所需权限的用户可以访问数据库的多个 Schemas 中的对象。

默认情况下，在数据库搜索路径中的第一个 schema 内创建对象。有关信息，请参阅此部分后面的[搜索路径](#c_Search_path)。

Schema 可帮助解决多用户环境中的组织和并发问题，方式如下：
+ 让多名开发人员使用同一数据库且互不干扰。
+ 将数据库对象组织到逻辑组以使其更易于管理。
+ 使应用程序能够将其对象放入到单独的 schemas 中，以使其对象名称不与其他应用程序所使用的对象名称冲突。

## 搜索路径
<a name="c_Search_path"></a>

搜索路径定义在 search\$1path 参数中，采用逗号分隔的 schema 名称列表形式。搜索路径指定在通过不包含 schemas 限定词的简单名称引用对象（例如，表或函数）时，搜索 schema 的顺序。

如果创建了对象而未指定目标 schema，则将该对象添加到搜索路径中列出的第一个 schema。当不同 schemas 中存在同名的对象时，未指定 schema 的对象名称将引用搜索路径中包含具有该名称的对象的第一个 schema。

要更改当前会话的默认 schema，请使用 [SET](r_SET.md) 命令。

有关更多信息，请参阅“配置引用”中的 [search\$1path](r_search_path.md) 描述。

# 创建、修改和删除架构
<a name="r_Schemas_and_tables-creating-altering-and-deleting-schemas"></a>

任何用户都可以创建 schema 和修改或删除其拥有的 schema。

您可以执行以下操作：
+ 要创建 schema，请使用 [CREATE SCHEMA](r_CREATE_SCHEMA.md) 命令。
+ 要更改 schema 所有者，请使用 [ALTER SCHEMA](r_ALTER_SCHEMA.md) 命令。
+ 要删除 schema 及其对象，请使用 [DROP SCHEMA](r_DROP_SCHEMA.md) 命令。
+ 要在 schema 内创建表，请以 *schema\$1name.table\$1name* 格式创建表。

要查看所有 Schemas 的列表，请查询 PG\$1NAMESPACE 系统目录表：

```
select * from pg_namespace;
```

要查看属于某 schema 的表列表，请查询 PG\$1TABLE\$1DEF 系统目录表。例如，以下查询会返回 PG\$1CATALOG schema 中的表列表。

```
select distinct(tablename) from pg_table_def
where schemaname = 'pg_catalog';
```

# 基于 Schema 的权限
<a name="r_Schemas_and_tables-schema-based-privileges"></a>

 基于 Schema 的权限由 Schema 的拥有者确定：
+ 默认情况下，所有用户都对数据库的 PUBLIC Schema 具有 CREATE 和 USAGE 权限。要禁止用户在数据库的 PUBLIC Schema 中创建对象，请使用 [REVOKE](r_REVOKE.md) 命令删除该权限。
+ 除非对象拥有者向用户授予了 USAGE 权限，否则用户无法访问其不拥有的 Schemas 中的任何对象。
+ 如果已向用户授予对其他用户所创建的 Schema 的 CREATE 权限，则这些用户可以在该 Schema 中创建对象。

# 基于角色的访问控制 (RBAC)
<a name="t_Roles"></a>

借助基于角色的访问控制 (RBAC) 在 Amazon Redshift 中管理数据库权限，可以简化 Amazon Redshift 中的安全权限管理。您可以通过总体或精细控制用户可以执行的操作来保护对敏感数据的访问。您还可以控制用户对通常仅限超级用户执行的任务的访问权限。通过将不同的权限分配给不同的角色，然后将角色分配给不同的用户，您可以更精细地控制用户访问权限。

用户获得分配的角色后，将只能执行由所分配角色指定的被授权执行的任务。例如，假设用户所分配的角色具有 CREATE TABLE 和 DROP TABLE 权限，则仅有权执行这些任务。您可以通过向不同用户授予不同级别的安全权限来访问其工作所需的数据，从而控制用户访问权限。

RBAC 根据用户的角色要求对用户执行最低权限原则，而不论所涉及的是何种对象类型。授予和撤消权限在角色级别执行，无需更新单个数据库对象的权限。

使用 RBAC，您可以创建具有相应权限的角色，以运行通常需要超级用户权限的命令。只要用户通过包含这些权限的角色获得授权，即可以运行这些命令。同样，您还可以创建角色来限制对某些命令的访问权限，并将角色分配给超级用户或已获得该角色授权的用户。

要了解 Amazon Redshift RBAC 的工作原理，请观看以下视频。

[![AWS Videos](http://img.youtube.com/vi/https://www.youtube.com/embed/IhHQ7mZ-tp4/0.jpg)](http://www.youtube.com/watch?v=https://www.youtube.com/embed/IhHQ7mZ-tp4)


# 角色层次结构
<a name="t_role_hierarchy"></a>

*角色*是可以分配给用户或其他角色的权限集合。您可以为角色分配系统或数据库权限。用户从所分配的角色继承权限。

在 RBAC 中，用户可以拥有嵌套角色。您可以向用户和角色授予角色。将一个角色授予某个用户时，您将向该用户授予此角色包括的所有权限。将角色 r1 授予某个用户时，您向该用户授予了来自 r1 的权限。用户现在拥有来自 r1 的权限以及他们已经拥有的任何现有权限。

将角色 (r1) 授予另一个角色 (r2) 时，您向 r2 授予了来自 r1 的权限。此外，在将 r2 授予另一个角色 (r3) 时，r3 的权限是来自 r1 和 r2 的权限的组合。由于角色层次结构的原因，r2 继承了 r1 的权限。Amazon Redshift 通过执行每个角色授权来传播权限。通过将 r1 授予 r2，然后将 r2 授予 r3，从而将这三个角色的所有权限授予了 r3。因此，将 r3 授予某个用户后，该用户将拥有这三个角色的所有权限。

Amazon Redshift 不允许创建角色循环授权。如果将嵌套角色分配回角色层次结构中的上级角色，将会出现角色循环授权，例如将 r3 分配回 r1。有关如何创建角色以及管理角色分配的更多信息，请参阅[管理 RBAC 中的角色](r_roles-managing.md)。

# 角色分配
<a name="t_role_assignment"></a>

超级用户和拥有 CREATE ROLE 权限的普通用户都可以使用 CREATE ROLE 语句创建角色。超级用户和角色管理员可以使用 GRANT ROLE 语句向其他人授予角色。他们可以使用 REVOKE ROLE 语句撤消授予其他人的角色，也可以使用 DROP ROLE 语句来删除角色。管理员角色包括所有者角色和已授予 ADMIN OPTION 权限角色的用户角色。

只有超级用户或角色管理员才能授予和撤销角色。您可以向一个或多个角色或用户授予或撤消一个或多个角色。使用 GRANT ROLE 语句和 WITH ADMIN OPTION 选项，可以向所有被授予者提供所有授予的角色的管理选项。

Amazon Redshift 支持不同的角色分配组合，例如授予多个角色或有多个被授予者。WITH ADMIN OPTION 选项仅适用于用户，而不适用于角色。同样，在 REVOKE ROLE 语句中使用 WITH ADMIN OPTION 选项将会删除相关角色并撤销被授予者的管理授权。使用 ADMIN OPTION 选项时，将仅撤销该角色的管理授权。

下面的示例将撤销授予 `user2` 的 `sample_role2` 角色的管理授权。

```
REVOKE ADMIN OPTION FOR sample_role2 FROM user2;
```

有关如何创建角色以及管理角色分配的更多信息，请参阅[管理 RBAC 中的角色](r_roles-managing.md)。

# Amazon Redshift 系统定义的角色
<a name="r_roles-default"></a>

Amazon Redshift 提供了使用特定权限定义的一些系统定义角色。系统特定角色以 `sys:` 前缀开头。仅具有适当访问权限的用户才能更改系统定义角色或创建自定义的系统定义角色。您将 `sys:` 前缀用于自定义的系统定义角色。

下表总结了各种角色及其权限。

[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/redshift/latest/dg/r_roles-default.html)

## 用于数据共享的系统定义角色和用户
<a name="r_roles-datashare"></a>

 Amazon Redshift 创建的角色和用户供内部使用，这些角色和用户对应于数据共享和数据共享使用者。每个内部角色名称和用户名都有保留的命名空间前缀 `ds:`。它们具有以下格式：

[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/redshift/latest/dg/r_roles-default.html)

 为每个数据共享创建一个数据共享角色。该角色拥有当前授予的对于数据共享的所有权限。将为数据共享的每个使用者创建一个数据共享用户。它被授予对单个数据共享角色的权限。添加到多个数据共享的使用者将为每个数据共享创建一个数据共享用户。

这些用户和角色是数据共享正常运行所必需的。不能修改或删除它们，也不能访问它们或将它们用于客户运行的任何任务。您可以放心地忽略它们。有关数据共享的更多信息，请参阅[在 Amazon Redshift 中跨集群共享数据](https://docs.aws.amazon.com/redshift/latest/dg/datashare-overview.html)。

**注意**  
您不能使用 `ds:` 前缀来创建用户定义的角色或用户。

# RBAC 的系统权限
<a name="r_roles-system-privileges"></a>

以下是可向角色授予或撤消的系统权限列表。

[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/redshift/latest/dg/r_roles-system-privileges.html)

# 数据库对象权限
<a name="r_roles-database-privileges"></a>

除了系统权限外，Amazon Redshift 还包括定义访问选项的数据库对象权限。这些权限包括各种选项，例如读取表和视图中的数据、写入数据、创建表和删除表等。有关更多信息，请参阅 [GRANT](r_GRANT.md)。

与系统权限的使用类似，您可以通过使用 RBAC 将数据库对象权限分配给角色。然后，您可以为用户分配角色、向用户授予系统权限以及向用户授予数据库权限。

# 适用于 RBAC 的 ALTER DEFAULT PRIVILEGES
<a name="r_roles-alter-default-privileges"></a>

使用 ALTER DEFAULT PRIVILEGES 来定义默认访问权限集，这些权限将应用于指定的用户未来创建的对象。默认情况下，用户只能更改他们自己的原定设置访问权限。使用 RBAC，您可以设置角色的默认访问权限。有关更多信息，请参阅 [ALTER DEFAULT PRIVILEGES](r_ALTER_DEFAULT_PRIVILEGES.md) 命令。

与系统权限类似，您可以通过 RBAC 将数据库对象权限分配给角色。然后，您可以为用户分配角色、向用户授予系统权限和/或数据库权限。

# RBAC 中的角色使用注意事项
<a name="r_role-usage-notes"></a>

在使用 RBAC 角色时，请注意以下事项：
+ Amazon Redshift 不允许角色循环授权。您不能将 r1 授予 r2，然后将 r2 授予 r1。
+ RBAC 支持原生 Amazon Redshift 对象和 Amazon Redshift Spectrum 表。
+ Amazon Redshift 管理员可以通过将集群升级到最新的维护补丁，从而开始使用 RBAC。
+ 只有超级用户和具有 CREATE ROLE 系统权限的用户才能创建角色。
+ 只有超级用户和角色管理员才能修改或删除角色。
+ 角色名称不能与用户名称相同。
+ 角色名称不能包含无效字符，例如“:/\$1n”。
+ 角色名称不能是保留字，例如 PUBLIC。
+ 角色名称不能以默认角色的保留前缀 `sys:` 开头。
+ 将具有 RESTRICT 参数的角色授予其他角色时，不能删除该角色。原定设置为 RESTRICT。当您尝试删除继承了其他角色的角色时，Amazon Redshift 会返回错误。
+ 无角色的管理员权限的用户不能授予或撤销角色。
+ 系统表和视图不完全支持 RBAC。系统表和视图的 RBAC 权限不会因升级、降级或调整大小而持续存在。我们建议使用 [Amazon Redshift 系统定义的角色用于数据共享的系统定义角色和用户](r_roles-default.md) 来管理系统表和视图权限。有关系统表的更多信息，请转至 [系统表和视图参考](cm_chap_system-tables.md)。

# 管理 RBAC 中的角色
<a name="r_roles-managing"></a>

要执行以下操作，请使用以下命令：
+ 要创建角色，请使用 [CREATE ROLE](r_CREATE_ROLE.md) 命令。
+ 要重命名角色或更改角色的拥有者，请使用 [ALTER ROLE](r_ALTER_ROLE.md) 命令。
+ 要删除角色，请使用 [DROP ROLE](r_DROP_ROLE.md) 命令。
+ 要向用户授予角色，请使用 [GRANT](r_GRANT.md) 命令。
+ 要撤消用户的角色，请使用 [REVOKE](r_REVOKE.md) 命令。
+ 要向角色授予系统权限，请使用 [GRANT](r_GRANT.md) 命令。
+ 要撤销角色的系统权限，请使用 [REVOKE](r_REVOKE.md) 命令。

要查看集群或工作组中的角色列表，请参阅[SVV\$1ROLES](r_SVV_ROLES.md)。

# 教程：使用 RBAC 创建角色和进行查询
<a name="r_tutorial-RBAC"></a>

使用 RBAC，您可以创建具有相应权限的角色，以运行通常需要超级用户权限的命令。只要用户通过包含这些权限的角色获得授权，即可以运行这些命令。

在本教程中，您将使用基于角色的访问控制（RBAC）来管理所创建数据库中的权限。然后，您将连接到数据库并从两个不同的角色查询数据库，以测试 RBAC 的功能。

您创建并用于查询数据库的两个角色是 `sales_ro` 和 `sales_rw`。您将创建 `sales_ro` 角色并以具有 `sales_ro` 角色的用户身份查询数据。`sales_ro` 用户只能使用 SELECT 命令，而不能使用 UPDATE 命令。然后，您将创建 `sales_rw` 角色并以具有 `sales_rw` 角色的用户身份查询数据。`sales_rw` 用户可以使用 SELECT 命令和 UPDATE 命令。

此外，您还可以创建角色来限制对某些命令的访问权限，并将角色分配给超级用户或普通用户。

**任务**：
+ [先决条件](#tutorial-rbac-prereqs)
+ [步骤 1：创建管理员用户](#tutorial-rbac-step1)
+ [步骤 2：设置架构](#tutorial-rbac-step2)
+ [步骤 3：创建只读用户](#tutorial-rbac-step3)
+ [步骤 4：以只读用户身份查询数据](#tutorial-rbac-step4)
+ [步骤 5：创建读写用户](#tutorial-rbac-step5)
+ [步骤 6：以继承了只读角色的用户身份查询数据](#tutorial-rbac-step6)
+ [步骤 7：向读写角色授予更新和插入权限](#tutorial-rbac-step7)
+ [步骤 8：以读写用户身份查询数据](#tutorial-rbac-step8)
+ [步骤 9：以管理员用户身份分析和清理数据库中的表](#tutorial-rbac-step9)
+ [步骤 10：以读写用户身份截断表](#tutorial-rbac-step10)
+ [RBAC 的系统功能（可选）](#tutorial-rbac-system-functions)
+ [RBAC 的系统视图（可选）](#tutorial-rbac-system-views)
+ [在 RBAC 中使用行级别安全性（可选）](#tutorial-rbac-rls)

## 先决条件
<a name="tutorial-rbac-prereqs"></a>
+ 创建装有 TICKIT 示例数据库的 Amazon Redshift 集群或 Serverless 工作组。要创建 Serverless 工作组，请参阅 [Redshift Serverless 数据仓库入门](https://docs.aws.amazon.com/redshift/latest/gsg/new-user-serverless.html)。要创建集群，请参阅[创建示例 Amazon Redshift 集群](https://docs.aws.amazon.com/redshift/latest/gsg/rs-gsg-launch-sample-cluster.html)。有关 TICKIT 示例数据库的更多信息，请参阅[示例数据库](c_sampledb.md)。
+ 可以访问具有超级用户或角色管理员权限的用户。只有超级用户或角色管理员才能授予或撤销角色。有关 RBAC 所需权限的更多信息，请参阅[RBAC 的系统权限](r_roles-system-privileges.md)。
+ 查看[RBAC 中的角色使用注意事项](r_role-usage-notes.md)。

## 步骤 1：创建管理员用户
<a name="tutorial-rbac-step1"></a>

要为本教程进行设置，请在此步骤中创建数据库管理员角色并将其附加到数据库管理员用户。必须将数据库管理员创建为超级用户或角色管理员。

在 Amazon Redshift [查询编辑器 v2](https://docs.aws.amazon.com/redshift/latest/mgmt/query-editor-v2-using.html) 中运行所有查询。

1. 要创建管理员角色 db\$1admin，请使用以下示例。

   ```
   CREATE ROLE db_admin;
   ```

1. 要创建名为 dbadmin 的数据库用户，请使用以下示例。

   ```
   CREATE USER dbadmin PASSWORD 'Test12345';
   ```

1. 要将名为 sys:dba 的系统定义角色授予 db\$1admin 角色，请使用以下示例。当被授予 sys:dba 角色后，dbadmin 用户就可以创建架构和表。有关更多信息，请参阅 [Amazon Redshift 系统定义的角色用于数据共享的系统定义角色和用户](r_roles-default.md)。

## 步骤 2：设置架构
<a name="tutorial-rbac-step2"></a>

在此步骤中，您将以数据库管理员的身份连接到您的数据库。然后，您将创建两个架构并向它们添加数据。

1. 使用查询编辑器 v2，以 dbadmin 用户身份连接到 dev 数据库。有关连接到数据库的更多信息，请参阅[使用查询编辑器 v2](https://docs.aws.amazon.com/redshift/latest/mgmt/query-editor-v2-using.html)。

1. 要创建销售和营销数据库架构，请使用以下示例。

   ```
   CREATE SCHEMA sales;
   CREATE SCHEMA marketing;
   ```

1. 要在销售架构的表中创建和插入值，请使用以下示例。

   ```
   CREATE TABLE sales.cat(
   catid smallint,
   catgroup varchar(10),
   catname varchar(10),
   catdesc varchar(50)
   );
   INSERT INTO sales.cat(SELECT * FROM category);
   
   CREATE TABLE sales.dates(
   dateid smallint,
   caldate date,
   day char(3),
   week smallint,
   month char(5),
   qtr char(5),
   year smallint,
   holiday boolean
   );
   INSERT INTO sales.dates(SELECT * FROM date);
   
   CREATE TABLE sales.events(
   eventid integer,
   venueid smallint,
   catid smallint,
   dateid smallint,
   eventname varchar(200),
   starttime timestamp
   );
   INSERT INTO sales.events(SELECT * FROM event);
   
    CREATE TABLE sales.sale(
   salesid integer,
   listid integer,
   sellerid integer,
   buyerid integer,
   eventid integer,
   dateid smallint,
   qtysold smallint,
   pricepaid decimal(8,2),
   commission decimal(8,2),
   saletime timestamp
   );
   INSERT INTO sales.sale(SELECT * FROM sales);
   ```

1. 要在营销架构的表中创建和插入值，请使用以下示例。

   ```
   CREATE TABLE marketing.cat(
   catid smallint,
   catgroup varchar(10),
   catname varchar(10),
   catdesc varchar(50)
   );
   INSERT INTO marketing.cat(SELECT * FROM category);
   
   CREATE TABLE marketing.dates(
   dateid smallint,
   caldate date,
   day char(3),
   week smallint,
   month char(5),
   qtr char(5),
   year smallint,
   holiday boolean
   );
   INSERT INTO marketing.dates(SELECT * FROM date);
   
   CREATE TABLE marketing.events(
   eventid integer,
   venueid smallint,
   catid smallint,
   dateid smallint,
   eventname varchar(200),
   starttime timestamp
   );
   INSERT INTO marketing.events(SELECT * FROM event);
   
   CREATE TABLE marketing.sale(
   marketingid integer,
   listid integer,
   sellerid integer,
   buyerid integer,
   eventid integer,
   dateid smallint,
   qtysold smallint,
   pricepaid decimal(8,2),
   commission decimal(8,2),
   saletime timestamp
   );
   INSERT INTO marketing.sale(SELECT * FROM marketing);
   ```

## 步骤 3：创建只读用户
<a name="tutorial-rbac-step3"></a>

在此步骤中，您将创建一个只读角色，并为该只读角色创建一个 salesanalyst 用户。销售分析师只需对销售架构中的表进行只读访问，即可完成分配给他们的任务，即查找产生最大佣金的事件。

1. 以 dbadmin 用户身份连接到数据库。

1. 要创建 sales\$1ro 角色，请使用以下示例。

   ```
   CREATE ROLE sales_ro;
   ```

1. 要创建 salesanalyst 用户，请使用以下示例。

   ```
   CREATE USER salesanalyst PASSWORD 'Test12345';
   ```

1. 要授予 sales\$1ro 角色使用权限并选择对销售架构对象的访问权限，请使用以下示例。

   ```
   GRANT USAGE ON SCHEMA sales TO ROLE sales_ro;
   GRANT SELECT ON ALL TABLES IN SCHEMA sales TO ROLE sales_ro;
   ```

1. 要向 salesanalyst 用户授予 sales\$1ro 角色，请使用以下示例。

   ```
   GRANT ROLE sales_ro TO salesanalyst;
   ```

## 步骤 4：以只读用户身份查询数据
<a name="tutorial-rbac-step4"></a>

在此步骤中，salesanalyst 用户从销售架构中查询数据。然后，salesanalyst 用户尝试更新一个表并读取营销架构中的表。

1. 以 salesanalyst 用户身份连接到数据库。

1. 要查找佣金最高的 10 笔销售，请使用以下示例。

   ```
   SET SEARCH_PATH TO sales;
   SELECT DISTINCT events.dateid, sale.commission, cat.catname
   FROM sale, events, dates, cat   
   WHERE events.dateid=dates.dateid AND events.dateid=sale.dateid AND events.catid = cat.catid
   ORDER BY 2 DESC LIMIT 10;
                  
   +--------+------------+----------+
   | dateid | commission | catname  |
   +--------+------------+----------+
   |   1880 |     1893.6 | Pop      |
   |   1880 |     1893.6 | Opera    |
   |   1880 |     1893.6 | Plays    |
   |   1880 |     1893.6 | Musicals |
   |   1861 |       1500 | Plays    |
   |   2003 |       1500 | Pop      |
   |   1861 |       1500 | Opera    |
   |   2003 |       1500 | Plays    |
   |   1861 |       1500 | Musicals |
   |   1861 |       1500 | Pop      |
   +--------+------------+----------+
   ```

1. 要从销售架构的事件表中选择 10 个事件，请使用以下示例。

   ```
   SELECT * FROM sales.events LIMIT 10;
                  
   +---------+---------+-------+--------+--------------------+---------------------+
   | eventid | venueid | catid | dateid |     eventname      |      starttime      |
   +---------+---------+-------+--------+--------------------+---------------------+
   |    4836 |      73 |     9 |   1871 | Soulfest           | 2008-02-14 19:30:00 |
   |    5739 |      41 |     9 |   1871 | Fab Faux           | 2008-02-14 19:30:00 |
   |     627 |     229 |     6 |   1872 | High Society       | 2008-02-15 14:00:00 |
   |    2563 |     246 |     7 |   1872 | Hamlet             | 2008-02-15 20:00:00 |
   |    7703 |      78 |     9 |   1872 | Feist              | 2008-02-15 14:00:00 |
   |    7903 |      90 |     9 |   1872 | Little Big Town    | 2008-02-15 19:30:00 |
   |    7925 |     101 |     9 |   1872 | Spoon              | 2008-02-15 19:00:00 |
   |    8113 |      17 |     9 |   1872 | Santana            | 2008-02-15 15:00:00 |
   |     463 |     303 |     8 |   1873 | Tristan und Isolde | 2008-02-16 19:00:00 |
   |     613 |     236 |     6 |   1873 | Pal Joey           | 2008-02-16 15:00:00 |
   +---------+---------+-------+--------+--------------------+---------------------+
   ```

1. 要尝试更新 eventid 1 的事件名称，请运行以下示例。此示例将导致权限被拒绝错误，因为 salesanalyst 用户仅对销售架构中的事件表具有 SELECT 权限。要更新事件表，必须向 sales\$1ro 角色授予 UPDATE 权限。有关如何授予权限以更新表的更多信息，请参阅 [GRANT](r_GRANT.md) 的 UPDATE 参数。有关 UPDATE 命令的更多信息，请参阅[UPDATE](r_UPDATE.md)。

   ```
   UPDATE sales.events
   SET eventname = 'Comment event'
   WHERE eventid = 1;
                     
   ERROR: permission denied for relation events
   ```

1. 要尝试从营销架构的事件表中选择所有事件，请使用以下示例。此示例将导致权限被拒绝错误，因为 salesanalyst 用户仅对销售架构中的事件表具有 SELECT 权限。要从营销架构的事件表中选择数据，必须授予 sales\$1ro 角色对营销架构中事件表的 SELECT 权限。

   ```
   SELECT * FROM marketing.events;
                  
                  ERROR: permission denied for schema marketing
   ```

## 步骤 5：创建读写用户
<a name="tutorial-rbac-step5"></a>

在此步骤中，负责为销售架构中的数据处理构建提取、转换、加载（ETL）管道的销售工程师将获得只读访问权限，但稍后将获得执行任务的读写权限。

1. 以 dbadmin 用户身份连接到数据库。

1. 要在销售架构中创建 sales\$1rw 角色，请使用以下示例。

   ```
   CREATE ROLE sales_rw;
   ```

1. 要创建 salesengineer 用户，请使用以下示例。

   ```
   CREATE USER salesengineer PASSWORD 'Test12345';
   ```

1. 要授予 sales\$1rw 角色使用权限，并通过向其分配 sales\$1ro 角色来选择对销售架构对象的访问权限，请使用以下示例。有关 Amazon Redshift 中角色如何继承权限的更多信息，请参阅[角色层次结构](t_role_hierarchy.md)。

   ```
   GRANT ROLE sales_ro TO ROLE sales_rw;
   ```

1. 要将 sales\$1rw 角色分配给 salesengineer 用户，请使用以下示例。

   ```
   GRANT ROLE sales_rw TO salesengineer;
   ```

## 步骤 6：以继承了只读角色的用户身份查询数据
<a name="tutorial-rbac-step6"></a>

在此步骤中，salesengineer 用户在被授予读取权限之前尝试更新事件表。

1. 以 salesengineer 用户身份连接到数据库。

1. salesengineer 用户可以从销售架构的事件表中成功读取数据。要从销售架构的事件表中选择 eventid 为 1 的事件，请使用以下示例。

   ```
   SELECT * FROM sales.events where eventid=1;
                     
   +---------+---------+-------+--------+-----------------+---------------------+
   | eventid | venueid | catid | dateid |    eventname    |      starttime      |
   +---------+---------+-------+--------+-----------------+---------------------+
   |       1 |     305 |     8 |   1851 | Gotterdammerung | 2008-01-25 14:30:00 |
   +---------+---------+-------+--------+-----------------+---------------------+
   ```

1. 要尝试从营销架构的事件表中选择所有事件，请使用以下示例。salesengineer 用户对营销架构中的表没有权限，因此，该查询将导致权限被拒绝错误。要从营销架构的事件表中选择数据，必须授予 sales\$1rw 角色对营销架构中事件表的 SELECT 权限。

   ```
   SELECT * FROM marketing.events;
   
   ERROR: permission denied for schema marketing
   ```

1. 要尝试更新 eventid 1 的事件名称，请运行以下示例。此示例将导致权限被拒绝错误，因为 salesengineer 用户仅对销售架构中的事件表具有 SELECT 权限。要更新事件表，必须向 sales\$1rw 角色授予 UPDATE 权限。

   ```
   UPDATE sales.events
   SET eventname = 'Comment event'
   WHERE eventid = 1;
   
   ERROR: permission denied for relation events
   ```

## 步骤 7：向读写角色授予更新和插入权限
<a name="tutorial-rbac-step7"></a>

在此步骤中，您向 sales\$1rw 角色授予 UPDATE 和 INSERT 权限。

1. 以 dbadmin 用户身份连接到数据库。

1. 要向 sales\$1rw 角色授予 UPDATE、INSERT 和 DELETE 权限，请使用以下示例。

   ```
   GRANT UPDATE, INSERT, ON ALL TABLES IN SCHEMA sales TO role sales_rw;
   ```

## 步骤 8：以读写用户身份查询数据
<a name="tutorial-rbac-step8"></a>

在此步骤中，salesengineer 在其角色被授予 INSERT 和 UPDATE 权限后成功更新表。接下来，salesengineer 尝试分析和清理事件表，但未能成功。

1. 以 salesengineer 用户身份连接到数据库。

1. 要更新 eventid 1 的事件名称，请运行以下示例。

   ```
   UPDATE sales.events
   SET eventname = 'Comment event'
   WHERE eventid = 1;
   ```

1. 要查看在上一个查询中进行的更改，请使用以下示例从销售架构的事件表中选择 eventid 为 1 的事件。

   ```
   SELECT * FROM sales.events WHERE eventid=1;
   
   +---------+---------+-------+--------+---------------+---------------------+
   | eventid | venueid | catid | dateid |   eventname   |      starttime      |
   +---------+---------+-------+--------+---------------+---------------------+
   |       1 |     305 |     8 |   1851 | Comment event | 2008-01-25 14:30:00 |
   +---------+---------+-------+--------+---------------+---------------------+
   ```

1. 要分析销售架构中更新的事件表，请使用以下示例。此示例将导致权限被拒绝错误，因为 salesengineer 用户没有必要的权限，也不是销售架构中事件表的所有者。要分析事件表，必须使用 GRANT 命令向 sales\$1rw 角色授予 ANALYZE 权限。有关 ANALYZE 命令的更多信息，请参阅 [ANALYZE](r_ANALYZE.md)。

   ```
   ANALYZE sales.events;
                  
                  ERROR: skipping "events" --- only table or database owner can analyze
   ```

1. 要清理更新的事件表，请使用以下示例。此示例将导致权限被拒绝错误，因为 salesengineer 用户没有必要的权限，也不是销售架构中事件表的所有者。要清理事件表，必须使用 GRANT 命令向 sales\$1rw 角色授予 VACUUM 权限。有关 VACUUM 命令的更多信息，请参阅 [VACUUM](r_VACUUM_command.md)。

   ```
   VACUUM sales.events;
                     
   ERROR: skipping "events" --- only table or database owner can vacuum it
   ```

## 步骤 9：以管理员用户身份分析和清理数据库中的表
<a name="tutorial-rbac-step9"></a>

在此步骤中，dbadmin 用户分析并清理所有表。用户对此数据库具有管理员权限，因此他们能够运行这些命令。

1. 以 dbadmin 用户身份连接到数据库。

1. 要分析销售架构中的事件表，请使用以下示例。

   ```
   ANALYZE sales.events;
   ```

1. 要清理销售架构中的事件表，请使用以下示例。

   ```
   VACUUM sales.events;
   ```

1. 要分析营销架构中的事件表，请使用以下示例。

   ```
   ANALYZE marketing.events;
   ```

1. 要清理营销架构中的事件表，请使用以下示例。

   ```
   VACUUM marketing.events;
   ```

## 步骤 10：以读写用户身份截断表
<a name="tutorial-rbac-step10"></a>

在此步骤中，salesengineer 用户尝试截断销售架构中的事件表，但只有在 dbadmin 用户授予 TRUNCATE 权限时才会成功。

1. 以 salesengineer 用户身份连接到数据库。

1. 要尝试删除销售架构中事件表的所有行，请使用以下示例。此示例将导致错误，因为 salesengineer 用户没有必要的权限，也不是销售架构中事件表的所有者。要截断事件表，必须使用 GRANT 命令向 sales\$1rw 角色授予 TRUNCATE 权限。有关 TRUNCATE 命令的更多信息，请参阅 [TRUNCATE](r_TRUNCATE.md)。

   ```
   TRUNCATE sales.events;
                  
   ERROR: must be owner of relation events
   ```

1. 以 dbadmin 用户身份连接到数据库。

1. 要向 sales\$1rw 角色授予截断表权限，请使用以下示例。

   ```
   GRANT TRUNCATE TABLE TO role sales_rw;
   ```

1. 使用查询编辑器 v2，以 salesengineer 用户身份连接到数据库。

1. 要读取销售架构事件表中的前 10 个事件，请使用以下示例。

   ```
   SELECT * FROM sales.events ORDER BY eventid LIMIT 10;
                  
   +---------+---------+-------+--------+-----------------------------+---------------------+
   | eventid | venueid | catid | dateid |          eventname          |      starttime      |
   +---------+---------+-------+--------+-----------------------------+---------------------+
   |       1 |     305 |     8 |   1851 | Comment event               | 2008-01-25 14:30:00 |
   |       2 |     306 |     8 |   2114 | Boris Godunov               | 2008-10-15 20:00:00 |
   |       3 |     302 |     8 |   1935 | Salome                      | 2008-04-19 14:30:00 |
   |       4 |     309 |     8 |   2090 | La Cenerentola (Cinderella) | 2008-09-21 14:30:00 |
   |       5 |     302 |     8 |   1982 | Il Trovatore                | 2008-06-05 19:00:00 |
   |       6 |     308 |     8 |   2109 | L Elisir d Amore            | 2008-10-10 19:30:00 |
   |       7 |     309 |     8 |   1891 | Doctor Atomic               | 2008-03-06 14:00:00 |
   |       8 |     302 |     8 |   1832 | The Magic Flute             | 2008-01-06 20:00:00 |
   |       9 |     308 |     8 |   2087 | The Fly                     | 2008-09-18 19:30:00 |
   |      10 |     305 |     8 |   2079 | Rigoletto                   | 2008-09-10 15:00:00 |
   +---------+---------+-------+--------+-----------------------------+---------------------+
   ```

1. 要截断销售架构中的事件表，请使用以下示例。

   ```
   TRUNCATE sales.events;
   ```

1. 要读取销售架构中更新的事件表中的数据，请使用以下示例。

   ```
   SELECT * FROM sales.events ORDER BY eventid LIMIT 10;
                  
   +---------+---------+-------+--------+-----------------------------+---------------------+
   | eventid | venueid | catid | dateid |          eventname          |      starttime      |
   +---------+---------+-------+--------+-----------------------------+---------------------+
   ```

### 为营销架构创建只读和读写角色（可选）
<a name="tutorial-rbac-create-marketing-schema"></a>

在此步骤中，您将为营销架构创建只读和读写角色。

1. 以 dbadmin 用户身份连接到数据库。

1. 要为营销架构创建只读和读写角色，请使用以下示例。

   ```
   CREATE ROLE marketing_ro;
   
   CREATE ROLE marketing_rw;
   
   GRANT USAGE ON SCHEMA marketing TO ROLE marketing_ro, ROLE marketing_rw;
   
   GRANT SELECT ON ALL TABLES IN SCHEMA marketing TO ROLE marketing_ro;
   
   GRANT ROLE marketing_ro TO ROLE marketing_rw;
   
   GRANT INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA marketing TO ROLE marketing_rw;
   
   CREATE USER marketinganalyst PASSWORD 'Test12345';
   
   CREATE USER marketingengineer PASSWORD 'Test12345';
   
   GRANT ROLE marketing_ro TO marketinganalyst;
   
   GRANT ROLE marketing_rw TO marketingengineer;
   ```

## RBAC 的系统功能（可选）
<a name="tutorial-rbac-system-functions"></a>

Amazon Redshift 有两个函数可提供有关用户成员资格和其他组或角色的角色成员资格的系统信息：role\$1is\$1member\$1of 和 user\$1is\$1member\$1of。这些函数可供超级用户和普通用户使用。超级用户可以查看所有角色成员资格。普通用户只能查看已被授予访问权限的角色的成员资格。

使用 role\$1is\$1member\$1of 函数

1. 以 salesengineer 用户身份连接到数据库。

1. 要查看 sales\$1rw 角色是否是 sales\$1ro 角色的成员，请使用以下示例。

   ```
   SELECT role_is_member_of('sales_rw', 'sales_ro');
                  
   +-------------------+
   | role_is_member_of |
   +-------------------+
   | true              |
   +-------------------+
   ```

1. 要查看 sales\$1ro 角色是否是 sales\$1rw 角色的成员，请使用以下示例。

   ```
   SELECT role_is_member_of('sales_ro', 'sales_rw');
                  
   +-------------------+
   | role_is_member_of |
   +-------------------+
   | false             |
   +-------------------+
   ```

使用 user\$1is\$1member\$1of 函数

1. 以 salesengineer 用户身份连接到数据库。

1. 以下示例尝试查看 salesanalyst 用户的用户成员资格。此查询会导致错误，因为 salesengineer 无权访问 salesanalyst。要成功运行此命令，请以 salesanalyst 用户身份连接到数据库并使用示例。

   ```
   SELECT user_is_member_of('salesanalyst', 'sales_ro');
                  
   ERROR
   ```

1. 以超级用户身份连接到数据库。

1. 以超级用户身份连接后，要查看 salesanalyst 用户的成员资格，请使用以下示例。

   ```
   SELECT user_is_member_of('salesanalyst', 'sales_ro');
                  
   +-------------------+
   | user_is_member_of |
   +-------------------+
   | true              |
   +-------------------+
   ```

1. 以 dbadmin 用户身份连接到数据库。

1. 要查看 salesengineer 用户的成员资格，请使用以下示例。

   ```
   SELECT user_is_member_of('salesengineer', 'sales_ro');
                  
   +-------------------+
   | user_is_member_of |
   +-------------------+
   | true              |
   +-------------------+
                  
   SELECT user_is_member_of('salesengineer', 'marketing_ro');
   
   +-------------------+
   | user_is_member_of |
   +-------------------+
   | false             |
   +-------------------+
                  
   SELECT user_is_member_of('marketinganalyst', 'sales_ro');
                  
   +-------------------+
   | user_is_member_of |
   +-------------------+
   | false             |
   +-------------------+
   ```

## RBAC 的系统视图（可选）
<a name="tutorial-rbac-system-views"></a>

要查看角色、用户角色分配、角色层次结构以及通过角色对数据库对象的权限，请使用 Amazon Redshift 的系统视图。超级用户和普通用户均可查看这些视图。超级用户可以查看所有角色详细信息。普通用户只能查看他们已被授予访问权限的角色的详细信息。

1. 要查看在集群中被显式授予了角色的用户列表，请使用以下示例。

   ```
   SELECT * FROM svv_user_grants;
   ```

1. 要查看在集群中被显式授予了角色的角色列表，请使用以下示例。

   ```
   SELECT * FROM svv_role_grants;
   ```

有关系统视图的完整列表，请参阅[SVV 元数据视图](svv_views.md)。

## 在 RBAC 中使用行级别安全性（可选）
<a name="tutorial-rbac-rls"></a>

要对敏感数据进行精细访问控制，请使用行级别安全性（RLS）。有关 RLS 的更多信息，请参阅 [行级别安全性](t_rls.md)。

在本节中，您将创建一个 RLS 策略，该策略仅允许 `salesengineer` 用户查看 `cat` 表中具有 Major League Baseball `catdesc` 值的行。然后，您以 `salesengineer` 用户身份查询数据库。

1. 以 `salesengineer` 用户身份连接到数据库。

1. 要查看 `cat` 表中的前 5 个条目，请使用以下示例。

   ```
   SELECT * 
   FROM sales.cat
   ORDER BY catid ASC
   LIMIT 5;
                     
   +-------+----------+---------+---------------------------------+
   | catid | catgroup | catname |             catdesc             |
   +-------+----------+---------+---------------------------------+
   |     1 | Sports   | MLB     | Major League Baseball           |
   |     2 | Sports   | NHL     | National Hockey League          |
   |     3 | Sports   | NFL     | National Football League        |
   |     4 | Sports   | NBA     | National Basketball Association |
   |     5 | Sports   | MLS     | Major League Soccer             |
   +-------+----------+---------+---------------------------------+
   ```

1. 以 `dbadmin` 用户身份连接到数据库。

1. 要为 `cat` 表中的 `catdesc` 列创建 RLS 策略，请使用以下示例。

   ```
   CREATE RLS POLICY policy_mlb_engineer
   WITH (catdesc VARCHAR(50)) 
   USING (catdesc = 'Major League Baseball');
   ```

1. 要将 RLS 策略附加到 `sales_rw` 角色，请使用以下示例。

   ```
   ATTACH RLS POLICY policy_mlb_engineer ON sales.cat TO ROLE sales_rw; 
   ```

1. 要更改表以打开 RLS，请使用以下示例。

   ```
   ALTER TABLE sales.cat ROW LEVEL SECURITY ON; 
   ```

1. 以 `salesengineer` 用户身份连接到数据库。

1. 要尝试查看 `cat` 表中的前 5 个条目，请使用以下示例。请注意，仅当 `catdesc` 列为 `Major League Baseball` 时，才会显示条目。

   ```
   SELECT * 
   FROM sales.cat
   ORDER BY catid ASC
   LIMIT 5;
                  
   +-------+----------+---------+-----------------------+
   | catid | catgroup | catname |        catdesc        |
   +-------+----------+---------+-----------------------+
   |     1 | Sports   | MLB     | Major League Baseball |
   +-------+----------+---------+-----------------------+
   ```

1. 以 `salesanalyst` 用户身份连接到数据库。

1. 要尝试查看 `cat` 表中的前 5 个条目，请使用以下示例。请注意，由于应用了默认的“全部拒绝”策略，因此不会显示任何条目。

   ```
   SELECT * 
   FROM sales.cat
   ORDER BY catid ASC
   LIMIT 5;
                  
   +-------+----------+---------+-----------------------+
   | catid | catgroup | catname |        catdesc        |
   +-------+----------+---------+-----------------------+
   ```

1. 以 `dbadmin` 用户身份连接到数据库。

1. 要向 `sales_ro` 角色授予 IGNORE RLS 权限，请使用以下示例。这将授予 `salesanalyst` 用户忽略 RLS 策略的权限，因为他们是 `sales_ro` 角色的成员。

   ```
   GRANT IGNORE RLS TO ROLE sales_ro; 
   ```

1. 以 `salesanalyst` 用户身份连接到数据库。

1. 要查看 `cat` 表中的前 5 个条目，请使用以下示例。

   ```
   SELECT * 
   FROM sales.cat
   ORDER BY catid ASC
   LIMIT 5;
                  
   +-------+----------+---------+---------------------------------+
   | catid | catgroup | catname |             catdesc             |
   +-------+----------+---------+---------------------------------+
   |     1 | Sports   | MLB     | Major League Baseball           |
   |     2 | Sports   | NHL     | National Hockey League          |
   |     3 | Sports   | NFL     | National Football League        |
   |     4 | Sports   | NBA     | National Basketball Association |
   |     5 | Sports   | MLS     | Major League Soccer             |
   +-------+----------+---------+---------------------------------+
   ```

1. 以 `dbadmin` 用户身份连接到数据库。

1. 要撤销 `sales_ro` 角色的 IGNORE RLS 权限，请使用以下示例。

   ```
   REVOKE IGNORE RLS FROM ROLE sales_ro;
   ```

1. 以 `salesanalyst` 用户身份连接到数据库。

1. 要尝试查看 `cat` 表中的前 5 个条目，请使用以下示例。请注意，由于应用了默认的“全部拒绝”策略，因此不会显示任何条目。

   ```
   SELECT * 
   FROM sales.cat
   ORDER BY catid ASC
   LIMIT 5;
                  
   +-------+----------+---------+-----------------------+
   | catid | catgroup | catname |        catdesc        |
   +-------+----------+---------+-----------------------+
   ```

1. 以 `dbadmin` 用户身份连接到数据库。

1. 要将 RLS 策略从 `cat` 表中分离，请使用以下示例。

   ```
   DETACH RLS POLICY policy_mlb_engineer ON cat FROM ROLE sales_rw;
   ```

1. 以 `salesanalyst` 用户身份连接到数据库。

1. 要尝试查看 `cat` 表中的前 5 个条目，请使用以下示例。请注意，由于应用了默认的“全部拒绝”策略，因此不会显示任何条目。

   ```
   SELECT * 
   FROM sales.cat
   ORDER BY catid ASC
   LIMIT 5;
                  
   +-------+----------+---------+---------------------------------+
   | catid | catgroup | catname |             catdesc             |
   +-------+----------+---------+---------------------------------+
   |     1 | Sports   | MLB     | Major League Baseball           |
   |     2 | Sports   | NHL     | National Hockey League          |
   |     3 | Sports   | NFL     | National Football League        |
   |     4 | Sports   | NBA     | National Basketball Association |
   |     5 | Sports   | MLS     | Major League Soccer             |
   +-------+----------+---------+---------------------------------+
   ```

1. 以 `dbadmin` 用户身份连接到数据库。

1. 要删除 RLS 策略，请使用以下示例。

   ```
   DROP RLS POLICY policy_mlb_engineer;
   ```

1. 要删除 RLS，请使用以下示例。

   ```
   ALTER TABLE cat ROW LEVEL SECURITY OFF;
   ```

## 相关主题
<a name="tutorial-rbac-related-topics"></a>

有关 RBAC 的更多信息，请参阅以下文档：
+ [角色层次结构](t_role_hierarchy.md)
+ [角色分配](t_role_assignment.md)
+ [数据库对象权限](r_roles-database-privileges.md)
+ [适用于 RBAC 的 ALTER DEFAULT PRIVILEGES](r_roles-alter-default-privileges.md)

# 行级别安全性
<a name="t_rls"></a>

使用 Amazon Redshift 中的行级别安全性 (RLS)，您可以对敏感数据进行精细访问控制。您可以根据在数据库对象级别定义的安全策略，来决定哪些用户或角色可以访问架构或表中数据的特定记录。除了列级别安全性（您可以向用户授予对列的子集的权限）之外，还可使用 RLS 策略进一步限制对可见列中特定行的访问。有关列级别安全性的更多信息，请参阅 [列级访问控制的使用说明](r_GRANT-usage-notes.md#r_GRANT-usage-notes-clp)。

在对表强制实施 RLS 策略时，您可以限制用户运行查询时返回的结果集。

在创建 RLS 策略时，您可以指定表达式，规定 Amazon Redshift 是否在查询中返回表中的任何现有行。通过创建 RLS 策略来限制访问，您不必在查询中添加或外部化其他条件。

在创建 RLS 策略时，我们建议您创建简单策略，并且避免在策略中使用复杂语句。在定义 RLS 策略时，不要在基于策略的策略定义中使用过多表联接。

当某个策略引用某个查找表时，Amazon Redshift 除了扫描该策略所在的表以外，还会扫描其他表。对于附加了 RLS 策略的用户和未附加任何策略的用户，同一查询之间将存在性能差异。

# 在 SQL 语句中使用 RLS 策略
<a name="t_rls_statements"></a>

在 SQL 语句中使用 RLS 策略时，Amazon Redshift 将应用以下规则：
+ 默认情况下，Amazon Redshift 会将 RLS 策略应用于 SELECT、UPDATE 和 DELETE 语句。
+ 对于 SELECT 和 UNLOAD，Amazon Redshift 将根据您定义的策略筛选行。
+ 对于 UPDATE，Amazon Redshift 将仅更新对您可见的行。如果策略限制了表中行的子集，则您将无法更新这些行。
+ 对于 DELETE，您只能删除对您可见的行。如果策略限制了表中行的子集，则您将无法删除这些行。对于 TRUNCATE，您仍然可以截断表。
+ 对于 CREATE TABLE LIKE，使用 LIKE 选项创建的表不会继承源表的权限设置。同样，目标表也不会继承源表的 RLS 策略。

# 为每个用户组合多个策略
<a name="t_rls_combine_policies"></a>

Amazon Redshift 中的 RLS 支持为每个用户和对象附加多个策略。当为一个用户定义了多个策略时，Amazon Redshift 会根据表的 RLS CONJUNCTION TYPE 设置，使用 AND 或 OR 语法应用所有策略。有关联接类型的更多信息，请参阅[ALTER TABLE](r_ALTER_TABLE.md)。

一个表上的多个策略可以与您关联。将多个策略直接附加到您，或是您属于多个角色，并且这些角色附加了不同策略。

当多个策略应限制给定关系中的行访问权限时，可以将该关系的 RLS CONJUNCTION TYPE 设置为 AND。考虑以下示例。Alice 只能看到策略指定的“catname”为 NBA 的体育赛事。

```
-- Create an analyst role and grant it to a user named Alice.
CREATE ROLE analyst;
CREATE USER alice WITH PASSWORD 'Name_is_alice_1';
GRANT ROLE analyst TO alice;

-- Create an RLS policy that only lets the user see sports.
CREATE RLS POLICY policy_sports
WITH (catgroup VARCHAR(10))
USING (catgroup = 'Sports');

-- Create an RLS policy that only lets the user see NBA.
CREATE RLS POLICY policy_nba
WITH (catname VARCHAR(10))
USING (catname = 'NBA');

-- Attach both to the analyst role.
ATTACH RLS POLICY policy_sports ON category TO ROLE analyst;
ATTACH RLS POLICY policy_nba ON category TO ROLE analyst;

-- Activate RLS on the category table with AND CONJUNCTION TYPE. 
ALTER TABLE category ROW LEVEL SECURITY ON CONJUNCTION TYPE AND;

-- Change session to Alice.
SET SESSION AUTHORIZATION alice;

-- Select all from the category table.
SELECT catgroup, catname
FROM category;

 catgroup | catname 
---------+---------
 Sports   | NBA
(1 row)
```

当多个策略应允许用户查看给定关系中的更多行时，用户可以将该关系的 RLS CONJUNCTION TYPE 设置为 OR。考虑以下示例。Alice 只能看到策略指定的“Concerts”和“Sports”。

```
-- Create an analyst role and grant it to a user named Alice.
CREATE ROLE analyst;
CREATE USER alice WITH PASSWORD 'Name_is_alice_1';
GRANT ROLE analyst TO alice;

-- Create an RLS policy that only lets the user see concerts.
CREATE RLS POLICY policy_concerts
WITH (catgroup VARCHAR(10))
USING (catgroup = 'Concerts');

-- Create an RLS policy that only lets the user see sports.
CREATE RLS POLICY policy_sports
WITH (catgroup VARCHAR(10))
USING (catgroup = 'Sports');

-- Attach both to the analyst role.
ATTACH RLS POLICY policy_concerts ON category TO ROLE analyst;
ATTACH RLS POLICY policy_sports ON category TO ROLE analyst;

-- Activate RLS on the category table with OR CONJUNCTION TYPE. 
ALTER TABLE category ROW LEVEL SECURITY ON CONJUNCTION TYPE OR;

-- Change session to Alice.
SET SESSION AUTHORIZATION alice;

-- Select all from the category table.
SELECT catgroup, count(*)
FROM category
GROUP BY catgroup ORDER BY catgroup;

 catgroup | count 
---------+-------
 Concerts |  3
 Sports   |  5
(2 rows)
```

# RLS 策略所有权和管理
<a name="t_rls_ownership"></a>

作为超级用户、安全管理员或具有 sys:secadmin 角色的用户，您可以创建、修改、附加和分离 RLS 策略。RLS 策略可以附加到表、视图、后期绑定视图（LBV）和实体化视图（MV）。在对象级别，您可以打开或关闭行级别安全性，而无需修改表的架构定义。

要开始使用行级别安全性，以下是您可以使用的 SQL 语句：
+ 使用 ALTER TABLE 语句可以开启或关闭表、视图或后期绑定视图上的 RLS。有关更多信息，请参阅 [ALTER TABLE](r_ALTER_TABLE.md)。
+ 使用 ALTER MATERIALIZED VIEW 语句可以开启或关闭实体化视图（MV）上的 RLS。有关更多信息，请参阅 [ALTER MATERIALIZED VIEW](r_ALTER_MATERIALIZED_VIEW.md)。
+ 使用 CREATE RLS POLICY 语句可为一个或多个表创建安全策略，并在该策略中指定一个或多个用户或角色。

  有关更多信息，请参阅 [CREATE RLS POLICY](r_CREATE_RLS_POLICY.md)。
+ 使用 ALTER RLS POLICY 语句更改策略，例如更改策略定义。您可以对多个表或视图使用相同的策略。

  有关更多信息，请参阅 [ALTER RLS POLICY](r_ALTER_RLS_POLICY.md)。
+ 使用 ATTACH RLS POLICY 语句可将策略附加到一个或多个关系、一个或多个用户，或者角色。

  有关更多信息，请参阅 [ATTACH RLS POLICY](r_ATTACH_RLS_POLICY.md)。
+ 使用 DETACH RLS POLICY 语句可将策略与一个或多个关系、一个或多个用户或者角色分离。

  有关更多信息，请参阅 [DETACH RLS POLICY](r_DETACH_RLS_POLICY.md)。
+ 使用 DROP RLS POLICY 语句可以删除策略。

  有关更多信息，请参阅 [DROP RLS POLICY](r_DROP_RLS_POLICY.md)。
+ 使用 GRANT 和 REVOKE 语句可以明确授予和撤消对引用查找表的 RLS 策略的 SELECT 权限。有关更多信息，请参阅[GRANT](r_GRANT.md)和[REVOKE](r_REVOKE.md)。

要监控创建的策略，sys:secadmin 可以查看 [SVV\$1RLS\$1POLICY](r_SVV_RLS_POLICY.md) 和 [SVV\$1RLS\$1ATTACHED\$1POLICY](r_SVV_RLS_ATTACHED_POLICY.md)。

要列出受 RLS 保护的关系，sys:secadmin 可以查看 [SVV\$1RLS\$1RELATION](r_SVV_RLS_RELATION.md)。

要跟踪 RLS 策略在引用受 RLS 保护的关系的查询中的应用情况，超级用户、sys:operator 或任何拥有系统权限 ACCESS SYSTEM TABLE 的用户均可查看 [SVV\$1RLS\$1APPLIED\$1POLICY](r_SVV_RLS_APPLIED_POLICY.md)。请注意，默认情况下不会向 sys:secadmin 授予这些权限。

要支持用户完全访问受 RLS 保护的关系，您可以授予 IGNORE RLS 权限。将自动向超级用户或 sys:secadmin 授予 IGNORE RLS。有关更多信息，请参阅 [GRANT](r_GRANT.md)。

要解释 EXPLAIN 计划中查询的 RLS 策略筛选器以解决与 RLS 相关的查询，您可以向任何用户授予 EXPLAIN RLS 权限。有关更多信息，请参阅[GRANT](r_GRANT.md)和[EXPLAIN](r_EXPLAIN.md)。

# 依赖于策略的对象和原则
<a name="t_rls_object_dependency"></a>

为了为应用程序提供安全性并防止策略对象过时或失效，Amazon Redshift 不允许删除或更改 RLS 策略引用的对象。

下面列出了 Amazon Redshift 针对 RLS 策略跟踪的架构对象依赖关系。
+ 在跟踪目标表的架构对象依赖关系时，Amazon Redshift 将遵循以下规则：
  + 当您删除目标表时，Amazon Redshift 会将策略与关系、用户、角色或公共分离。
  + 当您重命名目标表名称时，对附加的策略没有任何影响。
  + 如果您首先删除或分离策略，您只能删除策略定义中引用的目标表的列。在指定 CASCADE 选项时，这也将适用。您可以删除目标表中的其他列。
  + 您无法重命名目标表的引用列。要重命名引用列，请先分离策略。在指定 CASCADE 选项时，这也将适用。
  + 即便指定了 CASCADE 选项，您也无法更改引用列的类型。
+ 在跟踪查找表的架构对象依赖关系时，Amazon Redshift 将遵循以下规则：
  + 您无法删除查找表。要删除查找表，请先删除引用该查找表的策略。
  + 您无法重命名查找表。要重命名查找表，请先删除引用该查找表的策略。在指定 CASCADE 选项时，这也将适用。
  + 您无法删除策略定义中使用的查找表列。要删除策略定义中使用的查找表列，请先删除引用该查找表的策略。当在 ALTER TABLE DROP COLUMN 语句中指定了 CASCADE 选项时，此规则也适用。您可以删除查找表中的其他列。
  + 您无法重命名查找表的引用列。要重命名引用列，请先删除引用该查找表的策略。在指定 CASCADE 选项时，这也将适用。
  + 您无法更改引用列的类型。
+ 在删除用户或角色时，Amazon Redshift 将自动分离附加到该用户或角色的所有策略。
+ 当您在 DROP SCHEMA 语句中使用 CASCADE 选项时，Amazon Redshift 还会删除架构中的关系。它还会删除依赖于已删除架构中的关系的任何其他架构中的关系。对于作为策略中查找表的关系，Amazon Redshift 将使 DROP SCHEMA DDL 失败。对于 DROP SCHEMA 语句删除的任何关系，Amazon Redshift 将分离附加到这些关系的所有策略。
+ 当您同时删除策略时，您只能删除查找函数（在策略定义中引用的函数）。在指定 CASCADE 选项时，这也将适用。
+ 在将策略附加到表时，Amazon Redshift 会检查此表是否是不同策略中的查找表。如果属于这种情况，Amazon Redshift 将不允许将策略附加到此表。
+ 在创建 RLS 策略时，Amazon Redshift 会检查此表是否是任何其他 RLS 策略的目标表。如果属于这种情况，Amazon Redshift 将不允许在此表上创建策略。

## 示例
<a name="t_rls_object_dependency-example"></a>

下面的示例说明了如何跟踪架构依赖关系。

```
-- The CREATE and ATTACH policy statements for `policy_events` references some
-- target and lookup tables.
-- Target tables are tickit_event_redshift and target_schema.target_event_table.
-- Lookup table is tickit_sales_redshift.
-- Policy `policy_events` has following dependencies:
--   table tickit_sales_redshift column eventid, qtysold
--   table tickit_event_redshift column eventid
--   table target_event_table column eventid
--   schema public and target_schema
CREATE RLS POLICY policy_events
WITH (eventid INTEGER)
USING (
    eventid IN (SELECT eventid FROM tickit_sales_redshift WHERE qtysold <3)
);

ATTACH RLS POLICY policy_events ON tickit_event_redshift TO ROLE analyst;

ATTACH RLS POLICY policy_events ON target_schema.target_event_table TO ROLE consumer;
```

# 使用 RLS 策略的注意事项和限制因素
<a name="t_rls_usage"></a>

## 注意事项
<a name="t_rls_considerations"></a>

以下是使用 RLS 策略时的注意事项：
+ Amazon Redshift 可将 RLS 策略应用于 SELECT、UPDATE 或 DELETE 语句。
+ Amazon Redshift 不会将 RLS 策略应用于 INSERT、COPY、ALTER TABLE APPEND 语句。
+ RLS 策略可以附加到表、视图、后期绑定视图（LBV）和实体化视图（MV）。
+ 行级别安全性与列级别安全性配合使用，以保护您的数据。
+ 在为源关系启用 RLS 后，Amazon Redshift 将为超级用户、已被明确授予系统权限 IGNORE RLS 或 sys:secadmin 角色的用户支持 ALTER TABLE APPEND 语句。在这种情况下，您可以通过从现有源表移动数据，运行 ALTER TABLE APPEND 语句，以将行附加到目标表。Amazon Redshift 会将所有元组从源关系移动到目标关系中。目标关系的 RLS 状态不会影响 ALTER TABLE APPEND 语句。
+ 为了便于从其他数据仓库系统迁移，您可以通过指定变量名称和值，以设置和检索连接的自定义会话上下文变量。

  以下示例为行级别安全性 (RLS) 策略设置了会话上下文变量。

  ```
  -- Set a customized context variable.
  SELECT set_config(‘app.category’, ‘Concerts’, FALSE);
  
  -- Create a RLS policy using current_setting() to get the value of a customized context variable.
  CREATE RLS POLICY policy_categories
  WITH (catgroup VARCHAR(10)) 
  USING (catgroup = current_setting('app.category', FALSE));
  
  -- Set correct roles and attach the policy on the target table to one or more roles.
  ATTACH RLS POLICY policy_categories ON tickit_category_redshift 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)。
**重要**  
 在 RLS 策略中使用会话上下文变量时，安全策略依赖于调用该策略的用户或角色。在 RLS 策略中使用会话上下文变量时，请注意避免安全漏洞。
+ 在 DECLARE 和 FETCH 之间或后续 FETCH 语句之间使用 SET SESSION AUTHORIZATION 更改会话用户不会刷新根据 DECLARE 时的用户策略已经准备好的计划。将游标与受 RLS 保护的表一起使用时，请避免更改会话用户。
+ 当视图对象内的基础对象受 RLS 保护时，附加到运行查询的用户的策略将应用于相应的基本对象。这与对象级权限检查不同，在对象级权限检查中，根据视图基本对象检查视图所有者的权限。您可以在查询的 EXPLAIN 计划输出中查看受 RLS 保护的关系。
+ 当在附加到用户的关系的 RLS 策略中引用用户定义函数 (UDF) 时，用户必须拥有对该 UDF 的 EXECUTE 权限才能查询该关系。
+  行级安全性可能会限制查询优化。我们建议在大型数据集上部署受 RLS 保护的视图之前，仔细评估查询性能。
+  应用于后期绑定视图的行级安全策略可能会推送到联合表中。这些 RLS 策略可能在外部处理引擎日志中可见。

## 限制
<a name="t_rls_limitations"></a>

以下是使用 RLS 策略时的限制：
+ RLS 策略不能附加到外部表和其它几种关系类型。有关更多信息，请参阅 [ATTACH RLS POLICY](r_ATTACH_RLS_POLICY.md)。
+ Amazon Redshift 可以针对某些包含具有复杂联接的查询的 RLS 策略支持 SELECT 语句，但不支持 UPDATE 或 DELETE 语句。在使用 UPDATE 或 DELETE 语句的情况下，Amazon Redshift 将返回以下错误：

  ```
  ERROR: One of the RLS policies on target relation is not supported in UPDATE/DELETE.
  ```
+ 每当在附加到用户的关系的 RLS 策略中引用用户定义函数 (UDF) 时，用户都必须拥有对该 UDF 的 EXECUTE 权限才能查询该关系。
+ 不支持关联的子查询。Amazon Redshift 将返回以下错误：

  ```
  ERROR: RLS policy could not be rewritten.
  ```
+ Amazon Redshift 不支持与 RLS 的数据共享。如果关系没有对数据共享关闭 RLS，则使用者集群上的查询将失败，并出现以下错误：

  ```
  RLS-protected relation "rls_protected_table" cannot be accessed via datasharing query.
  ```

  您可以使用 ALTER TABLE 命令以及参数 ROW LEVEL SECURITY OFF FOR DATASHARES，关闭数据共享的 RLS。有关使用 ALTER TABLE 启用或禁用 RLS 的更多信息，请查看 [ALTER TABLE](r_ALTER_TABLE.md)。
+ 在跨数据库查询中，Amazon Redshift 会阻止读取受 RLS 保护的关系。拥有 IGNORE RLS 权限的用户可以使用跨数据库查询访问受保护的关系。当没有 IGNORE RLS 权限的用户通过跨数据库查询访问受 RLS 保护的关系时，会出现以下错误：

  ```
  RLS-protected relation "rls_protected_table" cannot be accessed via cross-database query.
  ```
+ ALTER RLS POLICY 仅支持使用 USING（using\$1predicate\$1exp）子句修改 RLS 策略。运行 ALTER RLS POLICY 时，您无法使用 WITH 子句修改 RLS 策略。
+ 如果以下任一配置选项的值与会话的默认值不匹配，则无法查询已开启行级安全性的关系：
  +  `enable_case_sensitive_super_attribute` 
  +  `enable_case_sensitive_identifier` 
  +  `downcase_delimited_identifier` 

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

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

  创建 RLS 策略时，我们建议您更改普通用户的默认配置选项设置，使其与创建策略时会话的配置选项设置相匹配。超级用户和具有 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) 命令替换具有行级安全策略的视图和后期绑定视图。要替换具有 RLS 策略的视图或 LBV，请先分离附加到这些视图的所有 RLS 策略，替换视图或 LBV，然后重新附加策略。具有 `sys:secadmin permission` 的超级用户和用户可以在具有 RLS 策略的视图或 LBV 上使用 CREATE VIEW，而无需分离策略。
+  具有行级安全策略的视图不能引用系统表和系统视图。
+  常规视图引用的后期绑定视图无法受到 RLS 保护。
+  无法在同一个查询中访问受 RLS 保护的关系和来自数据湖的嵌套数据。

# RLS 性能最佳实践
<a name="t_rls_performance"></a>

以下是确保 Amazon Redshift 在受 RLS 保护的表上能够获得更高性能的最佳实践。

## 运算符和函数的安全性
<a name="t_rls_safe_operators"></a>

当查询受 RLS 保护的表时，使用某些运算符或函数可能会导致性能下降。对于查询受 RLS 保护的表，Amazon Redshift 会将运算符和函数分类为安全或不安全。如果根据输入，函数或运算符没有任何可观察到的副作用，则该函数或运算符将被分类为 RLS 安全。特别是，RLS 安全的函数或运算符不能是以下情况之一：
+ 输出输入值，或任何依赖于输入值的值，无论是否显示错误消息。
+ 失败或返回依赖于输入值的错误。

RLS 不安全的运算符包括：
+ 算术运算符：\$1、-、/、\$1、%。
+ 文本运算符：LIKE 和 SIMILAR TO。
+ 强制转换运算符。
+ UDF。

使用以下 SELECT 语句以检查运算符和函数的安全性。

```
SELECT proname, proc_is_rls_safe(oid) FROM pg_proc;
```

在规划对受 RLS 保护的表进行查询时，Amazon Redshift 将对包含 RLS 不安全运算符和函数的用户谓词的评估顺序施加限制。在查询受 RLS 保护的表时，引用 RLS 不安全运算符或函数的查询可能会导致性能下降。当 Amazon Redshift 无法将 RLS 不安全谓词向下推送到基表扫描以利用排序键时，性能可能会显著下降。为了获得更高性能，请避免使用利用排序键的 RLS 不安全谓词进行的查询。要验证 Amazon Redshift 是否能够向下推送运算符和函数，您可以将 EXPLAIN 语句与系统权限 EXPLAIN RLS 结合使用。

## 结果缓存
<a name="t_rls_result_cache"></a>

为了缩短查询运行时间并提高系统性能，Amazon Redshift 在领导节点的内存中缓存特定查询类型的结果。

在满足未受保护的表的所有条件并且满足以下所有条件时，Amazon Redshift 会将缓存的结果用于新查询来扫描受 RLS 保护的表：
+ 未曾修改策略中的表或视图。
+ 策略不使用在每次运行时必须求值的函数，如 GETDATE 或 CURRENT\$1USER。

为了获得更高性能，请避免使用不满足前述条件的策略谓词。

有关 Amazon Redshift 中的结果缓存的更多信息，请参阅[结果缓存](c_challenges_achieving_high_performance_queries.md#result-caching)。

## 复杂策略
<a name="t_rls_complex_policies"></a>

为了获得更高性能，请避免将复杂策略与联接多个表的子查询配合使用。

# 行级安全性端到端示例
<a name="t_rls-example"></a>

下面是一个端到端的示例，用于说明超级用户如何创建某些用户和角色。然后，具有 secadmin 角色的用户将创建、附加、分离和删除 RLS 策略。此示例使用 tickit 示例数据库。有关更多信息，请参阅《Amazon Redshift 入门指南》**中的[将数据从 Amazon S3 加载到 Amazon Redshift](https://docs.aws.amazon.com/redshift/latest/gsg/rs-gsg-create-sample-db.html)。

```
-- Create users and roles referenced in the policy statements.
CREATE ROLE analyst;
CREATE ROLE consumer;
CREATE ROLE dbadmin;
CREATE ROLE auditor;
CREATE USER bob WITH PASSWORD 'Name_is_bob_1';
CREATE USER alice WITH PASSWORD 'Name_is_alice_1';
CREATE USER joe WITH PASSWORD 'Name_is_joe_1';
CREATE USER molly WITH PASSWORD 'Name_is_molly_1';
CREATE USER bruce WITH PASSWORD 'Name_is_bruce_1';
GRANT ROLE sys:secadmin TO bob;
GRANT ROLE analyst TO alice;
GRANT ROLE consumer TO joe;
GRANT ROLE dbadmin TO molly;
GRANT ROLE auditor TO bruce;
GRANT ALL ON TABLE tickit_category_redshift TO PUBLIC;
GRANT ALL ON TABLE tickit_sales_redshift TO PUBLIC;
GRANT ALL ON TABLE tickit_event_redshift TO PUBLIC;

-- Create table and schema referenced in the policy statements.
CREATE SCHEMA target_schema;
GRANT ALL ON SCHEMA target_schema TO PUBLIC;
CREATE TABLE target_schema.target_event_table (LIKE tickit_event_redshift);
GRANT ALL ON TABLE target_schema.target_event_table TO PUBLIC;

-- Change session to analyst alice.
SET SESSION AUTHORIZATION alice;

-- Check the tuples visible to analyst alice.
-- Should contain all 3 categories.
SELECT catgroup, count(*)
FROM tickit_category_redshift
GROUP BY catgroup ORDER BY catgroup;

-- Change session to security administrator bob.
SET SESSION AUTHORIZATION bob;

CREATE RLS POLICY policy_concerts
WITH (catgroup VARCHAR(10))
USING (catgroup = 'Concerts');

SELECT poldb, polname, polalias, polatts, polqual, polenabled, polmodifiedby FROM svv_rls_policy WHERE poldb = CURRENT_DATABASE();

ATTACH RLS POLICY policy_concerts ON tickit_category_redshift TO ROLE analyst, ROLE dbadmin;

ALTER TABLE tickit_category_redshift ROW LEVEL SECURITY ON;

SELECT * FROM svv_rls_attached_policy;

-- Change session to analyst alice.
SET SESSION AUTHORIZATION alice;

-- Check that tuples with only `Concert` category will be visible to analyst alice.
SELECT catgroup, count(*)
FROM tickit_category_redshift
GROUP BY catgroup ORDER BY catgroup;

-- Change session to consumer joe.
SET SESSION AUTHORIZATION joe;

-- Although the policy is attached to a different role, no tuples will be
-- visible to consumer joe because the default deny all policy is applied.
SELECT catgroup, count(*)
FROM tickit_category_redshift
GROUP BY catgroup ORDER BY catgroup;

-- Change session to dbadmin molly.
SET SESSION AUTHORIZATION molly;

-- Check that tuples with only `Concert` category will be visible to dbadmin molly.
SELECT catgroup, count(*)
FROM tickit_category_redshift
GROUP BY catgroup ORDER BY catgroup;

-- Check that EXPLAIN output contains RLS SecureScan to prevent disclosure of
-- sensitive information such as RLS filters.
EXPLAIN SELECT catgroup, count(*) FROM tickit_category_redshift GROUP BY catgroup ORDER BY catgroup;

-- Change session to security administrator bob.
SET SESSION AUTHORIZATION bob;

-- Grant IGNORE RLS permission so that RLS policies do not get applicable to role dbadmin.
GRANT IGNORE RLS TO ROLE dbadmin;

-- Grant EXPLAIN RLS permission so that anyone in role auditor can view complete EXPLAIN output.
GRANT EXPLAIN RLS TO ROLE auditor;

-- Change session to dbadmin molly.
SET SESSION AUTHORIZATION molly;

-- Check that all tuples are visible to dbadmin molly because `IGNORE RLS` is granted to role dbadmin.
SELECT catgroup, count(*)
FROM tickit_category_redshift
GROUP BY catgroup ORDER BY catgroup;

-- Change session to auditor bruce.
SET SESSION AUTHORIZATION bruce;

-- Check explain plan is visible to auditor bruce because `EXPLAIN RLS` is granted to role auditor.
EXPLAIN SELECT catgroup, count(*) FROM tickit_category_redshift GROUP BY catgroup ORDER BY catgroup;

-- Change session to security administrator bob.
SET SESSION AUTHORIZATION bob;

DETACH RLS POLICY policy_concerts ON tickit_category_redshift FROM ROLE analyst, ROLE dbadmin;

-- Change session to analyst alice.
SET SESSION AUTHORIZATION alice;

-- Check that no tuples are visible to analyst alice.
-- Although the policy is detached, no tuples will be visible to analyst alice
-- because of default deny all policy is applied if the table has RLS on.
SELECT catgroup, count(*)
FROM tickit_category_redshift
GROUP BY catgroup ORDER BY catgroup;

-- Change session to security administrator bob.
SET SESSION AUTHORIZATION bob;

CREATE RLS POLICY policy_events
WITH (eventid INTEGER) AS ev
USING (
    ev.eventid IN (SELECT eventid FROM tickit_sales_redshift WHERE qtysold <3)
);

ATTACH RLS POLICY policy_events ON tickit_event_redshift TO ROLE analyst;
ATTACH RLS POLICY policy_events ON target_schema.target_event_table TO ROLE consumer;

RESET SESSION AUTHORIZATION;

-- Can not cannot alter type of dependent column.
ALTER TABLE target_schema.target_event_table ALTER COLUMN eventid TYPE float;
ALTER TABLE tickit_event_redshift ALTER COLUMN eventid TYPE float;
ALTER TABLE tickit_sales_redshift ALTER COLUMN eventid TYPE float;
ALTER TABLE tickit_sales_redshift ALTER COLUMN qtysold TYPE float;

-- Can not cannot rename dependent column.
ALTER TABLE target_schema.target_event_table RENAME COLUMN eventid TO renamed_eventid;
ALTER TABLE tickit_event_redshift RENAME COLUMN eventid TO renamed_eventid;
ALTER TABLE tickit_sales_redshift RENAME COLUMN eventid TO renamed_eventid;
ALTER TABLE tickit_sales_redshift RENAME COLUMN qtysold TO renamed_qtysold;

-- Can not drop dependent column.
ALTER TABLE target_schema.target_event_table DROP COLUMN eventid CASCADE;
ALTER TABLE tickit_event_redshift DROP COLUMN eventid CASCADE;
ALTER TABLE tickit_sales_redshift DROP COLUMN eventid CASCADE;
ALTER TABLE tickit_sales_redshift DROP COLUMN qtysold CASCADE;

-- Can not drop lookup table.
DROP TABLE tickit_sales_redshift CASCADE;

-- Change session to security administrator bob.
SET SESSION AUTHORIZATION bob;

DROP RLS POLICY policy_concerts;
DROP RLS POLICY IF EXISTS policy_events;

ALTER TABLE tickit_category_redshift ROW LEVEL SECURITY OFF;

RESET SESSION AUTHORIZATION;

-- Drop users and roles.
DROP USER bob;
DROP USER alice;
DROP USER joe;
DROP USER molly;
DROP USER bruce;
DROP ROLE analyst;
DROP ROLE consumer;
DROP ROLE auditor FORCE;
DROP ROLE dbadmin FORCE;
```

# 元数据安全性
<a name="t_metadata_security"></a>

与 Amazon Redshift 的行级安全性一样，元数据安全性可让您对元数据进行更精细的控制。如果为预置集群或无服务器工作组启用了元数据安全性，则用户可以查看他们有权查看的对象的元数据。元数据安全性可让您根据自己的需求来区分可见性。例如，您可以使用单个数据仓库来集中所有数据存储。但是，如果您存储多个扇区的数据，则管理安全性可能会变得很麻烦。启用元数据安全性后，您可以配置自己的可见性。一个扇区的用户可以对其对象有更多的可见性，而您则限制另一个扇区用户的查看权限。元数据安全性支持所有对象类型，例如架构、表、视图、实体化视图、存储过程、用户定义的函数和机器学习模型。

用户可以在以下情况下查看对象的元数据：
+ 如果向用户授予对象访问权限。
+ 如果向用户所属的组或角色授予对象访问权限。
+ 对象是公开的。
+ 用户是数据库对象的拥有者。

要启用元数据安全性，请使用 [ALTER SYSTEM](https://docs.aws.amazon.com/redshift/latest/dg/r_ALTER_SYSTEM.html) 命令。以下是如何使用具有元数据安全性的 ALTER SYSTEM 命令的语法。

```
ALTER SYSTEM SET metadata_security=[true|t|on|false|f|off];
```

启用元数据安全性后，所有拥有必要权限的用户都可以查看他们有权访问的对象的相关元数据。如果您只希望某些用户能够查看元数据安全性，请向角色授予 `ACCESS CATALOG` 权限，然后将该角色分配给用户。有关使用角色更好地控制安全性的更多信息，请参阅[基于角色的访问控制](https://docs.aws.amazon.com/redshift/latest/dg/t_Roles.html)。

以下示例演示如何向角色授予 `ACCESS CATALOG` 权限，然后将该角色分配给用户。有关授予权限的更多信息，请参阅 [GRANT](https://docs.aws.amazon.com/redshift/latest/dg/r_GRANT.html) 命令。

```
CREATE ROLE sample_metadata_viewer;

GRANT ACCESS CATALOG TO ROLE sample_metadata_viewer;

GRANT ROLE sample_metadata_viewer to salesadmin;
```

如果您希望使用已定义的角色，则[系统定义的角色](https://docs.aws.amazon.com/redshift/latest/dg/r_roles-default.html) `operator`、`secadmin`、`dba` 和 `superuser` 都具有查看对象元数据的必要权限。默认情况下，超级用户可以看到完整的目录。

```
GRANT ROLE operator to sample_user;
```

如果您使用角色来控制元数据安全性，则可以访问基于角色的访问控制附带的所有系统视图和函数。例如，您可以查询 [ SVV\$1ROLES](https://docs.aws.amazon.com/redshift/latest/dg/r_SVV_ROLES.html) 视图以查看所有角色。要查看用户是否是角色或组的成员，请使用 [USER\$1IS\$1MEMBER\$1OF ](https://docs.aws.amazon.com/redshift/latest/dg/r_USER_IS_MEMBER_OF.html) 函数。有关 SVV 视图的完整列表，请参阅 [SVV 元数据视图](https://docs.aws.amazon.com/redshift/latest/dg/svv_views.html)。有关系统信息函数的列表，请参阅[系统信息函数](https://docs.aws.amazon.com/redshift/latest/dg/r_System_information_functions.html)。

# 动态数据掩蔽
<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;
```

# 限定范围权限
<a name="t_scoped-permissions"></a>

限定范围权限允许您向用户或角色授予对数据库或架构中某一类型的所有对象的访问权限。具有限定范围权限的用户和角色对数据库或架构中的所有当前和未来对象具有指定权限。

您可以在 [SVV\$1DATABASE\$1PRIVILEGES](r_SVV_DATABASE_PRIVILEGES.md) 中查看数据库级限定权限的范围。您可以在 [SVV\$1SCHEMA\$1PRIVILEGES](r_SVV_SCHEMA_PRIVILEGES.md) 中查看架构级限定权限的范围。

 有关应用限定范围权限的更多信息，请参阅[GRANT](r_GRANT.md)和[REVOKE](r_REVOKE.md)。

# 使用限定范围权限的注意事项
<a name="t_scoped-permissions-considerations"></a>

使用限定范围权限时，请注意以下事项：
+ 您可以使用限定范围权限将数据库或架构范围的权限授予指定用户或角色，或者撤销这些权限。
+ 您不能将限定范围权限授予用户组。
+ 授予或撤销限定范围权限会更改范围中所有当前和未来对象的权限。
+ 限定范围权限和对象级权限相互独立地运作。例如，在以下两种情况下，用户都将保留对表的权限。
  + 授予用户对表 schema1.table1 的 SELECT 权限和对 schema1 的 SELECT 限定范围权限。然后，用户撤消了对架构 schema1 中所有表的 SELECT 权限。用户在 schema1.table1 上保留 SELECT 权限。
  + 授予用户对表 schema1.table1 的 SELECT 权限和对 schema1 的 SELECT 限定范围权限。然后，用户撤销了对 schema1.table1 的 SELECT 权限。用户在 schema1.table1 上保留 SELECT 权限。
+ 要授予或撤销限定范围权限，您必须满足以下条件之一：
  + 超级用户。
  + 拥有该权限授权选项的用户。有关授权选项的更多信息，请参阅 [GRANT](r_GRANT.md) 中的 WITH GRANT OPTION 参数。
+ 只能针对已连接数据库或从数据共享导入的数据库的对象授予或撤销限定范围权限。
+ 您可以使用限定范围权限，为通过数据共享创建的数据库设置默认权限。被授予对共享数据库的限定范围权限的使用者端数据共享用户将自动获得对生产者端添加到数据共享的任何新对象的这些权限。
+ 生产者可以向数据共享（预览版）授予对架构内对象的限定范围权限。