Replace superuser check by ACLs for replication origin functions
authorMichael Paquier <michael@paquier.xyz>
Sun, 14 Jun 2020 03:40:37 +0000 (12:40 +0900)
committerMichael Paquier <michael@paquier.xyz>
Sun, 14 Jun 2020 03:40:37 +0000 (12:40 +0900)
This patch removes the hardcoded check for superuser privileges when
executing replication origin functions.  Instead, execution is revoked
from public, meaning that those functions can be executed by a superuser
and that access to them can be granted.

Author: Martín Marqués
Reviewed-by: Kyotaro Horiguchi, Michael Paquier, Masahiko Sawada
Discussion: https:/postgr.es/m/CAPdiE1xJMZOKQL3dgHMUrPqysZkgwzSMXETfKkHYnBAB7-0VRQ@mail.gmail.com

contrib/test_decoding/expected/replorigin.out
contrib/test_decoding/sql/replorigin.sql
doc/src/sgml/func.sgml
src/backend/catalog/system_views.sql
src/backend/replication/logical/origin.c

index 3b249f4856f3fd4ec59f3eddb920126ca0fe273a..80773187554df8a703932b5d75850d52b00f779b 100644 (file)
@@ -1,5 +1,34 @@
 -- predictability
 SET synchronous_commit = on;
+-- superuser required by default
+CREATE ROLE regress_origin_replication REPLICATION;
+SET ROLE regress_origin_replication;
+SELECT pg_replication_origin_advance('regress_test_decoding: perm', '0/1');
+ERROR:  permission denied for function pg_replication_origin_advance
+SELECT pg_replication_origin_create('regress_test_decoding: perm');
+ERROR:  permission denied for function pg_replication_origin_create
+SELECT pg_replication_origin_drop('regress_test_decoding: perm');
+ERROR:  permission denied for function pg_replication_origin_drop
+SELECT pg_replication_origin_oid('regress_test_decoding: perm');
+ERROR:  permission denied for function pg_replication_origin_oid
+SELECT pg_replication_origin_progress('regress_test_decoding: perm', false);
+ERROR:  permission denied for function pg_replication_origin_progress
+SELECT pg_replication_origin_session_is_setup();
+ERROR:  permission denied for function pg_replication_origin_session_is_setup
+SELECT pg_replication_origin_session_progress(false);
+ERROR:  permission denied for function pg_replication_origin_session_progress
+SELECT pg_replication_origin_session_reset();
+ERROR:  permission denied for function pg_replication_origin_session_reset
+SELECT pg_replication_origin_session_setup('regress_test_decoding: perm');
+ERROR:  permission denied for function pg_replication_origin_session_setup
+SELECT pg_replication_origin_xact_reset();
+ERROR:  permission denied for function pg_replication_origin_xact_reset
+SELECT pg_replication_origin_xact_setup('0/1', '2013-01-01 00:00');
+ERROR:  permission denied for function pg_replication_origin_xact_setup
+SELECT pg_show_replication_origin_status();
+ERROR:  permission denied for function pg_show_replication_origin_status
+RESET ROLE;
+DROP ROLE regress_origin_replication;
 CREATE TABLE origin_tbl(id serial primary key, data text);
 CREATE TABLE target_tbl(id serial primary key, data text);
 SELECT pg_replication_origin_create('regress_test_decoding: regression_slot');
index 8979b30616054508b6a337c7b3d08cc2bfe4e4f3..b68f819fa1f19d0f4b504a4285ca17c7fc80c163 100644 (file)
@@ -1,6 +1,24 @@
 -- predictability
 SET synchronous_commit = on;
 
+-- superuser required by default
+CREATE ROLE regress_origin_replication REPLICATION;
+SET ROLE regress_origin_replication;
+SELECT pg_replication_origin_advance('regress_test_decoding: perm', '0/1');
+SELECT pg_replication_origin_create('regress_test_decoding: perm');
+SELECT pg_replication_origin_drop('regress_test_decoding: perm');
+SELECT pg_replication_origin_oid('regress_test_decoding: perm');
+SELECT pg_replication_origin_progress('regress_test_decoding: perm', false);
+SELECT pg_replication_origin_session_is_setup();
+SELECT pg_replication_origin_session_progress(false);
+SELECT pg_replication_origin_session_reset();
+SELECT pg_replication_origin_session_setup('regress_test_decoding: perm');
+SELECT pg_replication_origin_xact_reset();
+SELECT pg_replication_origin_xact_setup('0/1', '2013-01-01 00:00');
+SELECT pg_show_replication_origin_status();
+RESET ROLE;
+DROP ROLE regress_origin_replication;
+
 CREATE TABLE origin_tbl(id serial primary key, data text);
 CREATE TABLE target_tbl(id serial primary key, data text);
 
index a8d57f4e39a4e351793c6ac372d3c3c8581cf396..b65aa28f344188eed0ebc97534c676abb919d42b 100644 (file)
@@ -24614,7 +24614,9 @@ postgres=# SELECT * FROM pg_walfile_name_offset(pg_stop_backup());
     <xref linkend="streaming-replication-slots"/>, and
     <xref linkend="replication-origins"/>
     for information about the underlying features.
-    Use of functions for replication origin is restricted to superusers.
+    Use of functions for replication origin is only allowed to the
+    superuser by default, but may be allowed to other users by using the
+    <literal>GRANT</literal> command.
     Use of functions for replication slots is restricted to superusers
     and users having <literal>REPLICATION</literal> privilege.
    </para>
index 56420bbc9d6f1bd6dd1ef7e312779f4412492540..5314e9348fa776217d7de9f829212894db53a0c5 100644 (file)
@@ -1463,6 +1463,19 @@ REVOKE EXECUTE ON FUNCTION pg_read_binary_file(text) FROM public;
 REVOKE EXECUTE ON FUNCTION pg_read_binary_file(text,bigint,bigint) FROM public;
 REVOKE EXECUTE ON FUNCTION pg_read_binary_file(text,bigint,bigint,boolean) FROM public;
 
+REVOKE EXECUTE ON FUNCTION pg_replication_origin_advance(text, pg_lsn) FROM public;
+REVOKE EXECUTE ON FUNCTION pg_replication_origin_create(text) FROM public;
+REVOKE EXECUTE ON FUNCTION pg_replication_origin_drop(text) FROM public;
+REVOKE EXECUTE ON FUNCTION pg_replication_origin_oid(text) FROM public;
+REVOKE EXECUTE ON FUNCTION pg_replication_origin_progress(text, boolean) FROM public;
+REVOKE EXECUTE ON FUNCTION pg_replication_origin_session_is_setup() FROM public;
+REVOKE EXECUTE ON FUNCTION pg_replication_origin_session_progress(boolean) FROM public;
+REVOKE EXECUTE ON FUNCTION pg_replication_origin_session_reset() FROM public;
+REVOKE EXECUTE ON FUNCTION pg_replication_origin_session_setup(text) FROM public;
+REVOKE EXECUTE ON FUNCTION pg_replication_origin_xact_reset() FROM public;
+REVOKE EXECUTE ON FUNCTION pg_replication_origin_xact_setup(pg_lsn, timestamp with time zone) FROM public;
+REVOKE EXECUTE ON FUNCTION pg_show_replication_origin_status() FROM public;
+
 REVOKE EXECUTE ON FUNCTION pg_stat_file(text) FROM public;
 REVOKE EXECUTE ON FUNCTION pg_stat_file(text,boolean) FROM public;
 
index dec9e9511957b113c43a4ec4928fcb698efdbbef..1b220315dff86aa56a3f39b6359349fb9a0f6ae5 100644 (file)
@@ -182,11 +182,6 @@ static ReplicationState *session_replication_state = NULL;
 static void
 replorigin_check_prerequisites(bool check_slots, bool recoveryOK)
 {
-   if (!superuser())
-       ereport(ERROR,
-               (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
-                errmsg("only superusers can query or manipulate replication origins")));
-
    if (check_slots && max_replication_slots == 0)
        ereport(ERROR,
                (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),