

 从补丁 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/)。

# 基于角色的访问控制 (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)