Replace superuser check by ACLs for replication origin functions

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
This commit is contained in:
Michael Paquier 2020-06-14 12:40:37 +09:00
parent 23cbeda50b
commit cc072641d4
5 changed files with 63 additions and 6 deletions

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

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

View 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>

View 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;

View 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),