暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

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

小希 2024-08-28
238

创建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表达员工部门,不同类型的安全标签组件比较大小的规则是不同的。

  1. 创建Security Policy
create security policy 
'staff_data_access' components 'rank,type,structure';

安全策略定义了安全标签的模式,其内部包含的安全标签必须遵守该模式,这里定义了staff_data_access安全策略,其内部的安全标签必须由rank,type,structure三个安全标签组件构成。

  1. 创建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,其表示只能由指定级别以上的员工访问,不限制其工种和部分。

创建用户

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及下级部门的员工信息

数据访问控制

LBAC功能全局开关

set global enable_lbac=true;

UDF测试

PolarDB-X内部提供了函数用于LBAC功能:

  • lbac_user_write_label(security_policy):返回当前用户在指定安全策略下的write_label;
  • lbac_user_read_label(security_policy):返回当前用户在指定安全策略下的read_label;
  • lbac_read(security_label1, security_label2):返回在读取场景,security_label1是否大于等于security_label2
  • lbac_write(security_label1, security_label2):返回在写入场景,security_label1是否大于等于security_label2

注意:目前实现中读取和写入场景的安全标签比较规则是一致的,所以lbac_read和lbac_write返回结果应该相同。

//1. 判断label1是否大于等于其他label 
select lbac_read('label1','label1'); //返回1
select lbac_read('label1','label2'); //返回1
select lbac_read('label1','label3'); //返回0
select lbac_read('label1','bossLabel');//返回0
select lbac_read('label1','level4Label');//返回1
select lbac_read('label1','level2Label');//返回1


//2. 判断label2是否大于等于其他label 
select lbac_write('label2','label1'); //返回0
select lbac_write('label2','label2'); //返回1
select lbac_write('label2','label3'); //返回0
select lbac_write('label2','bossLabel');//返回0
select lbac_write('label2','level4Label');//返回0
select lbac_write('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

  1. 情景一:查询所有员工的信息
select * from staff_info;

select salary from staff_info;

select username, seniority, performance, _polar_security_label from staff_info;

select count(1) from staff_info;

从执行结果可以看出:

  • 当SQL查询涉及到当前用户无法读取的列时,SQL执行会失败
  • 对于数据表中当前用户无法读取的行,数据对于当前用户是不可见的
  1. 情景二:查询工资高于10000的员工
select username from staff_info where salary > 10000;

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


  1. 情景三:查询每个员工和平均工资的差距
select username, (select (t1.salary - avg(t2.salary)) from staff_info as t2) from staff_info as t1;

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

除此之外,当SQL语句的order by,group by,window等部分包含无法读取的列时,SQL执行会失败。

Update

  1. 情景一:将员工的工龄增加1
update staff_info set seniority = seniority + 1 where username='name1';

update staff_info set seniority = seniority + 1 where username='name2';

update staff_info set seniority = seniority + 1 where username='name3';

从执行结果可以看出:

  • 当前用户无法读取name1员工的数据行,所以更新了0行,并没有更新成功。
  • 当前用户可以读取name2员工的数据行,但是无法写入更新,所以更新了0行,并没有更新成功。
  • 当前用户可以读取name3员工的数据行,也可以写入更新,所以更新了1行,更新成功。
  1. 情景二:将员工的工资增加1000
update staff_info set salary = salary + 1 where username='name3';

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


  1. 情景三:更新员工的PSL列
update staff_info set _polar_security_label = 'label1' where username='name3';

update staff_info set _polar_security_label = 'label2' where username='name3';

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

Insert

  1. 情景一:插入一条员工信息
insert into staff_info(username, seniority, _polar_security_label) values('name8', 8, 'label2');

insert into staff_info(username, seniority, performance, _polar_security_label) values('name9', 8, 'A','label2');

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

insert into staff_info(username, seniority, _polar_security_label) values('name10', 6, 'label1');

insert into staff_info(username, seniority) values('name11', 2);

select username, seniority, performance, _polar_security_label from staff_info where username='name11';

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

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

Delete

  1. 情景一:删除所有员工信息
/*TDDL:FORBID_EXECUTE_DML_ALL=FALSE*/delete from staff_info;

从执行结果可以看出,用户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");
//以tmb_pd_ld用户身份登录
select * from staff_info_new;

/*TDDL:FORBID_EXECUTE_DML_ALL=FALSE*/delete from staff_info_new;

select * from staff_info_new;

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

总结

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

参考

PolarDB-X 企业级特性之 TDE

PolarDB-X 企业级特性之三权分立

https://www.ibm.com/docs/zh/db2/10.5?topic=security-label-based-access-control-lbac

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论