mirror of
https://github.com/timescale/timescaledb.git
synced 2025-05-16 02:23:49 +08:00
Add password parameter to add_server()
Establishing a remote connection requires a password, unless the connection is made as a superuser. Therefore, this change adds the option to specify a password in the `add_server()` command. This is a required parameter unless called as a superuser.
This commit is contained in:
parent
652bb26415
commit
125f793307
@ -137,6 +137,8 @@ AS '@MODULE_PATHNAME@', 'ts_tablespace_detach_all_from_hypertable' LANGUAGE C VO
|
||||
CREATE OR REPLACE FUNCTION show_tablespaces(hypertable REGCLASS) RETURNS SETOF NAME
|
||||
AS '@MODULE_PATHNAME@', 'ts_tablespace_show' LANGUAGE C VOLATILE STRICT;
|
||||
|
||||
-- Add a server to a TimescaleDB cluster. This also add a
|
||||
-- corresponding user mapping, if one does not already exist.
|
||||
CREATE OR REPLACE FUNCTION add_server(
|
||||
server_name NAME,
|
||||
host TEXT = 'localhost',
|
||||
@ -144,10 +146,12 @@ CREATE OR REPLACE FUNCTION add_server(
|
||||
port INTEGER = 5432,
|
||||
local_user REGROLE = NULL,
|
||||
remote_user NAME = NULL,
|
||||
password TEXT = NULL,
|
||||
if_not_exists BOOLEAN = FALSE
|
||||
) RETURNS TABLE(server_name NAME, host TEXT, port INTEGER, database NAME, username NAME, server_username NAME, created BOOL)
|
||||
AS '@MODULE_PATHNAME@', 'ts_server_add' LANGUAGE C VOLATILE;
|
||||
|
||||
-- Delete a server from a TimescaleDB cluster
|
||||
CREATE OR REPLACE FUNCTION delete_server(
|
||||
server_name NAME,
|
||||
if_exists BOOLEAN = FALSE,
|
||||
|
@ -13,16 +13,17 @@
|
||||
#include <commands/dbcommands.h>
|
||||
#include <commands/defrem.h>
|
||||
#include <utils/builtins.h>
|
||||
#include <libpq/crypt.h>
|
||||
#include <miscadmin.h>
|
||||
#include <funcapi.h>
|
||||
|
||||
#include <hypertable_server.h>
|
||||
#include <compat.h>
|
||||
#include <catalog.h>
|
||||
|
||||
#include "fdw/timescaledb_fdw.h"
|
||||
#include "server.h"
|
||||
#include "compat.h"
|
||||
#include "catalog.h"
|
||||
|
||||
#define TS_FOREIGN_DATA_WRAPPER_NAME "timescaledb_fdw"
|
||||
#define TS_DEFAULT_POSTGRES_PORT 5432
|
||||
#define TS_DEFAULT_POSTGRES_HOST "localhost"
|
||||
|
||||
@ -30,10 +31,12 @@
|
||||
* Create a user mapping.
|
||||
*
|
||||
* Returns the OID of the created user mapping.
|
||||
*
|
||||
* Non-superusers must provide a password.
|
||||
*/
|
||||
static Oid
|
||||
create_user_mapping(const char *username, const char *server_username, const char *servername,
|
||||
bool if_not_exists)
|
||||
const char *password, bool if_not_exists)
|
||||
{
|
||||
ObjectAddress objaddr;
|
||||
RoleSpec rolespec = {
|
||||
@ -51,10 +54,27 @@ create_user_mapping(const char *username, const char *server_username, const cha
|
||||
.if_not_exists = if_not_exists,
|
||||
#endif
|
||||
.servername = (char *) servername,
|
||||
.options = list_make1(
|
||||
makeDefElemCompat("user", (Node *) makeString(pstrdup(server_username)), -1)),
|
||||
.options = NIL,
|
||||
};
|
||||
|
||||
Assert(NULL != username && NULL != server_username && NULL != servername);
|
||||
|
||||
stmt.options =
|
||||
list_make1(makeDefElemCompat("user", (Node *) makeString(pstrdup(server_username)), -1));
|
||||
|
||||
/* Non-superusers must provide a password */
|
||||
if (!superuser() && (NULL == password || password[0] == '\0'))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_PARAMETER),
|
||||
errmsg("no password specified for user \"%s\"", server_username),
|
||||
errhint("Specify a password to use when connecting to server \"%s\"",
|
||||
servername)));
|
||||
|
||||
if (NULL != password)
|
||||
stmt.options =
|
||||
lappend(stmt.options,
|
||||
makeDefElemCompat("password", (Node *) makeString(pstrdup(password)), -1));
|
||||
|
||||
objaddr = CreateUserMapping(&stmt);
|
||||
|
||||
return objaddr.objectId;
|
||||
@ -73,7 +93,7 @@ create_foreign_server(const char *servername, const char *host, int32 port, cons
|
||||
CreateForeignServerStmt stmt = {
|
||||
.type = T_CreateForeignServerStmt,
|
||||
.servername = (char *) servername,
|
||||
.fdwname = TS_FOREIGN_DATA_WRAPPER_NAME,
|
||||
.fdwname = TIMESCALEDB_FDW_NAME,
|
||||
.options =
|
||||
list_make3(makeDefElemCompat("host", (Node *) makeString(pstrdup(host)), -1),
|
||||
makeDefElemCompat("port", (Node *) makeInteger(port), -1),
|
||||
@ -170,7 +190,8 @@ server_add(PG_FUNCTION_ARGS)
|
||||
Oid userid = PG_ARGISNULL(4) ? GetUserId() : PG_GETARG_OID(4);
|
||||
const char *server_username =
|
||||
PG_ARGISNULL(5) ? GetUserNameFromId(userid, false) : PG_GETARG_CSTRING(5);
|
||||
bool if_not_exists = PG_ARGISNULL(6) ? false : PG_GETARG_BOOL(6);
|
||||
const char *password = PG_ARGISNULL(6) ? NULL : TextDatumGetCString(PG_GETARG_DATUM(6));
|
||||
bool if_not_exists = PG_ARGISNULL(7) ? false : PG_GETARG_BOOL(7);
|
||||
ForeignServer *server;
|
||||
UserMapping *um;
|
||||
const char *username;
|
||||
@ -221,7 +242,7 @@ server_add(PG_FUNCTION_ARGS)
|
||||
if (!created)
|
||||
elog(NOTICE, "adding user mapping for \"%s\" to server \"%s\"", username, servername);
|
||||
|
||||
create_user_mapping(username, server_username, servername, if_not_exists);
|
||||
create_user_mapping(username, server_username, servername, password, if_not_exists);
|
||||
|
||||
/* Make user mapping visible */
|
||||
CommandCounterIncrement();
|
||||
@ -288,7 +309,7 @@ server_get_servername_list(void)
|
||||
ScanKeyData scankey[1];
|
||||
SysScanDesc scandesc;
|
||||
Relation rel;
|
||||
ForeignDataWrapper *fdw = GetForeignDataWrapperByName(TS_FOREIGN_DATA_WRAPPER_NAME, false);
|
||||
ForeignDataWrapper *fdw = GetForeignDataWrapperByName(TIMESCALEDB_FDW_NAME, false);
|
||||
List *servers = NIL;
|
||||
|
||||
rel = table_open(ForeignServerRelationId, AccessShareLock);
|
||||
|
@ -3,25 +3,27 @@
|
||||
-- LICENSE-TIMESCALE for a copy of the license.
|
||||
-- Need to be super user to create extension and add servers
|
||||
\c :TEST_DBNAME :ROLE_SUPERUSER;
|
||||
-- Need explicit password for non-super users to connect
|
||||
ALTER ROLE :ROLE_DEFAULT_PERM_USER PASSWORD 'perm_user_pass';
|
||||
GRANT USAGE ON FOREIGN DATA WRAPPER timescaledb_fdw TO :ROLE_DEFAULT_PERM_USER;
|
||||
SET ROLE :ROLE_DEFAULT_PERM_USER;
|
||||
-- Add servers using TimescaleDB server management API
|
||||
SELECT * FROM add_server('server_1');
|
||||
server_name | host | port | database | username | server_username | created
|
||||
-------------+-----------+------+---------------------------+-------------------+-------------------+---------
|
||||
server_1 | localhost | 5432 | db_hypertable_distributed | default_perm_user | default_perm_user | t
|
||||
SELECT * FROM add_server('server_1', database => 'server_1', password => 'perm_user_pass');
|
||||
server_name | host | port | database | username | server_username | created
|
||||
-------------+-----------+------+----------+-------------------+-------------------+---------
|
||||
server_1 | localhost | 5432 | server_1 | default_perm_user | default_perm_user | t
|
||||
(1 row)
|
||||
|
||||
SELECT * FROM add_server('server_2');
|
||||
server_name | host | port | database | username | server_username | created
|
||||
-------------+-----------+------+---------------------------+-------------------+-------------------+---------
|
||||
server_2 | localhost | 5432 | db_hypertable_distributed | default_perm_user | default_perm_user | t
|
||||
SELECT * FROM add_server('server_2', database => 'server_2', password => 'perm_user_pass');
|
||||
server_name | host | port | database | username | server_username | created
|
||||
-------------+-----------+------+----------+-------------------+-------------------+---------
|
||||
server_2 | localhost | 5432 | server_2 | default_perm_user | default_perm_user | t
|
||||
(1 row)
|
||||
|
||||
SELECT * FROM add_server('server_3');
|
||||
server_name | host | port | database | username | server_username | created
|
||||
-------------+-----------+------+---------------------------+-------------------+-------------------+---------
|
||||
server_3 | localhost | 5432 | db_hypertable_distributed | default_perm_user | default_perm_user | t
|
||||
SELECT * FROM add_server('server_3', database => 'server_3', password => 'perm_user_pass');
|
||||
server_name | host | port | database | username | server_username | created
|
||||
-------------+-----------+------+----------+-------------------+-------------------+---------
|
||||
server_3 | localhost | 5432 | server_3 | default_perm_user | default_perm_user | t
|
||||
(1 row)
|
||||
|
||||
-- Create a distributed hypertable. Add a trigger and primary key
|
||||
|
@ -3,6 +3,7 @@
|
||||
-- LICENSE-TIMESCALE for a copy of the license.
|
||||
-- Need to be super user to create extension and add servers
|
||||
\c :TEST_DBNAME :ROLE_SUPERUSER;
|
||||
ALTER ROLE :ROLE_DEFAULT_PERM_USER PASSWORD 'perm_user_pass';
|
||||
GRANT USAGE ON FOREIGN DATA WRAPPER timescaledb_fdw TO :ROLE_DEFAULT_PERM_USER;
|
||||
CREATE OR REPLACE FUNCTION show_servers()
|
||||
RETURNS TABLE(server_name NAME, host TEXT, port INT, dbname NAME)
|
||||
@ -16,7 +17,7 @@ OPTIONS (host 'localhost', port '5432', dbname 'server_1');
|
||||
-- Create a user mapping for the server
|
||||
CREATE USER MAPPING FOR :ROLE_SUPERUSER SERVER server_1 OPTIONS (user 'cluster_user_1');
|
||||
-- Add servers using TimescaleDB server management API
|
||||
SELECT * FROM add_server('server_2');
|
||||
SELECT * FROM add_server('server_2', password => 'perm_user_pass');
|
||||
server_name | host | port | database | username | server_username | created
|
||||
-------------+-----------+------+-----------+-------------------+-------------------+---------
|
||||
server_2 | localhost | 5432 | db_server | default_perm_user | default_perm_user | t
|
||||
@ -24,30 +25,36 @@ SELECT * FROM add_server('server_2');
|
||||
|
||||
\set ON_ERROR_STOP 0
|
||||
-- Add again
|
||||
SELECT * FROM add_server('server_2');
|
||||
SELECT * FROM add_server('server_2', password => 'perm_user_pass');
|
||||
ERROR: server "server_2" already exists
|
||||
-- Add without password
|
||||
SELECT * FROM add_server('server_3');
|
||||
ERROR: no password specified for user "default_perm_user"
|
||||
-- Add NULL server
|
||||
SELECT * FROM add_server(NULL);
|
||||
ERROR: invalid server name
|
||||
\set ON_ERROR_STOP 1
|
||||
-- Should not generate error with if_not_exists option
|
||||
SELECT * FROM add_server('server_2', if_not_exists => true);
|
||||
SELECT * FROM add_server('server_2', password => 'perm_user_pass', if_not_exists => true);
|
||||
server_name | host | port | database | username | server_username | created
|
||||
-------------+-----------+------+-----------+-------------------+-------------------+---------
|
||||
server_2 | localhost | 5432 | db_server | default_perm_user | default_perm_user | f
|
||||
(1 row)
|
||||
|
||||
RESET ROLE;
|
||||
-- Superuser requires no password
|
||||
SELECT * FROM add_server('server_3', host => '192.168.3.4', database => 'server_2', remote_user => 'cluster_user_2');
|
||||
server_name | host | port | database | username | server_username | created
|
||||
-------------+-------------+------+----------+-------------------+-----------------+---------
|
||||
server_3 | 192.168.3.4 | 5432 | server_2 | default_perm_user | cluster_user_2 | t
|
||||
server_name | host | port | database | username | server_username | created
|
||||
-------------+-------------+------+----------+------------+-----------------+---------
|
||||
server_3 | 192.168.3.4 | 5432 | server_2 | super_user | cluster_user_2 | t
|
||||
(1 row)
|
||||
|
||||
SET ROLE :ROLE_DEFAULT_PERM_USER;
|
||||
-- Server exists, but no user mapping
|
||||
CREATE SERVER server_4 FOREIGN DATA WRAPPER timescaledb_fdw
|
||||
OPTIONS (host 'localhost', port '5432', dbname 'server_4');
|
||||
-- User mapping should be added with NOTICE
|
||||
SELECT * FROM add_server('server_4', if_not_exists => true);
|
||||
SELECT * FROM add_server('server_4', password => 'perm_user_pass', if_not_exists => true);
|
||||
NOTICE: adding user mapping for "default_perm_user" to server "server_4"
|
||||
server_name | host | port | database | username | server_username | created
|
||||
-------------+-----------+------+-----------+-------------------+-------------------+---------
|
||||
@ -92,28 +99,34 @@ SELECT rolname, srvname, umoptions
|
||||
FROM pg_user_mapping um, pg_authid a, pg_foreign_server fs
|
||||
WHERE a.oid = um.umuser AND fs.oid = um.umserver
|
||||
ORDER BY srvname;
|
||||
rolname | srvname | umoptions
|
||||
-------------------+----------+--------------------------
|
||||
rolname | srvname | umoptions
|
||||
-------------------+----------+--------------------------------------------------
|
||||
super_user | server_1 | {user=cluster_user_1}
|
||||
default_perm_user | server_2 | {user=default_perm_user}
|
||||
default_perm_user | server_3 | {user=cluster_user_2}
|
||||
default_perm_user | server_4 | {user=default_perm_user}
|
||||
default_perm_user | server_2 | {user=default_perm_user,password=perm_user_pass}
|
||||
super_user | server_3 | {user=cluster_user_2}
|
||||
default_perm_user | server_4 | {user=default_perm_user,password=perm_user_pass}
|
||||
(4 rows)
|
||||
|
||||
SET ROLE :ROLE_DEFAULT_PERM_USER;
|
||||
-- Delete a server
|
||||
\set ON_ERROR_STOP 0
|
||||
-- Cannot delete if not owner
|
||||
SELECT * FROM delete_server('server_3');
|
||||
ERROR: must be owner of foreign server server_3
|
||||
-- Must use cascade because of user mappings
|
||||
RESET ROLE;
|
||||
SELECT * FROM delete_server('server_3');
|
||||
ERROR: cannot drop server server_3 because other objects depend on it
|
||||
\set ON_ERROR_STOP 1
|
||||
-- Should work as superuser with cascade
|
||||
SELECT * FROM delete_server('server_3', cascade => true);
|
||||
NOTICE: drop cascades to user mapping for default_perm_user on server server_3
|
||||
NOTICE: drop cascades to user mapping for super_user on server server_3
|
||||
delete_server
|
||||
---------------
|
||||
t
|
||||
(1 row)
|
||||
|
||||
SET ROLE :ROLE_DEFAULT_PERM_USER;
|
||||
SELECT srvname, srvoptions
|
||||
FROM pg_foreign_server;
|
||||
srvname | srvoptions
|
||||
@ -128,11 +141,11 @@ SELECT rolname, srvname, umoptions
|
||||
FROM pg_user_mapping um, pg_authid a, pg_foreign_server fs
|
||||
WHERE a.oid = um.umuser AND fs.oid = um.umserver
|
||||
ORDER BY srvname;
|
||||
rolname | srvname | umoptions
|
||||
-------------------+----------+--------------------------
|
||||
rolname | srvname | umoptions
|
||||
-------------------+----------+--------------------------------------------------
|
||||
super_user | server_1 | {user=cluster_user_1}
|
||||
default_perm_user | server_2 | {user=default_perm_user}
|
||||
default_perm_user | server_4 | {user=default_perm_user}
|
||||
default_perm_user | server_2 | {user=default_perm_user,password=perm_user_pass}
|
||||
default_perm_user | server_4 | {user=default_perm_user,password=perm_user_pass}
|
||||
(3 rows)
|
||||
|
||||
\set ON_ERROR_STOP 0
|
||||
|
@ -4,13 +4,15 @@
|
||||
|
||||
-- Need to be super user to create extension and add servers
|
||||
\c :TEST_DBNAME :ROLE_SUPERUSER;
|
||||
-- Need explicit password for non-super users to connect
|
||||
ALTER ROLE :ROLE_DEFAULT_PERM_USER PASSWORD 'perm_user_pass';
|
||||
GRANT USAGE ON FOREIGN DATA WRAPPER timescaledb_fdw TO :ROLE_DEFAULT_PERM_USER;
|
||||
SET ROLE :ROLE_DEFAULT_PERM_USER;
|
||||
|
||||
-- Add servers using TimescaleDB server management API
|
||||
SELECT * FROM add_server('server_1');
|
||||
SELECT * FROM add_server('server_2');
|
||||
SELECT * FROM add_server('server_3');
|
||||
SELECT * FROM add_server('server_1', database => 'server_1', password => 'perm_user_pass');
|
||||
SELECT * FROM add_server('server_2', database => 'server_2', password => 'perm_user_pass');
|
||||
SELECT * FROM add_server('server_3', database => 'server_3', password => 'perm_user_pass');
|
||||
|
||||
-- Create a distributed hypertable. Add a trigger and primary key
|
||||
-- constraint to test how those work
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
-- Need to be super user to create extension and add servers
|
||||
\c :TEST_DBNAME :ROLE_SUPERUSER;
|
||||
ALTER ROLE :ROLE_DEFAULT_PERM_USER PASSWORD 'perm_user_pass';
|
||||
GRANT USAGE ON FOREIGN DATA WRAPPER timescaledb_fdw TO :ROLE_DEFAULT_PERM_USER;
|
||||
|
||||
CREATE OR REPLACE FUNCTION show_servers()
|
||||
@ -22,27 +23,31 @@ OPTIONS (host 'localhost', port '5432', dbname 'server_1');
|
||||
CREATE USER MAPPING FOR :ROLE_SUPERUSER SERVER server_1 OPTIONS (user 'cluster_user_1');
|
||||
|
||||
-- Add servers using TimescaleDB server management API
|
||||
SELECT * FROM add_server('server_2');
|
||||
SELECT * FROM add_server('server_2', password => 'perm_user_pass');
|
||||
|
||||
\set ON_ERROR_STOP 0
|
||||
-- Add again
|
||||
SELECT * FROM add_server('server_2');
|
||||
|
||||
SELECT * FROM add_server('server_2', password => 'perm_user_pass');
|
||||
-- Add without password
|
||||
SELECT * FROM add_server('server_3');
|
||||
-- Add NULL server
|
||||
SELECT * FROM add_server(NULL);
|
||||
\set ON_ERROR_STOP 1
|
||||
|
||||
-- Should not generate error with if_not_exists option
|
||||
SELECT * FROM add_server('server_2', if_not_exists => true);
|
||||
SELECT * FROM add_server('server_2', password => 'perm_user_pass', if_not_exists => true);
|
||||
|
||||
RESET ROLE;
|
||||
-- Superuser requires no password
|
||||
SELECT * FROM add_server('server_3', host => '192.168.3.4', database => 'server_2', remote_user => 'cluster_user_2');
|
||||
SET ROLE :ROLE_DEFAULT_PERM_USER;
|
||||
|
||||
-- Server exists, but no user mapping
|
||||
CREATE SERVER server_4 FOREIGN DATA WRAPPER timescaledb_fdw
|
||||
OPTIONS (host 'localhost', port '5432', dbname 'server_4');
|
||||
|
||||
-- User mapping should be added with NOTICE
|
||||
SELECT * FROM add_server('server_4', if_not_exists => true);
|
||||
SELECT * FROM add_server('server_4', password => 'perm_user_pass', if_not_exists => true);
|
||||
|
||||
SELECT * FROM show_servers();
|
||||
|
||||
@ -66,11 +71,15 @@ SET ROLE :ROLE_DEFAULT_PERM_USER;
|
||||
|
||||
-- Delete a server
|
||||
\set ON_ERROR_STOP 0
|
||||
-- Cannot delete if not owner
|
||||
SELECT * FROM delete_server('server_3');
|
||||
-- Must use cascade because of user mappings
|
||||
RESET ROLE;
|
||||
SELECT * FROM delete_server('server_3');
|
||||
\set ON_ERROR_STOP 1
|
||||
|
||||
-- Should work as superuser with cascade
|
||||
SELECT * FROM delete_server('server_3', cascade => true);
|
||||
SET ROLE :ROLE_DEFAULT_PERM_USER;
|
||||
|
||||
SELECT srvname, srvoptions
|
||||
FROM pg_foreign_server;
|
||||
|
Loading…
x
Reference in New Issue
Block a user