How to control who can see PostgreSQL function's source code

函数内容比较敏感时, 如何提高函数内容的隐射或安全性呢?

1. 可以使用加密函数的方法来提高安全性. 需要安装额外的插件.

2. 可以使用C函数, 用户无法看到函数内容.

3. 如果以上方法无法在你的生产环境实施的话, 那么可以通过控制pg_proc的权限来控制谁可以看到函数内容.

例如, 我们这里创建一个测试函数 :

postgres=# create or replace function f() returns int as $$
postgres$# declare
postgres$#  a int := 10;
postgres$# begin
postgres$#  return a;
postgres$# end;
postgres$# $$ language plpgsql;
CREATE FUNCTION

函数内容存在pg_proc.prosrc字段中.

postgres=# select prosrc from pg_proc where proname='f';
    prosrc
---------------
              +
 declare      +
  a int := 10;+
 begin        +
  return a;   +
 end;         +

(1 row)

创建一个普通用户, 因为pg_proc的权限给public角色了, 所以普通用户也可以查询到它的内容.

postgres=# create role test login;
CREATE ROLE
postgres=# \c postgres test
You are now connected to database "postgres" as user "test".
postgres=> select prosrc from pg_proc where proname='f';
    prosrc
---------------
              +
 declare      +
  a int := 10;+
 begin        +
  return a;   +
 end;         +

(1 row)

仅仅回收prosrc字段的权限是不够的, 为什么呢? 参考

http://www.postgresql.org/docs/9.4/static/sql-revoke.html

postgres=> \c postgres postgres
You are now connected to database "postgres" as user "postgres".
postgres=# revoke select(prosrc) on pg_proc from public;
REVOKE
postgres=# \c postgres test
You are now connected to database "postgres" as user "test".
postgres=> select prosrc from pg_proc where proname='f';
    prosrc
---------------
              +
 declare      +
  a int := 10;+
 begin        +
  return a;   +
 end;         +

(1 row)

将pg_proc的权限从public回收即可.

postgres=> \c postgres postgres
You are now connected to database "postgres" as user "postgres".
postgres=# revoke select on pg_proc from public;
REVOKE
postgres=# \c postgres test
You are now connected to database "postgres" as user "test".
postgres=> select prosrc from pg_proc where proname='f';
ERROR:  permission denied for relation pg_proc
postgres=> select proname from pg_proc where proname='f';
ERROR:  permission denied for relation pg_proc

但是这样做的话, 所有的普通用户都没有了查询权限, 包括不能列出函数名.

postgres=> \c postgres postgres
You are now connected to database "postgres" as user "postgres".
postgres=# \du
                             List of roles
 Role name |                   Attributes                   | Member of
-----------+------------------------------------------------+-----------
 d         |                                                | {}
 postgres  | Superuser, Create role, Create DB, Replication | {}
 test      |                                                | {}
postgres=> \df
ERROR:  permission denied for relation pg_proc

其他普通用户, 需要查询函数名, 必须赋予pg_proc的查询权限.

postgres=# grant select on pg_proc to d;
GRANT
postgres=# \c postgres d
You are now connected to database "postgres" as user "d".
postgres=> select prosrc from pg_proc where proname='f';
    prosrc
---------------
              +
 declare      +
  a int := 10;+
 begin        +
  return a;   +
 end;         +

(1 row)

这样就控制了某个用户没有查询函数, 函数内容的权限.

postgres=> \c postgres test
You are now connected to database "postgres" as user "test".
postgres=> select prosrc from pg_proc where proname='f';
ERROR:  permission denied for relation pg_proc

如果要做到可以列出函数名, 但是不能查询函数内容. 怎么做呢?

首先我们要知道列函数用到什么QUERY

postgres@localhost-> psql -E
postgres=> \df
********* QUERY **********
SELECT n.nspname as "Schema",
  p.proname as "Name",
  pg_catalog.pg_get_function_result(p.oid) as "Result data type",
  pg_catalog.pg_get_function_arguments(p.oid) as "Argument data types",
 CASE
  WHEN p.proisagg THEN 'agg'
  WHEN p.proiswindow THEN 'window'
  WHEN p.prorettype = 'pg_catalog.trigger'::pg_catalog.regtype THEN 'trigger'
  ELSE 'normal'
 END as "Type"
FROM pg_catalog.pg_proc p
     LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
WHERE pg_catalog.pg_function_is_visible(p.oid)
      AND n.nspname <> 'pg_catalog'
      AND n.nspname <> 'information_schema'
ORDER BY 1, 2, 4;
**************************
ERROR:  permission denied for relation pg_proc

那么需要将除prosrc以外的所有字段(包括oid)都赋予给test用户即可.

postgres=# grant select(oid,proname,pronamespace,proowner,prolang,procost,prorows,provariadic,protransform,proisagg,proiswindow,prosecdef,proleakproof,proisstrict,proretset,provolatile,pronargs,pronargdefaults,prorettype,proargtypes,proallargtypes,proargmodes,proargnames,proargdefaults,probin,proconfig,proacl) on pg_proc to test;
GRANT
postgres=# \c postgres test
You are now connected to database "postgres" as user "test".

现在test用户可以列函数名, 但是不能看函数内容了.

postgres=> select proname from pg_proc limit 1;
 proname
---------
 boolin
(1 row)

postgres=> select prosrc from pg_proc limit 1;
ERROR:  permission denied for relation pg_proc
postgres=> \df
                        List of functions
 Schema |          Name           |     Result data type      |
                                                  Argument data types
                                                        |  Type
--------+-------------------------+---------------------------+---------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------+--------
 public | dblink                  | SETOF record              | text                                                                

                                                        | normal
 public | dblink                  | SETOF record              | text, boolean

但是, 别高兴太早, 函数的内容不是这么查出来的, 而是通过pg_get_functiondef(oid)系统函数来获取的, 所以还需要回收这个系统函数的权限.

在回收权限前.

postgres=> select * from pg_get_functiondef(16649);
          pg_get_functiondef
---------------------------------------
 CREATE OR REPLACE FUNCTION public.f()+
  RETURNS integer                     +
  LANGUAGE plpgsql                    +
 AS $function$                        +
 declare                              +
  a int := 10;                        +
 begin                                +
  return a;                           +
 end;                                 +
 $function$                           +

(1 row)
postgres=> \sf f
CREATE OR REPLACE FUNCTION public.f()
 RETURNS integer
 LANGUAGE plpgsql
AS $function$
declare
 a int := 10;
begin
 return a;
end;
$function$

回收权限后

postgres=# revoke execute on function pg_get_functiondef(oid) from public;
REVOKE
postgres=> \c postgres postgres
You are now connected to database "postgres" as user "postgres".
postgres=# select oid from pg_proc where proname='f';
  oid
-------
 16649
(1 row)
postgres=# \c postgres test
You are now connected to database "postgres" as user "test".
postgres=> \sf f
ERROR:  permission denied for function pg_get_functiondef
postgres=> select * from pg_get_functiondef(16649);
ERROR:  permission denied for function pg_get_functiondef

[小结]

通过权限来控制普通用户是否有查看函数内容的权限方法. 

第三步对于不同的PostgreSQL版本可能不一样, 请注意.

1. revoke select on pg_proc from public;
2. grant select on pg_proc to 需要查看函数内容权限的普通用户;
3. grant select(oid,proname,pronamespace,proowner,prolang,procost,prorows,provariadic,protransform,proisagg,proiswindow,prosecdef,proleakproof,proisstrict,proretset,provolatile,pronargs,pronargdefaults,prorettype,proargtypes,proallargtypes,proargmodes,proargnames,proargdefaults,probin,proconfig,proacl) on pg_proc to 不需要查看函数内容权限的普通用户;
4. revoke select(prosrc) on pg_proc from 不需要查看函数内容权限的普通用户;
5.
postgres=# revoke execute on function pg_get_functiondef(oid) from public;
REVOKE
6.
postgres=# grant execute on function pg_get_functiondef(oid) to 需要查看函数内容权限的普通用户;

目前PostgreSQL在对象权限这块控制还是过于粗燥, 不像Oracle做得很细, 用户间的权限控制是非常严格的.

而Postgres-XL则做了一定的修改, 是在parser层面做的, 可参考 : 

http://blog.163.com/digoal@126/blog/static/163877040201462552243293/

这也是一个路子.

[参考]
1. http://www.postgresql.org/docs/9.4/static/sql-revoke.html

    When revoking privileges on a table, the corresponding column privileges (if any) are automatically revoked on each column of the table, as well. On the other hand, if a role has been granted privileges on a table, then revoking the same privileges from individual columns will have no effect.

2. http://www.cybertec.at/en/products/plpgsql_sec-encrypt-your-stored-procedure-codes/

时间: 2024-10-26 08:03:18

How to control who can see PostgreSQL function's source code的相关文章

小白,docker中运行nodejs网页保报错,Object function Object() { [native code] } has no method

问题描述 TypeError:ObjectfunctionObject(){[nativecode]}hasnomethod'assign'atObject.build(/p3/node_modules/node-xlsx/lib/index.js:46:57)atrouter.post.start(/p3/routes/index.js:322:26)atLayer.handle[ashandle_request](/p3/node_modules/express/lib/router/lay

多国语言字符串的加密、全文检索、模糊查询的支持

标签 PostgreSQL , 全文检索 , 模糊查询 , 前后模糊 , 多国字符串 , 透明加密 , 不可逆加密 , 可逆加密 , 函数安全 , C函数 背景 PostgreSQL中的全文检索和模糊查询是很好实现的. 通过pg_trgm插件,可以实现模糊查询(前.后.全模糊),近似查询,正则表达式查询的索引加速. 通过中文分词插件(pg_jieba, pg_scws, zhparser),可以实现中文分词,其他语种的分词,参考对应的插件. 但是,如果要让数据库支持加密存储,同时对加密前的数据实

又来勒索,有完没完 - 数据库安全指南

背景 数据库在一个企业中通常都处于非常核心的位置,数据库安全是一个非常严肃的话题. 从机房.网络.服务器.数据交换设备.操作系统.应用程序.数据库本身,数据库所处的环境非常复杂,安全隐患也非常多. 所以本文将从各个层面帮助大家理解和避免一些常见的安全隐患问题. 本文是PostgreSQL使用安全指导性的文章,涉及详细的用法或原理请参考相关链接. 如何安全的使用PostgreSQL,让用户高枕无忧呢? 可以分为如下几个方面来加固你的数据库. 一.认证安全 认证前的安全,端口暴露度的把握. Post

A Complete ActiveX Web Control Tutorial

Download demo project - 231 Kb Introduction ActiveX is a Microsoft technology developed in the mid 90's, that allows for the creation of applet-like applications that can be downloaded and run within Microsoft's Web browser. This article is intended

Top 5 open source Q&amp;A systems

推荐几个和stackoverflow类似的开源框架,PostgreSQL重度用户建议使用OSQA,可以支持问题,回答,comment的中文全文检索. [转载]http://www.mkyong.com/featured/top-5-open-source-qa-systems/ List of the open source Q&A implementation or stackoverflow-like website, with "Active" development a

Windows Forms中的数据绑定(二)

window|数据 运行我们运行这个程序来看看是否国家可以正常的显示了.1. 按下F5来运行程序.2. 点击Countries下拉框来看看是否国家数据已经可以显示了.如果正常的话,你就可以看到如下图8所示的程序: 图8.使用ComboBox来显示小数据集可以提高性能带参数的查询来显示数据现在已经可以看到ComboBox中的国家数据了,接着我们就来做选择ComboBox中的一个国家,在DataGrid中只显示这个国家的客户资料.我们按照这些步骤来做:1. 把form的load事件中读取DataGr

Using TreeControl (TreeView) under Win32 API

该例子在我的资源里面可以下载到完全可以运行的源代码http://download.111cn.net/source/463178 Introduction Hi all Win32 Coders, and happy new year to you all! This article is for those who did not find, any useful code examples and information regarding tree control (TreeView).

PostgreSQL 计算 任意类型 字段之间的线性相关性

PostgreSQL自带了计算numeric和numeric字段的线性相关性的聚合函数corr(numeric, numeric).例如: postgres=# select corr(c1,c2) from (values (1,2),(2,1),(100,90),(13,13),(25,27) ) t(c1,c2); corr ------------------- 0.998528203831946 (1 row) postgres=# \df+ corr List of function

HybridDB for PostgreSQL 列存表(AO表)的膨胀、垃圾检查与空间收缩

标签 PostgreSQL , Greenplum , 垃圾检测 , 膨胀 , 列存表 , gp_appendonly_compaction_threshold 背景 Greenplum支持行存储(堆存储)与AO存储,堆存储的垃圾回收和膨胀检测方法请参考: <如何检测.清理Greenplum膨胀.垃圾 - 阿里云HybridDB for PG最佳实践> 对于AO存储,虽然是appendonly,但实际上GP是支持DELETE和UPDATE的,被删除或更新的行,通过BITMAP来标记. AO存储