我有一个PostgreSQL的AWS RDS实例,在该实例中,我需要SQL使用dblink_connect(text)并且dblink_exec(text)以该postgres角色(我创建的)登录时在函数内执行一条语句。
SQL
dblink_connect(text)
dblink_exec(text)
postgres
CREATE OR REPLACE FUNCTION application.create_tenant_schemas(first integer, last integer) RETURNS void AS DECLARE tenant VARCHAR; sql VARCHAR; BEGIN FOR index IN first..last LOOP tenant := 'tenant_' || to_char(index, 'FM00000'); sql := 'CREATE SCHEMA ' || quote_ident(tenant); RAISE NOTICE '%', sql; PERFORM dblink_connect('dbname=application user=postgres'); PERFORM dblink_exec(sql); PERFORM dblink_disconnect(); END LOOP; END; $BODY$ LANGUAGE plpgsql;
的dblink_exec()是生产以下错误消息:
dblink_exec()
[2F003] ERROR: password is required Detail: Non-superusers must provide a password in the connection string. Where: SQL statement "SELECT dblink_connect('dbname=application user=postgres')"
我找到了建议使用的答案dblink_connect_u(text)。当我尝试这样做时,我收到以下错误消息:
dblink_connect_u(text)
[42501] ERROR: permission denied for function dblink_connect_u Where: SQL statement "SELECT dblink_connect_u('dbname=application user=postgres')"
在AWS上,如何授予创建RDS实例的用户执行功能的权限dblink_connect_u()?我尝试了以下操作,但未成功:
dblink_connect_u()
GRANT EXECUTE ON FUNCTION dblink_connect_u(text) TO postgres; GRANT EXECUTE ON FUNCTION dblink_connect_u(text, text) TO postgres;
看来我的postgres用户需要superuser我显然无法在AWS上获得的权限。
superuser
我也曾使用%APPDATA%\postgresql\pgpass.conf(在Windows上)提供密码,dblink_connect(text)但dblink_connect(text)显然忽略了该文件。
%APPDATA%\postgresql\pgpass.conf
我能够使用硬编码的密码字符串来调用dblink_connect(text),如下所示:
PERFORM "pascal"."dblink_connect_u"('dbname=pascal user=postgres password=secret');
…最终,由于密码的硬编码,因此这不是可接受的解决方案。
有没有人对如何使RDS PostgreSQL使用密码文件或允许我提供建议,GRANT EXECUTE ON FUNCTION dblink_connect_u(text)或者还有我没有遇到的另一种选择?
GRANT EXECUTE ON FUNCTION dblink_connect_u(text)
更新
链接到PostgreSQL文档,以尝试设置外部数据包装器/服务器,在其中存储正在执行的用户的密码 dblink_connect(text)
创建服务器
创建外部数据包装器
创建用户映射
结论
CREATE SERVER "password_server" FOREIGN DATA WRAPPER "dblink_fdw" OPTIONS (dbname 'application'); CREATE USER MAPPING FOR "postgres" SERVER "password_server" OPTIONS (user 'postgres', password 'pa55VV0&d');
…不同的源文件…
CREATE OR REPLACE FUNCTION application.create_tenant_schemas(first integer, last integer) RETURNS VOID AS $$ DECLARE tenant VARCHAR; sql VARCHAR; BEGIN FOR index IN first..last LOOP tenant := 'tenant_' || to_char(index, 'FM00000'); sql := 'CREATE SCHEMA ' || quote_ident(tenant); RAISE NOTICE '%', sql; PERFORM "dblink_connect"('password_server'); PERFORM "dblink_exec"(sql); PERFORM "dblink_disconnect"(); END LOOP; END; $BODY$ LANGUAGE plpgsql;
您可以创建用户映射:
create server application_srv foreign data wrapper dblink_fdw OPTIONS (...
create user mapping FOR app_user SERVER application_srv OPTIONS (user 'user_to_connect', password 'password goes here');
application_srv
。
t# select * from dblink('application_srv','select max(t) from t') as t(m timestamp(0)); m --------------------- 2017-06-13 11:41:05 (1 row)
现在,密码将以纯文本形式显示pg_user_mappings(pg_user_mappingRDS中的任何人都不能选择该密码),但实际的通行证将仅显示给rds_superuser
pg_user_mappings
pg_user_mapping
rds_superuser