赞
踩
1、背景:opengauss作为安全数据库,可能面临隐私泄露、信息篡改、数据丢失等风险。为了防止恶意攻击者访问、窃取、篡改和破坏数据库中的数据,阻止未经授权用户通过一些系统的漏洞进行仿冒、提权等路径恶意使用数据库,opengauss提供了一些列安全措施。这一小节主要对认证机制进行详细的分析。
2、认证机制的主要功能:
(1)身份认证
上述是一个简化的流程图,主要的流程是遍历HBA规则列表,检查连接类型、SSL状态、IP地址、数据库和用户信息等,以确定是否允许连接。
password_encryption_type | 加密方法 | 加密函数接口 |
0 | MD5 | pg_md5_encrypt |
1 | SHA256+MD5 | calculate_encrypted_combined_password |
PASSWORD_TYPE_SM3 | SM3 | gs_calculate_encrypted_sm3_password |
除上述的所有情况 | SH256 | calculate_encrypted_sha256_password |
加密时候,根据参数password_encryption_type配置选择对应的加密方式,加密完成后会清理内存中的敏感信息。
创建用户和修改用户属性的函数入口分别是CreteRole和AlterRole。在函数内对口令加密前会先检验是否满足口令的复杂度,如果满足则调用calculate_encrypted_password函数实现口令的加密。
认证方法 | 值 | 描述 |
uaReject | 0 | 无条件的拒绝连接 |
uaImplicitReject | 3 | 无条件的允许连接,即允许匹配HBA记录的客户端连入数据库 |
uaGSS | 7 | 通过GSS-API(通用安全服务;application programming interface)认证用户 |
基于选择的方法的实际身份验证 | / | 具体身份验证逻辑,如uaMD5,uaSHA256,uaSM3等等 |
在函数ClientAuthentication函数中先后调用hba_getauthmethod函数、check_hba函数,检查客户端地址、所连数据库、用户名在文件HBA中是否能有匹配的HBA记录。
’check_hba_replication‘函数的主要功能是检查walsender进程的认证是否符合HBA规则,并根据一系列条件设置认证方法。最终,将匹配的'HbaLine'复制到当前连接的HBA规则,并设置当前连接的认证方法。
'check_hba'函数的主要功能是根据用户连接的信息(包括用户名、角色等)检查和是否满足HBA规则,并根据规则设置相应的认证方法。
在OpenGauss数据库中,角色管理是构建安全高效权限体系的关键组成部分。角色作为拥有数据库对象和权限的实体,可以是用户、组,或两者兼具。这一管理系统包含角色的创建、修改、删除,以及权限的授予和回收等操作。这一小节主要围绕这四方面进行详细的分析。
与角色创建的相关数据结构为CreateRoleStmt,DefElem和RoleStmtType,CreateRoleStmt的代码和相关注释如下:
其中,DefElem节点代表一个角色创建语句中可以包含的附加信息或配置项,在处理创建角色语句时,可以遍历 options 链表,处理每个 DefElem 节点,从而实现对不同选项的解析和处理,其代码如下:
RoleStmtType是一个枚举类型,表示不同角色类型,分别是角色、用户和用户组,其相关代码如下:
openGauss创建角色时,主要调用了CreateRole函数,其实现的流程图如下:
option选项 | 释义 |
SUPERUSER | NOSUPERUSER | 角色是否是超级用户 |
CREATEDB | NOCREATEDB | 角色是否有创建数据库的权限 |
CREATEROLE | NOCREATEROLE | 角色是否有创建其他角色的权限 |
INHERIT | NOINHERIT | 角色是否继承权限 |
LOGIN | NOLOGIN | 角色是否允许登录数据库 |
REPLICATION | NOREPLICATION | 角色是否允许进行复制 |
PERSISTENCE | TEMPORARY | 角色是持久性的还是临时的 |
RESOURCE POOL respool_name | 角色关联的资源池 |
CONNECTION LIMIT connlimit | 角色的最大并发连接数限制 |
同时,数据库确保了这些选项在语法上和语义上是合法的,并在不合法或冲突的情况下报错。同时,它也负责在多次指定这些选项时进行清理,以确保选项的一致性和正确性。 比如数据库在处理创建角色时涉及密码的一些选项时:
与角色修改的相关数据结构是AlterRoleStmt,其代码和相关注释如下:
数据库这样设计主要是提供了一种在某些情况下允许操作失败,而在其他情况下继续执行的机制,提高操作的灵活性和容错性。
锁定角色是指将用户账户设置为不可用或暂时禁止登录的状态。通常是为了应对一些安全性问题,例如在检测到多次登录失败(可能是密码破解尝试)后,为了防止暴力攻击。
在热备模式下(即数据库的备用节点,可能是一个只读的从节点),发生一些异常情况时,会通过锁定角色来防止非法访问或者进一步损害数据库的安全性。
解锁角色是指取消对用户账户的锁定状态,允许用户正常登录和使用数据库。在热备模式下,解锁角色可能是因为在主节点上进行了一些修复或者安全性检查,因此需要允许该角色重新访问数据库。
删除操作完成后,进行资源的清理,同时保持锁定状态直到提交,这样可以确保在事务完成之前其他事务不能访问或修改已锁定的资源,维护了事务的隔离性,防止并发执行的事务之间发生不一致的情况。
与该功能有关的数据结构有GrantRoleStmt,相关的代码和注释如下:
AddRoleMems 函数是用于向指定角色添加成员的关键函数之一。该函数主要用于处理角色和成员之间的关联关系,管理角色成员的添加,并执行相应的权限检查,通过对角色关系的合法性进行详细的权限检查和成员关系检查,确保了数据库安全性和一致性。
参数名 | 说明 |
rolename | 角色名称 |
roleid | 角色的对象标识符(OID) |
memberNames | 待添加的成员角色名称列表 |
memberIds | 待添加的成员角色的对象标识符(OID)列表 |
grantorId | 执行授权的角色的对象标识符(OID) |
admin_opt | 是否包含管理员选项 |
SQL引擎负责对用户输入的SQL语言进行编译,生成可执行的执行计划,然后将执行计划交给执行引擎进行执行。SQL引擎整个编译的过程如图1所示,在编译的过程中需要对输入的SQL语言进行词法分析、语法分析、语义分析,从而生成逻辑执行计划,逻辑执行计划经过代数优化和代价优化之后,产生物理执行计划。
(1) 词法分析:从查询语句中识别出系统支持的关键字、标识符、操作符、终结符等,确定每个词自己固有的词性。常用工具如flex。
(2) 语法分析:根据SQL语言的标准定义语法规则,使用词法分析中产生的词去匹配语法规则,如果一个SQL语句能够匹配一个语法规则,则生成对应的抽象语法树(abstract synatax tree,AST)。常用工具如Bison。
(3) 语义分析:对抽象语法树进行有效性检查,检查语法树中对应的表、列、函数、表达式是否有对应的元数据,将抽象语法树转换为查询树。
openGuass中SQL解析代码流程如下所示:
其中词法结构和语法结构分别由scan.l和gram.y文件定义,并通过flex和bison分别编译成scan.cpp和gram.cpp文件。SQL解析的相关源文件如下表所示:
源文件 | 说明 |
src/common/backend/parser/scan.l | 定义词法结构,采用Lex编译后生成scan.cpp文件 |
src/common/backend/parser/gram.y | 定义语法结构,采用Yacc编译后生成gram.cpp文件 |
src/common/backend/parser/scansup.cpp | 提供词法分析的常用函数 |
src/common/backend/parser/parser.cpp | 词法、语法分析的主入口文件,入口函数是raw_parser |
src/common/backend/parser/analyze.cpp | 语义分析的主入口文件,入口函数是parse_analyze |
完成语义分析后,SQL解析过程完成,SQL引擎开始执行查询优化。
模块 | 目录 | 说明 |
查询重写 | src/gausskernel/optimizer/prep | 主要包括子查询优化、谓词化简及正则化、谓词传递闭包等查询重写优化技术 |
统计信息 | src/gausskernel/optimizer/commands/analyze.cpp | 生成各种类型的统计信息,供选择率估算、行数估算、代价估算使用 |
代价估算 | src/common/backend/utils/adt/selfuncs.cpp src/gausskernel/optimizer/path/costsize.cpp | 进行选择率估算、行数估算、代价估算 |
物理路径 | src/gausskernel/optimizer/path | 生成物理路径 |
动态规划 | src/gausskernel/optimizer/plan | 通过动态规划方法对物理路径进行搜索 |
遗传算法 | src/gausskernel/optimizer/geqo | 通过遗传算法对物理路径进行搜索 |
(4)查询重写
查询重写就是把用户输入的SQL语句转换为更高效的等价SQL,查询重写遵循两个基本原则。
(5)动态规划
目前openGauss已经完成了基于规则的查询重写优化和逻辑分解优化,并且已经生成各个基表的物理路径。基表的物理路径仅仅是优化器规划中很小的一部分,现在openGauss将进入优化器优化的另一个重要的工作,即生成Join连接路径。openGauss采用的是自底向上的优化方式,对于多表连接路径主要采用的是动态规划和遗传算法两种方式。这里主要介绍动态规划的方式,但如果表数量有很多,就需要用遗传算法。遗传算法可以避免在表数量过多情况下带来的连接路径搜索空间膨胀的问题。对于一般场景采用动态规划的方式即可,这也是openGauss默认采用的优化方式。
(6)遗传算法
区别于动态规划将问题分解成若干独立子问题求解的方法,遗传算法是一个选择的过程,它通过将染色体杂交构建新染色体的方法增大解空间,并在解空间中随时通过适应度函数进行筛选,推举良好基因,淘汰掉不良的基因。这就使得遗传算法获得的解不会像动态规划一样,一定是全局最优解,但可以通过改进杂交和变异的方式,来争取尽量的靠近全局最优解。
得益于在多表连接中的效率优势,在openGauss数据库中,遗传算法是动态规划方法的有益补充。只有在Enable_geqo参数打开,并且待连接的RelOptInfo的数量超过Geqo_threshold(默认12个)的情况下,才会使用遗传算法。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。