PolarDB-X 企业级特性之行级访问权限控制

简介: 本文介绍PolarDB-X数据库实现了基于标签的访问控制功能,可以在行、列级别对数据访问进行控制,精细化的限制用户对数据的访问和操作,保证了读写数据的安全。下文根据实际应用场景,介绍PolarDB-X的LBAC功能设计以及使用方法。

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的工种相同

image.png


PolarDB-X可以使用基于标签的访问控制(LBAC)实现上述要求,即为每个员工设置一个安全标签(security label),当员工1查询数据库中员工2的信息时,只有label1 >= label2时,才可以访问成功。那要如何设计安全标签的模式,才能满足上述数据访问控制策略呢?

image.png

我们将员工的安全标签分为三个组成部分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

image.png

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用户身份进行查询,可以访问所有数据:

image.png

根据上文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

情景一:查询所有员工的信息

22.png

从执行结果可以看出:

  • 当SQL查询涉及到当前用户无法读取的列时,SQL执行会失败
  • 对于数据表中当前用户无法读取的行,数据对于当前用户是不可见的


情景二:查询工资高于10000的员工

20231019191029.jpg

从执行结果可以看出,当where条件中包含无法读取的列时,SQL执行会失败;


情景三:查询每个员工和平均工资的差距

20231019191104.jpg

从执行结果可以看出,当子查询中包含无法读取的列时,SQL执行会失败; 除此之外,当SQL语句的order by,group by,window等部分包含无法读取的列时,SQL执行会失败。


Update

情景一:将员工的工龄增加1

20231019191153.jpg

从执行结果可以看出:

  • 当前用户无法读取name1员工的数据行,所以更新了0行,并没有更新成功。
  • 当前用户可以读取name2员工的数据行,但是无法写入更新,所以更新了0行,并没有更新成功。
  • 当前用户可以读取name3员工的数据行,也可以写入更新,所以更新了1行,更新成功。


情景二:将员工的工资增加1000

20231019191239.jpg

从执行结果可以看出,当用户更新数据行涉及到无法写入的列时,SQL执行会失败。


情景三:更新员工的PSL列

20231019191312.jpg

PolarDB-X规定,当用户更新数据表中的PSL列的值时,必须保证当前用户的write_label大于等于新的label值。所以从执行结果可以看出,当将name3员工的PSL列更新为label1时,SQL执行失败,更新为label2时,SQL执行成功。


Insert

情景一:插入一条员工信息

image.png

从执行结果可以看出,当插入数据行时涉及到无法写入的列时,SQL执行会失败。

20231019191731.jpg

PolarDB-X规定,当用户插入记录包含PSL列时,必须保证当前用户的write_label大于等于插入的label值。所以从执行结果中可以看出,当前用户插入label1时,SQL执行失败。

未标题-1.png

PolarDB-X规定,当用户插入记录不包含PSL列时,该行的PSL列值默认为当前用户的write_label。所以从执行结果可以看出,name11员工的PSL列值为label2。

Delete

情景一:删除所有员工信息

20231019191846.jpg

从执行结果可以看出,用户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");

image.png

从执行结果可以看出,用户删除数据时,只可以删除可以写入的数据行,对于无法写入的行是无法删除的。

5. 总结

本文基于实际的应用场景,介绍了PolarDB-X数据的LBAC功能的设计以及使用方法。LBAC通过为用户、行、列设置Security Label,在访问时通过比较用户的 Label 和行、列数据的 Label,达到约束用户对表中的数据访问的目的,实现数据访问的精细化控制。


本文作者:星铱


作者介绍
目录

相关产品

  • 云原生分布式数据库 PolarDB-X