KingbaseES用户角色与最小权限控制实践
KingbaseES 用户、角色与最小权限控制实践让账号只做该做的事本文是本系列第 15 篇。上一篇完成了逻辑备份和恢复演练本文进入权限治理讲解如何创建用户、角色并按最小权限访问kb_shop。引言上一篇文章强调了数据保护通过备份恢复确保数据出问题时能找回来。但数据安全不只靠备份还要靠权限控制。一个账号如果拥有过大的权限即使不是恶意操作也可能因为误删、误改造成事故。数据库权限管理的核心原则是最小权限也就是说一个账号只应该拥有完成工作所需的权限。报表用户只读报表业务写入用户只能写业务表管理员权限不要随意下放。本文会在kb_shop中创建两个角色角色用途kb_shop_readonly只读报表和查询kb_shop_writer允许写入业务表文章目录KingbaseES 用户、角色与最小权限控制实践让账号只做该做的事引言用户和角色的关系一、连接 kb_shop二、创建角色三、给只读角色授权四、创建报表用户五、给写入角色授权六、创建业务写入用户七、回收权限八、权限模型设计建议九、常见问题排查问题 1明明给了 SELECT仍提示无权限问题 2用户加入角色后仍提示模式权限不足问题 3插入 SERIAL 表失败问题 4不知道用户有什么角色问题 5创建角色或用户时提示已经存在十、本文小结用户和角色的关系在数据库中用户和角色都和权限有关。可以简单理解为用户用于登录 角色用于承载权限 用户加入角色后获得对应权限这样做的好处是权限可以复用。比如有 5 个报表账号不需要给每个账号逐条授权只要把它们加入kb_shop_readonly角色即可。这也是企业级数据库权限治理中比较常见的设计方式。电科金仓 KingbaseES 面向关键业务场景数据库账号往往会服务于应用系统、报表平台、运维脚本和人工管理等不同入口。如果所有入口都直接使用管理员账号后续很难判断某次变更由谁发起也很难控制误操作范围。用“用户负责登录、角色承载权限”的方式可以把登录身份和权限集合拆开让权限边界更清晰。从截图可以看到本文并不是只停留在授权语句本身而是通过\du、只读查询、写入失败、写入用户插入成功等结果验证了权限模型是否真正生效。投稿文章中建议保留这些执行结果因为权限控制最重要的不是“执行过 GRANT”而是能证明普通账号只能做被允许的操作。一、连接 kb_shopcd /d D:\Tools\Kingbase\ES\Server\bin ksql -U system -d kb_shop -h localhost -p 54321查看当前用户SELECTcurrent_database(),current_user;权限管理建议使用管理员用户执行避免中途因为权限不足失败。这里一定要确认当前数据库是kb_shop。如果上一篇恢复演练后还停留在kb_shop_restore#需要先退出再重新连接kb_shop\qksql -U system -d kb_shop -h localhost -p 54321模式、表和视图权限都是数据库内对象权限。在kb_shop_restore中执行的授权不会自动作用到kb_shop。二、创建角色CREATEROLE kb_shop_readonly;CREATEROLE kb_shop_writer;查看角色\du角色本身不一定用于登录它更像权限集合。三、给只读角色授权允许连接数据库GRANTCONNECTONDATABASEkb_shopTOkb_shop_readonly;允许访问模式GRANTUSAGEONSCHEMAsalesTOkb_shop_readonly;GRANTUSAGEONSCHEMAinventoryTOkb_shop_readonly;GRANTUSAGEONSCHEMAreportTOkb_shop_readonly;允许查询表和视图GRANTSELECTONALLTABLESINSCHEMAsalesTOkb_shop_readonly;GRANTSELECTONALLTABLESINSCHEMAinventoryTOkb_shop_readonly;GRANTSELECTONALLTABLESINSCHEMAreportTOkb_shop_readonly;这里的授权分两层先允许进入模式再允许查询模式下对象。只给表授权但不给模式USAGE访问时仍可能失败。这一步是很多初学者容易漏掉的地方。KingbaseES 和 PostgreSQL 风格数据库一样模式本身也是权限边界。访问report.v_order_list时用户既要有report模式的使用权限也要有视图对象的查询权限。把这两个层次分开理解后续排查“表有权限但仍然提示 schema 权限不足”会容易很多。四、创建报表用户CREATEUSERreport_userWITHPASSWORDReport123456;GRANTkb_shop_readonlyTOreport_user;如果report_user已经存在可以改为执行ALTERUSERreport_userWITHPASSWORDReport123456;GRANTkb_shop_readonlyTOreport_user;其中SELECT current_database();应返回kb_shop。测试连接ksql -U report_user -d kb_shop -h localhost -p 54321查询报表视图SELECT*FROMreport.v_order_listORDERBYcreated_atDESC;尝试写入客户表INSERTINTOsales.customer(customer_name,phone,customer_level)VALUES(只读测试,13900000001,normal);如果权限控制正确这条写入应该失败。这个失败是好事说明只读用户被限制住了。截图中的失败结果正好说明最小权限原则生效report_user能完成报表查询但不能直接向sales.customer写入数据。对真实系统来说这种失败不是异常而是安全边界的一部分。报表系统、BI 工具或临时查询账号应尽量只访问经过整理的视图或必要表避免因为报表端误操作影响交易数据。五、给写入角色授权测试完report_user后先退出当前连接\q后续授权和创建用户需要切回管理员用户执行ksql -U system -d kb_shop -h localhost -p 54321业务写入角色需要对基础表有增删改查权限GRANTCONNECTONDATABASEkb_shopTOkb_shop_writer;GRANTUSAGEONSCHEMAsalesTOkb_shop_writer;GRANTUSAGEONSCHEMAinventoryTOkb_shop_writer;GRANTSELECT,INSERT,UPDATE,DELETEONALLTABLESINSCHEMAsalesTOkb_shop_writer;GRANTSELECT,INSERT,UPDATEONALLTABLESINSCHEMAinventoryTOkb_shop_writer;如果表中使用了SERIAL还需要序列权限GRANTUSAGE,SELECTONALLSEQUENCESINSCHEMAsalesTOkb_shop_writer;GRANTUSAGE,SELECTONALLSEQUENCESINSCHEMAinventoryTOkb_shop_writer;序列权限容易被忽略。如果没有序列权限插入自增主键表时可能失败。业务写入角色和只读角色的差别不只在于INSERT、UPDATE、DELETE。如果表使用自增字段写入动作还会依赖序列对象。因此授权时要把表权限、模式权限和序列权限一起检查。截图中后续app_user能完成插入说明写入链路里的对象权限已经比较完整。六、创建业务写入用户CREATEUSERapp_userWITHPASSWORDApp123456;GRANTkb_shop_writerTOapp_user;如果app_user已经存在可以补执行ALTERUSERapp_userWITHPASSWORDApp123456;GRANTkb_shop_writerTOapp_user;退出管理员连接使用app_user重新连接后测试插入\qksql -U app_user -d kb_shop -h localhost -p 54321INSERTINTOsales.customer(customer_name,phone,customer_level)VALUES(应用用户测试,13900000002,normal);查询SELECTcustomer_id,customer_name,phoneFROMsales.customerWHEREphone13900000002;七、回收权限测试完app_user后如果要继续演示权限回收需要再次切回system管理员连接\qksql -U system -d kb_shop -h localhost -p 54321权限回收和授权一样重要。人员岗位变化、系统下线、临时账号过期都需要及时回收权限。这里先把回收操作作为演示语句说明不建议在当前学习环境中直接执行。原因是权限治理章节前后会反复使用report_user做只读验证如果马上回收角色读者后续回看本文查询报表视图时还需要重新授权。如果不再允许报表用户访问库存表可以执行REVOKESELECTONALLTABLESINSCHEMAinventoryFROMkb_shop_readonly;如果要撤销用户角色可以执行REVOKEkb_shop_readonlyFROMreport_user;如果你只是跟着专栏连续学习建议先不要执行上面两条REVOKE。否则后续再使用report_user复查报表只读权限时需要重新执行前面的授权语句。八、权限模型设计建议做权限设计的时候其实最好别围着某一个具体的人去搞而是得围着某一类职责去弄。那为什么要这样搞呢原因很简单。因为如果人变了的话你往往仅仅只需要去调一下用户和角色的对应关系就行了。也就不用去重写一大堆授权的语句了那样真的很麻烦。那么在咱们这个kb_shop里面的话通常来说是可以弄出这么一个权限模型出来的report_user - kb_shop_readonly - 查询 report / sales / inventory app_user - kb_shop_writer - 写入 sales / inventory system - 管理员 - 管理对象和权限这种设计到底好在哪呢其实也就是权限的边界搞得特别清楚。也就是说做报表的用户他没法去改数据应用层面的用户呢也不需要什么管理员权限。还有那个管理员账号你也千万别让应用程序一直长期去用着它这很不安全。那如果后续咱们还要增加审计用户的情况其实是可以接着去创建的就像这样CREATEROLE kb_shop_auditor;建好之后呢再去给他配上一些必须要有的查询权限就行了。权限模型这东西它应该是跟着业务角色去慢慢扩展的。你千万别把所有的权限都瞎堆在某一个账号上面这是一个大坑。九、常见问题排查问题 1明明给了 SELECT仍提示无权限遇到这种情况的话你得去查一查是不是忘了给模式的USAGE权限了。也就是说你得执行一下这个GRANTUSAGEONSCHEMAsalesTOkb_shop_readonly;问题 2用户加入角色后仍提示模式权限不足如果说你已经执行了下面这个把角色给用户的语句GRANTkb_shop_readonlyTOreport_user;但是呢你用report_user去查report.v_order_list的时候它还是给你报错说ERROR: 对模式 report 权限不够这是一个问题。那为什么会这样呢这时候你得先去检查一下你的授权语句到底是不是在那个正确的数据库里面执行的。你可以用管理员用户连上去然后跑一下这个看看SELECTcurrent_database();要是它返回的是kb_shop_restore的话那就说明你这时候还停留在上一篇那个恢复测试库里面没出来呢。那你得先退出来接着重新去连咱们的kb_shop像这样ksql -U system -d kb_shop -h localhost -p 54321进对了库之后再去kb_shop里面把这些授权的语句重新跑一遍GRANTUSAGEONSCHEMAreportTOkb_shop_readonly;GRANTSELECTONALLTABLESINSCHEMAreportTOkb_shop_readonly;GRANTkb_shop_readonlyTOreport_user;这里面有个常识大家得知道。模式、表还有视图的权限它往往仅仅只是对你当前连着的这个数据库里的东西才管用。你在kb_shop_restore里面去做授权那是没法让report_user拿到kb_shop.report这个模式的权限的。那么改好之后呢你得把report_user现在的连接给退了重新登进去再测一下才行ksql -U report_user -d kb_shop -h localhost -p 54321问题 3插入 SERIAL 表失败往那种带 SERIAL 类型的表里插数据如果失败了的话你得去看看序列的权限给没给GRANTUSAGE,SELECTONALLSEQUENCESINSCHEMAsalesTOkb_shop_writer;问题 4不知道用户有什么角色如果你搞不清楚某个用户到底有哪些角色的话直接去执行这个命令就行\du或者说是你去查一下系统表里的信息也是可以的。问题 5创建角色或用户时提示已经存在遇到这个提示那就说明你之前肯定已经跑过这篇文章里的那个建角色语句了。你可以先去用\du看看现在都有哪些角色和用户。要是kb_shop_readonly、kb_shop_writer、report_user或者app_user这些已经存在了的话那就别再去重复创建了。你直接接着往下走去跑后面的授权或者测试步骤就行了。十、本文小结本文承接第十四篇备份恢复从数据保护进入访问控制。我们创建了只读角色、写入角色、报表用户和应用用户并通过授权和回收体现最小权限原则。本文掌握了CREATE ROLE CREATE USER GRANT CONNECT GRANT USAGE ON SCHEMA GRANT SELECT / INSERT / UPDATE / DELETE GRANT SEQUENCE 权限 REVOKE 最小权限原则下一篇会继续安全主题进一步讨论账号安全、密码管理、敏感操作控制和日常安全检查让数据库不仅能用还要尽量安全地用。