Klustron设置行列级安全策略
Klustron设置行列级安全策略
注意:
如无特别说明,文中的版本号可以使用任何已发布版本的版本号代替。所有已发布版本详见Release Notes.
本文内容:
Klustron是一个安全的数据库集群,具有各种级别的广泛安全功能。在最上层,可以使用基于主机的身份验证、不同的身份验证方法(LDAP、PAM)、限制侦听地址以及PostgreSQL中提供的更多安全方法,使数据库集群免受未经授权的用户的攻击。
当授权用户获得数据库访问权限时,可以通过允许或拒绝访问特定对象,在对象级别实现进一步的安全性。这可以使用各种基于角色的身份验证措施以及GRANT和REVOKE命令来完成。
在本文中,我们将在更细粒度的级别上讨论安全性,虽然用户有表的访问权限,但我们不希望允许其查看特定列或特定行。
01 设置列级安全策略
顾名思义,实施了这种安全策略后,我们希望允许用户只查看特定的列或列集,通过阻止对所有其他列的访问使其成为私有列,这样用户在选择或排序时就无法看到或使用这些列。
设置列级安全策略可以有多种方法实现,我们依次探讨。
1.1 视图方式
具体案例:数据库中有一个员工表,里面有基本的员工详细信息和工资相关信息。业务想向查询用户提供部分员工信息,但不想显示员工工资和银行账号的信息。
准备用户、表和数据
psql -h 192.168.40.152 -p 47001 postgres
create user kunlun_test with password 'kunlun';
create database testdb;
grant all privileges on database testdb to kunlun_test;
create user readusr with password 'kunlun';
\c testdb kunlun_test
create table employee ( empno int, ename text, address text, salary int, account_number text );
insert into employee values (1, 'Tony', '2 down str', 10000, '612345578' );
insert into employee values (2, 'James', '132 south avn', 5000, '412345579' );
insert into employee values (3, 'Jack', 'Down st 17th', 6000, '542124566' );
grant select on employee to readusr;
\c testdb readusr
select * from employee;
使用readusr登录testdb,刚开始有访问employee表的权限
回收readusr访问employee表的权限,授权其通过视图访问部分字段。
revoke select on employee from readusr ;
create view emp_info as select empno, ename, address from employee;
grant select on emp_info to readusr;
\q
再次通过readusr访问employee, 发现已经没有权限访问。只能通过视图访问员工号、员工名和地址,但不能访问薪水和银行账号了。
1.2 字段权限
保护列安全的另一个好选择是仅向用户授予对特定列的访问权限。在上面的示例中,我们不希望readusr用户访问employee表的salary和account_number列。我们可以提供对除salary和account_number之外的所有列的访问,而不是创建视图。
psql -h 192.168.40.152 -p 47001 -U kunlun_test -d testdb
drop view emp_info;
grant select (empno, ename, address) on employee to readusr;
然后通过readusr登录,访问employee表
发现同样的可以限制readusr访问salary和account_number字段。
注意:
用户不应该对表具有GRANT访问权限。首先必须撤消对表的SELECT访问权限,并仅为希望用户访问的列提供列访问权限。如果用户已经对整个表具有SELECT访问权限,则对特定列的列访问将不起作用。
02 设置行级安全策略
行级安全性是Klustron一个重要安全特性。此功能使数据库管理员能够在表上定义策略,以便它可以控制每个用户对数据的查看和操作。行级策略可以理解为一个额外的过滤器;当用户试图对表执行操作时,在任何查询条件或筛选之前都会应用此筛选器,并且会根据特定策略缩减数据或拒绝访问。
可以创建特定语句的行级安全策略,例如SELECT或DML(INSERT/UPDATE/DELETE),或者使用ALL。行级安全策略也可以在特定角色或多个角色上创建。
创建一个名为Jack的用户,并赋予他查询employee表的权限。
create user jack with password 'kunlun';
\c testdb kunlun_test
grant select on employee to jack;
刚开始jack可以访问employee表
然后创建行安全的策略
psql -h 192.168.40.152 -p 47001 -U kunlun_test -d testdb
create policy emp_rls_policy on employee FOR ALL TO PUBLIC USING (upper(ename)=upper(current_user));
首先通过用户kunlun_test连接testdb,在本例中他也是表employee的所有者,然后创建了策略。
策略的名称emp_rls_policy是用户定义的名称。
employee就是表的名称。
这里的ALL代表所有操作,或者我们也可以指定select/insert/update/delete任何我们想要限制的操作。
此处的PUBLIC代表所有用户。我们也可以提供策略适用的特定用户名称。
使用(ename = current_user):这部分被称为表达式。它是一个返回布尔值的筛选条件,我们将ename与当前连接到数据库的用户进行了比较。
激活行安全策略
psql -h 192.168.40.152 -p 47001 -U kunlun_test -d testdb
ALTER TABLE employee ENABLE ROW LEVEL SECURITY;
然后以jack用户登录testdb,并查询employee表
启动了行策略之后,Jack只能查询到employee表中自己对应的记录了。
假设Jack在公司里转岗了,转到了HR部门。这个时候他有权限看到employee表中的所有记录。
Klustron具有BYPASSRLS和NOBYPASSRLS权限,可以分配给一个用户;默认情况下会指定NOBYPASSRLS。表所有者和超级用户具有BYPASSRLS权限,因此他们可以跳过行级安全策略。 现在需要设置jack拥有BYPASSRLS的权限。
psql -h 192.168.40.152 -p 47001 postgres
alter user jack bypassrls;
Jack再次登录数据库时,就可以看到employee表中所有的数据了。
可以通过下面的语句删除对应的行级安全策略
psql -h 192.168.40.152 -p 47001 -U kunlun_test -d testdb
drop policy emp_rls_policy ON employee;
用户jack再次登录,发现无法访问employee表中的数据了。其实这时行级安全策略仍然在employee表上生效,需要执行下面的语句禁用employee表上的行级安全策略
psql -h 192.168.40.152 -p 47001 -U kunlun_test -d testdb
alter table employee disable row level security;
Jack再次登录后,就可以看到employee表的所有记录了。
03 行列级安全策略结合使用
假如如果规定用户只能看到自己对应的行记录,并也限制其看到自己的薪水和银行账号。我们可以使用下面的行列级安全结合的策略。
psql -h 192.168.40.152 -p 47001 -U kunlun_test -d testdb
create policy emp_rls_policy on employee FOR ALL TO PUBLIC USING (upper(ename)=upper(current_user));
ALTER TABLE employee ENABLE ROW LEVEL SECURITY;
revoke SELECT on employee from jack;
grant select (empno, ename, address) on employee to jack;
实施了行列级安全策略后,用户jack只能查询自己的员工号、姓名和地址了。
04 行级安全策略在现实应用中的实施
为了实施行级安全性,需要为公司每一个员工在数据库中创建相应的数据库账户,这个在现实应用中往往很难实现。一般通过应用服务器连接到数据库的账户只有1-2个,这个时候可以用下面的方式实现行级安全性。
假设应用只通过appuser登录数据库进行相关的业务操作,数据库中并不存在jack的用户。
psql -h 192.168.40.152 -p 47001 postgres
drop user jack;
create user appuser with password 'kunlun';
\c testdb kunlun_test;
grant select on employee to appuser;
CREATE POLICY emp_rls_policy ON employee FOR all TO public USING (upper(ename)=upper(current_setting('rls.ename')));
ALTER TABLE employee ENABLE ROW LEVEL SECURITY;
使用appuser登录testdb,可以使用session变量rls.ename来实现行级安全策略。
通过显示设置session变量rls.name为登录用户的名字,从而实现了之前的行级安全策略。