Postgresql源码(114)视图权限授予逻辑

news/2024/7/9 23:13:19 标签: postgresql, 数据库, grant

0 速查

被授权的对象在系统表中记录授权信息,例如pg_namespace中的nspacl列:

{mingjie=UC/mingjie,=UC/mingjie,pusr1=UC/mingjie}

pusr1=UC/mingjie的含义:

  • mingjie是赋予者
  • pusr1是被赋予者
  • UC是权限,表示USAGE和CREATE

1 视图权限案例

有时会遇到下面场景,访问一个视图没有权限:

drop schema sch1 cascade;
drop user pusr1;
drop user pusr2;

create user pusr1;
create user pusr2;

create schema sch1;

create procedure sch1.func1(i int) as $$
begin
  raise notice 'func1';
end;
$$ language plpgsql;

\c - pusr1
call sch1.func1(1);

结果
在这里插入图片描述
查看namespace视图:
在这里插入图片描述
这种情况下,添加两种权限都可以访问函数:

grant all on schema sch1 to public;
grant all on schema sch1 to pusr1;

在这里插入图片描述

这里我们看到namespace元数据增加了两条规则,对应两条grant

grant all on schema sch1 to public;   →          =UC/mingjie           
grant all on schema sch1 to pusr1;    →     pusr1=UC/mingjie     

显然这两条规则就是权限判断的依据,下面分析这两条规则的使用流程。

2 权限判定流程分析

部分代码

static AclMode
pg_namespace_aclmask(Oid nsp_oid, Oid roleid,
					 AclMode mask, AclMaskHow how)
{
	...
	...

查pg_namespace表:

	tuple = SearchSysCache1(NAMESPACEOID, ObjectIdGetDatum(nsp_oid));

检查owner是谁?

	ownerId = ((Form_pg_namespace) GETSTRUCT(tuple))->nspowner;

拿到规则aclDatum:{mingjie=UC/mingjie,=UC/mingjie,pusr1=UC/mingjie}

	aclDatum = SysCacheGetAttr(NAMESPACEOID, tuple, Anum_pg_namespace_nspacl,
							   &isNull);

默认没grant的时候aclDatum字段是isNull,这时候owner有权限访问,其他没权限。

	if (isNull)
	{
		/* No ACL, so build default ACL */
		acl = acldefault(OBJECT_SCHEMA, ownerId);
		aclDatum = (Datum) 0;
	}

grant后,aclDatum字段有值了,把{mingjie=UC/mingjie,=UC/mingjie,pusr1=UC/mingjie}传入,detoast后变成valena变长类型。

	else
	{
		/* detoast ACL if necessary */
		acl = DatumGetAclP(aclDatum);
	}

拿着acl进入aclmask处理,判断roleid是否有访问权限。

	result = aclmask(acl, roleid, ownerId, mask, how);

	...
	...

	return result;
}

aclmask函数

AclMode
aclmask(const Acl *acl, Oid roleid, Oid ownerId,
		AclMode mask, AclMaskHow how)
{

入参:

  • valena变量含义{mingjie=UC/mingjie,=UC/mingjie,pusr1=UC/mingjie}
  • roleid:24601表示pusr1。
  • ownerId:10表示建库的超级用户。
  • mask:256表示#define ACL_USAGE (1<<8) /* for various object types */
  • how:ACLMASK_ANY

	num = ACL_NUM(acl);
	aidat = ACL_DAT(acl);

num = 3
(gdb) p aidat[0]
$6 = {ai_grantee = 10, ai_grantor = 10, ai_privs = 768}
(gdb) p aidat[1
$7 = {ai_grantee = 0, ai_grantor = 10, ai_privs = 768}
(gdb) p aidat[2
$8 = {ai_grantee = 24601, ai_grantor = 10, ai_privs = 768}

这里解释下这三个数据的含义
$8 = {ai_grantee = 24601, ai_grantor = 10, ai_privs = 768}

10表示建库的超级用户,赋予,24601表示pusr1,768的权限
768 = 1100000000 = ACL_USAGE | ACL_CREATE
#define ACL_USAGE (1<<8) /* for various object types */
#define ACL_CREATE (1<<9) /* for namespaces and databases */

注意这里有一个特殊的ai_grantee:ACL_ID_PUBLIC=0,表示被授权者是任意用户。

下面循环就是对上述逻辑进行判断:

	/*
	 * Check privileges granted directly to roleid or to public
	 */
	for (i = 0; i < num; i++)
	{
		AclItem    *aidata = &aidat[i];

		if (aidata->ai_grantee == ACL_ID_PUBLIC ||
			aidata->ai_grantee == roleid)
		{
			result |= aidata->ai_privs & mask;
			if ((how == ACLMASK_ALL) ? (result == mask) : (result != 0))

返回256:ACL_USAGE

				return result;
		}
	}
	...
	...
}

grant__to_public_165">3 系统schema的grant … to public是哪里赋值的?

注意到pg_catalog、public、information_schema三者都是有初始授权的,记录下赋值方法和位置。

postgres=> select * from pg_namespace ;
  oid  |      nspname       | nspowner |                            nspacl
-------+--------------------+----------+---------------------------------------------------------------
    99 | pg_toast           |       10 |
    11 | pg_catalog         |       10 | {mingjie=UC/mingjie,=U/mingjie}
  2200 | public             |     6171 | {pg_database_owner=UC/pg_database_owner,=U/pg_database_owner}
 13918 | information_schema |       10 | {mingjie=UC/mingjie,=U/mingjie}

information_schema

在information_schema.sql中赋权:

CREATE SCHEMA information_schema;
GRANT USAGE ON SCHEMA information_schema TO PUBLIC;
SET search_path TO information_schema;

pg_catalog / public

pg_namespace.dat里面插入pg_catalog的tuple,但没有权限信息:

[

{ oid => '11', oid_symbol => 'PG_CATALOG_NAMESPACE',
  descr => 'system catalog schema',
  nspname => 'pg_catalog', nspacl => '_null_' },
{ oid => '99', oid_symbol => 'PG_TOAST_NAMESPACE',
  descr => 'reserved schema for TOAST tables',
  nspname => 'pg_toast', nspacl => '_null_' },
# update dumpNamespace() if changing this descr
{ oid => '2200', oid_symbol => 'PG_PUBLIC_NAMESPACE',
  descr => 'standard public schema',
  nspname => 'public', nspowner => 'pg_database_owner', nspacl => '_null_' },

]

initdb初始化时在这里给pg_catalog授权:
在这里插入图片描述

(gdb) bt
#0  ExecGrant_common (istmt=0x7ffcc262d0c0, classid=2615, default_privs=768, object_check=0x0) at aclchk.c:2170
#1  0x000000000059d7d1 in ExecGrantStmt_oids (istmt=0x7ffcc262d0c0) at aclchk.c:625
#2  0x000000000059d6a6 in ExecuteGrantStmt (stmt=0x27458c8) at aclchk.c:583
#3  0x00000000009c0d56 in ProcessUtilitySlow (pstate=0x283fd28, pstmt=0x2745998, queryString=0x2744c88 "GRANT USAGE ON SCHEMA pg_catalog, public TO PUBLIC;\n", context=PROCESS_UTILITY_TOPLEVEL, params=0x0, queryEnv=0x0, dest=0xd64360 <debugtupDR>, qc=0x7ffcc262d890) at utility.c:1813
#4  0x00000000009bf16e in standard_ProcessUtility (pstmt=0x2745998, queryString=0x2744c88 "GRANT USAGE ON SCHEMA pg_catalog, public TO PUBLIC;\n", readOnlyTree=false, context=PROCESS_UTILITY_TOPLEVEL, params=0x0, queryEnv=0x0, dest=0xd64360 <debugtupDR>, qc=0x7ffcc262d890) at utility.c:977
#5  0x00000000009be69a in ProcessUtility (pstmt=0x2745998, queryString=0x2744c88 "GRANT USAGE ON SCHEMA pg_catalog, public TO PUBLIC;\n", readOnlyTree=false, context=PROCESS_UTILITY_TOPLEVEL, params=0x0, queryEnv=0x0, dest=0xd64360 <debugtupDR>, qc=0x7ffcc262d890) at utility.c:530
#6  0x00000000009bd2db in PortalRunUtility (portal=0x26f2bd8, pstmt=0x2745998, isTopLevel=true, setHoldSnapshot=false, dest=0xd64360 <debugtupDR>, qc=0x7ffcc262d890) at pquery.c:1158
#7  0x00000000009bd535 in PortalRunMulti (portal=0x26f2bd8, isTopLevel=true, setHoldSnapshot=false, dest=0xd64360 <debugtupDR>, altdest=0xd64360 <debugtupDR>, qc=0x7ffcc262d890) at pquery.c:1315
#8  0x00000000009bca6d in PortalRun (portal=0x26f2bd8, count=9223372036854775807, isTopLevel=true, run_once=true, dest=0xd64360 <debugtupDR>, altdest=0xd64360 <debugtupDR>, qc=0x7ffcc262d890) at pquery.c:791
#9  0x00000000009b6533 in exec_simple_query (query_string=0x2744c88 "GRANT USAGE ON SCHEMA pg_catalog, public TO PUBLIC;\n") at postgres.c:1274
#10 0x00000000009babc3 in PostgresMain (dbname=0x2699be0 "template1", username=0x2699350 "mingjie") at postgres.c:4637
#11 0x00000000009ba472 in PostgresSingleUserMain (argc=12, argv=0x2693a50, username=0x2699350 "mingjie") at postgres.c:4096
#12 0x00000000007b821e in main (argc=12, argv=0x2693a50) at main.c:195

http://www.niftyadmin.cn/n/5055543.html

相关文章

chrome扩展程序开发请求接口报错

解决HTTPS站点请求HTTP接口服务后报错&#xff1a;the content must be served over HTTPS Mixed Content: The page at <URL> was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint <URL>. This content should also be served over HTTPS…

leetCode 62.不同路径 动态规划 + 空间复杂度优化

62. 不同路径 - 力扣&#xff08;LeetCode&#xff09; 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish” &#xf…

mfc 动态加载dll库,Mat转CImage,读ini配置文件,鼠标操作,在edit控件上画框,调试信息打印

动态加载dll库 h文件中添加 #include "mydll.h" #ifdef UNICODE //区分字符集 #define LoadLibrary LoadLibraryW #else #define LoadLibrary LoadLibraryA #endif // !UNICODEtypedef double(*mydllPtr)(int, int);类内添加&#xff1a; mydllPtr m_mydll; cpp…

【BUG】记录使用PageHelper分页工具出现的问题?全是细节~

PageHelper原理 真的要理解这个插件的工作原理&#xff1a; PageHelper是MyBatis的一个插件&#xff0c;内部实现了一个PageInterceptor拦截器。Mybatis会加载这个拦截器到拦截器链中。在我们使用过程中先使用PageHelper.startPage这样的语句在当前线程上下文中设置一个Thread…

华为云云耀云服务器L实例评测使用 | 通过程序实现直播流自动分段录制

华为云云耀云服务器L实例评测使用 | 通过程序实现直播流自动分段录制 1. 准备工作2. 环境搭建3. 心得总结 1. 准备工作 随着云计算时代的进一步深入&#xff0c;越来越多的中小企业企业与开发者需要一款简单易用、高能高效的云计算基础设施产品来支撑自身业务运营和创新开发。基…

[FineReport]安装与使用(连接Hive3.1.2)

一、安装(对应hive3.1.2) 注&#xff1a;服务器的和本地的要同时安装。本地是测试环境&#xff0c;服务器的是生产环境 1、服务器安装 1、下载 免费下载FineReport - FineReport报表官网 向下滑找到 2、解压 [rootck1 /home/data_warehouse/software]# tar -zxvf tomcat…

与机器学习相比,人类的学习包括视觉、听觉、触觉、嗅觉、味觉的串并行混合学习...

视觉学习、听觉学习和触觉学习是人类感知和认知过程中的三个重要方面。 视觉学习&#xff1a;视觉学习是通过视觉感知信息进行学习和认知的过程。人类视觉系统能够感知并解读光线的反射或发射&#xff0c;从而获取关于物体、场景和环境的信息。视觉学习涉及识别、分类、空间感知…

5+SUMO化修饰+分型+实验,经典生信思路

今天给同学们分享一篇5SUMO化修饰分型实验的生信文章“SUMOylation patterns and signature characterize the tumor microenvironment and predict prognosis in lung adenocarcinoma”&#xff0c;这篇文章于2023年4月13日发表在Front Cell Dev Biol 期刊上&#xff0c;影响因…