你应该知道的数仓安全(代码片段)

华为云开发者社区 华为云开发者社区     2022-11-29     606

关键词:

摘要:防止数据泄露可以有两种技术路径。一是权限管理,采用最小化授权原则对使用数据的用户和应用程序授权。另一种是数据加密,包括使用SQL函数加密和透明加密。

本文分享自华为云社区《【安全无小事】你应该知道的数仓安全——加密函数》,原文作者:zhangkunhn。

前言

最近遇到一个客户场景,涉及共享schema的权限问题。场景简单可以描述为:一些用户是数据的生产方,需要在schema中创建表并写入数据;另一些用户是数据的消费方,读取schema中的数据做分析。对于该schema权限管理的一种实现方法是数据生产方在每次创建新表后告知管理员用户使用grant select on all tables in schema语法来授予消费方权限。这种方法有一定的局限性。如果生产方在schema下面又创建了一些新表,为了授权消费方使用这些新表还需要告知管理员用户再次使用grant select on all tables in schema来授权。有没有简单的应对方案?答案是肯定的,可以使用Alter default privilege。Alter default privilege用于将来创建的对象的权限的授予或回收。

语法介绍

 ALTER DEFAULT PRIVILEGES
     [ FOR  ROLE | USER  target_role [, ...] ]
     [ IN SCHEMA schema_name [, ...] ]
     abbreviated_grant_or_revoke;

其中abbreviated_grant_or_revoke子句用于指定对哪些对象进行授权或回收权限。对表授权语法是:

 GRANT   SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES  
     [, ...] | ALL [ PRIVILEGES ] 
     ON TABLES 
     TO  [ GROUP ] role_name | PUBLIC  [, ...]

参数说明

  • target_role

已有角色的名称。如果省略FOR ROLE/USER,则缺省值为当前角色/用户。

取值范围:已有角色的名称。

  • schema_name

现有模式的名称。

target_role必须有schema_name的CREATE权限。

取值范围:现有模式的名称。

  • role_name

被授予或者取消权限角色的名称。

取值范围:已存在的角色名称。

详见ALTER DEFAULT PRIVILEGES语法说明

场景示例

 testdb=# create user creator1 password \'Gauss_234\';  
 CREATE USER
 testdb=# create user creator2 password \'Gauss_234\';  
 CREATE ROLE
 testdb=# create user user1 password \'Gauss_234\';
 CREATE USER
 --创建共享schema,授予creator1和creator2创建权限,授予user1使用权限
 testdb=# create schema shared_schema;  
 CREATE SCHEMA
 testdb=> grant create, usage on schema shared_schema to creator1;
 GRANT
 testdb=> grant create, usage on schema shared_schema to creator2;
 GRANT
 testdb=# grant usage on schema shared_schema to user1;
 GRANT
 --将creator1和creator2在shared_schema中创建表的select权限授予user1
 testdb=# alter default privileges for user creator1, creator2 in schema shared_schema grant select on tables to user1;
 ALTER DEFAULT PRIVILEGES
 --切到creator1,建表
 testdb=# \\c testdb creator1
 You are now connected to database "testdb" as user "creator1".
 testdb=> create table shared_schema.t1 (c1 int);
 CREATE TABLE
 --切到creator2,建表
 testdb=> \\c testdb creator2
 You are now connected to database "testdb" as user "creator2".
 testdb=> create table shared_schema.t2 (c1 int);
 CREATE TABLE
 --切到user1,查询OK
 testdb=> \\c testdb user1
 You are now connected to database "testdb" as user "user1".
 testdb=> select * from shared_schema.t1 union select * from shared_schema.t2;
  c1 
 ----
 (0 rows)

查看默认权限的授予现状

查询系统表pg_default_acl可以查看当前哪些schema被授予了默认权限。从defaclacl字段可以看到creator1和creator2分别授予了user1对shared_schema中对象的select权限(r表示read)。

testdb=# select r.rolname, n.nspname, a.defaclobjtype, a.defaclacl from
 testdb-#     pg_default_acl a, pg_roles r, pg_namespace n
 testdb-#     where a.defaclrole=r.oid and a.defaclnamespace=n.oid;
  rolname  |    nspname    | defaclobjtype |     defaclacl      
 ----------+---------------+---------------+--------------------
  creator1 | shared_schema | r             | user1=r/creator1
  creator2 | shared_schema | r             | user1=r/creator2
 (2 rows)

一些细节

所有在共享schema中创建对象的用户都应该出现在alter default privileges for user之后的列表中。否则,如果有用户creator3没有在列表中,其在共享schema中创建的对象或者说那些Owner是creator3的对象将不能被user1查询。因为共享schema中creator3用户创建的表没有授予user1默认权限。

 testdb=# create user creator3 password \'Gauss_234\';
 CREATE USER
 testdb=# grant create, usage on schema shared_schema to creator3;
 GRANT
 testdb=# \\c testdb creator3
 You are now connected to database "testdb" as user "creator3".
 testdb=> create table shared_schema.t3 (c1 int);
 CREATE TABLE
 testdb=> \\c testdb user1
 You are now connected to database "testdb" as user "user1".
 testdb=> select * from shared_schema.t3;
 ERROR:  permission denied for relation t3

管理员可以通过alter default privileges for user将creator3放入列表中为user1授予访问creator3用户创建表的默认权限,也可以由creator3用户自己通过alter default privileges授权给user1. 前面语法参数说明中有如果省略FOR ROLE/USER,则缺省值为当前用户。

 testdb=> \\c testdb creator3
 You are now connected to database "testdb" as user "creator3".
 testdb=> alter default privileges in schema shared_schema grant select on tables to user1;
 ALTER DEFAULT PRIVILEGES
 testdb=> \\c testdb user1
 You are now connected to database "testdb" as user "user1".
 testdb=> select * from shared_schema.t3;
 ERROR:  permission denied for relation t3
 testdb=> \\c testdb creator3
 testdb=> create table shared_schema.t4 (c1 int);
 CREATE TABLE
 testdb=> \\c testdb user1
 You are now connected to database "testdb" as user "user1".
 testdb=> select * from shared_schema.t4;
  c1 
 ----
 (0 rows)

上述代码第3行为当前用户在shared_schema下面创建的表的select权限授予user1。第7行user1查询shared_schema.t3报权限不足,是因为alter default privileges只处理将来的对象。shared_schema.t3在是之前创建的。我们新建表shared_schema.t4,user1用户查询正常。

如果要处理已有表的权限,使用grant语句。参见grant语法说明

 testdb=> \\c testdb creator3
 You are now connected to database "testdb" as user "creator3".
 testdb=> grant select on all tables in schema shared_schema to user1;
 ERROR:  permission denied for relation t1
 testdb=> grant select on table shared_schema.t3 to user1;
 GRANT
 testdb=> \\c testdb user1
 You are now connected to database "testdb" as user "user1".
 testdb=> select * from shared_schema.t3;
  c1 
 ----
 (0 rows)

代码第3行中shared_schema中包含有3个用户创建的表,而creator3只是表t3的创建者(Owner)。所以授予整个schema的权限会报错,只授予creator3是Owner的表t3之后,user1用户查询正常。

alter default privileges只处理将来的对象,grant只处理已有的对象。进一步的,这两种语法授予权限时涉及的对象仅包括Owner是当前用户的对象。如果要为共享schema下面所有Owner的对象授予权限,需要使用管理员用户使用alter default privileges for user语法和grant语法。

透明加密

透明加密的应用场景

透明加密能够保障用户数据安全。更换磁盘、磁盘流出或者运维非法直接读取磁盘文件会绕过认证、权限管理和审计,从而导致数据泄露的风险。客户对业务数据有很高机密性要求时建议使用透明加密。

透明加密的原理

透明加密功能是对存在硬盘上的用户数据加密存储,对用户及上层使用SQL的应用不感知。透明的含义是指对客户来说是无感知的,仅需要创建GaussDB(DWS)集群时配置透明加密。目前支持行存表和列存表文件的加密存储,支持集群级别的透明加密配置。

集群级别的透明加密意味着集群中的所有库,库中的所有表都是加密存储。集群级别的透明加密还意味着需要在创建集群时进行配置,集群创建之后不可修改,既不能将非加密集群修改为加密集群,也不能将加密集群修改为非加密集群。

加密算法

透明加密核心是算法和密钥。我们采用AES-128算法,加密模式使用CTR。CTR流加密可以保证明文和密文长度相等,不会导致加密后数据存储空间膨胀。

密钥管理

使用华为公有云KMS服务管理,保证了用户的密钥安全。
加密密钥层次结构有三层。按层次结构顺序排列,这些密钥为主密钥(CMK)、集群密钥 (CEK)、数据库密钥 (DEK)。

  • 主密钥保存在KMS中,用于给CEK加密。
  • CEK用于加密DEK,CEK明文保存在集群内存中,密文保存在服务管理面中。
  • DEK用于加密数据库中的数据,DEK明文保存在集群内存中,密文保存在服务管理面中。

密钥轮转

出于安全考虑,用户可以执行密钥轮转操作。密钥轮转只轮转集群密钥,不论转数据库秘钥。

透明加密的后续演进

集群级透明加密的优点是所有数据包括用户表和系统表都加密,适用于所有加密需求。一枚硬币的两面性告诉我们,优点也可能是缺点。对所有数据库对象加密会对数据导入和查询带来性能上的开销。

为解决此问题,后续考虑支持细粒度透明加密。比如可以支持表级透明加密,用户在创建表时指定属性为加密表,该用户表的数据会加密存储。用户可以在包含敏感数据的表中开启加密属性,在查询和使用过程中不感知加解密过程。由于加密粒度较小,对性能的影响也较小。

透明加密是保障用户核心数据安全的有效手段。从使用场景和原理介绍了GaussDB(DWS)数仓的透明加密特性,指出了后续透明加密特性的研究方向。

SQL函数加密

技术背景

密码学中密码算法可以分为三类:哈希函数、对称密码算法和非对称密码算法。

  • 哈希函数

哈希函数又称为摘要算法,对于数据data,Hash函数会生成固定长度的数据,即Hash(data)=result。这个过程是不可逆的,即Hash函数不存在反函数,无法由result得到data。在不应保存明文场景,比如口令(password)属于敏感信息,系统管理员用户也不应该知道用户的明文口令,就应该使用哈希算法,存储口令的单向哈希值。

实际使用中会加入盐值和迭代次数,避免相同口令生成相同的哈希值,以防止彩虹表攻击。

  • 对称密码算法

对称密码算法使用相同的密钥来加密和解密数据。对称密码算法分为分组密码算法和流密码算法。

分组密码算法将明文分成固定长度的分组,用密钥对每个分组加密。由于分组长度固定,当明文长度不是分组长度的整数倍时,会对明文做填充处理。由于填充的存在,分组密码算法得到的密文长度会大于明文长度。

流密码算法将明文逐比特与密钥流运算。流密码算法不需要填充,得到的密文长度等于明文长度。

  • 非对称密码算法

非对称密码算法,又称为公钥密码算法。算法使用两个密钥:公钥和私钥。公钥向所有人公开,私钥保密。非对称密码算法应用于密钥协商、数字签名、数字证书等领域。

技术实现

GaussDB(DWS)主要提供了哈希函数和对称密码算法。哈希函数支持sha256, sha384, sha512和国密sm3。对称密码算法支持aes128, aes192, aes256和国密sm4。

哈希函数

  • md5(string)

将string使用MD5加密,并以16进制数作为返回值。MD5的安全性较低,不建议使用。

  • gs_hash(hashstr, hashmethod)

以hashmethod算法对hashstr字符串进行信息摘要,返回信息摘要字符串。支持的hashmethod:sha256, sha384, sha512, sm3。

testdb=# SELECT gs_hash(\'GaussDB(DWS)\', \'sha256\');
                             gs_hash                              
------------------------------------------------------------------
 cc2d1b97c6adfba44bbce7386516f63f16fc6e6a10bd938861d3aba501ac8aab
(1 row)

对称密码算法

  • gs_encrypt(encryptstr, keystr, cryptotype, cryptomode, hashmethod)
    采用cryptotype和cryptomode组成的加密算法以及hashmethod指定的HMAC算法,以keystr为密钥对encryptstr字符串进行加密,返回加密后的字符串。
    支持的cryptotype:aes128, aes192, aes256, sm4。
    支持的cryptomode:cbc。
    支持的hashmethod:sha256, sha384, sha512, sm3。
testdb=# SELECT gs_encrypt(\'GaussDB(DWS)\', \'1234\', \'aes128\', \'cbc\',  \'sha256\');
                                                        gs_encrypt                                                        
--------------------------------------------------------------------------------------------------------------------------
 AAAAAAAAAADlzZYiNQK1uB+p1gza4Lu3Moj3HdP4E1uJmqfDYBaXDLMt7RZoE0YVx9h2dMRYBQ5fhFNqqM49sUkeS72o8kX5vWRQvfW3fuocGyp+b+lX9A==
(1 row)
  • gs_decrypt(decryptstr, keystr,cryptotype, cryptomode, hashmethod)

采用cryptotype和cryptomode组成的加密算法以及hashmethod指定的HMAC算法,以keystr为密钥对decryptstr字符串进行解密,返回解密后的字符串。解密使用的keystr必须保证与加密时使用的keystr一致才能正常解密。

testdb=# SELECT gs_decrypt(\'AAAAAAAAAADlzZYiNQK1uB+p1gza4Lu3Moj3HdP4E1uJmqfDYBaXDLMt7RZoE0YVx9h2dMRYBQ5fhFNqqM49sUkeS72o8kX5vWRQvfW3fuocGyp+b+lX9A==\', \'1234\', \'aes128\', \'cbc\',  \'sha256\');
  gs_decrypt  
--------------
 GaussDB(DWS)
(1 row)

效果分析

有个student表,有id,name和score三个属性。name可以使用哈希函数加密保存,score可以使用对称密码算法保存。

testdb=# create table student (id int, name text, score text);
CREATE TABLE
testdb=# insert into student values (1, gs_hash(\'alice\', \'sha256\'), gs_encrypt(\'95\', \'12345\', \'aes128\', \'cbc\', \'sha256\'));
INSERT 0 1
testdb=# insert into student values (2, gs_hash(\'bob\', \'sha256\'), gs_encrypt(\'92\', \'12345\', \'aes128\', \'cbc\', \'sha256\'));
INSERT 0 1
testdb=# insert into student values (3, gs_hash(\'peter\', \'sha256\'), gs_encrypt(\'98\', \'12345\', \'aes128\', \'cbc\', \'sha256\'));
INSERT 0 1

没有密钥的用户即使拥有了select权限也无法看到name和score这两列加密数据。

testdb=# select * from student;
 id |                               name                               |                                                          score                                                           
----+------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------
  1 | 2bd806c97f0e00af1a1fc3328fa763a9269723c8db8fac4f93af71db186d6e90 | AAAAAAAAAAB26RmKZdGciLdOM1Z0sjsHg6Qh1b8taF3cY5KDVm+faJK5AT9tjufkr3Wogj3tIpFfiIEb6+miGqPHWcmKnFsArAMoBG9pPDawGs1Qze7xGg==
  2 | 81b637d8fcd2c6da6359e6963113a1170de795e4b725b84d1e0b4cfd9ec58ce9 | AAAAAAAAAAB26RmKZdGciLdOM1Z0sjsHZOHH7URkyme6r8Hfh1k0UsVbgbREjFMkgB52w+7GtUGqGgUik07ghajSD9PMIDLd/49wBCVROm2/HSOw6jzbxA==
  3 | 026ad9b14a7453b7488daa0c6acbc258b1506f52c441c7c465474c1a564394ff | AAAAAAAAAAB26RmKZdGciLdOM1Z0sjsHwv6p/OAfDUyVULAqpaHIrYJYMcqLmQSj3K/REyavfMoKB7hgUpEPXfHRutWur37bru68jjt5XcBHFBjZeMgowA==
(3 rows)

拥有密钥的用户可以通过解密查看到加密数据。

testdb=# select id, gs_decrypt(score, \'12345\', \'aes128\', \'cbc\', \'sha256\') from student;
 id | gs_decrypt 
----+------------
  1 | 95
  2 | 92
  3 | 98
(3 rows)

总结

数据加密是防止未授权访问和防护数据泄露的有效技术。介绍了密码算法的基本原理和GaussDB(DWS)数仓的加密函数,包括哈希函数gs_hash,对称密码算法gs_encrypt/gs_decrypt。举例说明了加密函数的使用场景。

想了解GuassDB(DWS)更多信息,欢迎微信搜索“GaussDB DWS”关注微信公众号,和您分享最新最全的PB级数仓黑科技~

 

点击关注,第一时间了解华为云新鲜技术~

数据膨胀了?你的数仓又没有空间了?(代码片段)

...数据膨胀,指的是物理数据文件的大小明显高于实际存储的数据量。甚至某些特殊场景下,一个表中只有一条简单的数据,但是表对应的物理文件可能已 查看详情

你应该知道的javascript是什么?(代码片段)

本文由乐字节Java课程赞助主要内容JavaScript简介?JavaScript是一种具有面向对象能力的、解释型的程序设计语言。更具体一点,它是基于对象和事件驱动并具有相对安全性的客户端脚本语言。它的主要目的是,验证发往服务器端的... 查看详情

你应该知道的javascript是什么?(代码片段)

本文由乐字节Java课程赞助主要内容JavaScript简介?JavaScript是一种具有面向对象能力的、解释型的程序设计语言。更具体一点,它是基于对象和事件驱动并具有相对安全性的客户端脚本语言。它的主要目的是,验证发往服务器端的... 查看详情

大数据开发工程师需要了解的数仓中的维度设计(代码片段)

目录(1)数仓模型如何分层(2)企业数仓模型分层架构(3)维度设计如何理解(4)维表是怎么生成的(5)维度整合的两种策略(6)维度拆分的最佳方案(7)缓慢变化维的... 查看详情

你应该知道的jvm运行原理(代码片段)

背景:曾几何时,我也曾疑惑过,我们编写的代码到底安不安全。我们创建一个对象去请求api接口,我们接口直接调用的数据会不会互相影响,读了本文,将会解答你的所有的困惑。1.jvm内存区域划分以jdk1... 查看详情

数仓备机dn重建:快速修复你的数仓dn单点故障

摘要:大规模分布式系统中的故障无法避免。当DN发生单点故障时,恢复手段有哪些,又是如何恢复的,本节重点介绍操作gs_ctlbuild是如何修复DN单点故障的。本文分享自华为云社区《华为云数仓备机DN重建,快速修复DN单点故障!... 查看详情

hadoop离线day08--数据仓库apachehive(代码片段)

...PT事务OLAPA分析数仓的分层架构#2、当下大数据领域最著名的数仓软件ApacheHiveHive是什么数仓基于Hadoop的数仓如何理解和Hadoop关系核心 查看详情

spingioc和di你应该知道事情1(代码片段)

springIOC和springDI作为springcore的核心思想,有必要学习下才能更好的使用spring===================================================================================AbstractXmlApplicationContextabstractXmlApplicationContext=new 查看详情

盘点数据仓库建设需要知道的那些事(代码片段)

...护航者。为了数据体系能够长久健康的发展,数仓管理,应该从人治逐步转变到制度化、规范化、工具化的道路上了来。在数据仓库开发的过程中,遵循一定的规范能够避免我们的开发偏离原有设计的方向,也能够保证数据安全... 查看详情

你应该知道的springbootmongodbjpa那些小tip.(代码片段)

官方文档https://docs.spring.io/spring-data/data-mongodb/docs/current/reference/html/index.html查询:***************************************************************************mongoTemple查询和修改@AutowiredMongoT 查看详情

你应该知道的reactrouter4(代码片段)

  看完Router的变化,接着来说<Switch>组件。在3.X中,你可以指定很多子路由,但是只有第一个匹配的路径才会被渲染。就像这样,<Routepath=‘/‘component=App><IndexRoutecomponent=Home/><Routepath=‘about‘component=About/><R... 查看详情

这些linux技巧你应该知道(代码片段)

...metime-savingtipsthateveryLinuxusershouldknow?》——Linux用户有哪些应该知道的提高效率的技巧。我觉得挺好的,总结得比较好,把其转过来& 查看详情

你应该知道的rocketmq(代码片段)

1.概述在很久之前写过一篇Kafka相关的文章,你需要知道的Kafka,那个时候在业务上更多的是使用的是Kafka,而现在换了公司之后,更多的使用的是Rocketmq,本篇文章会尽力全面的介绍RocketMQ和Kafka各个关键点的比较,希望大家读完... 查看详情

转发:你应该知道的rpc原理(代码片段)

from:https://www.cnblogs.com/LBSer/p/4853234.html 你应该知道的RPC原理  在学校期间大家都写过不少程序,比如写个helloworld服务类,然后本地调用下,如下所示。这些程序的特点是服务消费方和服务提供方是本地调用关系。  而一... 查看详情

你应该知道的reactrouter4(代码片段)

  上一篇我们说到了路由组件的嵌套。想必你已经运用自如了。那么,这一次我们来聊一聊4.X中Router的变更。在3.X中我们若使用路由的模式,可通过在Router上配置history的值即可。例如,importRouter,Route,hashHistoryfrom"react-router"impor... 查看详情

网络安全你应该知道的几个网络安全概念

我们大家都知道网络安全的重要性,但对于网络安全相关知识了解的少之又少。今天我们小编就告诉你几个网络安全概念,以便大家了解。一、安全Web网关安全Web网关已经从其过去优化互联网带宽的目的演变为保护用户... 查看详情

关于防御性编程,你应该知道的事(代码片段)

*请求处理通用类@NotBlank(message="参数str不能为空")privateStringstr;@NotNull(message="参数i不能为空")privateIntegeri;@Min(value=0,message="最小值不能小于0")privateintmin;@Max(value=100,message="最大值不能大约100")privateintmax;public 查看详情

大数据开发工程师需要了解的数仓中的维度设计(代码片段)

...属性的处理方式(1)数仓模型如何分层企业常用的数据模型分为三层:操作数据层(ODS)公共维度模型层(CDM)数据应用层(ADS)其中公共维度模型层包括:明细数据层(DWD)汇总... 查看详情