Amazon Redshift 是一项完全托管的 PB 级云数据仓库服务。借助 Amazon Redshift,您可以分析所有数据,从而获得有关您业务和客户的全面见解。安全性面临的挑战之一是,企业希望在行级别为敏感数据提供精细的访问控制。要实现此目标,您可以为不同的用户创建视图或使用不同的数据库和架构。但是,这种方法不可扩展,且会随着时间的推移变得难以维护。客户要求我们,通过提供控制精细访问的功能来简化保护其数据的流程。
Amazon Redshift 中的行级安全性 (RLS) 构建在基于角色的访问控制 (RBAC) 基础之上。RLS 允许您根据在数据库对象级别定义的安全策略,控制哪些用户或角色可以访问表中的特定数据记录。借助 Amazon Redshift 中的这一新 RLS 功能,您可以动态筛选表中的现有数据行。这是对列级访问控制的补充,您可以在其中向用户授予对列子集的权限。现在,您可以将列级访问控制与 RLS 策略结合起来,进一步限制对可见列的特定行的访问。
在本文中,我们将探讨 Amazon Redshift 的行级安全功能,以及如何使用角色来简化最终用户所需的权限管理。
客户反馈
TrustLogix 是一家由 Norwest Venture Partners 支持的数据安全治理领域的云安全初创公司。TrustLogix 提供强大的监控、可观察性、审核和细粒度数据授权功能,使 Amazon Redshift 客户端能够为其数字化转型计划实施以数据为中心的安全性。
“对于与 Amazon Redshift 这种全新更深层次的集成,我们感到非常高兴。我们在金融服务、医疗保健和制药等安全前沿和高度监管领域的共同客户,需要对允许哪些用户访问哪些数据以及在哪些特定环境下访问哪些数据进行难以置信的精细控制。新的行级安全功能将使我们的客户能够根据其业务授权精确规定数据访问控制,同时将它们从复杂的技术中抽象出来。全新 Amazon Redshift RLS 功能将使我们的共同客户能够在业务级别对策略建模,通过安全即代码模式部署和实施策略,从而确保安全、一致地访问其敏感数据。”
-TrustLogix 创始人兼首席执行官 Ganesh Kirti。
Amazon Redshift 中的行级安全性概述
行级安全性允许您将某些记录限制为特定用户或角色,具体取决于这些记录的内容。借助 RLS,您可以定义策略来实施精细的行级访问控制。创建 RLS 策略时,您可以指定表达式来控制 Amazon Redshift 是否在查询中返回表中的任何现有行。通过限制访问权限的 RLS 策略,您不必在查询中添加或外部化其他条件。您可以将多个策略附加到一个表,一个策略可以附加到多个表,从而使这种实施关系成为多对多关系。附加后,RLS 策略将应用于关系和一组用户或角色,以运行 SELECT、UPDATE 和 DELETE 操作。所有附加的 RLS 策略必须一起评估为 true,才能通过查询返回记录。RBAC 内置角色安全管理员负责管理策略。
下图展示了工作流。
使用 RLS,您可以执行以下操作:
- 根据角色限制行访问权限 – 安全管理员根据 RLS 策略,创建并定义角色是否可以访问表中的特定数据记录。
- 为每个用户或角色组合多个策略 – 可以为每个用户或角色定义多个策略,且所有策略都使用 AND 语法进行应用。
- 增强精细访问控制 – RLS 构建在基于角色的访问控制之上,可以与列级访问控制配合使用。
- 在不应用策略时无访问权限 – 在受 RLS 保护的表上没有适用策略时,将阻止所有数据访问。
- 在表上启用行级和列级安全性 – 在以下示例中,用户 house 是角色 staff 的一部分。当 house 查询表时,只返回一条与 house 相关的记录;其余记录将按照 RLS 策略进行筛选。敏感列也受到限制,因此,角色 staff 的用户无法查看此列。用户 cuddy 是角色 manager 的一部分。当 cuddy 查询 employees 表时,将返回所有记录和列。
行级安全相关使用案例
有了行级安全性,许多精细访问控制的使用案例成为可能。以下只是众多应用使用案例中的一部分:
- 由于数据合规性要求,在不同国家/地区拥有数据分析师的跨国公司可以根据地理位置对分析师实施数据访问限制。
- 销售部门可以创建策略,允许他们限制访问特定于特定销售人员或地区的销售业绩信息。
- 薪资部门可以创建 RLS 策略来限制查看个人工资单的权限,但经理需要其直接下属的相关工资信息。经理不需要知道其他部门的工资单详细信息。
- 医院可以创建 RLS 策略,仅允许医生和护士查看其患者的数据行。
- 银行可以根据员工的业务部门或在公司中的角色创建策略,来限制对财务数据行的访问。
- 多租户应用程序可以创建策略,从逻辑上强制将每个租户的数据行与其他每个租户的数据行分离。
在以下示例使用案例中,我们演示了对虚拟医疗保健机构强制执行 RLS 策略。我们根据为经理、医生和部门制定的策略,针对 medicine_data 表和 patients 表演示了 RLS。我们还将介绍如何使用自定义会话变量上下文为多租户表 customer 设置 RLS 策略。
要下载脚本并设置表,请选择 rls_createtable.sql。
示例 1:读写权限
要授予读写权限,请完成以下步骤:
- 使用 secadmin 角色定义四个 RLS 策略:
- all_can_see – 没有要施加的限制
- hide_confidential – 限制非机密行的记录
- only_doctors_can_see – 限制记录以便只有医生才能查看数据
- see_only_own_department – 将记录限制为只能查看自己部门的数据
CREATE RLS POLICY all_can_see
USING ( true );
CREATE RLS POLICY hide_confidential
WITH ( confidential BOOLEAN )
USING ( confidential = false )
;
Note: Employee table is used as lookup in this policy
CREATE RLS POLICY only_doctors_can_see
USING (
true = (
SELECT employee_is_doctor
FROM employees
WHERE employee_username = current_user
)
)
;
GRANT SELECT ON employees
TO RLS POLICY only_doctors_can_see;
CREATE RLS POLICY see_only_own_department
WITH ( patient_dept_id INTEGER )
USING (
patient_dept_id IN (
SELECT department_id
FROM employees_departments
WHERE employee_username = current_user
)
)
;
GRANT SELECT ON employees_departments
TO RLS POLICY see_only_own_department;
- 创建 STAFF、MANAGER 和 EXTERNAL 这三个角色:
CREATE ROLE staff;
CREATE ROLE manager;
CREATE ROLE external;
- 现在,我们为正在实施 RLS 策略的角色和列定义列级访问控制:
- MANAGER 可以访问 Patients 和 Medicine_data 表中的所有列,包括用于定义 RLS 策略的 confidential 列:
--- manager can see full table patients and medicine data
GRANT SELECT ON employees, employees_departments, patients, medicine_data TO ROLE manager, ROLE external;
- STAFF 角色可以访问除 confidential 列之外的所有列:
--- staff can see limited columns from medicine data
GRANT SELECT (medicine_name, medicine_price) ON medicine_data
TO ROLE staff;
--- staff can see limited columns from patients
GRANT SELECT (patient_dept_id, patient_name, patient_birthday, patient_medicine, diagnosis) ON patients TO ROLE staff;
- 将 RLS 策略附加到我们创建的角色:
--- manager can see all medicine data
ATTACH RLS POLICY all_can_see
ON medicine_data
TO ROLE manager;
--- manager can see all patient data
ATTACH RLS POLICY all_can_see
ON patients
TO ROLE manager;
--- staff cannot see confidential medicine data
ATTACH RLS POLICY hide_confidential
ON medicine_data
TO ROLE staff;
--- staff cannot see confidential patient data
ATTACH RLS POLICY hide_confidential
ON patients
TO ROLE staff;
--- only doctors can see patient data
ATTACH RLS POLICY only_doctors_can_see
ON patients
TO PUBLIC;
--- regular staff (doctors) can see data for patients in their department only
ATTACH RLS POLICY see_only_own_department
ON patients
TO ROLE staff;
- 对对象启用 RLS 安全性:
ALTER TABLE medicine_data ROW LEVEL SECURITY on;
ALTER TABLE patients ROW LEVEL SECURITY on;
- 创建用户并向其授予角色:
CREATE USER house PASSWORD DISABLE;
CREATE USER cuddy PASSWORD DISABLE;
CREATE USER external PASSWORD DISABLE;
GRANT ROLE staff TO house;
GRANT ROLE manager TO cuddy;
GRANT ROLE external TO external;
我们可以通过 SELECT 查询查看 RLS 的运行情况:
--- As Cuddy, who is a doctor and a manager
SET SESSION AUTHORIZATION 'cuddy';
SELECT * FROM medicine_data;
--- policies applied: all_can_see
SELECT * FROM patients;
--- policies applied: all_can_see, only_doctors_can_see
作为超级用户和 secadmin,您可以查询 svv_rls_applied_policy 来审核和监控应用的策略。我们将在本文稍后部分讨论用于审计和监控的系统视图。
--- As House, who is a doctor but not a manager - he is staff in department id 1
SET SESSION AUTHORIZATION 'house';
SELECT * FROM medicine_data;
--- column level access control applied
SELECT current_user, medicine_name, medicine_price FROM medicine_data;
--- CLS + RLS policy = hide_confidential
SELECT * FROM patients;
--- column level access control applied
SELECT current_user, patient_dept_id, patient_name, patient_birthday, patient_medicine, diagnosis FROM patients;
--- CLS + RLS policies = hide_confidential, only_doctors_can_see, see_only_own_department
--- As External, who has no permission granted
SET SESSION AUTHORIZATION 'external';
SELECT * FROM medicine_data;
--- RLS policy applied: none - so no access
SELECT * FROM patients;
--- policies applied: none - so no access
通过 UPDATE 命令,根据部门 1 的 RLS,应该只有用户 house 才能更新 patients 记录:
SET SESSION AUTHORIZATION 'house';
UPDATE patients
SET diagnosis = 'house updated diagnosis';
select current_user, * from patients; --house should only be able to query department 1 non-confidential records
为了测试 DELETE,作为用户 house,让我们从患者表中删除记录。根据 RLS 策略,只能删除 patient_dept_id 中的两条非机密记录:
SET SESSION AUTHORIZATION 'house';
delete from patients;
由于 house 有权访问的两条记录都已从 patients 中删除,因此,从表中选择将不返回记录。
当我们切换到用户 cuddy,其是 manager 和 doctor,我们可以访问机密记录,并可看到三条记录:
SET SESSION AUTHORIZATION 'cuddy';
SELECT current_user, * from patients;
作为安全管理员,您可以将策略与表、用户或角色分离。在此示例中,我们将策略 hide_confidential 与表 patients 和角色 staff 分离:
DETACH RLS POLICY hide_confidential ON patients FROM ROLE staff;
当用户 house 查询 patients 表时,他们现在应该可以访问机密记录:
SET SESSION AUTHORIZATION 'house';
SELECT * from patients;
使用安全管理员角色,您可以删除策略 hide_confidential:
DROP RLS POLICY IF EXISTS hide_confidential;
由于 hide_confidential RLS 策略仍附加到 medicine_data 表中,因此,您会收到依赖项错误。
要从所有表、用户和角色中删除此策略,您可以使用 cascade 选项:
DROP RLS POLICY IF EXISTS hide_confidential cascade;
当用户 house 查询 medicine_data 表时,不会返回任何记录,因为 medicine_data 表开启了 RLS,且未将任何 RLS 策略附加到此表的角色 staff。f
SET SESSION AUTHORIZATION 'house';
SELECT * from MEDICINE_DATA;
我们使用安全管理员角色关闭表 medicine_data 的行级安全性:
ALTER TABLE MEDICINE_DATA ROW LEVEL SECURITY OFF;
SET SESSION AUTHORIZATION 'house';
SELECT * FROM MEDICINE_DATA;
示例 2:会话上下文变量
有些应用程序要求您使用连接池,您可以使用基于应用程序的用户身份验证,而不是为每个用户使用单独的数据库用户。借助 Amazon Redshift 中的会话上下文变量功能,您可以将应用程序用户 ID 传递到数据库,以应用基于角色的安全性。
现在,Amazon Redshift 允许您使用 set_config 设置自定义会话上下文变量。使用会话上下文变量允许您使用 RLS 提供此类精细访问。
在此示例中,我们演示了您拥有常见表 customer 的使用案例,即您从多个客户那里获取数据。该表的一列带有 c_customer_id,用于区分各个客户的数据。
- 创建 external 用户并授予 external 角色:
CREATE USER external_user PASSWORD 'Testemp1';
grant role EXTERNAL to external_user;
- 将 customer 表的 SELECT 授予给角色 external:
grant usage on schema report to role EXTERNAL;
GRANT select ON TABLE report.customer TO ROLE EXTERNAL;
- 启用 report.customer 表的行级安全性:
ALTER TABLE report.customer row level security on;
- 使用会话上下文变量 app.customer_id 创建行级安全策略,强制执行该策略以筛选 c_customer_id 的记录:
CREATE RLS POLICY see_only_own_customer_rows
WITH ( c_customer_id char(16) )
USING ( c_customer_id = current_setting('app.customer_id', FALSE));
ATTACH RLS POLICY see_only_own_customer_rows ON report.customer TO ROLE EXTERNAL;
现在,我们可以观察 RLS 的运行情况。当您查询 customer 表,且其会话上下文设置为客户 ID AAAAAAAAJNGEGCBA 时,仅强制执行行级策略,以返回一个 customer 行,其与会话变量值匹配:
SET SESSION AUTHORIZATION 'external_user';
select set_config('app.customer_id', 'AAAAAAAAJNGEGCBA', FALSE);
select * from report.customer limit 10;
审核和监控 RLS 策略
Amazon Redshift 增加了几个新的系统视图,以便能够监控行级策略。下表列出了具有访问权限的系统视图、用户和角色以及视图的功能。
系统视图 |
用户 |
功能 |
SVV_RLS_POLICY |
sys:secadmin |
查看创建的所有行级安全策略的列表 |
SVV_RLS_RELATION |
sys:secadmin |
查看在当前连接的数据库上附加了一个或多个行级安全策略的所有关系和用户的列表 |
SVV_RLS_APPLIED_POLICY |
sys:secadmin |
列出受 RLS 保护的关系 |
SVV_RLS_ATTACHED_POLICY |
超级用户、sys:operator 或任何具有系统权限 ACCESS SYSTEM TABLE 的用户 |
跟踪 RLS 策略对引用 RLS 保护关系的查询的应用情况 |
结论
在本文中,我们演示了如何简化行级安全性的管理,以便在基于角色的访问控制的基础上对敏感数据进行精细访问控制。有关 RLS 最佳实践的更多信息,请参阅 Amazon Redshift 安全概述。在未来的 Amazon Redshift 实施中试用 RLS,随时就您的使用案例和体验发表评论。
Amazon Redshift Spectrum 支持对存储在 Amazon Simple Storage Service (Amazon S3) 中并由 AWS Lake Formation 管理的数据进行行级、列级和单元级访问控制。在以后的文章中,我们将展示如何使用 Lake Formation 为 Redshift Spectrum 表实施行级安全性。
关于作者
Harshida Patel 是AWS 分析的高级专家解决方案架构师。
Milind Oke 是一名来自纽约的高级专家解决方案架构师。20 多年来,他一直在构建数据仓库解决方案,专门研究 Amazon Redshift。
Abhilash Nagilla 是 AWS 分析的专业解决方案架构师。
Yanzhu Ji 是 Amazon Redshift 团队的产品经理。在成为产品经理之前,她曾在 Amazon Redshift 团队担任软件工程师。在如何构建面向客户的 Amazon Redshift 功能(从规划到发布)方面,她拥有丰富的经验,且始终将客户的需求视为第一要务。在她的个人生活中,Yanzhu 喜欢绘画、摄影,打网球。
Kiran Chinta 是 Amazon Redshift 的软件开发经理。他在查询处理、SQL 语言、数据安全和性能方面领导着一支强大的团队。Kiran 热衷于提供与客户业务应用程序无缝集成的产品,使其具有适当的易用性和性能。在业余时间,他喜欢阅读,打网球。
Debu Panda 是 AWS 产品管理的高级经理。他是分析、应用程序平台和数据库技术领域的行业领导者,在 IT 领域拥有超过 25 年的经验。Debu 发表了许多关于分析、企业 Java 和数据库的文章,并在 AWS re:Invent、Oracle Open World 和 Java One 等多个会议上发表过演讲。他是《EJB3 in Action》(Manning Publications 2007, 2014) 和《Middleware Management》(Packt) 的主要作者。