使用dblink_connect()时,PostgreSQL RDS避免硬编码连接密码

问题描述 投票:3回答:1

我有一个PostgreSQL的AWS RDS实例,我需要使用SQLdblink_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()产生以下错误消息:

[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')"

我找到了一个建议使用answerdblink_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()功能的权限?我尝试了以下但没有成功:

GRANT EXECUTE ON FUNCTION dblink_connect_u(text) TO postgres;
GRANT EXECUTE ON FUNCTION dblink_connect_u(text, text) TO postgres;

看来我的postgres用户需要superuser权限,我显然不能在AWS上使用。

我也玩过使用%APPDATA%\postgresql\pgpass.conf(在Windows上)为dblink_connect(text)提供密码,但dblink_connect(text)显然忽略了这个文件。

我能够使用硬编码的密码字符串来调用dblink_connect(text),如下所示:

PERFORM "pascal"."dblink_connect_u"('dbname=pascal user=postgres password=secret');

...最终,由于密码的硬编码,这不是一个可接受的解决方案。

有没有人建议如何让RDS PostgreSQL使用密码文件或允许我使用GRANT EXECUTE ON FUNCTION dblink_connect_u(text)或是否有另一种我没有遇到过的替代方案?

UPDATE

链接到PostgreSQL文档,用于尝试设置外部数据包装器/服务器,在其中存储执行dblink_connect(text)的用户的密码

CREATE SERVER

CREATE FOREIGN DATA WRAPPER

CREATE USER MAPPING

结论

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;
sql postgresql plpgsql amazon-rds rds
1个回答
2
投票

您可以创建用户映射:

  1. create server application_srv foreign data wrapper dblink_fdw OPTIONS (...;
  2. create user mapping FOR app_user SERVER application_srv OPTIONS (user 'user_to_connect', password 'password goes here');
  3. 在dblink连接名称中使用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_mapping应该不能为RDS中的任何人选择),但实际的传递将仅显示给rds_superuser

© www.soinside.com 2019 - 2024. All rights reserved.