2017-06-20 3 views
2

J'ai une instance AWS RDS de PostgreSQL dans lequel je dois exécuter une instruction SQL au sein d'une fonction à l'aide dblink_connect(text) et dblink_exec(text) lorsque vous êtes connecté avec le rôle postgres (que je créé).PostgreSQL éviter RDS codage dur le mot de passe de connexion lors de l'utilisation dblink_connect()

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; 

Le dblink_exec() produit les messages d'erreur suivants:

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

J'ai trouvé un answer qui a suggéré d'utiliser dblink_connect_u(text). Quand j'ai essayé cela, je suis les messages d'erreur suivants:

[42501] ERROR: permission denied for function dblink_connect_u 
Where: SQL statement "SELECT dblink_connect_u('dbname=application user=postgres')" 

sur AWS comment puis-je donner à l'utilisateur qui a créé l'autorisation de l'instance RDS pour exécuter la fonction dblink_connect_u()? J'ai essayé ce qui suit sans succès:

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

Il semble que mon utilisateur a besoin postgressuperuser autorisations auxquelles je ne peux pas apparemment avoir sur AWS.

Je joue aussi avec l'aide %APPDATA%\postgresql\pgpass.conf (sous Windows) pour fournir le mot de passe dblink_connect(text) mais dblink_connect(text) ne tient pas apparemment ce fichier.

j'ai pu utiliser un disque codé la chaîne de mot de passe pour appeler dblink_connect(text) comme suit:

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

... en fin de compte, ce n'est pas une solution acceptable en raison du codage dur du mot de passe. Est-ce que quelqu'un a une suggestion sur la façon d'obtenir RDS PostgreSQL soit pour utiliser le fichier de mot de passe ou pour m'autoriser à GRANT EXECUTE ON FUNCTION dblink_connect_u(text) ou y at-il une autre alternative que je n'ai pas rencontrée?

MISE À JOUR

liens vers la documentation PostgreSQL pour essayer de mettre en place un wrapper/serveur de données étrangères dans lequel stocker le mot de passe pour l'utilisateur qui est d'exécution dblink_connect(text)

CREATE SERVER

CREATE FOREIGN DATA WRAPPER

CREATE USER MAPPING

CONCLUSION

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'); 

... autre fichier source ...

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; 

Répondre

2

Vous pouvez créer le mappage des utilisateurs:

  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. utilisation application_srv Nom de connexion dblink:

.

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) 

maintenant le mot de passe sera affiché dans le texte brut pg_user_mappings (pg_user_mapping ne devrait pas être sélectionnable pour tous ceux qui en RDS), mais la passe réelle ne sera affichée que pour rds_superuser

+0

idée Nice. Malheureusement il semble que pour faire la commande 'CREATE SERVER' je doive définir un' FOREIGN DATA WRAPPER' et pour définir 'FOREIGN DATA WRAPPER' j'ai besoin de privilèges de superutilisateur qui me ramènent là où j'ai commencé ... – Neoheurist

+0

non - J'ai donné cette solution à partir de mon péage. C'est comme ça que je le fais sur RDS. s'il vous plaît divulguer la déclaration et l'erreur –

+0

Mon erreur. J'avais besoin d'installer l'extension 'dblink' dans la base de données dans laquelle j'essayais d'ajouter le' FOREIGN DATA WRAPPER' - j'expérimentais dans une base de données qui n'avait pas l'extension 'dblink' installée ... – Neoheurist