1. 背景
数据库软件诞生至今,经过了几十年的发展和演进,已经成为IT系统中不可或缺的关键技术。由于数据库存储了大量的敏感数据,因此需要对数据库进行访问控制和权限管理,以保护数据的安全和隐私。MYSQL数据库提供了权限管理功能,通过使用GRANT语句授权用户或用户组对特定数据库对象的操作权限,如全局级别、数据库级别、表级别、视图级别或列级别的权限。PolarDB-X数据库除了普通的权限管理能力,还支持了三权分立、TDE的企业级特性,进一步加强数据库的权限管理、数据加密的能力,防止数据泄露、篡改和损坏,从数据库层面降低了安全风险。
但是MYSQL权限管理能力的最小粒度表级别和列级别,无法针对每个数据行的读写访问进行控制。而这种需求在实际应用场景中是十分常见的,如公司某部门Leader只能查询到该部门的员工信息,其他部门员工信息对其不可见。PolarDB-X数据库实现了基于标签的访问控制(LBAC, Label-based access control)功能,可以在行、列级别对数据访问进行控制,精细化的限制用户对数据的访问和操作,保证了读写数据的安全。下文根据实际应用场景,介绍PolarDB-X的LBAC功能设计以及使用方法。
2. LBAC应用场景
某公司在PolarDB-X数据库上存储了所有员工的个人信息(姓名、工龄、绩效、薪资等),并为部分员工创建数据库账号,可以进行数据查询以及更新。但是为了保证数据的访问安全,公司执行了以下数据访问控制策略: 员工A可以访问到员工B的个人信息需满足三个条件:
- 员工A的级别大于员工B
- 员工A在员工B的同部门或上级部门
- 员工A和员工B的工种相同
PolarDB-X可以使用基于标签的访问控制(LBAC)实现上述要求,即为每个员工设置一个安全标签(security label),当员工1查询数据库中员工2的信息时,只有label1 >= label2时,才可以访问成功。那要如何设计安全标签的模式,才能满足上述数据访问控制策略呢?
我们将员工的安全标签分为三个组成部分rank、type、structure分别表示员工的级别、工种以及部门。对于不同的组成部分使用不同的比较规则:
- rank部分:次序关系比较大小。如M5 >= M4,M4 >= M3,M3 >= M2
- type部分:包含关系比较大小。如(pd, se) >= (pd),(pd) >= (pd)
- structure部分:层级关系比较大小。division >= teamB,teamA >= group1
- rank、type、structure部分的空值表示最小值。
label1 >= label2的充分必要条件为:label1的每个组成部分大于等于label2对应组成部分
- label1.rank >= label2.rank
- label1.type >= label2.type
- label1.structure >= label2.structure
从上图中可以看出:
- label1 >= label2、level4Label
- bossLabel >= label1/2/3、level4Label
安全标签不仅可以用来保护数据库中的数据行(某个员工信息),也同样可以保护数据列(所有员工的某方面信息)。比如员工信息表中有数据列为工资信息,且只允许boss查看,则可以为工资列设置安全标签为bossLabel,只有用户的安全标签大于等于bossLabel时才能查询该列信息。PSL列(PolarSecurityLabelColumn)用来存储每一行数据的security label
3. LBAC基本概念
3.1 Security Label(安全标签)
Security Label是实现访问控制的标签。
- Security Label的可赋予实体类型:行、列、用户
- LBAC基于标签的的访问控制的本质为:比较用户与行、列的Security Label的大小关系,决定是否可以访问
- Security Label的大小关系:CanRead、CanWrite,两种比较规则可自定义
3.2 Security Policy(安全策略)
Security Policy定义了Security Label的模式,也代表了一组Security Label集合。
- Security Policy内部的Security Label模式全部相同。
- 只有当Security Labels属于同一个Security Policy时,才能比较其之间的大小关系
- Security Policy可赋予的实体类型:表,其表示表的行、列所使用的Security Label都必须属于这个Security Policy。
3.3 Security Label Component(安全标签组件)
Security Policy使用一个或者多个Security Label Component,定义Security Label的模式。
- Security Label Component有三种类型:Array、Set、Tree
- Security Label比较大小关系,其实际上是比较其内部的Component的大小关系。
- Component的大小比较:
- Array:次序关系
- Set:包含关系
- Tree:层级关系
3.4 PolarSecurityLabelColumn(PSL列)
PolarSecurityColumn是PolarDB-X数据库专门用于数据表中存储Security Label的特殊列,其在数据表中的列名为_polar_security_label
,但PSL列的数据类型只能为varchar。
- PSL列存储的内容为Security Label的name,不存储具体label内容。
- 当数据表中存在PSL列时,数据将会受到LBAC保护。
- PSL列拥有和普通列同样的特性。
4. LBAC使用方法
下面将基于上述应用场景,介绍如何基于PolarDB-X数据库使用LBAC功能实现数据访问控制策略。
4.1 创建Security属性
首先需要根据应用场景设计安全标签的模式。
1.创建Security Label Component
create security label component 'rank' array 'm5,m4,m3,m2'; create security label component 'type' set 'se,op,pd'; create security label component 'structure' tree '(division,teama);(division,teamb);(teama,group1);(teama,group2);(teamb,group3);(teamb,group4)';
安全标签组件是安全标签的组成部分,这里用rank表达员工级别,type表达员工工种,structure表达员工部门,不同类型的安全标签组件比较大小的规则是不同的。
2.创建Security Policy
create security policy 'staff_data_access' components 'rank,type,structure';
安全策略定义了安全标签的模式,其内部包含的安全标签必须遵守该模式,这里定义了staff_data_access安全策略,其内部的安全标签必须由rank,type,structure三个安全标签组件构成。
3.创建Security label
create security label staff_data_access.label1 '(m4):(pd):(teamb)'; create security label staff_data_access.label2 '(m3):(pd):(group4)'; create security label staff_data_access.label3 '(m2):(se):(group3)'; create security label staff_data_access.bossLabel'(m4):(pd,se,op):(division)'; create security label staff_data_access.level4Label '(m4):():()'; create security label staff_data_access.level2Label '(m2):():()';
这里创建了6个安全标签,它们都属于staff_data_access安全策略,所以它们的模式是相同的。
- label1、2、3分别表示了不同级别、工作、部分的普通员工;
- bossLabel表示了最高权限的安全标签,其具有最高级别、所有工种类型,最上层部门;
- level2Label和level4Label内部只包含了level,其表示只能由指定级别以上的员工访问,不限制其工种和部分。
4.2 创建用户
create user tmb_pd_ld identified by 'password'; grant all privileges on *.* to tmb_pd_ld; grant security label staff_data_access.label1 to user 'tmb_pd_ld'@'%' for read access; grant security label staff_data_access.label2 to user 'tmb_pd_ld'@'%' for write access;
PolarDB-X规定每个用户对于单个安全策略都可以具有read_label、write_label两个安全标签,分别用于数据读写访问控制。在PolarDB-X数据库中,我们强制要求read_label >= write_label,这样保证了用户可更新的数据范围是可读取的数据范围的子集。 这里为teamB部门中负责group4小组的产品leader创建了一个数据库账户'tmb_pd_ld'@'%':
- read_label为label1,表示可以读取级别为m4及以下,工种为产品,部门为teamB及下级部门的员工信息
- write_label为label2,表示可以写入级别为m3及以下,工种为产品,部门为group4及下级部门的员工信息
4.3 数据访问控制
UDF测试
PolarDB-X内部提供了函数用于LBAC功能:
- lbac_user_write_label(security_policy):返回当前用户在指定安全策略下的write_label;
- lbac_user_read_label(security_policy):返回当前用户在指定安全策略下的read_label;
- lbac_check(security_label1, security_label2):返回security_label1是否大于等于security_label2
//1. 判断label1是否大于等于其他label select lbac_check('label1','label1'); //返回1 select lbac_check('label1','label2'); //返回1 select lbac_check('label1','label3'); //返回0 select lbac_check('label1','bossLabel');//返回0 select lbac_check('label1','level4Label');//返回1 select lbac_check('label1','level2Label');//返回1 //2. 判断label2是否大于等于其他label select lbac_check('label2','label1'); //返回0 select lbac_check('label2','label2'); //返回1 select lbac_check('label2','label3'); //返回0 select lbac_check('label2','bossLabel');//返回0 select lbac_check('label2','level4Label');//返回0 select lbac_check('label2','level2Label');//返回1
创建数据表
//以root用户身份登录 create table staff_info( username varchar(255), seniority int column secured with level2Label, performance varchar(50) column secured with level4Label, salary int column secured with bossLabel, _polar_security_label varchar(255) )security policy=staff_data_access; insert into staff_info values("name1",10,"A",20000,"bossLabel"); insert into staff_info values("name2",6,"B",15000,"label1"); insert into staff_info values("name3",3,"C",10000,"label2"); insert into staff_info values("name4",2,"B",8000,"label3"); insert into staff_info values("name5",5,"C",12000,"label1"); insert into staff_info values("name6",4,"B",11000,"label2"); insert into staff_info values("name7",1,"D",5000,"label3");
以root用户身份进行查询,可以访问所有数据:
根据上文LBAC相关函数测试结果可知,对于用户tmb_pd_ld:
- 可以读取的列:username, seniority, performance, _polar_security_label
- 可以写入的列:username, seniority, _polar_security_label
- 可以读取的行:name2, name3, name5, name6
- 可以写入的行:name3, name6
为了验证PolarDB-X数据库的LBAC访问控制能力,下文以tmb_pd_ld用户身份登录,测试Select、Update、Insert、Delete四种SQL语句的执行情况。
Select
情景一:查询所有员工的信息
从执行结果可以看出:
- 当SQL查询涉及到当前用户无法读取的列时,SQL执行会失败;
- 对于数据表中当前用户无法读取的行,数据对于当前用户是不可见的。
情景二:查询工资高于10000的员工
从执行结果可以看出,当where条件中包含无法读取的列时,SQL执行会失败;
情景三:查询每个员工和平均工资的差距
从执行结果可以看出,当子查询中包含无法读取的列时,SQL执行会失败; 除此之外,当SQL语句的order by,group by,window等部分包含无法读取的列时,SQL执行会失败。
Update
情景一:将员工的工龄增加1
从执行结果可以看出:
- 当前用户无法读取name1员工的数据行,所以更新了0行,并没有更新成功。
- 当前用户可以读取name2员工的数据行,但是无法写入更新,所以更新了0行,并没有更新成功。
- 当前用户可以读取name3员工的数据行,也可以写入更新,所以更新了1行,更新成功。
情景二:将员工的工资增加1000
从执行结果可以看出,当用户更新数据行涉及到无法写入的列时,SQL执行会失败。
情景三:更新员工的PSL列
PolarDB-X规定,当用户更新数据表中的PSL列的值时,必须保证当前用户的write_label大于等于新的label值。所以从执行结果可以看出,当将name3员工的PSL列更新为label1时,SQL执行失败,更新为label2时,SQL执行成功。
Insert
情景一:插入一条员工信息
从执行结果可以看出,当插入数据行时涉及到无法写入的列时,SQL执行会失败。
PolarDB-X规定,当用户插入记录包含PSL列时,必须保证当前用户的write_label大于等于插入的label值。所以从执行结果中可以看出,当前用户插入label1时,SQL执行失败。
PolarDB-X规定,当用户插入记录不包含PSL列时,该行的PSL列值默认为当前用户的write_label。所以从执行结果可以看出,name11员工的PSL列值为label2。
Delete
情景一:删除所有员工信息
从执行结果可以看出,用户delete数据时会要求可以数据表的所有列都是可以写入的,所以当存在无法写入的列时,SQL会执行失败。 为了更好的展示delete的效果,我们创建一个新的表,使得所有列可写入。
//以root用户身份登录 create table staff_info_new( username varchar(255), seniority int column secured with level2Label, performance varchar(50) column secured with level2Label, salary int column secured with level2Label, _polar_security_label varchar(255) )security policy=staff_data_access; insert into staff_info_new values("name1",10,"A",20000,"bossLabel"); insert into staff_info_new values("name2",6,"B",15000,"label1"); insert into staff_info_new values("name3",3,"C",10000,"label2"); insert into staff_info_new values("name4",2,"B",8000,"label3"); insert into staff_info_new values("name5",5,"C",12000,"label1"); insert into staff_info_new values("name6",4,"B",11000,"label2"); insert into staff_info_new values("name7",1,"D",5000,"label3");
从执行结果可以看出,用户删除数据时,只可以删除可以写入的数据行,对于无法写入的行是无法删除的。
5. 总结
本文基于实际的应用场景,介绍了PolarDB-X数据的LBAC功能的设计以及使用方法。LBAC通过为用户、行、列设置Security Label,在访问时通过比较用户的 Label 和行、列数据的 Label,达到约束用户对表中的数据访问的目的,实现数据访问的精细化控制。
本文作者:星铱