public inbox for [email protected]
help / color / mirror / Atom feed[PATCH] Add object names to partition errors
68+ messages / 7 participants
[nested] [flat]
* [PATCH] Add object names to partition errors
@ 2020-02-29 18:47 Chris Bandy <[email protected]>
0 siblings, 0 replies; 68+ messages in thread
From: Chris Bandy @ 2020-02-29 18:47 UTC (permalink / raw)
All errors of SQLSTATE class 23 should include the name of an object
associated with the error.
---
src/backend/commands/tablecmds.c | 6 +-
src/backend/executor/execMain.c | 3 +-
src/backend/executor/execPartition.c | 3 +-
src/backend/partitioning/partbounds.c | 3 +-
src/backend/utils/adt/ri_triggers.c | 3 +-
src/test/regress/expected/partition_errors.out | 93 ++++++++++++++++++++++++++
src/test/regress/parallel_schedule | 2 +-
src/test/regress/sql/partition_errors.sql | 62 +++++++++++++++++
8 files changed, 168 insertions(+), 7 deletions(-)
create mode 100644 src/test/regress/expected/partition_errors.out
create mode 100644 src/test/regress/sql/partition_errors.sql
diff --git src/backend/commands/tablecmds.c src/backend/commands/tablecmds.c
index 02a7c04fdb..6a32812a1f 100644
--- src/backend/commands/tablecmds.c
+++ src/backend/commands/tablecmds.c
@@ -5342,12 +5342,14 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
ereport(ERROR,
(errcode(ERRCODE_CHECK_VIOLATION),
errmsg("updated partition constraint for default partition \"%s\" would be violated by some row",
- RelationGetRelationName(oldrel))));
+ RelationGetRelationName(oldrel)),
+ errtable(oldrel)));
else
ereport(ERROR,
(errcode(ERRCODE_CHECK_VIOLATION),
errmsg("partition constraint of relation \"%s\" is violated by some row",
- RelationGetRelationName(oldrel))));
+ RelationGetRelationName(oldrel)),
+ errtable(oldrel)));
}
/* Write the tuple out to the new relation */
diff --git src/backend/executor/execMain.c src/backend/executor/execMain.c
index 28130fbc2b..4fdffad6f3 100644
--- src/backend/executor/execMain.c
+++ src/backend/executor/execMain.c
@@ -1878,7 +1878,8 @@ ExecPartitionCheckEmitError(ResultRelInfo *resultRelInfo,
(errcode(ERRCODE_CHECK_VIOLATION),
errmsg("new row for relation \"%s\" violates partition constraint",
RelationGetRelationName(resultRelInfo->ri_RelationDesc)),
- val_desc ? errdetail("Failing row contains %s.", val_desc) : 0));
+ val_desc ? errdetail("Failing row contains %s.", val_desc) : 0,
+ errtable(resultRelInfo->ri_RelationDesc)));
}
/*
diff --git src/backend/executor/execPartition.c src/backend/executor/execPartition.c
index c13b1d3501..a5542b92c7 100644
--- src/backend/executor/execPartition.c
+++ src/backend/executor/execPartition.c
@@ -345,7 +345,8 @@ ExecFindPartition(ModifyTableState *mtstate,
RelationGetRelationName(rel)),
val_desc ?
errdetail("Partition key of the failing row contains %s.",
- val_desc) : 0));
+ val_desc) : 0,
+ errtable(rel)));
}
if (partdesc->is_leaf[partidx])
diff --git src/backend/partitioning/partbounds.c src/backend/partitioning/partbounds.c
index 35953f23fa..4c47f54a57 100644
--- src/backend/partitioning/partbounds.c
+++ src/backend/partitioning/partbounds.c
@@ -1366,7 +1366,8 @@ check_default_partition_contents(Relation parent, Relation default_rel,
ereport(ERROR,
(errcode(ERRCODE_CHECK_VIOLATION),
errmsg("updated partition constraint for default partition \"%s\" would be violated by some row",
- RelationGetRelationName(default_rel))));
+ RelationGetRelationName(default_rel)),
+ errtable(default_rel)));
ResetExprContext(econtext);
CHECK_FOR_INTERRUPTS();
diff --git src/backend/utils/adt/ri_triggers.c src/backend/utils/adt/ri_triggers.c
index 4ab7cda110..bb49e80d16 100644
--- src/backend/utils/adt/ri_triggers.c
+++ src/backend/utils/adt/ri_triggers.c
@@ -2452,7 +2452,8 @@ ri_ReportViolation(const RI_ConstraintInfo *riinfo,
NameStr(riinfo->conname)),
errdetail("Key (%s)=(%s) is still referenced from table \"%s\".",
key_names.data, key_values.data,
- RelationGetRelationName(fk_rel))));
+ RelationGetRelationName(fk_rel)),
+ errtableconstraint(fk_rel, NameStr(riinfo->conname))));
else if (onfk)
ereport(ERROR,
(errcode(ERRCODE_FOREIGN_KEY_VIOLATION),
diff --git src/test/regress/expected/partition_errors.out src/test/regress/expected/partition_errors.out
new file mode 100644
index 0000000000..8f3da6c74f
--- /dev/null
+++ src/test/regress/expected/partition_errors.out
@@ -0,0 +1,93 @@
+--
+-- Tests for partition error fields
+--
+-- Some partition errors are emitted with SQLSTATE 23xxx. Such errors
+-- should include the name of a database object as a separate field.
+--
+-- The fields of interest are shown at the same verbosity level as
+-- volatile details such as source-code line numbers. To produce stable
+-- regression output, the following function returns a portion of the
+-- full error reported.
+\pset expanded on
+\pset tuples_only on
+CREATE FUNCTION partition_error_record(
+ dml text,
+ OUT err_sqlstate text,
+ OUT err_message text,
+ OUT err_detail text,
+ OUT err_schema text,
+ OUT err_table text,
+ OUT err_constraint text)
+AS $$
+BEGIN
+ EXECUTE $1;
+EXCEPTION
+ WHEN integrity_constraint_violation THEN GET STACKED DIAGNOSTICS
+ err_sqlstate := RETURNED_SQLSTATE,
+ err_message := MESSAGE_TEXT,
+ err_detail := PG_EXCEPTION_DETAIL,
+ err_schema := SCHEMA_NAME,
+ err_table := TABLE_NAME,
+ err_constraint := CONSTRAINT_NAME;
+END;
+$$ LANGUAGE plpgsql;
+-- no partitions
+CREATE TABLE pterr1 (x int, y int, PRIMARY KEY (x, y)) PARTITION BY RANGE (y);
+SELECT * FROM partition_error_record($$
+ INSERT INTO pterr1 VALUES (10, 10);
+$$);
+err_sqlstate | 23514
+err_message | no partition of relation "pterr1" found for row
+err_detail | Partition key of the failing row contains (y) = (10).
+err_schema | public
+err_table | pterr1
+err_constraint |
+
+-- outside the only partition
+CREATE TABLE pterr1_p1 PARTITION OF pterr1 FOR VALUES FROM (1) TO (5);
+SELECT * FROM partition_error_record($$
+ INSERT INTO pterr1 VALUES (10, 10);
+$$);
+err_sqlstate | 23514
+err_message | no partition of relation "pterr1" found for row
+err_detail | Partition key of the failing row contains (y) = (10).
+err_schema | public
+err_table | pterr1
+err_constraint |
+
+SELECT * FROM partition_error_record($$
+ INSERT INTO pterr1_p1 VALUES (10, 10);
+$$);
+err_sqlstate | 23514
+err_message | new row for relation "pterr1_p1" violates partition constraint
+err_detail | Failing row contains (10, 10).
+err_schema | public
+err_table | pterr1_p1
+err_constraint |
+
+-- conflict with default
+CREATE TABLE pterr1_default PARTITION OF pterr1 DEFAULT;
+INSERT INTO pterr1 VALUES (10, 10);
+SELECT * FROM partition_error_record($$
+ CREATE TABLE pterr1_p2 PARTITION OF pterr1 FOR VALUES FROM (6) TO (20);
+$$);
+err_sqlstate | 23514
+err_message | updated partition constraint for default partition "pterr1_default" would be violated by some row
+err_detail |
+err_schema | public
+err_table | pterr1_default
+err_constraint |
+
+-- foreign key reference
+CREATE TABLE pterr2 (x int, y int, FOREIGN KEY (x, y) REFERENCES pterr1);
+INSERT INTO pterr2 VALUES (10, 10);
+SELECT * FROM partition_error_record($$
+ ALTER TABLE pterr1 DETACH PARTITION pterr1_default;
+$$);
+err_sqlstate | 23503
+err_message | removing partition "pterr1_default" violates foreign key constraint "pterr2_x_y_fkey2"
+err_detail | Key (x, y)=(10, 10) is still referenced from table "pterr2".
+err_schema | public
+err_table | pterr2
+err_constraint | pterr2_x_y_fkey2
+
diff --git src/test/regress/parallel_schedule src/test/regress/parallel_schedule
index d2b17dd3ea..e1708c87ec 100644
--- src/test/regress/parallel_schedule
+++ src/test/regress/parallel_schedule
@@ -112,7 +112,7 @@ test: plancache limit plpgsql copy2 temp domain rangefuncs prepare conversion tr
# ----------
# Another group of parallel tests
# ----------
-test: partition_join partition_prune reloptions hash_part indexing partition_aggregate partition_info tuplesort explain
+test: partition_errors partition_join partition_prune reloptions hash_part indexing partition_aggregate partition_info tuplesort explain
# event triggers cannot run concurrently with any test that runs DDL
test: event_trigger
diff --git src/test/regress/sql/partition_errors.sql src/test/regress/sql/partition_errors.sql
new file mode 100644
index 0000000000..054ec2e059
--- /dev/null
+++ src/test/regress/sql/partition_errors.sql
@@ -0,0 +1,62 @@
+--
+-- Tests for partition error fields
+--
+-- Some partition errors are emitted with SQLSTATE 23xxx. Such errors
+-- should include the name of a database object as a separate field.
+--
+-- The fields of interest are shown at the same verbosity level as
+-- volatile details such as source-code line numbers. To produce stable
+-- regression output, the following function returns a portion of the
+-- full error reported.
+\pset expanded on
+\pset tuples_only on
+CREATE FUNCTION partition_error_record(
+ dml text,
+ OUT err_sqlstate text,
+ OUT err_message text,
+ OUT err_detail text,
+ OUT err_schema text,
+ OUT err_table text,
+ OUT err_constraint text)
+AS $$
+BEGIN
+ EXECUTE $1;
+EXCEPTION
+ WHEN integrity_constraint_violation THEN GET STACKED DIAGNOSTICS
+ err_sqlstate := RETURNED_SQLSTATE,
+ err_message := MESSAGE_TEXT,
+ err_detail := PG_EXCEPTION_DETAIL,
+ err_schema := SCHEMA_NAME,
+ err_table := TABLE_NAME,
+ err_constraint := CONSTRAINT_NAME;
+END;
+$$ LANGUAGE plpgsql;
+
+-- no partitions
+CREATE TABLE pterr1 (x int, y int, PRIMARY KEY (x, y)) PARTITION BY RANGE (y);
+SELECT * FROM partition_error_record($$
+ INSERT INTO pterr1 VALUES (10, 10);
+$$);
+
+-- outside the only partition
+CREATE TABLE pterr1_p1 PARTITION OF pterr1 FOR VALUES FROM (1) TO (5);
+SELECT * FROM partition_error_record($$
+ INSERT INTO pterr1 VALUES (10, 10);
+$$);
+SELECT * FROM partition_error_record($$
+ INSERT INTO pterr1_p1 VALUES (10, 10);
+$$);
+
+-- conflict with default
+CREATE TABLE pterr1_default PARTITION OF pterr1 DEFAULT;
+INSERT INTO pterr1 VALUES (10, 10);
+SELECT * FROM partition_error_record($$
+ CREATE TABLE pterr1_p2 PARTITION OF pterr1 FOR VALUES FROM (6) TO (20);
+$$);
+
+-- foreign key reference
+CREATE TABLE pterr2 (x int, y int, FOREIGN KEY (x, y) REFERENCES pterr1);
+INSERT INTO pterr2 VALUES (10, 10);
+SELECT * FROM partition_error_record($$
+ ALTER TABLE pterr1 DETACH PARTITION pterr1_default;
+$$);
--
2.11.0
--------------6EEC49708FE57EDEB52FEBE7--
^ permalink raw reply [nested|flat] 68+ messages in thread
* Non-superuser subscription owners
@ 2021-10-20 18:40 Mark Dilger <[email protected]>
2021-10-25 07:26 ` Re: Non-superuser subscription owners Ronan Dunklau <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
0 siblings, 2 replies; 68+ messages in thread
From: Mark Dilger @ 2021-10-20 18:40 UTC (permalink / raw)
To: pgsql-hackers; +Cc: Andrew Dunstan <[email protected]>
These patches have been split off the now deprecated monolithic "Delegating superuser tasks to new security roles" thread at [1].
The purpose of these patches is to allow non-superuser subscription owners without risk of them overwriting tables they lack privilege to write directly. This both allows subscriptions to be managed by non-superusers, and protects servers with subscriptions from malicious activity on the publisher side.
[1] https://www.postgresql.org/message-id/flat/F9408A5A-B20B-42D2-9E7F-49CD3D1547BC%40enterprisedb.com
—
Mark Dilger
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
Attachments:
[application/octet-stream] v1-0001-Handle-non-superuser-subscription-owners-sensibly.patch (11.0K, ../../[email protected]/2-v1-0001-Handle-non-superuser-subscription-owners-sensibly.patch)
download | inline diff:
From c2a9a709b70d47b1ede7dfc3bcb58328fe1fce53 Mon Sep 17 00:00:00 2001
From: Mark Dilger <[email protected]>
Date: Sun, 26 Sep 2021 18:21:26 -0700
Subject: [PATCH v1 1/3] Handle non-superuser subscription owners sensibly
Stop pretending that subscriptions are always owned by superusers
and instead fix security problems that arise as a consequence of
them not being superuser. Specifically, disallow a non-superuser
changing the connection, the list of publications, or the options
for their subscription.
The prior behavior violated the principle of least surprise,
allowing a non-superuser in possession of a subscription to change
all aspects of the subscription, connecting it to a different server
and subscribing a different set of publications, effectively
amounting to a non-superuser creating a new subscription.
The new behavior restricts the non-superuser owner to enabling,
disabling, refreshing, renaming, and further assigning ownership of
the subscription.
---
doc/src/sgml/ref/alter_subscription.sgml | 11 ++++-
src/backend/commands/subscriptioncmds.c | 20 +++++++++
src/test/regress/expected/subscription.out | 51 ++++++++++++++++++++++
src/test/regress/sql/subscription.sql | 35 +++++++++++++++
4 files changed, 115 insertions(+), 2 deletions(-)
diff --git a/doc/src/sgml/ref/alter_subscription.sgml b/doc/src/sgml/ref/alter_subscription.sgml
index 0b027cc346..b1fd73f776 100644
--- a/doc/src/sgml/ref/alter_subscription.sgml
+++ b/doc/src/sgml/ref/alter_subscription.sgml
@@ -47,8 +47,6 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
You must own the subscription to use <command>ALTER SUBSCRIPTION</command>.
To alter the owner, you must also be a direct or indirect member of the
new owning role. The new owner has to be a superuser.
- (Currently, all subscription owners must be superusers, so the owner checks
- will be bypassed in practice. But this might change in the future.)
</para>
<para>
@@ -99,6 +97,9 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
<xref linkend="sql-createsubscription"/>. See there for more
information.
</para>
+ <para>
+ Only superusers may change the connection property.
+ </para>
</listitem>
</varlistentry>
@@ -139,6 +140,9 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
<literal>REFRESH PUBLICATION</literal> may be specified, to control the
implicit refresh operation.
</para>
+ <para>
+ Only superusers may change the list of subscribed publications.
+ </para>
</listitem>
</varlistentry>
@@ -204,6 +208,9 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
<literal>binary</literal>, and
<literal>streaming</literal>.
</para>
+ <para>
+ Only superusers may alter subscription parameters.
+ </para>
</listitem>
</varlistentry>
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index c47ba26369..6a5d192128 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -868,6 +868,11 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt,
{
case ALTER_SUBSCRIPTION_OPTIONS:
{
+ if (!superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("must be superuser to alter the options for a subscription")));
+
supported_opts = (SUBOPT_SLOT_NAME |
SUBOPT_SYNCHRONOUS_COMMIT | SUBOPT_BINARY |
SUBOPT_STREAMING);
@@ -946,6 +951,11 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt,
}
case ALTER_SUBSCRIPTION_CONNECTION:
+ if (!superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("must be superuser to alter the connection for a subscription")));
+
/* Load the library providing us libpq calls. */
load_file("libpqwalreceiver", false);
/* Check the connection info string. */
@@ -959,6 +969,11 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt,
case ALTER_SUBSCRIPTION_SET_PUBLICATION:
{
+ if (!superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("must be superuser to alter publications for a subscription")));
+
supported_opts = SUBOPT_COPY_DATA | SUBOPT_REFRESH;
parse_subscription_options(pstate, stmt->options,
supported_opts, &opts);
@@ -1006,6 +1021,11 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt,
List *publist;
bool isadd = stmt->kind == ALTER_SUBSCRIPTION_ADD_PUBLICATION;
+ if (!superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("must be superuser to alter publications for a subscription")));
+
supported_opts = SUBOPT_REFRESH | SUBOPT_COPY_DATA;
parse_subscription_options(pstate, stmt->options,
supported_opts, &opts);
diff --git a/src/test/regress/expected/subscription.out b/src/test/regress/expected/subscription.out
index 15a1ac6398..a05e6f1795 100644
--- a/src/test/regress/expected/subscription.out
+++ b/src/test/regress/expected/subscription.out
@@ -144,6 +144,57 @@ HINT: The owner of a subscription must be a superuser.
ALTER ROLE regress_subscription_user2 SUPERUSER;
-- now it works
ALTER SUBSCRIPTION regress_testsub OWNER TO regress_subscription_user2;
+-- revoke superuser from new owner
+ALTER ROLE regress_subscription_user2 NOSUPERUSER;
+SET SESSION AUTHORIZATION regress_subscription_user2;
+-- fail - non-superuser owner cannot change connection parameter
+ALTER SUBSCRIPTION regress_testsub CONNECTION 'dbname=somethingelse';
+ERROR: must be superuser to alter the connection for a subscription
+-- fail - non-superuser owner cannot alter the publications list
+ALTER SUBSCRIPTION regress_testsub ADD PUBLICATION somepub;
+ERROR: must be superuser to alter publications for a subscription
+ALTER SUBSCRIPTION regress_testsub DROP PUBLICATION otherpub;
+ERROR: must be superuser to alter publications for a subscription
+ALTER SUBSCRIPTION regress_testsub SET PUBLICATION somepub, otherpub;
+ERROR: must be superuser to alter publications for a subscription
+-- fail - non-superuser owner cannot change subscription parameters
+ALTER SUBSCRIPTION regress_testsub SET (copy_data = true);
+ERROR: must be superuser to alter the options for a subscription
+ALTER SUBSCRIPTION regress_testsub SET (copy_data = false);
+ERROR: must be superuser to alter the options for a subscription
+ALTER SUBSCRIPTION regress_testsub SET (create_slot = true);
+ERROR: must be superuser to alter the options for a subscription
+ALTER SUBSCRIPTION regress_testsub SET (create_slot = false);
+ERROR: must be superuser to alter the options for a subscription
+ALTER SUBSCRIPTION regress_testsub SET (slot_name = 'somethingelse');
+ERROR: must be superuser to alter the options for a subscription
+ALTER SUBSCRIPTION regress_testsub SET (synchronous_commit = on);
+ERROR: must be superuser to alter the options for a subscription
+ALTER SUBSCRIPTION regress_testsub SET (synchronous_commit = off);
+ERROR: must be superuser to alter the options for a subscription
+ALTER SUBSCRIPTION regress_testsub SET (synchronous_commit = local);
+ERROR: must be superuser to alter the options for a subscription
+ALTER SUBSCRIPTION regress_testsub SET (synchronous_commit = remote_write);
+ERROR: must be superuser to alter the options for a subscription
+ALTER SUBSCRIPTION regress_testsub SET (synchronous_commit = remote_apply);
+ERROR: must be superuser to alter the options for a subscription
+ALTER SUBSCRIPTION regress_testsub SET (binary = on);
+ERROR: must be superuser to alter the options for a subscription
+ALTER SUBSCRIPTION regress_testsub SET (binary = off);
+ERROR: must be superuser to alter the options for a subscription
+ALTER SUBSCRIPTION regress_testsub SET (connect = on);
+ERROR: must be superuser to alter the options for a subscription
+ALTER SUBSCRIPTION regress_testsub SET (connect = off);
+ERROR: must be superuser to alter the options for a subscription
+ALTER SUBSCRIPTION regress_testsub SET (streaming = on);
+ERROR: must be superuser to alter the options for a subscription
+ALTER SUBSCRIPTION regress_testsub SET (streaming = off);
+ERROR: must be superuser to alter the options for a subscription
+ALTER SUBSCRIPTION regress_testsub SET (two_phase = on);
+ERROR: must be superuser to alter the options for a subscription
+ALTER SUBSCRIPTION regress_testsub SET (two_phase = off);
+ERROR: must be superuser to alter the options for a subscription
+SET SESSION AUTHORIZATION 'regress_subscription_user';
-- fail - cannot do DROP SUBSCRIPTION inside transaction block with slot name
BEGIN;
DROP SUBSCRIPTION regress_testsub;
diff --git a/src/test/regress/sql/subscription.sql b/src/test/regress/sql/subscription.sql
index 7faa935a2a..8f66709441 100644
--- a/src/test/regress/sql/subscription.sql
+++ b/src/test/regress/sql/subscription.sql
@@ -105,6 +105,41 @@ ALTER ROLE regress_subscription_user2 SUPERUSER;
-- now it works
ALTER SUBSCRIPTION regress_testsub OWNER TO regress_subscription_user2;
+-- revoke superuser from new owner
+ALTER ROLE regress_subscription_user2 NOSUPERUSER;
+
+SET SESSION AUTHORIZATION regress_subscription_user2;
+
+-- fail - non-superuser owner cannot change connection parameter
+ALTER SUBSCRIPTION regress_testsub CONNECTION 'dbname=somethingelse';
+
+-- fail - non-superuser owner cannot alter the publications list
+ALTER SUBSCRIPTION regress_testsub ADD PUBLICATION somepub;
+ALTER SUBSCRIPTION regress_testsub DROP PUBLICATION otherpub;
+ALTER SUBSCRIPTION regress_testsub SET PUBLICATION somepub, otherpub;
+
+-- fail - non-superuser owner cannot change subscription parameters
+ALTER SUBSCRIPTION regress_testsub SET (copy_data = true);
+ALTER SUBSCRIPTION regress_testsub SET (copy_data = false);
+ALTER SUBSCRIPTION regress_testsub SET (create_slot = true);
+ALTER SUBSCRIPTION regress_testsub SET (create_slot = false);
+ALTER SUBSCRIPTION regress_testsub SET (slot_name = 'somethingelse');
+ALTER SUBSCRIPTION regress_testsub SET (synchronous_commit = on);
+ALTER SUBSCRIPTION regress_testsub SET (synchronous_commit = off);
+ALTER SUBSCRIPTION regress_testsub SET (synchronous_commit = local);
+ALTER SUBSCRIPTION regress_testsub SET (synchronous_commit = remote_write);
+ALTER SUBSCRIPTION regress_testsub SET (synchronous_commit = remote_apply);
+ALTER SUBSCRIPTION regress_testsub SET (binary = on);
+ALTER SUBSCRIPTION regress_testsub SET (binary = off);
+ALTER SUBSCRIPTION regress_testsub SET (connect = on);
+ALTER SUBSCRIPTION regress_testsub SET (connect = off);
+ALTER SUBSCRIPTION regress_testsub SET (streaming = on);
+ALTER SUBSCRIPTION regress_testsub SET (streaming = off);
+ALTER SUBSCRIPTION regress_testsub SET (two_phase = on);
+ALTER SUBSCRIPTION regress_testsub SET (two_phase = off);
+
+SET SESSION AUTHORIZATION 'regress_subscription_user';
+
-- fail - cannot do DROP SUBSCRIPTION inside transaction block with slot name
BEGIN;
DROP SUBSCRIPTION regress_testsub;
--
2.21.1 (Apple Git-122.3)
[application/octet-stream] v1-0002-Allow-subscription-ownership-by-non-superusers.patch (4.9K, ../../[email protected]/3-v1-0002-Allow-subscription-ownership-by-non-superusers.patch)
download | inline diff:
From 9b1be64005e0e78694f9b6965075b35cfa77072e Mon Sep 17 00:00:00 2001
From: Mark Dilger <[email protected]>
Date: Sun, 26 Sep 2021 18:24:07 -0700
Subject: [PATCH v1 2/3] Allow subscription ownership by non-superusers
Non-superusers can already end up owning subscriptions if superuser
is revoked from a subscription owner, so quit the pretense and
simply allow the ownership transfer overtly by ALTER SUBSCRIPTION.
The prior situation did more to give a false sense that
subscriptions would never be owned by non-superusers than it did to
actually prevent that scenario from arising.
---
doc/src/sgml/ref/alter_subscription.sgml | 2 +-
src/backend/commands/subscriptioncmds.c | 9 ++-------
src/test/regress/expected/subscription.out | 12 ++++--------
src/test/regress/sql/subscription.sql | 11 ++++-------
4 files changed, 11 insertions(+), 23 deletions(-)
diff --git a/doc/src/sgml/ref/alter_subscription.sgml b/doc/src/sgml/ref/alter_subscription.sgml
index b1fd73f776..bc52339eba 100644
--- a/doc/src/sgml/ref/alter_subscription.sgml
+++ b/doc/src/sgml/ref/alter_subscription.sgml
@@ -46,7 +46,7 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
<para>
You must own the subscription to use <command>ALTER SUBSCRIPTION</command>.
To alter the owner, you must also be a direct or indirect member of the
- new owning role. The new owner has to be a superuser.
+ new owning role.
</para>
<para>
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index 6a5d192128..d75183cd12 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -1476,13 +1476,8 @@ AlterSubscriptionOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_SUBSCRIPTION,
NameStr(form->subname));
- /* New owner must be a superuser */
- if (!superuser_arg(newOwnerId))
- ereport(ERROR,
- (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- errmsg("permission denied to change owner of subscription \"%s\"",
- NameStr(form->subname)),
- errhint("The owner of a subscription must be a superuser.")));
+ /* Must be able to assign ownership to the target role */
+ check_is_member_of_role(GetUserId(), newOwnerId);
form->subowner = newOwnerId;
CatalogTupleUpdate(rel, &tup->t_self, tup);
diff --git a/src/test/regress/expected/subscription.out b/src/test/regress/expected/subscription.out
index a05e6f1795..9b4dac9c0e 100644
--- a/src/test/regress/expected/subscription.out
+++ b/src/test/regress/expected/subscription.out
@@ -137,16 +137,12 @@ HINT: Available values: local, remote_write, remote_apply, on, off.
-- rename back to keep the rest simple
ALTER SUBSCRIPTION regress_testsub_foo RENAME TO regress_testsub;
--- fail - new owner must be superuser
+-- superuser can assign the ownership to a non-superuser
ALTER SUBSCRIPTION regress_testsub OWNER TO regress_subscription_user2;
-ERROR: permission denied to change owner of subscription "regress_testsub"
-HINT: The owner of a subscription must be a superuser.
-ALTER ROLE regress_subscription_user2 SUPERUSER;
--- now it works
-ALTER SUBSCRIPTION regress_testsub OWNER TO regress_subscription_user2;
--- revoke superuser from new owner
-ALTER ROLE regress_subscription_user2 NOSUPERUSER;
SET SESSION AUTHORIZATION regress_subscription_user2;
+-- fail - not a member of the target role
+ALTER SUBSCRIPTION regress_testsub OWNER TO regress_subscription_user;
+ERROR: must be member of role "regress_subscription_user"
-- fail - non-superuser owner cannot change connection parameter
ALTER SUBSCRIPTION regress_testsub CONNECTION 'dbname=somethingelse';
ERROR: must be superuser to alter the connection for a subscription
diff --git a/src/test/regress/sql/subscription.sql b/src/test/regress/sql/subscription.sql
index 8f66709441..6c68d547d1 100644
--- a/src/test/regress/sql/subscription.sql
+++ b/src/test/regress/sql/subscription.sql
@@ -99,17 +99,14 @@ ALTER SUBSCRIPTION regress_testsub_foo SET (synchronous_commit = foobar);
-- rename back to keep the rest simple
ALTER SUBSCRIPTION regress_testsub_foo RENAME TO regress_testsub;
--- fail - new owner must be superuser
-ALTER SUBSCRIPTION regress_testsub OWNER TO regress_subscription_user2;
-ALTER ROLE regress_subscription_user2 SUPERUSER;
--- now it works
+-- superuser can assign the ownership to a non-superuser
ALTER SUBSCRIPTION regress_testsub OWNER TO regress_subscription_user2;
--- revoke superuser from new owner
-ALTER ROLE regress_subscription_user2 NOSUPERUSER;
-
SET SESSION AUTHORIZATION regress_subscription_user2;
+-- fail - not a member of the target role
+ALTER SUBSCRIPTION regress_testsub OWNER TO regress_subscription_user;
+
-- fail - non-superuser owner cannot change connection parameter
ALTER SUBSCRIPTION regress_testsub CONNECTION 'dbname=somethingelse';
--
2.21.1 (Apple Git-122.3)
[application/octet-stream] v1-0003-Respect-permissions-within-logical-replication.patch (14.4K, ../../[email protected]/4-v1-0003-Respect-permissions-within-logical-replication.patch)
download | inline diff:
From cf0e0575e0a97f0b3a1aebee2d2fc4d3822daaeb Mon Sep 17 00:00:00 2001
From: Mark Dilger <[email protected]>
Date: Sun, 26 Sep 2021 18:25:32 -0700
Subject: [PATCH v1 3/3] Respect permissions within logical replication
Prevent logical replication workers from performing insert, update,
delete, truncate, or copy commands on tables unless the subscription
owner has permission to do so. This makes it much safer to allow
non-superusers to create subscriptions, since they can only cause
changes to replicate into schemas and tables that they would be able
to directly make themselves. This also reduces the amount of trust
that a subscriber must have in a publisher; if the subscription is
set up by a DBA using an account that is intentionally restricted to
only those tables or schemas that the DBA expects the publication to
touch, then the DBA can be create and refresh the subscription
without fear that a malicious publisher will have added other
critical tables to the publication and thereby overwrite them on the
subscriber side. In many setups this is likely a non-issue, as the
same DBA manages both the publisher and the subscriber, but it seems
wiser not to hard-code that assumption into the security model of
logical replication.
---
doc/src/sgml/logical-replication.sgml | 49 +++++---
src/backend/replication/logical/tablesync.c | 13 +++
src/backend/replication/logical/worker.c | 29 +++++
src/test/subscription/t/025_nosuperuser.pl | 118 ++++++++++++++++++++
4 files changed, 196 insertions(+), 13 deletions(-)
create mode 100644 src/test/subscription/t/025_nosuperuser.pl
diff --git a/doc/src/sgml/logical-replication.sgml b/doc/src/sgml/logical-replication.sgml
index 88646bc859..d6c7698847 100644
--- a/doc/src/sgml/logical-replication.sgml
+++ b/doc/src/sgml/logical-replication.sgml
@@ -330,6 +330,15 @@
will simply be skipped.
</para>
+ <para>
+ Logical replication operations are performed with the privileges of the role
+ which owns the subscription. Only superusers may create subscriptions, but
+ if the ownership of the subscription is transferred, or if the owner
+ subsequently has superuser privileges revoked, permissions failures can
+ cause conflicts. (Note that <productname>PostgreSQL</productname> prior to
+ version 15.0 did no permissions checking when applying changes.)
+ </para>
+
<para>
A conflict will produce an error and will stop the replication; it must be
resolved manually by the user. Details about the conflict can be found in
@@ -337,7 +346,7 @@
</para>
<para>
- The resolution can be done either by changing data on the subscriber so
+ The resolution can be done either by changing data or permissions on the subscriber so
that it does not conflict with the incoming change or by skipping the
transaction that conflicts with the existing data. The transaction can be
skipped by calling the <link linkend="pg-replication-origin-advance">
@@ -530,13 +539,15 @@
<para>
A user able to modify the schema of subscriber-side tables can execute
- arbitrary code as a superuser. Limit ownership
- and <literal>TRIGGER</literal> privilege on such tables to roles that
- superusers trust. Moreover, if untrusted users can create tables, use only
- publications that list tables explicitly. That is to say, create a
- subscription <literal>FOR ALL TABLES</literal> only when superusers trust
- every user permitted to create a non-temp table on the publisher or the
- subscriber.
+ arbitrary code as the role which owns any subscription which modifies those
+ tables. Limit ownership and <literal>TRIGGER</literal> privilege on such
+ tables to trusted roles. Likewise, limit privileges of the subscription
+ owner to only the privileges needed to modify the tables that the
+ subscription should be able to change. Moreover, if untrusted users can
+ create tables, use only publications that list tables explicitly. That is
+ to say, create a subscription <literal>FOR ALL TABLES</literal> only when
+ superusers trust every user permitted to create a non-temp table on the
+ publisher or the subscriber.
</para>
<para>
@@ -569,18 +580,30 @@
</para>
<para>
- To create a subscription, the user must be a superuser.
+ To create a subscription, the user must be a superuser. The ownership can
+ subsequently be transferred or the role have superuser privilege removed.
</para>
<para>
The subscription apply process will run in the local database with the
- privileges of a superuser.
+ privileges of the subscription owner.
+ </para>
+
+ <para>
+ On the publisher, privileges are only checked once at the start of a
+ replication connection and are not re-checked as each change record is read.
</para>
<para>
- Privileges are only checked once at the start of a replication connection.
- They are not re-checked as each change record is read from the publisher,
- nor are they re-checked for each change when applied.
+ On the subscriber, the subscription owner's privileges are re-checked for
+ each change record when applied, but beware that a change of ownership for a
+ subscription may not be noticed immediately by the replication workers.
+ Changes made on the publisher may be applied on the subscriber as
+ the old owner. In such cases, the old owner's privileges will be the ones
+ that matter. Worse still, it may be hard to predict when replication
+ workers will notice the new ownership. Subscriptions created disabled and
+ only enabled after ownership has been changed will not be subject to this
+ race condition.
</para>
</sect1>
diff --git a/src/backend/replication/logical/tablesync.c b/src/backend/replication/logical/tablesync.c
index f07983a43c..2400ef8c45 100644
--- a/src/backend/replication/logical/tablesync.c
+++ b/src/backend/replication/logical/tablesync.c
@@ -111,6 +111,7 @@
#include "replication/origin.h"
#include "storage/ipc.h"
#include "storage/lmgr.h"
+#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
@@ -924,6 +925,7 @@ LogicalRepSyncTableStart(XLogRecPtr *origin_startpos)
char relstate;
XLogRecPtr relstate_lsn;
Relation rel;
+ AclResult aclresult;
WalRcvExecResult *res;
char originname[NAMEDATALEN];
RepOriginId originid;
@@ -1042,6 +1044,17 @@ LogicalRepSyncTableStart(XLogRecPtr *origin_startpos)
*/
rel = table_open(MyLogicalRepWorker->relid, RowExclusiveLock);
+ /*
+ * Check that our table sync worker has permission to insert into the
+ * target table.
+ */
+ aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(),
+ ACL_INSERT);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult,
+ get_relkind_objtype(rel->rd_rel->relkind),
+ RelationGetRelationName(rel));
+
/*
* Start a transaction in the remote node in REPEATABLE READ mode. This
* ensures that both the replication slot we create (see below) and the
diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c
index 8d96c926b4..459d9b5ae1 100644
--- a/src/backend/replication/logical/worker.c
+++ b/src/backend/replication/logical/worker.c
@@ -179,6 +179,7 @@
#include "storage/proc.h"
#include "storage/procarray.h"
#include "tcop/tcopprot.h"
+#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/catcache.h"
#include "utils/dynahash.h"
@@ -1537,6 +1538,7 @@ apply_handle_insert(StringInfo s)
LogicalRepRelMapEntry *rel;
LogicalRepTupleData newtup;
LogicalRepRelId relid;
+ AclResult aclresult;
ApplyExecutionData *edata;
EState *estate;
TupleTableSlot *remoteslot;
@@ -1559,6 +1561,12 @@ apply_handle_insert(StringInfo s)
end_replication_step();
return;
}
+ aclresult = pg_class_aclcheck(RelationGetRelid(rel->localrel), GetUserId(),
+ ACL_INSERT);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult,
+ get_relkind_objtype(rel->localrel->rd_rel->relkind),
+ get_rel_name(rel->localreloid));
/* Set relation for error callback */
apply_error_callback_arg.rel = rel;
@@ -1659,6 +1667,7 @@ apply_handle_update(StringInfo s)
{
LogicalRepRelMapEntry *rel;
LogicalRepRelId relid;
+ AclResult aclresult;
ApplyExecutionData *edata;
EState *estate;
LogicalRepTupleData oldtup;
@@ -1686,6 +1695,12 @@ apply_handle_update(StringInfo s)
end_replication_step();
return;
}
+ aclresult = pg_class_aclcheck(RelationGetRelid(rel->localrel), GetUserId(),
+ ACL_UPDATE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult,
+ get_relkind_objtype(rel->localrel->rd_rel->relkind),
+ get_rel_name(rel->localreloid));
/* Set relation for error callback */
apply_error_callback_arg.rel = rel;
@@ -1826,6 +1841,7 @@ apply_handle_delete(StringInfo s)
LogicalRepRelMapEntry *rel;
LogicalRepTupleData oldtup;
LogicalRepRelId relid;
+ AclResult aclresult;
ApplyExecutionData *edata;
EState *estate;
TupleTableSlot *remoteslot;
@@ -1848,6 +1864,12 @@ apply_handle_delete(StringInfo s)
end_replication_step();
return;
}
+ aclresult = pg_class_aclcheck(RelationGetRelid(rel->localrel), GetUserId(),
+ ACL_DELETE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult,
+ get_relkind_objtype(rel->localrel->rd_rel->relkind),
+ get_rel_name(rel->localreloid));
/* Set relation for error callback */
apply_error_callback_arg.rel = rel;
@@ -2220,6 +2242,7 @@ apply_handle_truncate(StringInfo s)
{
LogicalRepRelId relid = lfirst_oid(lc);
LogicalRepRelMapEntry *rel;
+ AclResult aclresult;
rel = logicalrep_rel_open(relid, lockmode);
if (!should_apply_changes_for_rel(rel))
@@ -2231,6 +2254,12 @@ apply_handle_truncate(StringInfo s)
logicalrep_rel_close(rel, lockmode);
continue;
}
+ aclresult = pg_class_aclcheck(RelationGetRelid(rel->localrel),
+ GetUserId(), ACL_TRUNCATE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult,
+ get_relkind_objtype(rel->localrel->rd_rel->relkind),
+ get_rel_name(rel->localreloid));
remote_rels = lappend(remote_rels, rel);
rels = lappend(rels, rel->localrel);
diff --git a/src/test/subscription/t/025_nosuperuser.pl b/src/test/subscription/t/025_nosuperuser.pl
new file mode 100644
index 0000000000..93c830a0ed
--- /dev/null
+++ b/src/test/subscription/t/025_nosuperuser.pl
@@ -0,0 +1,118 @@
+
+# Copyright (c) 2021, PostgreSQL Global Development Group
+
+# Test subscriptions owned by non-superusers
+use strict;
+use warnings;
+use PostgresNode;
+use TestLib;
+use Test::More tests => 3;
+
+# Setup
+
+my $node_publisher = PostgresNode->new('publisher');
+$node_publisher->init(allows_streaming => 'logical');
+$node_publisher->start;
+
+my $node_subscriber = PostgresNode->new('subscriber');
+$node_subscriber->init(allows_streaming => 'logical');
+$node_subscriber->start;
+
+my $publisher_connstr = $node_publisher->connstr . ' dbname=postgres';
+
+# Create the same schema, roles and permissions on both nodes.
+my $sql = qq(
+CREATE ROLE alice NOSUPERUSER NOLOGIN;
+GRANT CREATE ON DATABASE postgres TO alice;
+SET ROLE alice;
+CREATE SCHEMA alice;
+CREATE TABLE alice.tbl1 (i1 INTEGER);
+ALTER TABLE alice.tbl1 REPLICA IDENTITY FULL;
+RESET ROLE;
+
+CREATE ROLE bob NOSUPERUSER NOLOGIN;
+GRANT CREATE ON DATABASE postgres TO bob;
+SET ROLE bob;
+CREATE SCHEMA bob;
+CREATE TABLE bob.tbl1 (i1 INTEGER);
+CREATE TABLE bob.tbl2 (i2 INTEGER);
+ALTER TABLE bob.tbl1 REPLICA IDENTITY FULL;
+ALTER TABLE bob.tbl2 REPLICA IDENTITY FULL;
+RESET ROLE;
+);
+$node_publisher->safe_psql('postgres', $sql);
+$node_subscriber->safe_psql('postgres', $sql);
+
+# Bob publishes.
+$node_publisher->safe_psql('postgres', qq(
+SET ROLE bob;
+CREATE PUBLICATION bob_pub FOR TABLE bob.tbl1;
+INSERT INTO bob.tbl1 VALUES (1);
+));
+
+# Bob gets DBA to create a subscribe for him.
+$node_subscriber->safe_psql('postgres', qq(
+CREATE SUBSCRIPTION bob_sub CONNECTION '$publisher_connstr' PUBLICATION bob_pub;
+ALTER SUBSCRIPTION bob_sub OWNER TO bob;
+));
+
+# Wait for initial sync of all subscriptions.
+my $synced_query =
+ "SELECT count(1) = 0 FROM pg_subscription_rel WHERE srsubstate NOT IN ('r', 's');";
+$node_subscriber->poll_query_until('postgres', $synced_query)
+ or die "Timed out while waiting for subscriber to synchronize data";
+
+# Check that the data came through.
+my $result = $node_subscriber->safe_psql('postgres', qq(
+SET ROLE bob;
+SELECT i1 FROM bob.tbl1;
+));
+is( $result, '1', 'data from schema bob was replicated');
+
+# A malicious dba on publisher adds alice's tables to publication "bob_pub".
+$node_publisher->safe_psql('postgres', qq(
+ALTER PUBLICATION bob_pub ADD TABLE alice.tbl1;
+INSERT INTO alice.tbl1 VALUES (1);
+));
+
+# Bob adds another table on publisher side to the publication and performs
+# DML on the new table.
+$node_publisher->safe_psql('postgres', qq(
+SET ROLE bob;
+ALTER PUBLICATION bob_pub ADD TABLE bob.tbl2;
+INSERT INTO bob.tbl2 VALUES (2);
+));
+
+# Bob refreshes on subscriber side to get the new data from "bob.tbl2", not
+# knowing that alice's tables have been added. An error during tablesync or
+# apply should prevent the data in schema "alice" being replicated.
+#
+$node_subscriber->psql('postgres', qq(
+SET ROLE bob;
+ALTER SUBSCRIPTION bob_sub REFRESH PUBLICATION;
+));
+
+# Wait for sync of all subscriptions.
+$node_subscriber->poll_query_until('postgres', $synced_query)
+ or die "Timed out while waiting for subscriber to synchronize data";
+
+# The data for schema "bob" might not be replicated, because the replication
+# may abort first on a permissions error for schema "alice". We insist that
+# data for "alice" not be replicated, but we only insist that if data from
+# "bob" gets replicated that it be the correct new data and not corrupted.
+$result = $node_subscriber->safe_psql('postgres', qq(
+SELECT a.i1::text || '_' ||
+ coalesce(b.i2::text,'null') || '_' ||
+ coalesce(c.i1::text,'null')
+ FROM bob.tbl1 a
+ LEFT JOIN bob.tbl2 b ON TRUE
+ LEFT JOIN alice.tbl1 c ON TRUE;
+));
+like ($result, qr/^(?:1_null_null|1_2_null)$/,
+ 'subscriber side schema bob data is reasonable and alice data is unreplicated');
+
+# check that the logs on the subscriber side contain the expected permissions
+# error associated with a failed attempt to replicate into schema "alice".
+my $subscriber_log = TestLib::slurp_file($node_subscriber->logfile);
+like ($subscriber_log, qr/ERROR: permission denied for schema alice/msi,
+ 'subscriber lacks permission for schema alice');
--
2.21.1 (Apple Git-122.3)
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
@ 2021-10-25 07:26 ` Ronan Dunklau <[email protected]>
1 sibling, 0 replies; 68+ messages in thread
From: Ronan Dunklau @ 2021-10-25 07:26 UTC (permalink / raw)
To: pgsql-hackers; [email protected]; +Cc: Andrew Dunstan <[email protected]>; Mark Dilger <[email protected]>
Le mercredi 20 octobre 2021, 20:40:39 CEST Mark Dilger a écrit :
> These patches have been split off the now deprecated monolithic "Delegating
> superuser tasks to new security roles" thread at [1].
>
> The purpose of these patches is to allow non-superuser subscription owners
> without risk of them overwriting tables they lack privilege to write
> directly. This both allows subscriptions to be managed by non-superusers,
> and protects servers with subscriptions from malicious activity on the
> publisher side.
Thank you Mark for splitting this.
This patch looks good to me, and provides both better security (by closing the
"dropping superuser role" loophole) and usefule features.
--
Ronan Dunklau
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
@ 2021-11-01 14:18 ` Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
1 sibling, 1 reply; 68+ messages in thread
From: Andrew Dunstan @ 2021-11-01 14:18 UTC (permalink / raw)
To: Mark Dilger <[email protected]>; pgsql-hackers
On 10/20/21 14:40, Mark Dilger wrote:
> These patches have been split off the now deprecated monolithic "Delegating superuser tasks to new security roles" thread at [1].
>
> The purpose of these patches is to allow non-superuser subscription owners without risk of them overwriting tables they lack privilege to write directly. This both allows subscriptions to be managed by non-superusers, and protects servers with subscriptions from malicious activity on the publisher side.
>
> [1] https://www.postgresql.org/message-id/flat/F9408A5A-B20B-42D2-9E7F-49CD3D1547BC%40enterprisedb.com
These patches look good on their face. The code changes are very
straightforward.
w.r.t. this:
+ On the subscriber, the subscription owner's privileges are
re-checked for
+ each change record when applied, but beware that a change of
ownership for a
+ subscription may not be noticed immediately by the replication workers.
+ Changes made on the publisher may be applied on the subscriber as
+ the old owner. In such cases, the old owner's privileges will be
the ones
+ that matter. Worse still, it may be hard to predict when replication
+ workers will notice the new ownership. Subscriptions created
disabled and
+ only enabled after ownership has been changed will not be subject to
this
+ race condition.
maybe we should disable the subscription before making such a change and
then re-enable it?
cheers
andrew
--
Andrew Dunstan
EDB: https://www.enterprisedb.com
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
@ 2021-11-01 17:58 ` Mark Dilger <[email protected]>
2021-11-01 22:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-16 18:08 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
0 siblings, 3 replies; 68+ messages in thread
From: Mark Dilger @ 2021-11-01 17:58 UTC (permalink / raw)
To: Andrew Dunstan <[email protected]>; +Cc: pgsql-hackers
> On Nov 1, 2021, at 7:18 AM, Andrew Dunstan <[email protected]> wrote:
>
> w.r.t. this:
>
> + On the subscriber, the subscription owner's privileges are
> re-checked for
> + each change record when applied, but beware that a change of
> ownership for a
> + subscription may not be noticed immediately by the replication workers.
> + Changes made on the publisher may be applied on the subscriber as
> + the old owner. In such cases, the old owner's privileges will be
> the ones
> + that matter. Worse still, it may be hard to predict when replication
> + workers will notice the new ownership. Subscriptions created
> disabled and
> + only enabled after ownership has been changed will not be subject to
> this
> + race condition.
>
>
> maybe we should disable the subscription before making such a change and
> then re-enable it?
Right. I commented the code that way because there is a clear concern, but I was uncertain which way around the problem was best.
ALTER SUBSCRIPTION..[ENABLE | DISABLE] do not synchronously start or stop subscription workers. The ALTER command updates the catalog's subenabled field, but workers only lazily respond to that. Disabling and enabling the subscription as part of the OWNER TO would not reliably accomplish anything.
The attached patch demonstrates the race condition. It sets up a publisher and subscriber, and toggles the subscription on and off on the subscriber node, interleaved with inserts and deletes on the publisher node. If the ALTER SUBSCRIPTION commands were synchronous, the test results would be deterministic, with only the inserts performed while the subscription is enabled being replicated, but because the ALTER commands are asynchronous, the results are nondeterministic.
It is unclear that I can make ALTER SUBSCRIPTION..OWNER TO synchronous without redesigning the way workers respond to pg_subscription catalog updates generally. That may be a good project to eventually tackle, but I don't see that it is more important to close the race condition in an OWNER TO than for a DISABLE.
Thoughts?
—
Mark Dilger
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
Attachments:
[application/octet-stream] alter_subscription_race.patch (3.3K, ../../[email protected]/2-alter_subscription_race.patch)
download | inline diff:
diff --git a/src/test/subscription/t/026_race.pl b/src/test/subscription/t/026_race.pl
new file mode 100644
index 0000000000..cbbe6c34e2
--- /dev/null
+++ b/src/test/subscription/t/026_race.pl
@@ -0,0 +1,86 @@
+
+# Copyright (c) 2021, PostgreSQL Global Development Group
+
+# Test subscriptions owned by non-superusers
+use strict;
+use warnings;
+use PostgresNode;
+use TestLib;
+use Test::More;
+
+our $LOOPCOUNT = 100;
+plan tests => 2 * $LOOPCOUNT;
+my $result;
+
+# Setup
+
+my $node_publisher = PostgresNode->new('publisher');
+$node_publisher->init(allows_streaming => 'logical');
+$node_publisher->start;
+
+my $node_subscriber = PostgresNode->new('subscriber');
+$node_subscriber->init(allows_streaming => 'logical');
+$node_subscriber->start;
+
+my $publisher_connstr = $node_publisher->connstr . ' dbname=postgres';
+
+$node_publisher->safe_psql('postgres', qq(
+CREATE TABLE t (i INTEGER);
+ALTER TABLE t REPLICA IDENTITY FULL;
+CREATE PUBLICATION pub FOR TABLE t;
+));
+
+$node_subscriber->safe_psql('postgres', qq(
+CREATE TABLE t (i INTEGER);
+CREATE SUBSCRIPTION sub CONNECTION '$publisher_connstr' PUBLICATION pub;
+CREATE TABLE b (LIKE t);
+));
+
+# Wait for initial sync of all subscriptions.
+my $synced_query =
+ "SELECT count(1) = 0 FROM pg_subscription_rel WHERE srsubstate NOT IN ('r', 's');";
+$node_subscriber->poll_query_until('postgres', $synced_query)
+ or die "Timed out while waiting for subscriber to synchronize data";
+
+# Upon first entry to this loop, the subscription is enabled
+foreach my $loop (1..$LOOPCOUNT)
+{
+ my $even = $loop * 2;
+ my $odd = ($loop * 2) + 1;
+
+ # The subscription is enabled. This even number is fair game for
+ # replication.
+ $node_publisher->safe_psql('postgres', "INSERT INTO t (i) VALUES ($even)");
+
+ # We may replicate the even number before the subscription is disabled, but
+ # maybe not.
+ $node_subscriber->safe_psql('postgres', "ALTER SUBSCRIPTION sub DISABLE");
+
+ # The subscription is now disabled, but workers on the subscriber side may
+ # not have gotten the message yet. As such, this odd number may slip
+ # through.
+ $node_publisher->safe_psql('postgres', "INSERT INTO t (i) VALUES ($odd)");
+
+ # See if we can catch any odd numbers in the subscriber's copy of table t
+ $result = $node_subscriber->safe_psql('postgres',
+ "SELECT COUNT(*) FROM t WHERE i % 2 = 1");
+ is ($result, 0, "No odd numbers in subscriber copy of table t before delete on publisher");
+
+ # Clear out all values on the publisher side, so that the odd number cannot
+ # be replicated after we re-enable the subscription. Of course, it may have
+ # already slipped through, and it is also possible that the even number has
+ # not replicated yet.
+ #
+ # Since the publication only publishes INSERTs, this delete should only have
+ # effect on the publisher side.
+ $node_publisher->safe_psql('postgres', "DELETE FROM t WHERE i = $odd");
+
+ # Enable the subscription for the next loop. Note that at this point, the
+ # table is empty on the publisher side.
+ $node_subscriber->safe_psql('postgres', "ALTER SUBSCRIPTION sub ENABLE");
+
+ # See if we can catch an odd number before the delete is propogated
+ $result = $node_subscriber->safe_psql('postgres',
+ "SELECT COUNT(*) FROM t WHERE i % 2 = 1");
+ is ($result, 0, "No odd numbers in subscriber copy of table t after delete on publisher");
+}
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
@ 2021-11-01 22:44 ` Mark Dilger <[email protected]>
2021-11-02 15:17 ` Re: Non-superuser subscription owners Robert Haas <[email protected]>
2 siblings, 1 reply; 68+ messages in thread
From: Mark Dilger @ 2021-11-01 22:44 UTC (permalink / raw)
To: pgsql-hackers; +Cc: Andrew Dunstan <[email protected]>
> On Nov 1, 2021, at 10:58 AM, Mark Dilger <[email protected]> wrote:
>
> ALTER SUBSCRIPTION..[ENABLE | DISABLE] do not synchronously start or stop subscription workers. The ALTER command updates the catalog's subenabled field, but workers only lazily respond to that. Disabling and enabling the subscription as part of the OWNER TO would not reliably accomplish anything.
Having discussed this with Andrew off-list, we've concluded that updating the documentation for logical replication to make this point more clear is probably sufficient, but I wonder if anyone thinks otherwise?
—
Mark Dilger
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 22:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
@ 2021-11-02 15:17 ` Robert Haas <[email protected]>
0 siblings, 0 replies; 68+ messages in thread
From: Robert Haas @ 2021-11-02 15:17 UTC (permalink / raw)
To: Mark Dilger <[email protected]>; +Cc: pgsql-hackers; Andrew Dunstan <[email protected]>
On Mon, Nov 1, 2021 at 6:44 PM Mark Dilger <[email protected]> wrote:
> > ALTER SUBSCRIPTION..[ENABLE | DISABLE] do not synchronously start or stop subscription workers. The ALTER command updates the catalog's subenabled field, but workers only lazily respond to that. Disabling and enabling the subscription as part of the OWNER TO would not reliably accomplish anything.
>
> Having discussed this with Andrew off-list, we've concluded that updating the documentation for logical replication to make this point more clear is probably sufficient, but I wonder if anyone thinks otherwise?
The question in my mind is whether there's some reasonable amount of
time that a user should expect to have to wait for the changes to take
effect. If it could easily happen that the old permissions are still
in use a month after the change is made, I think that's probably not
good. If there's reason to think that, barring unusual circumstances,
changes will be noticed within a few minutes, I think that's fine.
--
Robert Haas
EDB: http://www.enterprisedb.com
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
@ 2021-11-03 19:50 ` Mark Dilger <[email protected]>
2021-11-16 20:06 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-18 11:37 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2 siblings, 3 replies; 68+ messages in thread
From: Mark Dilger @ 2021-11-03 19:50 UTC (permalink / raw)
To: Andrew Dunstan <[email protected]>; +Cc: pgsql-hackers; Robert Haas <[email protected]>
> On Nov 1, 2021, at 10:58 AM, Mark Dilger <[email protected]> wrote:
>
> ALTER SUBSCRIPTION..[ENABLE | DISABLE] do not synchronously start or stop subscription workers. The ALTER command updates the catalog's subenabled field, but workers only lazily respond to that. Disabling and enabling the subscription as part of the OWNER TO would not reliably accomplish anything.
I have rethought my prior analysis. The problem in the previous patch was that the subscription apply workers did not check for a change in ownership the way they checked for other changes, instead only picking up the new ownership information when the worker restarted for some other reason. This next patch set fixes that. The application of a change record may continue under the old ownership permissions when a concurrent command changes the ownership of the subscription, but the worker will pick up the new permissions before applying the next record. I think that is consistent enough with reasonable expectations.
The first two patches are virtually unchanged. The third updates the behavior of the apply workers, and updates the documentation to match.
—
Mark Dilger
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
Attachments:
[application/octet-stream] v2-0001-Handle-non-superuser-subscription-owners-sensibly.patch (11.0K, ../../[email protected]/2-v2-0001-Handle-non-superuser-subscription-owners-sensibly.patch)
download | inline diff:
From 6225780bd7e4282ec47e153c19ef59fc10648c17 Mon Sep 17 00:00:00 2001
From: Mark Dilger <[email protected]>
Date: Sun, 26 Sep 2021 18:21:26 -0700
Subject: [PATCH v2 1/3] Handle non-superuser subscription owners sensibly
Stop pretending that subscriptions are always owned by superusers
and instead fix security problems that arise as a consequence of
them not being superuser. Specifically, disallow a non-superuser
changing the connection, the list of publications, or the options
for their subscription.
The prior behavior violated the principle of least surprise,
allowing a non-superuser in possession of a subscription to change
all aspects of the subscription, connecting it to a different server
and subscribing a different set of publications, effectively
amounting to a non-superuser creating a new subscription.
The new behavior restricts the non-superuser owner to enabling,
disabling, refreshing, renaming, and further assigning ownership of
the subscription.
---
doc/src/sgml/ref/alter_subscription.sgml | 11 ++++-
src/backend/commands/subscriptioncmds.c | 20 +++++++++
src/test/regress/expected/subscription.out | 51 ++++++++++++++++++++++
src/test/regress/sql/subscription.sql | 35 +++++++++++++++
4 files changed, 115 insertions(+), 2 deletions(-)
diff --git a/doc/src/sgml/ref/alter_subscription.sgml b/doc/src/sgml/ref/alter_subscription.sgml
index 0b027cc346..b1fd73f776 100644
--- a/doc/src/sgml/ref/alter_subscription.sgml
+++ b/doc/src/sgml/ref/alter_subscription.sgml
@@ -47,8 +47,6 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
You must own the subscription to use <command>ALTER SUBSCRIPTION</command>.
To alter the owner, you must also be a direct or indirect member of the
new owning role. The new owner has to be a superuser.
- (Currently, all subscription owners must be superusers, so the owner checks
- will be bypassed in practice. But this might change in the future.)
</para>
<para>
@@ -99,6 +97,9 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
<xref linkend="sql-createsubscription"/>. See there for more
information.
</para>
+ <para>
+ Only superusers may change the connection property.
+ </para>
</listitem>
</varlistentry>
@@ -139,6 +140,9 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
<literal>REFRESH PUBLICATION</literal> may be specified, to control the
implicit refresh operation.
</para>
+ <para>
+ Only superusers may change the list of subscribed publications.
+ </para>
</listitem>
</varlistentry>
@@ -204,6 +208,9 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
<literal>binary</literal>, and
<literal>streaming</literal>.
</para>
+ <para>
+ Only superusers may alter subscription parameters.
+ </para>
</listitem>
</varlistentry>
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index c47ba26369..6a5d192128 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -868,6 +868,11 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt,
{
case ALTER_SUBSCRIPTION_OPTIONS:
{
+ if (!superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("must be superuser to alter the options for a subscription")));
+
supported_opts = (SUBOPT_SLOT_NAME |
SUBOPT_SYNCHRONOUS_COMMIT | SUBOPT_BINARY |
SUBOPT_STREAMING);
@@ -946,6 +951,11 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt,
}
case ALTER_SUBSCRIPTION_CONNECTION:
+ if (!superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("must be superuser to alter the connection for a subscription")));
+
/* Load the library providing us libpq calls. */
load_file("libpqwalreceiver", false);
/* Check the connection info string. */
@@ -959,6 +969,11 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt,
case ALTER_SUBSCRIPTION_SET_PUBLICATION:
{
+ if (!superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("must be superuser to alter publications for a subscription")));
+
supported_opts = SUBOPT_COPY_DATA | SUBOPT_REFRESH;
parse_subscription_options(pstate, stmt->options,
supported_opts, &opts);
@@ -1006,6 +1021,11 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt,
List *publist;
bool isadd = stmt->kind == ALTER_SUBSCRIPTION_ADD_PUBLICATION;
+ if (!superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("must be superuser to alter publications for a subscription")));
+
supported_opts = SUBOPT_REFRESH | SUBOPT_COPY_DATA;
parse_subscription_options(pstate, stmt->options,
supported_opts, &opts);
diff --git a/src/test/regress/expected/subscription.out b/src/test/regress/expected/subscription.out
index 15a1ac6398..a05e6f1795 100644
--- a/src/test/regress/expected/subscription.out
+++ b/src/test/regress/expected/subscription.out
@@ -144,6 +144,57 @@ HINT: The owner of a subscription must be a superuser.
ALTER ROLE regress_subscription_user2 SUPERUSER;
-- now it works
ALTER SUBSCRIPTION regress_testsub OWNER TO regress_subscription_user2;
+-- revoke superuser from new owner
+ALTER ROLE regress_subscription_user2 NOSUPERUSER;
+SET SESSION AUTHORIZATION regress_subscription_user2;
+-- fail - non-superuser owner cannot change connection parameter
+ALTER SUBSCRIPTION regress_testsub CONNECTION 'dbname=somethingelse';
+ERROR: must be superuser to alter the connection for a subscription
+-- fail - non-superuser owner cannot alter the publications list
+ALTER SUBSCRIPTION regress_testsub ADD PUBLICATION somepub;
+ERROR: must be superuser to alter publications for a subscription
+ALTER SUBSCRIPTION regress_testsub DROP PUBLICATION otherpub;
+ERROR: must be superuser to alter publications for a subscription
+ALTER SUBSCRIPTION regress_testsub SET PUBLICATION somepub, otherpub;
+ERROR: must be superuser to alter publications for a subscription
+-- fail - non-superuser owner cannot change subscription parameters
+ALTER SUBSCRIPTION regress_testsub SET (copy_data = true);
+ERROR: must be superuser to alter the options for a subscription
+ALTER SUBSCRIPTION regress_testsub SET (copy_data = false);
+ERROR: must be superuser to alter the options for a subscription
+ALTER SUBSCRIPTION regress_testsub SET (create_slot = true);
+ERROR: must be superuser to alter the options for a subscription
+ALTER SUBSCRIPTION regress_testsub SET (create_slot = false);
+ERROR: must be superuser to alter the options for a subscription
+ALTER SUBSCRIPTION regress_testsub SET (slot_name = 'somethingelse');
+ERROR: must be superuser to alter the options for a subscription
+ALTER SUBSCRIPTION regress_testsub SET (synchronous_commit = on);
+ERROR: must be superuser to alter the options for a subscription
+ALTER SUBSCRIPTION regress_testsub SET (synchronous_commit = off);
+ERROR: must be superuser to alter the options for a subscription
+ALTER SUBSCRIPTION regress_testsub SET (synchronous_commit = local);
+ERROR: must be superuser to alter the options for a subscription
+ALTER SUBSCRIPTION regress_testsub SET (synchronous_commit = remote_write);
+ERROR: must be superuser to alter the options for a subscription
+ALTER SUBSCRIPTION regress_testsub SET (synchronous_commit = remote_apply);
+ERROR: must be superuser to alter the options for a subscription
+ALTER SUBSCRIPTION regress_testsub SET (binary = on);
+ERROR: must be superuser to alter the options for a subscription
+ALTER SUBSCRIPTION regress_testsub SET (binary = off);
+ERROR: must be superuser to alter the options for a subscription
+ALTER SUBSCRIPTION regress_testsub SET (connect = on);
+ERROR: must be superuser to alter the options for a subscription
+ALTER SUBSCRIPTION regress_testsub SET (connect = off);
+ERROR: must be superuser to alter the options for a subscription
+ALTER SUBSCRIPTION regress_testsub SET (streaming = on);
+ERROR: must be superuser to alter the options for a subscription
+ALTER SUBSCRIPTION regress_testsub SET (streaming = off);
+ERROR: must be superuser to alter the options for a subscription
+ALTER SUBSCRIPTION regress_testsub SET (two_phase = on);
+ERROR: must be superuser to alter the options for a subscription
+ALTER SUBSCRIPTION regress_testsub SET (two_phase = off);
+ERROR: must be superuser to alter the options for a subscription
+SET SESSION AUTHORIZATION 'regress_subscription_user';
-- fail - cannot do DROP SUBSCRIPTION inside transaction block with slot name
BEGIN;
DROP SUBSCRIPTION regress_testsub;
diff --git a/src/test/regress/sql/subscription.sql b/src/test/regress/sql/subscription.sql
index 7faa935a2a..8f66709441 100644
--- a/src/test/regress/sql/subscription.sql
+++ b/src/test/regress/sql/subscription.sql
@@ -105,6 +105,41 @@ ALTER ROLE regress_subscription_user2 SUPERUSER;
-- now it works
ALTER SUBSCRIPTION regress_testsub OWNER TO regress_subscription_user2;
+-- revoke superuser from new owner
+ALTER ROLE regress_subscription_user2 NOSUPERUSER;
+
+SET SESSION AUTHORIZATION regress_subscription_user2;
+
+-- fail - non-superuser owner cannot change connection parameter
+ALTER SUBSCRIPTION regress_testsub CONNECTION 'dbname=somethingelse';
+
+-- fail - non-superuser owner cannot alter the publications list
+ALTER SUBSCRIPTION regress_testsub ADD PUBLICATION somepub;
+ALTER SUBSCRIPTION regress_testsub DROP PUBLICATION otherpub;
+ALTER SUBSCRIPTION regress_testsub SET PUBLICATION somepub, otherpub;
+
+-- fail - non-superuser owner cannot change subscription parameters
+ALTER SUBSCRIPTION regress_testsub SET (copy_data = true);
+ALTER SUBSCRIPTION regress_testsub SET (copy_data = false);
+ALTER SUBSCRIPTION regress_testsub SET (create_slot = true);
+ALTER SUBSCRIPTION regress_testsub SET (create_slot = false);
+ALTER SUBSCRIPTION regress_testsub SET (slot_name = 'somethingelse');
+ALTER SUBSCRIPTION regress_testsub SET (synchronous_commit = on);
+ALTER SUBSCRIPTION regress_testsub SET (synchronous_commit = off);
+ALTER SUBSCRIPTION regress_testsub SET (synchronous_commit = local);
+ALTER SUBSCRIPTION regress_testsub SET (synchronous_commit = remote_write);
+ALTER SUBSCRIPTION regress_testsub SET (synchronous_commit = remote_apply);
+ALTER SUBSCRIPTION regress_testsub SET (binary = on);
+ALTER SUBSCRIPTION regress_testsub SET (binary = off);
+ALTER SUBSCRIPTION regress_testsub SET (connect = on);
+ALTER SUBSCRIPTION regress_testsub SET (connect = off);
+ALTER SUBSCRIPTION regress_testsub SET (streaming = on);
+ALTER SUBSCRIPTION regress_testsub SET (streaming = off);
+ALTER SUBSCRIPTION regress_testsub SET (two_phase = on);
+ALTER SUBSCRIPTION regress_testsub SET (two_phase = off);
+
+SET SESSION AUTHORIZATION 'regress_subscription_user';
+
-- fail - cannot do DROP SUBSCRIPTION inside transaction block with slot name
BEGIN;
DROP SUBSCRIPTION regress_testsub;
--
2.21.1 (Apple Git-122.3)
[application/octet-stream] v2-0002-Allow-subscription-ownership-by-non-superusers.patch (4.9K, ../../[email protected]/3-v2-0002-Allow-subscription-ownership-by-non-superusers.patch)
download | inline diff:
From f4cae21ee2c7045fe5c89fbba5ecf7a3de3e2283 Mon Sep 17 00:00:00 2001
From: Mark Dilger <[email protected]>
Date: Sun, 26 Sep 2021 18:24:07 -0700
Subject: [PATCH v2 2/3] Allow subscription ownership by non-superusers
Non-superusers can already end up owning subscriptions if superuser
is revoked from a subscription owner, so quit the pretense and
simply allow the ownership transfer overtly by ALTER SUBSCRIPTION.
The prior situation did more to give a false sense that
subscriptions would never be owned by non-superusers than it did to
actually prevent that scenario from arising.
---
doc/src/sgml/ref/alter_subscription.sgml | 2 +-
src/backend/commands/subscriptioncmds.c | 9 ++-------
src/test/regress/expected/subscription.out | 12 ++++--------
src/test/regress/sql/subscription.sql | 11 ++++-------
4 files changed, 11 insertions(+), 23 deletions(-)
diff --git a/doc/src/sgml/ref/alter_subscription.sgml b/doc/src/sgml/ref/alter_subscription.sgml
index b1fd73f776..bc52339eba 100644
--- a/doc/src/sgml/ref/alter_subscription.sgml
+++ b/doc/src/sgml/ref/alter_subscription.sgml
@@ -46,7 +46,7 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
<para>
You must own the subscription to use <command>ALTER SUBSCRIPTION</command>.
To alter the owner, you must also be a direct or indirect member of the
- new owning role. The new owner has to be a superuser.
+ new owning role.
</para>
<para>
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index 6a5d192128..d75183cd12 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -1476,13 +1476,8 @@ AlterSubscriptionOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_SUBSCRIPTION,
NameStr(form->subname));
- /* New owner must be a superuser */
- if (!superuser_arg(newOwnerId))
- ereport(ERROR,
- (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- errmsg("permission denied to change owner of subscription \"%s\"",
- NameStr(form->subname)),
- errhint("The owner of a subscription must be a superuser.")));
+ /* Must be able to assign ownership to the target role */
+ check_is_member_of_role(GetUserId(), newOwnerId);
form->subowner = newOwnerId;
CatalogTupleUpdate(rel, &tup->t_self, tup);
diff --git a/src/test/regress/expected/subscription.out b/src/test/regress/expected/subscription.out
index a05e6f1795..9b4dac9c0e 100644
--- a/src/test/regress/expected/subscription.out
+++ b/src/test/regress/expected/subscription.out
@@ -137,16 +137,12 @@ HINT: Available values: local, remote_write, remote_apply, on, off.
-- rename back to keep the rest simple
ALTER SUBSCRIPTION regress_testsub_foo RENAME TO regress_testsub;
--- fail - new owner must be superuser
+-- superuser can assign the ownership to a non-superuser
ALTER SUBSCRIPTION regress_testsub OWNER TO regress_subscription_user2;
-ERROR: permission denied to change owner of subscription "regress_testsub"
-HINT: The owner of a subscription must be a superuser.
-ALTER ROLE regress_subscription_user2 SUPERUSER;
--- now it works
-ALTER SUBSCRIPTION regress_testsub OWNER TO regress_subscription_user2;
--- revoke superuser from new owner
-ALTER ROLE regress_subscription_user2 NOSUPERUSER;
SET SESSION AUTHORIZATION regress_subscription_user2;
+-- fail - not a member of the target role
+ALTER SUBSCRIPTION regress_testsub OWNER TO regress_subscription_user;
+ERROR: must be member of role "regress_subscription_user"
-- fail - non-superuser owner cannot change connection parameter
ALTER SUBSCRIPTION regress_testsub CONNECTION 'dbname=somethingelse';
ERROR: must be superuser to alter the connection for a subscription
diff --git a/src/test/regress/sql/subscription.sql b/src/test/regress/sql/subscription.sql
index 8f66709441..6c68d547d1 100644
--- a/src/test/regress/sql/subscription.sql
+++ b/src/test/regress/sql/subscription.sql
@@ -99,17 +99,14 @@ ALTER SUBSCRIPTION regress_testsub_foo SET (synchronous_commit = foobar);
-- rename back to keep the rest simple
ALTER SUBSCRIPTION regress_testsub_foo RENAME TO regress_testsub;
--- fail - new owner must be superuser
-ALTER SUBSCRIPTION regress_testsub OWNER TO regress_subscription_user2;
-ALTER ROLE regress_subscription_user2 SUPERUSER;
--- now it works
+-- superuser can assign the ownership to a non-superuser
ALTER SUBSCRIPTION regress_testsub OWNER TO regress_subscription_user2;
--- revoke superuser from new owner
-ALTER ROLE regress_subscription_user2 NOSUPERUSER;
-
SET SESSION AUTHORIZATION regress_subscription_user2;
+-- fail - not a member of the target role
+ALTER SUBSCRIPTION regress_testsub OWNER TO regress_subscription_user;
+
-- fail - non-superuser owner cannot change connection parameter
ALTER SUBSCRIPTION regress_testsub CONNECTION 'dbname=somethingelse';
--
2.21.1 (Apple Git-122.3)
[application/octet-stream] v2-0003-Respect-permissions-within-logical-replication.patch (15.5K, ../../[email protected]/4-v2-0003-Respect-permissions-within-logical-replication.patch)
download | inline diff:
From cc8e820799d4423f329346e43b82e3bf0216842c Mon Sep 17 00:00:00 2001
From: Mark Dilger <[email protected]>
Date: Tue, 2 Nov 2021 15:08:54 -0700
Subject: [PATCH v2 3/3] Respect permissions within logical replication
Prevent logical replication workers from performing insert, update,
delete, truncate, or copy commands on tables unless the subscription
owner has permission to do so. This makes it much safer to allow
non-superusers to create subscriptions, since they can only cause
changes to replicate into schemas and tables that they would be able
to directly make themselves. This also reduces the amount of trust
that a subscriber must have in a publisher; if the subscription is
set up by a DBA using an account that is intentionally restricted to
only those tables or schemas that the DBA expects the publication to
touch, then the DBA can be create and refresh the subscription
without fear that a malicious publisher will have added other
critical tables to the publication and thereby overwrite them on the
subscriber side. In many setups this is likely a non-issue, as the
same DBA manages both the publisher and the subscriber, but it seems
wiser not to hard-code that assumption into the security model of
logical replication.
---
doc/src/sgml/logical-replication.sgml | 35 ++++--
doc/src/sgml/ref/alter_subscription.sgml | 7 +-
src/backend/commands/subscriptioncmds.c | 2 +
src/backend/replication/logical/tablesync.c | 13 +++
src/backend/replication/logical/worker.c | 30 +++++
src/test/subscription/t/026_nosuperuser.pl | 118 ++++++++++++++++++++
6 files changed, 194 insertions(+), 11 deletions(-)
create mode 100644 src/test/subscription/t/026_nosuperuser.pl
diff --git a/doc/src/sgml/logical-replication.sgml b/doc/src/sgml/logical-replication.sgml
index 45b2e1e28f..5968958f03 100644
--- a/doc/src/sgml/logical-replication.sgml
+++ b/doc/src/sgml/logical-replication.sgml
@@ -330,6 +330,15 @@
will simply be skipped.
</para>
+ <para>
+ Logical replication operations are performed with the privileges of the role
+ which owns the subscription. Only superusers may create subscriptions, but
+ if the ownership of the subscription is transferred, or if the owner
+ subsequently has superuser privileges revoked, permissions failures can
+ cause conflicts. (Note that <productname>PostgreSQL</productname> prior to
+ version 15.0 did no permissions checking when applying changes.)
+ </para>
+
<para>
A conflict will produce an error and will stop the replication; it must be
resolved manually by the user. Details about the conflict can be found in
@@ -337,7 +346,7 @@
</para>
<para>
- The resolution can be done either by changing data on the subscriber so
+ The resolution can be done either by changing data or permissions on the subscriber so
that it does not conflict with the incoming change or by skipping the
transaction that conflicts with the existing data. The transaction can be
skipped by calling the <link linkend="pg-replication-origin-advance">
@@ -530,9 +539,9 @@
<para>
A user able to modify the schema of subscriber-side tables can execute
- arbitrary code as a superuser. Limit ownership
- and <literal>TRIGGER</literal> privilege on such tables to roles that
- superusers trust. Moreover, if untrusted users can create tables, use only
+ arbitrary code as the role which owns any subscription which modifies those tables. Limit ownership
+ and <literal>TRIGGER</literal> privilege on such tables to trusted roles.
+ Moreover, if untrusted users can create tables, use only
publications that list tables explicitly. That is to say, create a
subscription <literal>FOR ALL TABLES</literal> or
<literal>FOR ALL TABLES IN SCHEMA</literal> only when superusers trust
@@ -571,18 +580,26 @@
</para>
<para>
- To create a subscription, the user must be a superuser.
+ To create a subscription, the user must be a superuser. The ownership can
+ subsequently be transferred or the role have superuser privilege removed.
</para>
<para>
The subscription apply process will run in the local database with the
- privileges of a superuser.
+ privileges of the subscription owner.
+ </para>
+
+ <para>
+ On the publisher, privileges are only checked once at the start of a
+ replication connection and are not re-checked as each change record is read.
</para>
<para>
- Privileges are only checked once at the start of a replication connection.
- They are not re-checked as each change record is read from the publisher,
- nor are they re-checked for each change when applied.
+ On the subscriber, the subscription owner's privileges are re-checked for
+ each change record when applied. If a worker is in the process of applying a
+ change record when the ownership of the subscription is changed by a
+ concurrent transaction, the application of the change record may finish
+ under the old permissions.
</para>
</sect1>
diff --git a/doc/src/sgml/ref/alter_subscription.sgml b/doc/src/sgml/ref/alter_subscription.sgml
index bc52339eba..41bf16e740 100644
--- a/doc/src/sgml/ref/alter_subscription.sgml
+++ b/doc/src/sgml/ref/alter_subscription.sgml
@@ -45,8 +45,11 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
<para>
You must own the subscription to use <command>ALTER SUBSCRIPTION</command>.
- To alter the owner, you must also be a direct or indirect member of the
- new owning role.
+ To alter the owner, you must also be a direct or indirect member of the new
+ owning role. Replicated changes will be applied to the target relations as
+ the subscription owner. If the subscription owner lacks sufficient
+ privileges on the target relations, the replication workers will fail to
+ apply the changes.
</para>
<para>
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index d75183cd12..0b17a582dd 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -1489,6 +1489,8 @@ AlterSubscriptionOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
InvokeObjectPostAlterHook(SubscriptionRelationId,
form->oid, 0);
+
+ ApplyLauncherWakeupAtCommit();
}
/*
diff --git a/src/backend/replication/logical/tablesync.c b/src/backend/replication/logical/tablesync.c
index f07983a43c..2400ef8c45 100644
--- a/src/backend/replication/logical/tablesync.c
+++ b/src/backend/replication/logical/tablesync.c
@@ -111,6 +111,7 @@
#include "replication/origin.h"
#include "storage/ipc.h"
#include "storage/lmgr.h"
+#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
@@ -924,6 +925,7 @@ LogicalRepSyncTableStart(XLogRecPtr *origin_startpos)
char relstate;
XLogRecPtr relstate_lsn;
Relation rel;
+ AclResult aclresult;
WalRcvExecResult *res;
char originname[NAMEDATALEN];
RepOriginId originid;
@@ -1042,6 +1044,17 @@ LogicalRepSyncTableStart(XLogRecPtr *origin_startpos)
*/
rel = table_open(MyLogicalRepWorker->relid, RowExclusiveLock);
+ /*
+ * Check that our table sync worker has permission to insert into the
+ * target table.
+ */
+ aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(),
+ ACL_INSERT);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult,
+ get_relkind_objtype(rel->rd_rel->relkind),
+ RelationGetRelationName(rel));
+
/*
* Start a transaction in the remote node in REPEATABLE READ mode. This
* ensures that both the replication slot we create (see below) and the
diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c
index 8d96c926b4..6ae0b3fb21 100644
--- a/src/backend/replication/logical/worker.c
+++ b/src/backend/replication/logical/worker.c
@@ -179,6 +179,7 @@
#include "storage/proc.h"
#include "storage/procarray.h"
#include "tcop/tcopprot.h"
+#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/catcache.h"
#include "utils/dynahash.h"
@@ -1537,6 +1538,7 @@ apply_handle_insert(StringInfo s)
LogicalRepRelMapEntry *rel;
LogicalRepTupleData newtup;
LogicalRepRelId relid;
+ AclResult aclresult;
ApplyExecutionData *edata;
EState *estate;
TupleTableSlot *remoteslot;
@@ -1559,6 +1561,12 @@ apply_handle_insert(StringInfo s)
end_replication_step();
return;
}
+ aclresult = pg_class_aclcheck(RelationGetRelid(rel->localrel), GetUserId(),
+ ACL_INSERT);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult,
+ get_relkind_objtype(rel->localrel->rd_rel->relkind),
+ get_rel_name(rel->localreloid));
/* Set relation for error callback */
apply_error_callback_arg.rel = rel;
@@ -1659,6 +1667,7 @@ apply_handle_update(StringInfo s)
{
LogicalRepRelMapEntry *rel;
LogicalRepRelId relid;
+ AclResult aclresult;
ApplyExecutionData *edata;
EState *estate;
LogicalRepTupleData oldtup;
@@ -1686,6 +1695,12 @@ apply_handle_update(StringInfo s)
end_replication_step();
return;
}
+ aclresult = pg_class_aclcheck(RelationGetRelid(rel->localrel), GetUserId(),
+ ACL_UPDATE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult,
+ get_relkind_objtype(rel->localrel->rd_rel->relkind),
+ get_rel_name(rel->localreloid));
/* Set relation for error callback */
apply_error_callback_arg.rel = rel;
@@ -1826,6 +1841,7 @@ apply_handle_delete(StringInfo s)
LogicalRepRelMapEntry *rel;
LogicalRepTupleData oldtup;
LogicalRepRelId relid;
+ AclResult aclresult;
ApplyExecutionData *edata;
EState *estate;
TupleTableSlot *remoteslot;
@@ -1848,6 +1864,12 @@ apply_handle_delete(StringInfo s)
end_replication_step();
return;
}
+ aclresult = pg_class_aclcheck(RelationGetRelid(rel->localrel), GetUserId(),
+ ACL_DELETE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult,
+ get_relkind_objtype(rel->localrel->rd_rel->relkind),
+ get_rel_name(rel->localreloid));
/* Set relation for error callback */
apply_error_callback_arg.rel = rel;
@@ -2220,6 +2242,7 @@ apply_handle_truncate(StringInfo s)
{
LogicalRepRelId relid = lfirst_oid(lc);
LogicalRepRelMapEntry *rel;
+ AclResult aclresult;
rel = logicalrep_rel_open(relid, lockmode);
if (!should_apply_changes_for_rel(rel))
@@ -2231,6 +2254,12 @@ apply_handle_truncate(StringInfo s)
logicalrep_rel_close(rel, lockmode);
continue;
}
+ aclresult = pg_class_aclcheck(RelationGetRelid(rel->localrel),
+ GetUserId(), ACL_TRUNCATE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult,
+ get_relkind_objtype(rel->localrel->rd_rel->relkind),
+ get_rel_name(rel->localreloid));
remote_rels = lappend(remote_rels, rel);
rels = lappend(rels, rel->localrel);
@@ -2912,6 +2941,7 @@ maybe_reread_subscription(void)
strcmp(newsub->slotname, MySubscription->slotname) != 0 ||
newsub->binary != MySubscription->binary ||
newsub->stream != MySubscription->stream ||
+ newsub->owner != MySubscription->owner ||
!equal(newsub->publications, MySubscription->publications))
{
ereport(LOG,
diff --git a/src/test/subscription/t/026_nosuperuser.pl b/src/test/subscription/t/026_nosuperuser.pl
new file mode 100644
index 0000000000..03a5ac8c52
--- /dev/null
+++ b/src/test/subscription/t/026_nosuperuser.pl
@@ -0,0 +1,118 @@
+
+# Copyright (c) 2021, PostgreSQL Global Development Group
+
+# Test subscriptions owned by non-superusers
+use strict;
+use warnings;
+use PostgreSQL::Test::Cluster;
+use PostgreSQL::Test::Utils;
+use Test::More tests => 3;
+
+# Setup
+
+my $node_publisher = PostgreSQL::Test::Cluster->new('publisher');
+$node_publisher->init(allows_streaming => 'logical');
+$node_publisher->start;
+
+my $node_subscriber = PostgreSQL::Test::Cluster->new('subscriber');
+$node_subscriber->init(allows_streaming => 'logical');
+$node_subscriber->start;
+
+my $publisher_connstr = $node_publisher->connstr . ' dbname=postgres';
+
+# Create the same schema, roles and permissions on both nodes.
+my $sql = qq(
+CREATE ROLE regress_role_alice NOSUPERUSER NOLOGIN;
+GRANT CREATE ON DATABASE postgres TO regress_role_alice;
+SET ROLE regress_role_alice;
+CREATE SCHEMA alice;
+CREATE TABLE alice.tbl1 (i1 INTEGER);
+ALTER TABLE alice.tbl1 REPLICA IDENTITY FULL;
+RESET ROLE;
+
+CREATE ROLE regress_role_bob NOSUPERUSER NOLOGIN;
+GRANT CREATE ON DATABASE postgres TO regress_role_bob;
+SET ROLE regress_role_bob;
+CREATE SCHEMA bob;
+CREATE TABLE bob.tbl1 (i1 INTEGER);
+CREATE TABLE bob.tbl2 (i2 INTEGER);
+ALTER TABLE bob.tbl1 REPLICA IDENTITY FULL;
+ALTER TABLE bob.tbl2 REPLICA IDENTITY FULL;
+RESET ROLE;
+);
+$node_publisher->safe_psql('postgres', $sql);
+$node_subscriber->safe_psql('postgres', $sql);
+
+# Bob publishes.
+$node_publisher->safe_psql('postgres', qq(
+SET ROLE regress_role_bob;
+CREATE PUBLICATION bob_pub FOR TABLE bob.tbl1;
+INSERT INTO bob.tbl1 VALUES (1);
+));
+
+# Bob gets DBA to create a subscribe for him.
+$node_subscriber->safe_psql('postgres', qq(
+CREATE SUBSCRIPTION bob_sub CONNECTION '$publisher_connstr' PUBLICATION bob_pub;
+ALTER SUBSCRIPTION bob_sub OWNER TO regress_role_bob;
+));
+
+# Wait for initial sync of all subscriptions.
+my $synced_query =
+ "SELECT count(1) = 0 FROM pg_subscription_rel WHERE srsubstate NOT IN ('r', 's');";
+$node_subscriber->poll_query_until('postgres', $synced_query)
+ or die "Timed out while waiting for subscriber to synchronize data";
+
+# Check that the data came through.
+my $result = $node_subscriber->safe_psql('postgres', qq(
+SET ROLE regress_role_bob;
+SELECT i1 FROM bob.tbl1;
+));
+is( $result, '1', 'data from schema bob was replicated');
+
+# A malicious dba on publisher adds alice's tables to publication "bob_pub".
+$node_publisher->safe_psql('postgres', qq(
+ALTER PUBLICATION bob_pub ADD TABLE alice.tbl1;
+INSERT INTO alice.tbl1 VALUES (1);
+));
+
+# Bob adds another table on publisher side to the publication and performs
+# DML on the new table.
+$node_publisher->safe_psql('postgres', qq(
+SET ROLE regress_role_bob;
+ALTER PUBLICATION bob_pub ADD TABLE bob.tbl2;
+INSERT INTO bob.tbl2 VALUES (2);
+));
+
+# Bob refreshes on subscriber side to get the new data from "bob.tbl2", not
+# knowing that alice's tables have been added. An error during tablesync or
+# apply should prevent the data in schema "alice" being replicated.
+#
+$node_subscriber->psql('postgres', qq(
+SET ROLE regress_role_bob;
+ALTER SUBSCRIPTION bob_sub REFRESH PUBLICATION;
+));
+
+# Wait for sync of all subscriptions.
+$node_subscriber->poll_query_until('postgres', $synced_query)
+ or die "Timed out while waiting for subscriber to synchronize data";
+
+# The data for schema "bob" might not be replicated, because the replication
+# may abort first on a permissions error for schema "alice". We insist that
+# data for "alice" not be replicated, but we only insist that if data from
+# "bob" gets replicated that it be the correct new data and not corrupted.
+$result = $node_subscriber->safe_psql('postgres', qq(
+SELECT a.i1::text || '_' ||
+ coalesce(b.i2::text,'null') || '_' ||
+ coalesce(c.i1::text,'null')
+ FROM bob.tbl1 a
+ LEFT JOIN bob.tbl2 b ON TRUE
+ LEFT JOIN alice.tbl1 c ON TRUE;
+));
+like ($result, qr/^(?:1_null_null|1_2_null)$/,
+ 'subscriber side schema bob data is reasonable and alice data is unreplicated');
+
+# check that the logs on the subscriber side contain the expected permissions
+# error associated with a failed attempt to replicate into schema "alice".
+my $subscriber_log = slurp_file($node_subscriber->logfile);
+like ($subscriber_log, qr/ERROR: permission denied for schema alice/msi,
+ 'subscriber lacks permission for schema alice');
--
2.21.1 (Apple Git-122.3)
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
@ 2021-11-16 20:06 ` Andrew Dunstan <[email protected]>
2021-11-16 20:08 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 20:26 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2 siblings, 2 replies; 68+ messages in thread
From: Andrew Dunstan @ 2021-11-16 20:06 UTC (permalink / raw)
To: Mark Dilger <[email protected]>; +Cc: pgsql-hackers; Robert Haas <[email protected]>
On 11/3/21 15:50, Mark Dilger wrote:
>> On Nov 1, 2021, at 10:58 AM, Mark Dilger <[email protected]> wrote:
>>
>> ALTER SUBSCRIPTION..[ENABLE | DISABLE] do not synchronously start or stop subscription workers. The ALTER command updates the catalog's subenabled field, but workers only lazily respond to that. Disabling and enabling the subscription as part of the OWNER TO would not reliably accomplish anything.
> I have rethought my prior analysis. The problem in the previous patch was that the subscription apply workers did not check for a change in ownership the way they checked for other changes, instead only picking up the new ownership information when the worker restarted for some other reason. This next patch set fixes that. The application of a change record may continue under the old ownership permissions when a concurrent command changes the ownership of the subscription, but the worker will pick up the new permissions before applying the next record. I think that is consistent enough with reasonable expectations.
>
> The first two patches are virtually unchanged. The third updates the behavior of the apply workers, and updates the documentation to match.
I'm generally happier about this than the previous patch set. With the
exception of some slight documentation modifications I think it's
basically committable. There doesn't seem to be a CF item for it but I'm
inclined to commit it in a couple of days time.
cheers
andrew
--
Andrew Dunstan
EDB: https://www.enterprisedb.com
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-16 20:06 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
@ 2021-11-16 20:08 ` Mark Dilger <[email protected]>
2021-11-16 20:40 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
1 sibling, 1 reply; 68+ messages in thread
From: Mark Dilger @ 2021-11-16 20:08 UTC (permalink / raw)
To: Andrew Dunstan <[email protected]>; +Cc: pgsql-hackers; Robert Haas <[email protected]>
> On Nov 16, 2021, at 12:06 PM, Andrew Dunstan <[email protected]> wrote:
>
> There doesn't seem to be a CF item for it but I'm
> inclined to commit it in a couple of days time.
https://commitfest.postgresql.org/36/3414/
—
Mark Dilger
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-16 20:06 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-16 20:08 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
@ 2021-11-16 20:40 ` Andrew Dunstan <[email protected]>
0 siblings, 0 replies; 68+ messages in thread
From: Andrew Dunstan @ 2021-11-16 20:40 UTC (permalink / raw)
To: Mark Dilger <[email protected]>; +Cc: pgsql-hackers; Robert Haas <[email protected]>
On 11/16/21 15:08, Mark Dilger wrote:
>
>> On Nov 16, 2021, at 12:06 PM, Andrew Dunstan <[email protected]> wrote:
>>
>> There doesn't seem to be a CF item for it but I'm
>> inclined to commit it in a couple of days time.
> https://commitfest.postgresql.org/36/3414/
>
OK, got it, thanks.
cheers
andrew
--
Andrew Dunstan
EDB: https://www.enterprisedb.com
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-16 20:06 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
@ 2021-11-17 20:26 ` Andrew Dunstan <[email protected]>
1 sibling, 0 replies; 68+ messages in thread
From: Andrew Dunstan @ 2021-11-17 20:26 UTC (permalink / raw)
To: Mark Dilger <[email protected]>; +Cc: pgsql-hackers; Robert Haas <[email protected]>
On 11/16/21 15:06, Andrew Dunstan wrote:
> On 11/3/21 15:50, Mark Dilger wrote:
>>> On Nov 1, 2021, at 10:58 AM, Mark Dilger <[email protected]> wrote:
>>>
>>> ALTER SUBSCRIPTION..[ENABLE | DISABLE] do not synchronously start or stop subscription workers. The ALTER command updates the catalog's subenabled field, but workers only lazily respond to that. Disabling and enabling the subscription as part of the OWNER TO would not reliably accomplish anything.
>> I have rethought my prior analysis. The problem in the previous patch was that the subscription apply workers did not check for a change in ownership the way they checked for other changes, instead only picking up the new ownership information when the worker restarted for some other reason. This next patch set fixes that. The application of a change record may continue under the old ownership permissions when a concurrent command changes the ownership of the subscription, but the worker will pick up the new permissions before applying the next record. I think that is consistent enough with reasonable expectations.
>>
>> The first two patches are virtually unchanged. The third updates the behavior of the apply workers, and updates the documentation to match.
>
> I'm generally happier about this than the previous patch set. With the
> exception of some slight documentation modifications I think it's
> basically committable. There doesn't seem to be a CF item for it but I'm
> inclined to commit it in a couple of days time.
>
>
Given there is some debate about the patch set I will hold off any
action for the time being.
cheers
andrew
--
Andrew Dunstan
EDB: https://www.enterprisedb.com
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
@ 2021-11-17 04:11 ` Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2 siblings, 1 reply; 68+ messages in thread
From: Jeff Davis @ 2021-11-17 04:11 UTC (permalink / raw)
To: Mark Dilger <[email protected]>; Andrew Dunstan <[email protected]>; +Cc: pgsql-hackers; Robert Haas <[email protected]>
On Wed, 2021-11-03 at 12:50 -0700, Mark Dilger wrote:
> The first two patches are virtually unchanged. The third updates the
> behavior of the apply workers, and updates the documentation to
> match.
v2-0001 corrects some surprises, but may create others. Why is renaming
allowed, but not changing the options? What if we add new options, and
some of them seem benign for a non-superuser to change?
The commit message part of the patch says that it's to prevent non-
superusers from being able to (effectively) create subscriptions, but
don't we want privileged non-superusers to be able to create
subscriptions?
Regards,
Jeff Davis
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
@ 2021-11-17 15:44 ` Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
0 siblings, 1 reply; 68+ messages in thread
From: Mark Dilger @ 2021-11-17 15:44 UTC (permalink / raw)
To: Jeff Davis <[email protected]>; +Cc: Andrew Dunstan <[email protected]>; pgsql-hackers; Robert Haas <[email protected]>
> On Nov 16, 2021, at 8:11 PM, Jeff Davis <[email protected]> wrote:
>
> On Wed, 2021-11-03 at 12:50 -0700, Mark Dilger wrote:
>> The first two patches are virtually unchanged. The third updates the
>> behavior of the apply workers, and updates the documentation to
>> match.
>
> v2-0001 corrects some surprises, but may create others. Why is renaming
> allowed, but not changing the options? What if we add new options, and
> some of them seem benign for a non-superuser to change?
The patch cannot anticipate which logical replication options may be added to the project in some later commit. We can let that commit adjust the behavior to allow the option if we agree it is sensible for non-superusers to do so.
> The commit message part of the patch says that it's to prevent non-
> superusers from being able to (effectively) create subscriptions, but
> don't we want privileged non-superusers to be able to create
> subscriptions?
Perhaps, but I don't think merely owning a subscription should entitle a role to create new subscriptions. Administrators may quite intentionally create low-power users, ones without access to anything but a single table, or a single schema, as a means of restricting the damage that a subscription might do (or more precisely, what the publisher might do via the subscription.) It would be surprising if that low-power user was then able to recreate the subscription into something different.
We should probably come back to this topic in a different patch, perhaps a patch that introduces a new pg_manage_subscriptions role or such.
—
Mark Dilger
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
@ 2021-11-17 17:33 ` Jeff Davis <[email protected]>
2021-11-17 18:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 18:48 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
0 siblings, 2 replies; 68+ messages in thread
From: Jeff Davis @ 2021-11-17 17:33 UTC (permalink / raw)
To: Mark Dilger <[email protected]>; +Cc: Andrew Dunstan <[email protected]>; pgsql-hackers; Robert Haas <[email protected]>
On Wed, 2021-11-17 at 07:44 -0800, Mark Dilger wrote:
> Administrators may quite
> intentionally create low-power users, ones without access to anything
> but a single table, or a single schema, as a means of restricting the
> damage that a subscription might do (or more precisely, what the
> publisher might do via the subscription.) It would be surprising if
> that low-power user was then able to recreate the subscription into
> something different.
I am still trying to understand this use case. It doesn't feel like
"ownership" to me, it feels more like some kind of delegation.
Is GRANT a better fit here? That would allow more than one user to
REFRESH, or ENABLE/DISABLE the same subscription. It wouldn't allow
RENAME, but I don't see why we'd separate privileges for
CREATE/DROP/RENAME anyway.
This would not address the weirdness of the existing code where a
superuser loses their superuser privileges but still owns a
subscription. But perhaps we can solve that a different way, like just
performing a check when someone loses their superuser privileges that
they don't own any subscriptions.
Regards,
Jeff Davis
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
@ 2021-11-17 18:25 ` Mark Dilger <[email protected]>
2021-11-17 21:06 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-18 10:50 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
1 sibling, 2 replies; 68+ messages in thread
From: Mark Dilger @ 2021-11-17 18:25 UTC (permalink / raw)
To: Jeff Davis <[email protected]>; +Cc: Andrew Dunstan <[email protected]>; pgsql-hackers; Robert Haas <[email protected]>
> On Nov 17, 2021, at 9:33 AM, Jeff Davis <[email protected]> wrote:
>
> I am still trying to understand this use case. It doesn't feel like
> "ownership" to me, it feels more like some kind of delegation.
>
> Is GRANT a better fit here? That would allow more than one user to
> REFRESH, or ENABLE/DISABLE the same subscription. It wouldn't allow
> RENAME, but I don't see why we'd separate privileges for
> CREATE/DROP/RENAME anyway.
We may eventually allow non-superusers to create subscriptions, but there are lots of details to work out. Should there be limits on how many subscriptions they can create? Should there be limits to the number of simultaneously open connections they can create out to other database servers (publishers)? Should they need to be granted USAGE on a database publisher in order to use the connection string for that publisher in a subscription they create? Should they need to be granted USAGE on a publication in order to replicate it? Yes, there may be restrictions on the publisher side, too, but the user model on subscriber and publisher might differ, and the connection string used might not match the subscription owner, so some restriction on the subscriber side may be needed.
The implementation of [CREATE | ALTER] SUBSCRIPTION was designed at a time when only superusers could execute them, and as far as I can infer from the design, no effort to constrain the effects of those commands was made. Since we're trying to make subscriptions into things that non-superusers can use, we have to deal with some things in those functions. For example, ALTER SUBSCRIPTION can change the database connection parameter, or the publication subscribed, or whether synchronous_commit is used. I don't see that a subscription owner should necessarily be allowed to mess with that, at least not without some other privilege checks beyond mere ownership.
I think this is pretty analogous to how security definer functions work. You might call those "delegation" also, but the basic idea is that the function will run under the privileges of the function's owner, who might be quite privileged if you want the function to do highly secure things for you, but who could also intentionally be limited in privilege. It wouldn't make much sense to say the owner of a security definer function can arbitrarily escalate their privileges to do things like open connections to other database servers, or have the transactions in which they run have a different setting of synchronous_commit. Yet with subscriptions, if the subscription owner can run all forms of ALTER SUBSCRIPTION, that's what they can do.
I took a conservative position in the design of the patch to avoid giving away too much. I suspect that we'll come back to these design decisions and relax them at some point, but the exact way in which we relax them is not obvious. We could just agree to remove them (as you seem to propose), or we might agree to create predefined roles and say that the subscription owner can change certain aspects of the subscription if and only if they are members of one or more of those roles, or we may create new grantable privileges. Each of those debates may be long and hard fought, so I don't want to invite that as part of this thread, or this patch will almost surely miss the cutoff for v15.
> This would not address the weirdness of the existing code where a
> superuser loses their superuser privileges but still owns a
> subscription. But perhaps we can solve that a different way, like just
> performing a check when someone loses their superuser privileges that
> they don't own any subscriptions.
I gave that a slight amount of thought during the design of this patch, but didn't think we could refuse to revoke superuser on such a basis, and didn't see what we should do with the subscription other than have it continue to be owned by the recently-non-superuser. If you have a better idea, we can discuss it, but to some degree I think that is also orthogonal to the purpose of this patch. The only sense in which this patch depends on that issue is that this patch proposes that non-superuser subscription owners are already an issue, and therefore that this patch isn't creating a new issue, but rather making more sane something that already can happen.
—
Mark Dilger
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 18:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
@ 2021-11-17 21:06 ` Jeff Davis <[email protected]>
2021-11-18 00:17 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
1 sibling, 1 reply; 68+ messages in thread
From: Jeff Davis @ 2021-11-17 21:06 UTC (permalink / raw)
To: Mark Dilger <[email protected]>; +Cc: Andrew Dunstan <[email protected]>; pgsql-hackers; Robert Haas <[email protected]>
On Wed, 2021-11-17 at 10:25 -0800, Mark Dilger wrote:
> We may eventually allow non-superusers to create subscriptions, but
> there are lots of details to work out.
I am setting aside the idea of subscriptions created by non-superusers.
My comments were about your idea for "low-power users" that can still
do things with subscriptions. And for that, GRANT seems like a better
fit than ownership.
With v2-0001, there are several things that seem weird to me:
* Why can there be only one low-power user per subscription?
* Why is RENAME a separate capability from CREATE/DROP?
* What if you want to make the privileges more fine-grained, or make
changes in the future? Ownership is a single bit, so it requires that
everyone agree. Maybe some people want RENAME to be a part of that, and
others don't.
GRANT seems to provide better answers here.
> Since we're trying to make subscriptions into things that non-
> superusers can use, we have to deal with some things in those
> functions.
I understand the use case where a superuser isn't required anywhere in
the process, and some special users can create and own subscriptions. I
also understand that's not what these patches are trying to accomplish
(though v2-0003 seems like a good step in that direction).
I don't understand the use case as well where a non-superuser can
merely "use" a subscription. I'm sure such use cases exist and I'm fine
to go along with that idea, but I'd like to understand why ownership
(partial ownership?) is the right way to do this and GRANT is the wrong
way.
> For example, ALTER SUBSCRIPTION can change the database connection
> parameter, or the publication subscribed, or whether
> synchronous_commit is used. I don't see that a subscription owner
> should necessarily be allowed to mess with that, at least not without
> some other privilege checks beyond mere ownership.
That violates my expectations of what "ownership" means.
> I think this is pretty analogous to how security definer functions
> work.
The analogy to SECURITY DEFINER functions seems to support my
suggestion for GRANT at least as much as your modified definition of
ownership.
> > This would not address the weirdness of the existing code where a
> > superuser loses their superuser privileges but still owns a
> > subscription. But perhaps we can solve that a different way, like
> > just
> > performing a check when someone loses their superuser privileges
> > that
> > they don't own any subscriptions.
>
> I gave that a slight amount of thought during the design of this
> patch, but didn't think we could refuse to revoke superuser on such a
> basis,
I don't necessarily see a problem there, but I could be missing
something.
> and didn't see what we should do with the subscription other than
> have it continue to be owned by the recently-non-superuser. If you
> have a better idea, we can discuss it, but to some degree I think
> that is also orthogonal to the purpose of this patch. The only sense
> in which this patch depends on that issue is that this patch proposes
> that non-superuser subscription owners are already an issue, and
> therefore that this patch isn't creating a new issue, but rather
> making more sane something that already can happen.
By introducing and documenting a way to get non-superusers to own a
subscription, it makes it more likely that people will do it, and
harder for us to change. That means the standard should be "this is
what we really want", rather than just "more sane than before".
Regards,
Jeff Davis
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 18:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 21:06 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
@ 2021-11-18 00:17 ` Mark Dilger <[email protected]>
2021-11-18 18:29 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-18 18:50 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
0 siblings, 2 replies; 68+ messages in thread
From: Mark Dilger @ 2021-11-18 00:17 UTC (permalink / raw)
To: Jeff Davis <[email protected]>; +Cc: Andrew Dunstan <[email protected]>; pgsql-hackers; Robert Haas <[email protected]>
> On Nov 17, 2021, at 1:06 PM, Jeff Davis <[email protected]> wrote:
>
> On Wed, 2021-11-17 at 10:25 -0800, Mark Dilger wrote:
>> We may eventually allow non-superusers to create subscriptions, but
>> there are lots of details to work out.
>
> I am setting aside the idea of subscriptions created by non-superusers.
Ok, fair enough. I think eventually we'll want that, but I'm also setting that aside for this patch.
> My comments were about your idea for "low-power users" that can still
> do things with subscriptions. And for that, GRANT seems like a better
> fit than ownership.
This patch has basically no value beyond the fact that it allows the replication to be *applied* as a user other than superuser. Throw that out, and there isn't any point. Everything else is window dressing. The real security problem with subscriptions is that they act with superuser power. That naturally means that they must be owned and operated by superuser, too, otherwise they serve as a privilege escalation attack vector. It really doesn't make any sense to think of subscriptions as operating under the permissions of multiple non-superusers. You must choose a single role you want the subscription to run under. What purpose would be served by GRANTing privileges on a subscription to more than one non-superuser? It still operates as just the one user. I agree you *could* give multiple users privileges to mess with it, but you'd still need to assign a single role as the one whose privileges matter for the purpose of applying replication changes. I'm using "owner" for that purpose, and I think that is consistent with how security definer functions work. They run as the owner, too. It's perfectly well-precedented to use "owner" for this.
I think the longer term plan is that non-superusers who have some privileged role will be allowed to create subscriptions, and naturally they will own the subscriptions that they create, at least until an ALTER SUBSCRIPTION..OWNER TO is successfully executed to transfer ownership. Once that longer term plan is complete, non-superusers will be able to create publications of their tables on one database, and subscriptions to those publications on another database, all without needing the help of a superuser. This patch doesn't get us all the way there, but it heads directly toward that goal.
> With v2-0001, there are several things that seem weird to me:
>
> * Why can there be only one low-power user per subscription?
Because the apply workers run as only one user. Currently it is always superuser. After this patch, it is always the owner, which amounts to the same thing for legacy subscriptions created and owned by superuser prior to upgrading to v15, but not necessarily for new ones or ones that have ownership transferred after upgrade.
We could think about subscriptions that act under multiple roles, perhaps taking role information as part of the data-stream from the publisher, but that's a pretty complicated proposal, and it is far from clear that we want it anyway. There is a security case to be made for *not* allowing the publisher to call all the shots, so such a proposal would at best be an alternate mode of operation, not the one and only mode.
> * Why is RENAME a separate capability from CREATE/DROP?
I don't care enough to argue this point. If you want me to remove RENAME privilege from the owner, I can resubmit with it removed. It just doesn't seem like it's dangerous to allow a non-superuser to rename their subscriptions, so I saw no compelling reason to disallow it.
CREATE clearly must be disallowed since it gives the creator the ability to form network connections, set fsync modes, etc., and there is no reason to assume arbitrary non-superusers should be able to do that.
The argument against DROP is a bit weaker. It doesn't seem like a user who cannot bring subscriptions into existence should be able to drop them either. I was expecting to visit that issue in a follow-on patch which deals with non-superuser predefined roles that have some power to create and drop subscriptions. What that patch will propose to do is not obvious, since some of what you can do with subscriptions is so powerful we may not want non-superusers doing it, even with a privileged role. If you can't picture what I mean, consider that you might use a connection parameter that connects outside and embeds data into the connection string, with a server listening on the other end, not really to publish data, but to harvest the secret data that you are embedding in the network connection attempt.
> * What if you want to make the privileges more fine-grained, or make
> changes in the future? Ownership is a single bit, so it requires that
> everyone agree.
We can modify the patch to have the subscription owner have zero privileges on the subscription, not even the ability to see how it is defined, and just have "owner" mean the role under whose privileges the logical replication workers apply changes. Would that be better? I would expect people to find that odd.
The problem is that we want a setuid/setgid type behavior. Actual setuid/setgid programs act as the user/group of the executable. There's no reason that user/group needs to be one that any real human uses to log into the system. Likewise, we need the subscription to act under a role, and we're establishing which role that is by having that role own the subscription. That is like how setuid/setgid programs work by executing as the user/group that owns the executable, except that postgres doesn't have separate user/group concepts, just roles. Isn't this design pattern completely commonplace?
> Maybe some people want RENAME to be a part of that, and
> others don't.
Fair enough. Should I remove RENAME from what the patch allows the owner to do? On this particular point, I genuinely don't care. I think it can be reasonably argued either way.
> GRANT seems to provide better answers here.
No, because we don't have infinite privilege bits to burn.
>> Since we're trying to make subscriptions into things that non-
>> superusers can use, we have to deal with some things in those
>> functions.
>
> I understand the use case where a superuser isn't required anywhere in
> the process, and some special users can create and own subscriptions. I
> also understand that's not what these patches are trying to accomplish
> (though v2-0003 seems like a good step in that direction).
There is a cart-before-the-horse problem here. If I propose a patch with a privileged role for creating and owning subscriptions *before* I tighten down how non-superuser-owned subscriptions work, that patch would surely be rejected. So I either propose this first, and only if/when it gets accepted, propose the other, or I propose them together. That's a damned-if-you-do--damned-if-you-dont situation, because if I propose them together, I'll get arguments that they are clearly separable and should be proposed separately, and if I do them one before the other, I'll get the argument that you are making now. I fully expect the privileged role proposal to be made (possibly by me), though it is unclear if there will be time left to do it in v15.
> I don't understand the use case as well where a non-superuser can
> merely "use" a subscription. I'm sure such use cases exist and I'm fine
> to go along with that idea, but I'd like to understand why ownership
> (partial ownership?) is the right way to do this and GRANT is the wrong
> way.
Even if we had the privilege bits to burn, no spelling of that GRANT idea sounds all that great:
GRANT RUN AS ON subscription TO role;
GRANT RUN AS ON role TO subscription;
GRANT SUDO ON subscription TO role;
GRANT SETUID ON role TO subscription;
...
I just don't see how that really works. I'm not inclined to spend time being more clever, since I already know that privilege bits are in short supply, but if you want to propose something, go ahead. Elsewhere you proposed GRANT REFRESH or something, not looking at that email just now, but that's not the same thing as GRANT RUN AS, and burns another privilege bit, and still doesn't get us all the way there, because you presumably also want GRANT RENAME, GRANT ALTER CONNECTION SETTING, GRANT ALTER FSYNC SETTING, ..., and we're out of privilege bits before we're done.
>> For example, ALTER SUBSCRIPTION can change the database connection
>> parameter, or the publication subscribed, or whether
>> synchronous_commit is used. I don't see that a subscription owner
>> should necessarily be allowed to mess with that, at least not without
>> some other privilege checks beyond mere ownership.
>
> That violates my expectations of what "ownership" means.
I think that's because you're thinking of these settings as properties of the subscription. You may *own* the subscription, but the subscription doesn't *own* the right to make connections to arbitrary databases, nor *own* the right to change buffer cache settings, nor *own* the right to bring data from a publication on some other server which, if it existed on the local server, would violate site policy and possibly constitute a civil or criminal violation of data privacy laws. I may own my house, and the land it sits on, and my driveway, but that doesn't mean I own the ability to make my driveway go across my neighbor's field, down through town, and to the waterfront. But that's the kind of ownership definition you seem to be defending.
Some of what I perceive as the screwiness of your argument I must admin is not your fault. The properties of subscriptions are defined in ways that don't make sense to me. It would be far more sensible if connection strings were objects in their own right, and you could grant USAGE on a connection string to a role, and USAGE on a subscription to a role, and only if the subscription worker's role had privileges on the connection string could they use it as part of fulfilling their task of replicating the data, and otherwise they'd error out in the attempt. Likewise, fsync modes could be proper objects, and only if the subscription's role had privileges on the fsync mode they wanted to use would they be able to use it. But we don't have these things as proper objects, with acl lists on them, so we're stuck trying to design around that. To my mind, that means subscription owners *do not own* properties associated with the subscription. To your mind, that's not what "ownership" means. What to do?
>> I think this is pretty analogous to how security definer functions
>> work.
>
> The analogy to SECURITY DEFINER functions seems to support my
> suggestion for GRANT at least as much as your modified definition of
> ownership.
I don't see how. Can you please explain?
>>> This would not address the weirdness of the existing code where a
>>> superuser loses their superuser privileges but still owns a
>>> subscription. But perhaps we can solve that a different way, like
>>> just
>>> performing a check when someone loses their superuser privileges
>>> that
>>> they don't own any subscriptions.
>>
>> I gave that a slight amount of thought during the design of this
>> patch, but didn't think we could refuse to revoke superuser on such a
>> basis,
>
> I don't necessarily see a problem there, but I could be missing
> something.
Close your eyes and imagine that I have superuser on your database... really picture it in your mind. Now, do you want the revoke command you are issuing to work?
>> and didn't see what we should do with the subscription other than
>> have it continue to be owned by the recently-non-superuser. If you
>> have a better idea, we can discuss it, but to some degree I think
>> that is also orthogonal to the purpose of this patch. The only sense
>> in which this patch depends on that issue is that this patch proposes
>> that non-superuser subscription owners are already an issue, and
>> therefore that this patch isn't creating a new issue, but rather
>> making more sane something that already can happen.
>
> By introducing and documenting a way to get non-superusers to own a
> subscription, it makes it more likely that people will do it, and
> harder for us to change. That means the standard should be "this is
> what we really want", rather than just "more sane than before".
Ok, I'll wait to hear back from you on the points above.
—
Mark Dilger
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 18:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 21:06 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-18 00:17 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
@ 2021-11-18 18:29 ` Jeff Davis <[email protected]>
2021-11-19 10:23 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
1 sibling, 1 reply; 68+ messages in thread
From: Jeff Davis @ 2021-11-18 18:29 UTC (permalink / raw)
To: Mark Dilger <[email protected]>; +Cc: Andrew Dunstan <[email protected]>; pgsql-hackers; Robert Haas <[email protected]>
On Wed, 2021-11-17 at 16:17 -0800, Mark Dilger wrote:
> You must choose a single role you want the subscription to run
> under.
I think that was the source of a lot of my confusion:
Your patches are creating the notion of a "run as" user by assigning
ownership-that-isn't-really-ownership. I got distracted wondering why
you would really care if some user could enable/disable/refresh/rename
a subscription, but the main point was to change who the subscription
runs as.
That's a more general idea: I could see how "run as" could apply to
subscriptions as well as functions (right now it can only run as the
owner or the invoker, not an arbitrary role). And I better understand
your analogy to security definer now.
But it's also not exactly a simple idea, and I think the current
patches oversimplify it and conflate it with ownership.
> I think the longer term plan is that non-superusers who have some
> privileged role will be allowed to create subscriptions,
You earlier listed some challenges with that:
https://postgr.es/m/[email protected]
But it seems like it's really the right direction to go. Probably the
biggest concern is connection strings that read server files, but
dblink solved that by requiring password auth.
What are the reasonable steps to get there? Do you think anything is
doable for v15?
> There is a cart-before-the-horse problem here.
I don't think we need to hold up v2-0003. It seems like a step in the
right direction, though I haven't looked closely yet.
Regards,
Jeff Davis
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 18:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 21:06 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-18 00:17 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-18 18:29 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
@ 2021-11-19 10:23 ` Amit Kapila <[email protected]>
2021-11-19 16:12 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
0 siblings, 1 reply; 68+ messages in thread
From: Amit Kapila @ 2021-11-19 10:23 UTC (permalink / raw)
To: Jeff Davis <[email protected]>; +Cc: Mark Dilger <[email protected]>; Andrew Dunstan <[email protected]>; pgsql-hackers; Robert Haas <[email protected]>
On Fri, Nov 19, 2021 at 12:00 AM Jeff Davis <[email protected]> wrote:
>
> On Wed, 2021-11-17 at 16:17 -0800, Mark Dilger wrote:
> > You must choose a single role you want the subscription to run
> > under.
>
> I think that was the source of a lot of my confusion:
>
> Your patches are creating the notion of a "run as" user by assigning
> ownership-that-isn't-really-ownership. I got distracted wondering why
> you would really care if some user could enable/disable/refresh/rename
> a subscription, but the main point was to change who the subscription
> runs as.
>
> That's a more general idea: I could see how "run as" could apply to
> subscriptions as well as functions (right now it can only run as the
> owner or the invoker, not an arbitrary role). And I better understand
> your analogy to security definer now.
>
I was thinking why not separate the ownership and "run as" privileges
for the subscriptions? We can introduce a new syntax in addition to
the current syntax for "Owner" for this as:
Create Subscription sub RUNAS <role_name> ...;
Alter Subscription sub RUNAS <role_name>
Now, RUNAS role will be used to apply changes and perform the initial
table sync. The owner will be tied to changing some of the other
properties (enabling, disabling, etc.) of the subscription. Now, we
still need a superuser to create subscription and change properties
like CONNECTION for a subscription but we can solve that by having
roles specific to it as being indicated by Mark in some of his
previous emails.
--
With Regards,
Amit Kapila.
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 18:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 21:06 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-18 00:17 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-18 18:29 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-19 10:23 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
@ 2021-11-19 16:12 ` Mark Dilger <[email protected]>
0 siblings, 0 replies; 68+ messages in thread
From: Mark Dilger @ 2021-11-19 16:12 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: Jeff Davis <[email protected]>; Andrew Dunstan <[email protected]>; pgsql-hackers; Robert Haas <[email protected]>
> On Nov 19, 2021, at 2:23 AM, Amit Kapila <[email protected]> wrote:
>
> I was thinking why not separate the ownership and "run as" privileges
> for the subscriptions? We can introduce a new syntax in addition to
> the current syntax for "Owner" for this as:
>
> Create Subscription sub RUNAS <role_name> ...;
> Alter Subscription sub RUNAS <role_name>
>
> Now, RUNAS role will be used to apply changes and perform the initial
> table sync. The owner will be tied to changing some of the other
> properties (enabling, disabling, etc.) of the subscription. Now, we
> still need a superuser to create subscription and change properties
> like CONNECTION for a subscription but we can solve that by having
> roles specific to it as being indicated by Mark in some of his
> previous emails.
I feel disquieted about the "runas" idea. I can't really say why yet. Maybe it is ok, but it feels like a larger design decision than just an implementation detail about how subscriptions work. We should consider if we won't soon be doing the same thing for other parts of the system. If so, we should choose a solution that makes sense when applied more broadly.
Security definer functions could benefit from splitting the owner from the runas role.
Event triggers might benefit from having a runas role. Currently, event triggers are always owned by superusers, but we've discussed allowing non-superuser owners. That proposal still has outstanding issues to be resolved, so I can't be sure if runas would be helpful, but it might.
Table triggers might benefit from having a runas role. I don't have a proposal here, just an intuition that we should think about this before designing how "runas" works.
—
Mark Dilger
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 18:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 21:06 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-18 00:17 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
@ 2021-11-18 18:50 ` Jeff Davis <[email protected]>
1 sibling, 0 replies; 68+ messages in thread
From: Jeff Davis @ 2021-11-18 18:50 UTC (permalink / raw)
To: Mark Dilger <[email protected]>; +Cc: Andrew Dunstan <[email protected]>; pgsql-hackers; Robert Haas <[email protected]>
On Wed, 2021-11-17 at 16:17 -0800, Mark Dilger wrote:
> Some of what I perceive as the screwiness of your argument I must
> admin is not your fault. The properties of subscriptions are defined
> in ways that don't make sense to me. It would be far more sensible
> if connection strings were objects in their own right, and you could
> grant USAGE on a connection string to a role,
We sort of have that with CREATE SERVER, in fact dblink can use a
server instead of a string.
Regards,
Jeff Davis
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 18:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
@ 2021-11-18 10:50 ` Amit Kapila <[email protected]>
2021-11-18 15:33 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
1 sibling, 1 reply; 68+ messages in thread
From: Amit Kapila @ 2021-11-18 10:50 UTC (permalink / raw)
To: Mark Dilger <[email protected]>; +Cc: Jeff Davis <[email protected]>; Andrew Dunstan <[email protected]>; pgsql-hackers; Robert Haas <[email protected]>
On Wed, Nov 17, 2021 at 11:56 PM Mark Dilger
<[email protected]> wrote:
>
> > On Nov 17, 2021, at 9:33 AM, Jeff Davis <[email protected]> wrote:
> >
>
> > This would not address the weirdness of the existing code where a
> > superuser loses their superuser privileges but still owns a
> > subscription. But perhaps we can solve that a different way, like just
> > performing a check when someone loses their superuser privileges that
> > they don't own any subscriptions.
>
> I gave that a slight amount of thought during the design of this patch, but didn't think we could refuse to revoke superuser on such a basis, and didn't see what we should do with the subscription other than have it continue to be owned by the recently-non-superuser. If you have a better idea, we can discuss it, but to some degree I think that is also orthogonal to the purpose of this patch. The only sense in which this patch depends on that issue is that this patch proposes that non-superuser subscription owners are already an issue, and therefore that this patch isn't creating a new issue, but rather making more sane something that already can happen.
>
Don't we want to close this gap irrespective of the other part of the
feature? I mean if we take out the part of your 0003 patch that checks
whether the current user has permission to perform a particular
operation on the target table then the gap related to the owner losing
superuser privileges should be addressed.
--
With Regards,
Amit Kapila.
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 18:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-18 10:50 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
@ 2021-11-18 15:33 ` Mark Dilger <[email protected]>
2021-11-19 09:44 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
0 siblings, 1 reply; 68+ messages in thread
From: Mark Dilger @ 2021-11-18 15:33 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: Jeff Davis <[email protected]>; Andrew Dunstan <[email protected]>; pgsql-hackers; Robert Haas <[email protected]>
> On Nov 18, 2021, at 2:50 AM, Amit Kapila <[email protected]> wrote:
>
>> I gave that a slight amount of thought during the design of this patch, but didn't think we could refuse to revoke superuser on such a basis, and didn't see what we should do with the subscription other than have it continue to be owned by the recently-non-superuser. If you have a better idea, we can discuss it, but to some degree I think that is also orthogonal to the purpose of this patch. The only sense in which this patch depends on that issue is that this patch proposes that non-superuser subscription owners are already an issue, and therefore that this patch isn't creating a new issue, but rather making more sane something that already can happen.
>>
>
> Don't we want to close this gap irrespective of the other part of the
> feature? I mean if we take out the part of your 0003 patch that checks
> whether the current user has permission to perform a particular
> operation on the target table then the gap related to the owner losing
> superuser privileges should be addressed.
I don't think there is a gap. The patch does the right thing, causing the subscription whose owner has had superuser revoked to itself no longer function with superuser privileges. Whether that causes the subscription to fail depends on whether the previously-superuser now non-superuser owner now lacks sufficient privileges on the target relation(s). I think removing that part of the patch would be a regression.
Let's compare two scenarios. In the first, we have a regular user "alice" who owns a subscription which replicates into table "accounting.receipts" for which she has been granted privileges by the table's owner. What would you expect to happen after the table's owner revokes privileges from alice? I would expect that the subscription can no longer function, and periodic attempts to replicate into that table result in permission denied errors in the logs.
In the second, we have a superuser "alice" who owns a subscription that replicates into table "accounting.receipts", and she only has sufficient privileges to modify "accounting.receipts" by virtue of being superuser. I would expect that when she has superuser revoked, the subscription can likewise no longer function.
Now, maybe I'm wrong in both cases, and both should continue to function. But I would find it really strange if the first situation behaved differently from the second.
I think intuitions about how subscriptions behave differ depending on the reason you expect the subscription to be owned by a particular user. If the reason the user owns the subscription is that the user just happens to be the user who created it, but isn't in your mind associated with the subscription, then having the subscription continue to function regardless of what happens to the user, even the user being dropped, is probably consistent with your expectations. In a sense, you think of the user who creates the subscription as having gifted it to the universe rather than continuing to own it. Or perhaps you think of the creator of the subscription as a solicitor/lawyer/agent working on behalf of client, and once that legal transaction is completed, you don't expect the lawyer being disbarred should impact the subscription which exists for the benefit of the client.
If instead you think about the subscription owner as continuing to be closely associated with the subscription (as I do), then you expect changes in the owner's permissions to impact the subscription.
I think the "gifted to the universe"/"lawyer" mental model is not consistent with how the system is already designed to work. You can't drop the subscription's owner without first running REASSIGN OWNED, or ALTER SUBSCRIPTION..OWNER TO, or simply dropping the subscription:
DROP ROLE regress_subscription_user;
ERROR: role "regress_subscription_user" cannot be dropped because some objects depend on it
DETAIL: owner of subscription regress_testsub
—
Mark Dilger
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 18:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-18 10:50 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-18 15:33 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
@ 2021-11-19 09:44 ` Amit Kapila <[email protected]>
2021-11-19 15:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
0 siblings, 1 reply; 68+ messages in thread
From: Amit Kapila @ 2021-11-19 09:44 UTC (permalink / raw)
To: Mark Dilger <[email protected]>; +Cc: Jeff Davis <[email protected]>; Andrew Dunstan <[email protected]>; pgsql-hackers; Robert Haas <[email protected]>
On Thu, Nov 18, 2021 at 9:03 PM Mark Dilger
<[email protected]> wrote:
>
> > On Nov 18, 2021, at 2:50 AM, Amit Kapila <[email protected]> wrote:
> >
> >> I gave that a slight amount of thought during the design of this patch, but didn't think we could refuse to revoke superuser on such a basis, and didn't see what we should do with the subscription other than have it continue to be owned by the recently-non-superuser. If you have a better idea, we can discuss it, but to some degree I think that is also orthogonal to the purpose of this patch. The only sense in which this patch depends on that issue is that this patch proposes that non-superuser subscription owners are already an issue, and therefore that this patch isn't creating a new issue, but rather making more sane something that already can happen.
> >>
> >
> > Don't we want to close this gap irrespective of the other part of the
> > feature? I mean if we take out the part of your 0003 patch that checks
> > whether the current user has permission to perform a particular
> > operation on the target table then the gap related to the owner losing
> > superuser privileges should be addressed.
>
> I don't think there is a gap. The patch does the right thing, causing the subscription whose owner has had superuser revoked to itself no longer function with superuser privileges. Whether that causes the subscription to fail depends on whether the previously-superuser now non-superuser owner now lacks sufficient privileges on the target relation(s). I think removing that part of the patch would be a regression.
>
I think we are saying the same thing. I intend to say that your 0003*
patch closes the current gap in the code and we should consider
applying it irrespective of what we do with respect to changing the
... OWNER TO .. behavior. Is there a reason why 0003* patch (or
something on those lines) shouldn't be considered to be applied?
--
With Regards,
Amit Kapila.
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 18:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-18 10:50 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-18 15:33 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-19 09:44 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
@ 2021-11-19 15:25 ` Mark Dilger <[email protected]>
2021-11-20 00:45 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
0 siblings, 1 reply; 68+ messages in thread
From: Mark Dilger @ 2021-11-19 15:25 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; Jeff Davis <[email protected]>; +Cc: Andrew Dunstan <[email protected]>; pgsql-hackers; Robert Haas <[email protected]>
> On Nov 19, 2021, at 1:44 AM, Amit Kapila <[email protected]> wrote:
>
> I think we are saying the same thing. I intend to say that your 0003*
> patch closes the current gap in the code and we should consider
> applying it irrespective of what we do with respect to changing the
> ... OWNER TO .. behavior. Is there a reason why 0003* patch (or
> something on those lines) shouldn't be considered to be applied?
Jeff Davis and I had a long conversation off-list yesterday and reached the same conclusion. I will be submitting a version of 0003 which does not depend on the prior two patches.
—
Mark Dilger
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 18:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-18 10:50 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-18 15:33 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-19 09:44 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-19 15:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
@ 2021-11-20 00:45 ` Mark Dilger <[email protected]>
2021-11-25 00:30 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
0 siblings, 1 reply; 68+ messages in thread
From: Mark Dilger @ 2021-11-20 00:45 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; Jeff Davis <[email protected]>; +Cc: Andrew Dunstan <[email protected]>; pgsql-hackers; Robert Haas <[email protected]>
> On Nov 19, 2021, at 7:25 AM, Mark Dilger <[email protected]> wrote:
>
> Jeff Davis and I had a long conversation off-list yesterday and reached the same conclusion. I will be submitting a version of 0003 which does not depend on the prior two patches.
Renamed as 0001 in version 3, as it is the only remaining patch. For anyone who reviewed the older patch set, please note that I made some changes to the src/test/subscription/t/026_nosuperuser.pl test case relative to the prior version.
—
Mark Dilger
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
Attachments:
[application/octet-stream] v3-0001-Respect-permissions-within-logical-replication.patch (12.7K, ../../[email protected]/2-v3-0001-Respect-permissions-within-logical-replication.patch)
download | inline diff:
From f7a61501dc990d21ce522cb9de749e5ecb331831 Mon Sep 17 00:00:00 2001
From: Mark Dilger <[email protected]>
Date: Fri, 19 Nov 2021 16:08:40 -0800
Subject: [PATCH v3] Respect permissions within logical replication
Prevent logical replication workers from performing insert, update,
delete, truncate, or copy commands on tables unless the subscription
owner has permission to do so.
---
doc/src/sgml/logical-replication.sgml | 30 ++++--
src/backend/commands/subscriptioncmds.c | 2 +
src/backend/replication/logical/tablesync.c | 13 +++
src/backend/replication/logical/worker.c | 30 ++++++
src/test/subscription/t/026_nosuperuser.pl | 107 ++++++++++++++++++++
5 files changed, 174 insertions(+), 8 deletions(-)
create mode 100644 src/test/subscription/t/026_nosuperuser.pl
diff --git a/doc/src/sgml/logical-replication.sgml b/doc/src/sgml/logical-replication.sgml
index 45b2e1e28f..7083c46d97 100644
--- a/doc/src/sgml/logical-replication.sgml
+++ b/doc/src/sgml/logical-replication.sgml
@@ -330,6 +330,13 @@
will simply be skipped.
</para>
+ <para>
+ Logical replication operations are performed with the privileges of the role
+ which owns the subscription. Permissions failures may cause replication
+ conflicts. (Note that <productname>PostgreSQL</productname> prior to
+ version 15.0 did no permissions checking when applying changes.)
+ </para>
+
<para>
A conflict will produce an error and will stop the replication; it must be
resolved manually by the user. Details about the conflict can be found in
@@ -337,7 +344,7 @@
</para>
<para>
- The resolution can be done either by changing data on the subscriber so
+ The resolution can be done either by changing data or permissions on the subscriber so
that it does not conflict with the incoming change or by skipping the
transaction that conflicts with the existing data. The transaction can be
skipped by calling the <link linkend="pg-replication-origin-advance">
@@ -530,9 +537,9 @@
<para>
A user able to modify the schema of subscriber-side tables can execute
- arbitrary code as a superuser. Limit ownership
- and <literal>TRIGGER</literal> privilege on such tables to roles that
- superusers trust. Moreover, if untrusted users can create tables, use only
+ arbitrary code as the role which owns any subscription which modifies those tables. Limit ownership
+ and <literal>TRIGGER</literal> privilege on such tables to trusted roles.
+ Moreover, if untrusted users can create tables, use only
publications that list tables explicitly. That is to say, create a
subscription <literal>FOR ALL TABLES</literal> or
<literal>FOR ALL TABLES IN SCHEMA</literal> only when superusers trust
@@ -576,13 +583,20 @@
<para>
The subscription apply process will run in the local database with the
- privileges of a superuser.
+ privileges of the subscription owner.
+ </para>
+
+ <para>
+ On the publisher, privileges are only checked once at the start of a
+ replication connection and are not re-checked as each change record is read.
</para>
<para>
- Privileges are only checked once at the start of a replication connection.
- They are not re-checked as each change record is read from the publisher,
- nor are they re-checked for each change when applied.
+ On the subscriber, the subscription owner's privileges are re-checked for
+ each transaction when applied. If a worker is in the process of applying a
+ transaction when the ownership of the subscription is changed by a
+ concurrent transaction, the application of the current transaction will
+ continue under the old owner's privileges.
</para>
</sect1>
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index c47ba26369..27a782b6e1 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -1474,6 +1474,8 @@ AlterSubscriptionOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
InvokeObjectPostAlterHook(SubscriptionRelationId,
form->oid, 0);
+
+ ApplyLauncherWakeupAtCommit();
}
/*
diff --git a/src/backend/replication/logical/tablesync.c b/src/backend/replication/logical/tablesync.c
index f07983a43c..2400ef8c45 100644
--- a/src/backend/replication/logical/tablesync.c
+++ b/src/backend/replication/logical/tablesync.c
@@ -111,6 +111,7 @@
#include "replication/origin.h"
#include "storage/ipc.h"
#include "storage/lmgr.h"
+#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
@@ -924,6 +925,7 @@ LogicalRepSyncTableStart(XLogRecPtr *origin_startpos)
char relstate;
XLogRecPtr relstate_lsn;
Relation rel;
+ AclResult aclresult;
WalRcvExecResult *res;
char originname[NAMEDATALEN];
RepOriginId originid;
@@ -1042,6 +1044,17 @@ LogicalRepSyncTableStart(XLogRecPtr *origin_startpos)
*/
rel = table_open(MyLogicalRepWorker->relid, RowExclusiveLock);
+ /*
+ * Check that our table sync worker has permission to insert into the
+ * target table.
+ */
+ aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(),
+ ACL_INSERT);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult,
+ get_relkind_objtype(rel->rd_rel->relkind),
+ RelationGetRelationName(rel));
+
/*
* Start a transaction in the remote node in REPEATABLE READ mode. This
* ensures that both the replication slot we create (see below) and the
diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c
index ae1b391bda..da57d8461c 100644
--- a/src/backend/replication/logical/worker.c
+++ b/src/backend/replication/logical/worker.c
@@ -179,6 +179,7 @@
#include "storage/proc.h"
#include "storage/procarray.h"
#include "tcop/tcopprot.h"
+#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/catcache.h"
#include "utils/dynahash.h"
@@ -1540,6 +1541,7 @@ apply_handle_insert(StringInfo s)
LogicalRepRelMapEntry *rel;
LogicalRepTupleData newtup;
LogicalRepRelId relid;
+ AclResult aclresult;
ApplyExecutionData *edata;
EState *estate;
TupleTableSlot *remoteslot;
@@ -1562,6 +1564,12 @@ apply_handle_insert(StringInfo s)
end_replication_step();
return;
}
+ aclresult = pg_class_aclcheck(RelationGetRelid(rel->localrel), GetUserId(),
+ ACL_INSERT);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult,
+ get_relkind_objtype(rel->localrel->rd_rel->relkind),
+ get_rel_name(rel->localreloid));
/* Set relation for error callback */
apply_error_callback_arg.rel = rel;
@@ -1662,6 +1670,7 @@ apply_handle_update(StringInfo s)
{
LogicalRepRelMapEntry *rel;
LogicalRepRelId relid;
+ AclResult aclresult;
ApplyExecutionData *edata;
EState *estate;
LogicalRepTupleData oldtup;
@@ -1689,6 +1698,12 @@ apply_handle_update(StringInfo s)
end_replication_step();
return;
}
+ aclresult = pg_class_aclcheck(RelationGetRelid(rel->localrel), GetUserId(),
+ ACL_UPDATE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult,
+ get_relkind_objtype(rel->localrel->rd_rel->relkind),
+ get_rel_name(rel->localreloid));
/* Set relation for error callback */
apply_error_callback_arg.rel = rel;
@@ -1829,6 +1844,7 @@ apply_handle_delete(StringInfo s)
LogicalRepRelMapEntry *rel;
LogicalRepTupleData oldtup;
LogicalRepRelId relid;
+ AclResult aclresult;
ApplyExecutionData *edata;
EState *estate;
TupleTableSlot *remoteslot;
@@ -1851,6 +1867,12 @@ apply_handle_delete(StringInfo s)
end_replication_step();
return;
}
+ aclresult = pg_class_aclcheck(RelationGetRelid(rel->localrel), GetUserId(),
+ ACL_DELETE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult,
+ get_relkind_objtype(rel->localrel->rd_rel->relkind),
+ get_rel_name(rel->localreloid));
/* Set relation for error callback */
apply_error_callback_arg.rel = rel;
@@ -2223,6 +2245,7 @@ apply_handle_truncate(StringInfo s)
{
LogicalRepRelId relid = lfirst_oid(lc);
LogicalRepRelMapEntry *rel;
+ AclResult aclresult;
rel = logicalrep_rel_open(relid, lockmode);
if (!should_apply_changes_for_rel(rel))
@@ -2234,6 +2257,12 @@ apply_handle_truncate(StringInfo s)
logicalrep_rel_close(rel, lockmode);
continue;
}
+ aclresult = pg_class_aclcheck(RelationGetRelid(rel->localrel),
+ GetUserId(), ACL_TRUNCATE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult,
+ get_relkind_objtype(rel->localrel->rd_rel->relkind),
+ get_rel_name(rel->localreloid));
remote_rels = lappend(remote_rels, rel);
rels = lappend(rels, rel->localrel);
@@ -2915,6 +2944,7 @@ maybe_reread_subscription(void)
strcmp(newsub->slotname, MySubscription->slotname) != 0 ||
newsub->binary != MySubscription->binary ||
newsub->stream != MySubscription->stream ||
+ newsub->owner != MySubscription->owner ||
!equal(newsub->publications, MySubscription->publications))
{
ereport(LOG,
diff --git a/src/test/subscription/t/026_nosuperuser.pl b/src/test/subscription/t/026_nosuperuser.pl
new file mode 100644
index 0000000000..05717d5111
--- /dev/null
+++ b/src/test/subscription/t/026_nosuperuser.pl
@@ -0,0 +1,107 @@
+
+# Copyright (c) 2021, PostgreSQL Global Development Group
+
+# Basic logical replication test
+use strict;
+use warnings;
+use PostgreSQL::Test::Cluster;
+use PostgreSQL::Test::Utils qw(slurp_file);
+use Test::More tests => 3;
+use Time::HiRes qw(usleep gettimeofday tv_interval);
+
+# Initialize publisher node
+my $node_publisher = PostgreSQL::Test::Cluster->new('publisher');
+$node_publisher->init(allows_streaming => 'logical');
+$node_publisher->start;
+
+# Create subscriber node
+my $node_subscriber = PostgreSQL::Test::Cluster->new('subscriber');
+$node_subscriber->init(allows_streaming => 'logical');
+$node_subscriber->start;
+
+my $publisher_connstr = $node_publisher->connstr . ' dbname=postgres';
+
+# Create identical structres on publisher and subscriber
+for my $node ($node_publisher, $node_subscriber)
+{
+ $node->safe_psql('postgres', qq(
+ CREATE ROLE regress_admin SUPERUSER LOGIN;
+ CREATE ROLE regress_alice NOSUPERUSER NOLOGIN;
+ GRANT CREATE ON DATABASE postgres TO regress_alice;
+ SET SESSION AUTHORIZATION regress_alice;
+ CREATE SCHEMA alice;
+ CREATE TABLE alice.tbl (i INTEGER);
+ GRANT USAGE ON SCHEMA alice TO regress_admin;
+ ALTER TABLE alice.tbl REPLICA IDENTITY FULL;
+ GRANT SELECT ON TABLE alice.tbl TO regress_admin;
+ ));
+}
+
+# Alice creates data, adjusts privileges, and creates a publication on
+# publisher node
+$node_publisher->safe_psql('postgres', qq(
+ SET SESSION AUTHORIZATION regress_alice;
+ INSERT INTO alice.tbl (i) VALUES (1);
+ CREATE PUBLICATION alice FOR TABLE alice.tbl;
+));
+
+# Superuser creates a subscription on the subscriber node
+$node_subscriber->safe_psql('postgres', qq(
+ SET SESSION AUTHORIZATION regress_admin;
+ CREATE SUBSCRIPTION admin_sub CONNECTION '$publisher_connstr' PUBLICATION alice;
+));
+
+# Wait for subscription catch-up on subscriber
+$node_publisher->wait_for_catchup('admin_sub');
+
+ok(1, "initial sync finished");
+
+my $result = $node_subscriber->safe_psql('postgres', qq(
+ SELECT COUNT(i), MAX(i) FROM alice.tbl));
+is ($result, '1|1', "superuser admin replicates data");
+
+# Revoke superuser from admin on the subscriber, without which the admin has no
+# authority to insert into alice's table
+$node_subscriber->safe_psql('postgres', "ALTER ROLE regress_admin NOSUPERUSER");
+
+# Alice inserts new data into her table on the publisher node
+$node_publisher->safe_psql('postgres', qq(
+SET SESSION AUTHORIZATION regress_alice;
+INSERT INTO alice.tbl (i) VALUES (2);
+));
+
+# We cannot wait for catchup, as that will hang. Instead, we poll for the
+# error message in the logs. To avoid hanging infinitely, retry for at most
+# 180 seconds. Also, in case the data replicates rather than failing, check
+# for it rather than burning a full three minutes waiting.
+#
+my $log;
+my $t0 = [gettimeofday];
+RETRY: {
+ $log = slurp_file($node_subscriber->logfile);
+ unless($log =~ qr/ERROR: permission denied for table tbl/msi)
+ {
+ my $elapsed = tv_interval ( $t0 );
+
+ # For the two seconds, retry every 1/10th second
+ if ($elapsed < 1.0)
+ {
+ usleep(100000); # sleep 1/10th second
+ redo RETRY;
+ }
+ # For the remainder of the test, retry no more than once per second,
+ # and also check if the data has come through, as there is no point
+ # waiting for the error if it we know it won't happen.
+ elsif ($elapsed < 179.0)
+ {
+ $result = $node_subscriber->safe_psql('postgres', qq(
+ SELECT MAX(i) FROM alice.tbl));
+ last RETRY if $result > 1;
+ sleep 1;
+ redo RETRY;
+ }
+ }
+}
+
+like ($log, qr/ERROR: permission denied for table tbl/msi,
+ 'subscriber lacks permission after superuser is revoked');
--
2.21.1 (Apple Git-122.3)
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 18:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-18 10:50 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-18 15:33 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-19 09:44 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-19 15:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-20 00:45 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
@ 2021-11-25 00:30 ` Jeff Davis <[email protected]>
2021-11-25 04:21 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-27 18:05 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-12-15 20:23 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
0 siblings, 3 replies; 68+ messages in thread
From: Jeff Davis @ 2021-11-25 00:30 UTC (permalink / raw)
To: Mark Dilger <[email protected]>; Amit Kapila <[email protected]>; +Cc: Andrew Dunstan <[email protected]>; pgsql-hackers; Robert Haas <[email protected]>
On Fri, 2021-11-19 at 16:45 -0800, Mark Dilger wrote:
> Renamed as 0001 in version 3, as it is the only remaining patch. For
> anyone who reviewed the older patch set, please note that I made some
> changes to the src/test/subscription/t/026_nosuperuser.pl test case
> relative to the prior version.
We need to do permission checking for WITH CHECK OPTION and RLS. The
patch right now allows the subscription to write data that an RLS
policy forbids.
A couple other points:
* We shouldn't refer to the behavior of previous versions in the docs
unless there's a compelling reason
* Do we need to be smarter about partitioned tables, where an insert
can turn into an update?
* Should we refactor to borrow logic from ExecInsert so that it's less
likely that we miss something in the future?
Regards,
Jeff Davis
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 18:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-18 10:50 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-18 15:33 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-19 09:44 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-19 15:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-20 00:45 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-25 00:30 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
@ 2021-11-25 04:21 ` Amit Kapila <[email protected]>
2021-11-25 20:06 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2 siblings, 1 reply; 68+ messages in thread
From: Amit Kapila @ 2021-11-25 04:21 UTC (permalink / raw)
To: Jeff Davis <[email protected]>; +Cc: Mark Dilger <[email protected]>; Andrew Dunstan <[email protected]>; pgsql-hackers; Robert Haas <[email protected]>
On Thu, Nov 25, 2021 at 6:00 AM Jeff Davis <[email protected]> wrote:
>
> On Fri, 2021-11-19 at 16:45 -0800, Mark Dilger wrote:
> > Renamed as 0001 in version 3, as it is the only remaining patch. For
> > anyone who reviewed the older patch set, please note that I made some
> > changes to the src/test/subscription/t/026_nosuperuser.pl test case
> > relative to the prior version.
>
> We need to do permission checking for WITH CHECK OPTION and RLS. The
> patch right now allows the subscription to write data that an RLS
> policy forbids.
>
Won't it be better to just check if the current user is superuser
before applying each change as a matter of this first patch? Sorry, I
was under impression that first, we want to close the current gap
where we allow to proceed with replication if the user's superuser
privileges were revoked during replication. To allow non-superusers
owners, I thought it might be better to first try to detect the change
of ownership as soon as possible instead of at the transaction
boundary.
--
With Regards,
Amit Kapila.
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 18:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-18 10:50 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-18 15:33 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-19 09:44 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-19 15:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-20 00:45 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-25 00:30 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-25 04:21 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
@ 2021-11-25 20:06 ` Jeff Davis <[email protected]>
2021-11-29 04:13 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
0 siblings, 1 reply; 68+ messages in thread
From: Jeff Davis @ 2021-11-25 20:06 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: Mark Dilger <[email protected]>; Andrew Dunstan <[email protected]>; pgsql-hackers; Robert Haas <[email protected]>
On Thu, 2021-11-25 at 09:51 +0530, Amit Kapila wrote:
> Won't it be better to just check if the current user is superuser
> before applying each change as a matter of this first patch? Sorry, I
> was under impression that first, we want to close the current gap
> where we allow to proceed with replication if the user's superuser
> privileges were revoked during replication.
That could be a first step, and I don't oppose it. But it seems like a
very small first step that would be made obsolete when v3-0001 is
ready, which I think will be very soon.
> To allow non-superusers
> owners, I thought it might be better to first try to detect the
> change
> of ownership
In the case of revoked superuser privileges, there's no change in
ownership, just a change of privileges (SUPERUSER -> NOSUPERUSER). And
if we're detecting a change of privileges, why not just do it in
something closer to the right way, which is what v3-0001 is attempting
to do.
> as soon as possible instead of at the transaction
> boundary.
I don't understand why it's important to detect a loss of privileges
faster than a transaction boundary. Can you elaborate?
Regards,
Jeff Davis
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 18:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-18 10:50 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-18 15:33 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-19 09:44 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-19 15:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-20 00:45 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-25 00:30 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-25 04:21 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-25 20:06 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
@ 2021-11-29 04:13 ` Amit Kapila <[email protected]>
2021-11-29 19:26 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
0 siblings, 1 reply; 68+ messages in thread
From: Amit Kapila @ 2021-11-29 04:13 UTC (permalink / raw)
To: Jeff Davis <[email protected]>; +Cc: Mark Dilger <[email protected]>; Andrew Dunstan <[email protected]>; pgsql-hackers; Robert Haas <[email protected]>
On Fri, Nov 26, 2021 at 1:36 AM Jeff Davis <[email protected]> wrote:
>
> > as soon as possible instead of at the transaction
> > boundary.
>
> I don't understand why it's important to detect a loss of privileges
> faster than a transaction boundary. Can you elaborate?
>
The first reason is that way it would be consistent with what we can
see while doing the operations from the backend. For example, if we
revoke privileges from the user during the transaction, the results
will be reflected.
postgres=> Begin;
BEGIN
postgres=*> insert into t1 values(1);
INSERT 0 1
postgres=*> insert into t1 values(2);
ERROR: permission denied for table t1
In this case, after the first insert, I have revoked the privileges of
the user from table t1 and the same is reflected in the very next
operation. Another reason is to make behavior predictable as users can
always expect when exactly the privilege change will be reflected and
it won't depend on the number of changes in the transaction.
--
With Regards,
Amit Kapila.
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 18:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-18 10:50 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-18 15:33 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-19 09:44 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-19 15:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-20 00:45 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-25 00:30 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-25 04:21 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-25 20:06 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-29 04:13 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
@ 2021-11-29 19:26 ` Jeff Davis <[email protected]>
2021-11-30 11:55 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
0 siblings, 1 reply; 68+ messages in thread
From: Jeff Davis @ 2021-11-29 19:26 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: Mark Dilger <[email protected]>; Andrew Dunstan <[email protected]>; pgsql-hackers; Robert Haas <[email protected]>
On Mon, 2021-11-29 at 09:43 +0530, Amit Kapila wrote:
> The first reason is that way it would be consistent with what we can
> see while doing the operations from the backend.
Logical replication is not interactive, so it doesn't seem quite the
same.
If you have a long running INSERT INTO SELECT or COPY FROM, the
permission checks just happen at the beginning. As a user, it wouldn't
surprise me if logical replication was similar.
> operation. Another reason is to make behavior predictable as users
> can
> always expect when exactly the privilege change will be reflected and
> it won't depend on the number of changes in the transaction.
This patch does detect ownership changes more quickly (at the
transaction boundary) than the current code (only when it reloads for
some other reason). Transaction boundary seems like a reasonable time
to detect the change to me.
Detecting faster might be nice, but I don't have a strong opinion about
it and I don't see why it necessarily needs to happen before this patch
goes in.
Also, do you think the cost of doing maybe_reread_subscription() per-
tuple instead of per-transaction would be detectable? If we lock
ourselves into semantics that detect changes quickly, it will be harder
to optimize the per-tuple path later.
Regards,
Jeff Davis
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 18:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-18 10:50 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-18 15:33 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-19 09:44 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-19 15:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-20 00:45 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-25 00:30 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-25 04:21 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-25 20:06 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-29 04:13 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-29 19:26 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
@ 2021-11-30 11:55 ` Amit Kapila <[email protected]>
2021-11-30 20:42 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-12-09 15:41 ` Re: Non-superuser subscription owners Robert Haas <[email protected]>
0 siblings, 2 replies; 68+ messages in thread
From: Amit Kapila @ 2021-11-30 11:55 UTC (permalink / raw)
To: Jeff Davis <[email protected]>; +Cc: Mark Dilger <[email protected]>; Andrew Dunstan <[email protected]>; pgsql-hackers; Robert Haas <[email protected]>
On Tue, Nov 30, 2021 at 12:56 AM Jeff Davis <[email protected]> wrote:
>
> On Mon, 2021-11-29 at 09:43 +0530, Amit Kapila wrote:
> > The first reason is that way it would be consistent with what we can
> > see while doing the operations from the backend.
>
> Logical replication is not interactive, so it doesn't seem quite the
> same.
>
> If you have a long running INSERT INTO SELECT or COPY FROM, the
> permission checks just happen at the beginning. As a user, it wouldn't
> surprise me if logical replication was similar.
>
> > operation. Another reason is to make behavior predictable as users
> > can
> > always expect when exactly the privilege change will be reflected and
> > it won't depend on the number of changes in the transaction.
>
> This patch does detect ownership changes more quickly (at the
> transaction boundary) than the current code (only when it reloads for
> some other reason). Transaction boundary seems like a reasonable time
> to detect the change to me.
>
> Detecting faster might be nice, but I don't have a strong opinion about
> it and I don't see why it necessarily needs to happen before this patch
> goes in.
>
I think it would be better to do it before we allow subscription
owners to be non-superusers.
> Also, do you think the cost of doing maybe_reread_subscription() per-
> tuple instead of per-transaction would be detectable?
>
Yeah, it is possible that is why I suggested in one of the emails
above to allow changing the owners only for disabled subscriptions.
--
With Regards,
Amit Kapila.
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 18:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-18 10:50 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-18 15:33 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-19 09:44 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-19 15:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-20 00:45 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-25 00:30 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-25 04:21 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-25 20:06 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-29 04:13 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-29 19:26 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-30 11:55 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
@ 2021-11-30 20:42 ` Jeff Davis <[email protected]>
2021-12-01 13:36 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
1 sibling, 1 reply; 68+ messages in thread
From: Jeff Davis @ 2021-11-30 20:42 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: Mark Dilger <[email protected]>; Andrew Dunstan <[email protected]>; pgsql-hackers; Robert Haas <[email protected]>
On Tue, 2021-11-30 at 17:25 +0530, Amit Kapila wrote:
> I think it would be better to do it before we allow subscription
> owners to be non-superusers.
There are a couple other things to consider before allowing non-
superusers to create subscriptions anyway. For instance, a non-
superuser shouldn't be able to use a connection string that reads the
certificate file from the server unless they also have
pg_read_server_files privs.
> Yeah, it is possible that is why I suggested in one of the emails
> above to allow changing the owners only for disabled subscriptions.
The current patch detects the following cases at the transaction
boundary:
* ALTER SUBSCRIPTION ... OWNER TO ...
* ALTER ROLE ... NOSUPERUSER
* privileges revoked one way or another (aside from the RLS/WCO
problems, which will be fixed)
If we want to detect at row boundaries we need to capture all of those
cases too, or else we're being inconsistent. The latter two cannot be
tied to whether the subscription is disabled or not, so I don't think
that's a complete solution.
How about (as a separate patch) we just do maybe_reread_subscription()
every K operations within a transaction? That would speed up
permissions errors if a revoke happens.
Regards,
Jeff Davis
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 18:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-18 10:50 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-18 15:33 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-19 09:44 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-19 15:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-20 00:45 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-25 00:30 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-25 04:21 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-25 20:06 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-29 04:13 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-29 19:26 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-30 11:55 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-30 20:42 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
@ 2021-12-01 13:36 ` Amit Kapila <[email protected]>
2021-12-01 19:21 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
0 siblings, 1 reply; 68+ messages in thread
From: Amit Kapila @ 2021-12-01 13:36 UTC (permalink / raw)
To: Jeff Davis <[email protected]>; +Cc: Mark Dilger <[email protected]>; Andrew Dunstan <[email protected]>; pgsql-hackers; Robert Haas <[email protected]>
On Wed, Dec 1, 2021 at 2:12 AM Jeff Davis <[email protected]> wrote:
>
> On Tue, 2021-11-30 at 17:25 +0530, Amit Kapila wrote:
> > I think it would be better to do it before we allow subscription
> > owners to be non-superusers.
>
> There are a couple other things to consider before allowing non-
> superusers to create subscriptions anyway. For instance, a non-
> superuser shouldn't be able to use a connection string that reads the
> certificate file from the server unless they also have
> pg_read_server_files privs.
>
Isn't allowing to create subscriptions via non-superusers and allowing
to change the owner two different things? I am under the impression
that the latter one is more towards allowing the workers to apply
changes with a non-superuser role.
--
With Regards,
Amit Kapila.
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 18:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-18 10:50 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-18 15:33 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-19 09:44 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-19 15:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-20 00:45 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-25 00:30 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-25 04:21 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-25 20:06 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-29 04:13 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-29 19:26 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-30 11:55 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-30 20:42 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-12-01 13:36 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
@ 2021-12-01 19:21 ` Mark Dilger <[email protected]>
2021-12-02 09:29 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
0 siblings, 1 reply; 68+ messages in thread
From: Mark Dilger @ 2021-12-01 19:21 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: Jeff Davis <[email protected]>; Andrew Dunstan <[email protected]>; pgsql-hackers; Robert Haas <[email protected]>
> On Dec 1, 2021, at 5:36 AM, Amit Kapila <[email protected]> wrote:
>
> On Wed, Dec 1, 2021 at 2:12 AM Jeff Davis <[email protected]> wrote:
>>
>> On Tue, 2021-11-30 at 17:25 +0530, Amit Kapila wrote:
>>> I think it would be better to do it before we allow subscription
>>> owners to be non-superusers.
>>
>> There are a couple other things to consider before allowing non-
>> superusers to create subscriptions anyway. For instance, a non-
>> superuser shouldn't be able to use a connection string that reads the
>> certificate file from the server unless they also have
>> pg_read_server_files privs.
>>
>
> Isn't allowing to create subscriptions via non-superusers and allowing
> to change the owner two different things? I am under the impression
> that the latter one is more towards allowing the workers to apply
> changes with a non-superuser role.
The short-term goal is to have logical replication workers respect the privileges of the role which owns the subscription.
The long-term work probably includes creating a predefined role with permission to create subscriptions, and the ability to transfer those subscriptions to roles who might be neither superuser nor members of any particular predefined role; the idea being that logical replication subscriptions can be established without any superuser involvement, and may thereafter run without any special privilege.
The more recent patches on this thread are not as ambitious as the earlier patch-sets. We are no longer trying to support transferring subscriptions to non-superusers.
Right now, on HEAD, if a subscription owner has superuser revoked, the subscription can continue to operate as superuser in so far as its replication actions are concerned. That seems like a pretty big security hole.
This patch mostly plugs that hole by adding permissions checks, so that a subscription owned by a role who has privileges revoked cannot (for the most part) continue to act under the old privileges.
There are two problematic edge cases that can occur after transfer of ownership. Remember, the new owner is required to be superuser for the transfer of ownership to occur.
1) A subscription is transferred to a new owner, and the new owner then has privilege revoked.
2) A subscription is transferred to a new owner, and then the old owner has privileges increased.
In both cases, a currently running logical replication worker may finish a transaction in progress acting with the current privileges of the old owner. The clearest solution is, as you suggest, to refuse transfer of ownership of subscriptions that are enabled.
Doing so will create a failure case for REASSIGN OWNED BY. Will that be ok?
—
Mark Dilger
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 18:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-18 10:50 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-18 15:33 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-19 09:44 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-19 15:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-20 00:45 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-25 00:30 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-25 04:21 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-25 20:06 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-29 04:13 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-29 19:26 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-30 11:55 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-30 20:42 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-12-01 13:36 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-12-01 19:21 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
@ 2021-12-02 09:29 ` Amit Kapila <[email protected]>
2021-12-03 13:31 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
0 siblings, 1 reply; 68+ messages in thread
From: Amit Kapila @ 2021-12-02 09:29 UTC (permalink / raw)
To: Mark Dilger <[email protected]>; +Cc: Jeff Davis <[email protected]>; Andrew Dunstan <[email protected]>; pgsql-hackers; Robert Haas <[email protected]>
On Thu, Dec 2, 2021 at 12:51 AM Mark Dilger
<[email protected]> wrote:
>
>
> > On Dec 1, 2021, at 5:36 AM, Amit Kapila <[email protected]> wrote:
> >
> > On Wed, Dec 1, 2021 at 2:12 AM Jeff Davis <[email protected]> wrote:
> >>
> >> On Tue, 2021-11-30 at 17:25 +0530, Amit Kapila wrote:
> >>> I think it would be better to do it before we allow subscription
> >>> owners to be non-superusers.
> >>
> >> There are a couple other things to consider before allowing non-
> >> superusers to create subscriptions anyway. For instance, a non-
> >> superuser shouldn't be able to use a connection string that reads the
> >> certificate file from the server unless they also have
> >> pg_read_server_files privs.
> >>
> >
> > Isn't allowing to create subscriptions via non-superusers and allowing
> > to change the owner two different things? I am under the impression
> > that the latter one is more towards allowing the workers to apply
> > changes with a non-superuser role.
>
> The short-term goal is to have logical replication workers respect the privileges of the role which owns the subscription.
>
> The long-term work probably includes creating a predefined role with permission to create subscriptions, and the ability to transfer those subscriptions to roles who might be neither superuser nor members of any particular predefined role; the idea being that logical replication subscriptions can be established without any superuser involvement, and may thereafter run without any special privilege.
>
> The more recent patches on this thread are not as ambitious as the earlier patch-sets. We are no longer trying to support transferring subscriptions to non-superusers.
>
> Right now, on HEAD, if a subscription owner has superuser revoked, the subscription can continue to operate as superuser in so far as its replication actions are concerned. That seems like a pretty big security hole.
>
> This patch mostly plugs that hole by adding permissions checks, so that a subscription owned by a role who has privileges revoked cannot (for the most part) continue to act under the old privileges.
>
If we want to maintain the property that subscriptions can only be
owned by superuser for your first version then isn't a simple check
like ((!superuser()) for each of the operations is sufficient?
> There are two problematic edge cases that can occur after transfer of ownership. Remember, the new owner is required to be superuser for the transfer of ownership to occur.
>
> 1) A subscription is transferred to a new owner, and the new owner then has privilege revoked.
>
> 2) A subscription is transferred to a new owner, and then the old owner has privileges increased.
>
In (2), I am not clear what do you mean by "the old owner has
privileges increased"? If the owners can only be superusers then what
does it mean to increase the privileges.
> In both cases, a currently running logical replication worker may finish a transaction in progress acting with the current privileges of the old owner. The clearest solution is, as you suggest, to refuse transfer of ownership of subscriptions that are enabled.
>
> Doing so will create a failure case for REASSIGN OWNED BY. Will that be ok?
>
I think so. Do we see any problem with that? I think we have some
failure cases currently as well like "All Tables Publication" can only
be owned by superusers whereas ownership for others can be to
non-superusers and similarly we can't change ownership for pinned
objects. I think the case being discussed is not exactly the same but
I am not able to see a problem with it.
--
With Regards,
Amit Kapila.
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 18:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-18 10:50 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-18 15:33 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-19 09:44 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-19 15:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-20 00:45 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-25 00:30 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-25 04:21 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-25 20:06 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-29 04:13 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-29 19:26 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-30 11:55 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-30 20:42 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-12-01 13:36 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-12-01 19:21 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-12-02 09:29 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
@ 2021-12-03 13:31 ` Mark Dilger <[email protected]>
2021-12-06 10:19 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
0 siblings, 1 reply; 68+ messages in thread
From: Mark Dilger @ 2021-12-03 13:31 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: Jeff Davis <[email protected]>; Andrew Dunstan <[email protected]>; pgsql-hackers; Robert Haas <[email protected]>
> On Dec 2, 2021, at 1:29 AM, Amit Kapila <[email protected]> wrote:
>
> If we want to maintain the property that subscriptions can only be
> owned by superuser for your first version then isn't a simple check
> like ((!superuser()) for each of the operations is sufficient?
As things stand today, nothing prevents a superuser subscription owner from having superuser revoked. The patch does nothing to change this.
> In (2), I am not clear what do you mean by "the old owner has
> privileges increased"? If the owners can only be superusers then what
> does it mean to increase the privileges.
The old owner may have had privileges reduced (no superuser, only permission to write into a specific schema, etc.) and the subscription enabled only after those privilege reductions were put in place. This is a usage pattern this patch is intended to support, by honoring those privilege restrictions.
—
Mark Dilger
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 18:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-18 10:50 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-18 15:33 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-19 09:44 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-19 15:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-20 00:45 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-25 00:30 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-25 04:21 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-25 20:06 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-29 04:13 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-29 19:26 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-30 11:55 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-30 20:42 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-12-01 13:36 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-12-01 19:21 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-12-02 09:29 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-12-03 13:31 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
@ 2021-12-06 10:19 ` Amit Kapila <[email protected]>
2021-12-06 15:56 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
0 siblings, 1 reply; 68+ messages in thread
From: Amit Kapila @ 2021-12-06 10:19 UTC (permalink / raw)
To: Mark Dilger <[email protected]>; +Cc: Jeff Davis <[email protected]>; Andrew Dunstan <[email protected]>; pgsql-hackers; Robert Haas <[email protected]>
On Fri, Dec 3, 2021 at 10:37 PM Mark Dilger
<[email protected]> wrote:
>
> > On Dec 2, 2021, at 1:29 AM, Amit Kapila <[email protected]> wrote:
> >
> > If we want to maintain the property that subscriptions can only be
> > owned by superuser for your first version then isn't a simple check
> > like ((!superuser()) for each of the operations is sufficient?
>
> As things stand today, nothing prevents a superuser subscription owner from having superuser revoked. The patch does nothing to change this.
>
I understand that but won't that get verified when we look up the
information in pg_authid as part of superuser() check?
--
With Regards,
Amit Kapila.
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 18:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-18 10:50 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-18 15:33 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-19 09:44 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-19 15:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-20 00:45 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-25 00:30 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-25 04:21 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-25 20:06 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-29 04:13 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-29 19:26 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-30 11:55 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-30 20:42 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-12-01 13:36 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-12-01 19:21 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-12-02 09:29 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-12-03 13:31 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-12-06 10:19 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
@ 2021-12-06 15:56 ` Mark Dilger <[email protected]>
2021-12-07 09:39 ` Re: Non-superuser subscription owners Ronan Dunklau <[email protected]>
2021-12-07 10:29 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
0 siblings, 2 replies; 68+ messages in thread
From: Mark Dilger @ 2021-12-06 15:56 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: Jeff Davis <[email protected]>; Andrew Dunstan <[email protected]>; pgsql-hackers; Robert Haas <[email protected]>
> On Dec 6, 2021, at 2:19 AM, Amit Kapila <[email protected]> wrote:
>
>>> If we want to maintain the property that subscriptions can only be
>>> owned by superuser
We don't want to maintain such a property, or at least, that's not what I want. I don't think that's what Jeff wants, either.
To clarify, I'm not entirely sure how to interpret the verb "maintain" in your question, since before the patch the property does not exist, and after the patch, it continues to not exist. We could *add* such a property, of course, though this patch does not attempt any such thing.
> I understand that but won't that get verified when we look up the
> information in pg_authid as part of superuser() check?
If we added a superuser() check, then yes, but that would take things in a direction I do not want to go.
As I perceive the roadmap:
1) Fix the current bug wherein subscription changes are applied with superuser force after the subscription owner has superuser privileges revoked.
2) Allow the transfer of subscriptions to non-superuser owners.
3) Allow the creation of subscriptions by non-superusers who are members of some as yet to be created predefined role, say "pg_create_subscriptions"
I may be wrong, but it sounds like you interpret the intent of this patch as enforcing superuserness. That's not so. This patch intends to correctly handle the situation where a subscription is owned by a non-superuser (task 1, above) without going so far as creating new paths by which that situation could arise (tasks 2 and 3, above).
—
Mark Dilger
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 18:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-18 10:50 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-18 15:33 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-19 09:44 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-19 15:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-20 00:45 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-25 00:30 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-25 04:21 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-25 20:06 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-29 04:13 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-29 19:26 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-30 11:55 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-30 20:42 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-12-01 13:36 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-12-01 19:21 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-12-02 09:29 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-12-03 13:31 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-12-06 10:19 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-12-06 15:56 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
@ 2021-12-07 09:39 ` Ronan Dunklau <[email protected]>
1 sibling, 0 replies; 68+ messages in thread
From: Ronan Dunklau @ 2021-12-07 09:39 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; [email protected]; +Cc: Jeff Davis <[email protected]>; Andrew Dunstan <[email protected]>; pgsql-hackers; Robert Haas <[email protected]>; Mark Dilger <[email protected]>
Le lundi 6 décembre 2021, 16:56:56 CET Mark Dilger a écrit :
> > On Dec 6, 2021, at 2:19 AM, Amit Kapila <[email protected]> wrote:
> >>> If we want to maintain the property that subscriptions can only be
> >>> owned by superuser
>
> We don't want to maintain such a property, or at least, that's not what I
> want. I don't think that's what Jeff wants, either.
That's not what I want either: the ability to run and refresh subscriptions as
a non superuser is a desirable feature.
The REFRESH part was possible before PG 14, when it was allowed to run REFRESH
in a function, which could be made to run as security definer.
> As I perceive the roadmap:
>
> 1) Fix the current bug wherein subscription changes are applied with
> superuser force after the subscription owner has superuser privileges
> revoked. 2) Allow the transfer of subscriptions to non-superuser owners.
> 3) Allow the creation of subscriptions by non-superusers who are members of
> some as yet to be created predefined role, say "pg_create_subscriptions"
This roadmap seems sensible.
--
Ronan Dunklau
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 18:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-18 10:50 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-18 15:33 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-19 09:44 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-19 15:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-20 00:45 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-25 00:30 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-25 04:21 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-25 20:06 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-29 04:13 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-29 19:26 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-30 11:55 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-30 20:42 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-12-01 13:36 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-12-01 19:21 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-12-02 09:29 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-12-03 13:31 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-12-06 10:19 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-12-06 15:56 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
@ 2021-12-07 10:29 ` Amit Kapila <[email protected]>
2021-12-07 14:55 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
1 sibling, 1 reply; 68+ messages in thread
From: Amit Kapila @ 2021-12-07 10:29 UTC (permalink / raw)
To: Mark Dilger <[email protected]>; +Cc: Jeff Davis <[email protected]>; Andrew Dunstan <[email protected]>; pgsql-hackers; Robert Haas <[email protected]>
On Mon, Dec 6, 2021 at 9:26 PM Mark Dilger <[email protected]> wrote:
>
> > On Dec 6, 2021, at 2:19 AM, Amit Kapila <[email protected]> wrote:
> >
> >>> If we want to maintain the property that subscriptions can only be
> >>> owned by superuser
>
> We don't want to maintain such a property, or at least, that's not what I want. I don't think that's what Jeff wants, either.
>
> To clarify, I'm not entirely sure how to interpret the verb "maintain" in your question, since before the patch the property does not exist, and after the patch, it continues to not exist. We could *add* such a property, of course, though this patch does not attempt any such thing.
>
Okay, let me try to explain again. Following is the text from docs
[1]: " (a) To create a subscription, the user must be a superuser. (b)
The subscription apply process will run in the local database with the
privileges of a superuser. (c) Privileges are only checked once at the
start of a replication connection. They are not re-checked as each
change record is read from the publisher, nor are they re-checked for
each change when applied.
My understanding is that we want to improve what is written as (c)
which I think is the same as what you mentioned later as "Fix the
current bug wherein subscription changes are applied with superuser
force after the subscription owner has superuser privileges revoked.".
Am I correct till here? If so, I think what I am suggesting should fix
this with the assumption that we still want to follow (b) at least for
the first patch. One possibility is that our understanding of the
first problem is the same but you want to allow apply worker running
even when superuser privileges are revoked provided the user with
which it is running has appropriate privileges on the objects being
accessed by apply worker.
We will talk about other points of the roadmap you mentioned once our
understanding for the first one matches.
[1] - https://www.postgresql.org/docs/devel/logical-replication-security.html
--
With Regards,
Amit Kapila.
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 18:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-18 10:50 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-18 15:33 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-19 09:44 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-19 15:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-20 00:45 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-25 00:30 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-25 04:21 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-25 20:06 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-29 04:13 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-29 19:26 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-30 11:55 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-30 20:42 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-12-01 13:36 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-12-01 19:21 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-12-02 09:29 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-12-03 13:31 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-12-06 10:19 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-12-06 15:56 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-12-07 10:29 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
@ 2021-12-07 14:55 ` Mark Dilger <[email protected]>
2021-12-09 04:58 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
0 siblings, 1 reply; 68+ messages in thread
From: Mark Dilger @ 2021-12-07 14:55 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: Jeff Davis <[email protected]>; Andrew Dunstan <[email protected]>; pgsql-hackers; Robert Haas <[email protected]>
> On Dec 7, 2021, at 2:29 AM, Amit Kapila <[email protected]> wrote:
>
> Okay, let me try to explain again. Following is the text from docs
> [1]: " (a) To create a subscription, the user must be a superuser. (b)
> The subscription apply process will run in the local database with the
> privileges of a superuser. (c) Privileges are only checked once at the
> start of a replication connection. They are not re-checked as each
> change record is read from the publisher, nor are they re-checked for
> each change when applied.
>
> My understanding is that we want to improve what is written as (c)
> which I think is the same as what you mentioned later as "Fix the
> current bug wherein subscription changes are applied with superuser
> force after the subscription owner has superuser privileges revoked.".
> Am I correct till here? If so, I think what I am suggesting should fix
> this with the assumption that we still want to follow (b) at least for
> the first patch.
Ok, that's a point of disagreement. I was trying to fix both (b) and (c) in the first patch.
> One possibility is that our understanding of the
> first problem is the same but you want to allow apply worker running
> even when superuser privileges are revoked provided the user with
> which it is running has appropriate privileges on the objects being
> accessed by apply worker.
Correct, that's what I'm trying to make safe.
> We will talk about other points of the roadmap you mentioned once our
> understanding for the first one matches.
I am happy to have an off-list phone call with you, if you like.
—
Mark Dilger
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 18:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-18 10:50 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-18 15:33 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-19 09:44 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-19 15:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-20 00:45 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-25 00:30 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-25 04:21 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-25 20:06 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-29 04:13 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-29 19:26 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-30 11:55 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-30 20:42 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-12-01 13:36 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-12-01 19:21 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-12-02 09:29 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-12-03 13:31 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-12-06 10:19 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-12-06 15:56 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-12-07 10:29 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-12-07 14:55 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
@ 2021-12-09 04:58 ` Amit Kapila <[email protected]>
2021-12-09 15:47 ` Re: Non-superuser subscription owners Robert Haas <[email protected]>
0 siblings, 1 reply; 68+ messages in thread
From: Amit Kapila @ 2021-12-09 04:58 UTC (permalink / raw)
To: Mark Dilger <[email protected]>; +Cc: Jeff Davis <[email protected]>; Andrew Dunstan <[email protected]>; pgsql-hackers; Robert Haas <[email protected]>
On Tue, Dec 7, 2021 at 8:25 PM Mark Dilger <[email protected]> wrote:
>
> > On Dec 7, 2021, at 2:29 AM, Amit Kapila <[email protected]> wrote:
> >
> > Okay, let me try to explain again. Following is the text from docs
> > [1]: " (a) To create a subscription, the user must be a superuser. (b)
> > The subscription apply process will run in the local database with the
> > privileges of a superuser. (c) Privileges are only checked once at the
> > start of a replication connection. They are not re-checked as each
> > change record is read from the publisher, nor are they re-checked for
> > each change when applied.
> >
> > My understanding is that we want to improve what is written as (c)
> > which I think is the same as what you mentioned later as "Fix the
> > current bug wherein subscription changes are applied with superuser
> > force after the subscription owner has superuser privileges revoked.".
> > Am I correct till here? If so, I think what I am suggesting should fix
> > this with the assumption that we still want to follow (b) at least for
> > the first patch.
>
> Ok, that's a point of disagreement. I was trying to fix both (b) and (c) in the first patch.
>
But, I think as soon as we are trying to fix (b), we seem to be
allowing non-superusers to apply changes. If we want to do that then
we should be even allowed to change the owners to non-superusers. I
was thinking of the below order:
1. First fix (c) from the above description "Privileges are only
checked once at the start of a replication connection."
2A. Allow the transfer of subscriptions to non-superuser owners. This
will be allowed only on disabled subscriptions to make this action
predictable.
2B. The apply worker should be able to apply the changes provided the
user has appropriate privileges on the objects being accessed by apply
worker.
3) Allow the creation of subscriptions by non-superusers who are
members of some as yet to be created predefined role, say
"pg_create_subscriptions"
We all seem to agree that (3) can be done later as an independent
project. 2A, 2B can be developed as separate patches but they need to
be considered together for commit. After 2A, 2B, the first one (1)
won't be required so, in fact, we can just ignore (1) but the only
benefit I see is that if we stuck with some design problem during the
development of 2A, 2B, we would have at least something better than
what we have now.
You seem to be indicating let's do 2B first as that will anyway be
used later after 2A and 1 won't be required if we do that. I see that
but I personally feel either we should follow 1, 2(A, B) or just do
2(A, B).
--
With Regards,
Amit Kapila.
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 18:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-18 10:50 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-18 15:33 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-19 09:44 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-19 15:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-20 00:45 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-25 00:30 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-25 04:21 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-25 20:06 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-29 04:13 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-29 19:26 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-30 11:55 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-30 20:42 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-12-01 13:36 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-12-01 19:21 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-12-02 09:29 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-12-03 13:31 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-12-06 10:19 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-12-06 15:56 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-12-07 10:29 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-12-07 14:55 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-12-09 04:58 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
@ 2021-12-09 15:47 ` Robert Haas <[email protected]>
2021-12-09 17:48 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
0 siblings, 1 reply; 68+ messages in thread
From: Robert Haas @ 2021-12-09 15:47 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: Mark Dilger <[email protected]>; Jeff Davis <[email protected]>; Andrew Dunstan <[email protected]>; pgsql-hackers
On Wed, Dec 8, 2021 at 11:58 PM Amit Kapila <[email protected]> wrote:
> But, I think as soon as we are trying to fix (b), we seem to be
> allowing non-superusers to apply changes. If we want to do that then
> we should be even allowed to change the owners to non-superusers. I
> was thinking of the below order:
> 1. First fix (c) from the above description "Privileges are only
> checked once at the start of a replication connection."
> 2A. Allow the transfer of subscriptions to non-superuser owners. This
> will be allowed only on disabled subscriptions to make this action
> predictable.
> 2B. The apply worker should be able to apply the changes provided the
> user has appropriate privileges on the objects being accessed by apply
> worker.
> 3) Allow the creation of subscriptions by non-superusers who are
> members of some as yet to be created predefined role, say
> "pg_create_subscriptions"
>
> We all seem to agree that (3) can be done later as an independent
> project. 2A, 2B can be developed as separate patches but they need to
> be considered together for commit. After 2A, 2B, the first one (1)
> won't be required so, in fact, we can just ignore (1) but the only
> benefit I see is that if we stuck with some design problem during the
> development of 2A, 2B, we would have at least something better than
> what we have now.
>
> You seem to be indicating let's do 2B first as that will anyway be
> used later after 2A and 1 won't be required if we do that. I see that
> but I personally feel either we should follow 1, 2(A, B) or just do
> 2(A, B).
1 and 2B seem to require changing the same code, or related code. 1A
seems to require a completely different set of changes. If I'm right
about that, it seems like a good reason for doing 1+2B first and
leaving 2A for a separate patch.
--
Robert Haas
EDB: http://www.enterprisedb.com
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 18:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-18 10:50 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-18 15:33 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-19 09:44 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-19 15:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-20 00:45 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-25 00:30 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-25 04:21 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-25 20:06 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-29 04:13 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-29 19:26 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-30 11:55 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-30 20:42 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-12-01 13:36 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-12-01 19:21 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-12-02 09:29 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-12-03 13:31 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-12-06 10:19 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-12-06 15:56 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-12-07 10:29 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-12-07 14:55 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-12-09 04:58 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-12-09 15:47 ` Re: Non-superuser subscription owners Robert Haas <[email protected]>
@ 2021-12-09 17:48 ` Mark Dilger <[email protected]>
0 siblings, 0 replies; 68+ messages in thread
From: Mark Dilger @ 2021-12-09 17:48 UTC (permalink / raw)
To: Robert Haas <[email protected]>; +Cc: Amit Kapila <[email protected]>; Jeff Davis <[email protected]>; Andrew Dunstan <[email protected]>; pgsql-hackers
> On Dec 9, 2021, at 7:47 AM, Robert Haas <[email protected]> wrote:
>
> 1 and 2B seem to require changing the same code, or related code. 1A
> seems to require a completely different set of changes. If I'm right
> about that, it seems like a good reason for doing 1+2B first and
> leaving 2A for a separate patch.
There are unresolved problems with 2A and 3 which were discussed upthread. I don't want to include fixes for them in this patch, as it greatly expands the scope of this patch, and is a logically separate effort. We can come back to those problems after this first patch is committed.
Specifically, a non-superuser owner can perform ALTER SUBSCRIPTION and do things that are morally equivalent to creating a new subscription. This is problematic where things like the connection string are concerned, because it means the non-superuser owner can connect out to entirely different servers, without any access control checks to make sure the owner should be able to connect to these servers.
This problem already exists, right now. I'm not fixing it in this first patch, but I'm also not making it any worse.
The solution Jeff Davis proposed seems right to me. We change subscriptions to use a foreign server rather than a freeform connection string. When creating or altering a subscription, the role performing the action must have privileges on any foreign server they use.
—
Mark Dilger
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 18:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-18 10:50 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-18 15:33 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-19 09:44 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-19 15:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-20 00:45 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-25 00:30 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-25 04:21 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-25 20:06 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-29 04:13 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-29 19:26 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-30 11:55 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
@ 2021-12-09 15:41 ` Robert Haas <[email protected]>
2021-12-09 17:22 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
1 sibling, 1 reply; 68+ messages in thread
From: Robert Haas @ 2021-12-09 15:41 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: Jeff Davis <[email protected]>; Mark Dilger <[email protected]>; Andrew Dunstan <[email protected]>; pgsql-hackers
On Tue, Nov 30, 2021 at 6:55 AM Amit Kapila <[email protected]> wrote:
> > This patch does detect ownership changes more quickly (at the
> > transaction boundary) than the current code (only when it reloads for
> > some other reason). Transaction boundary seems like a reasonable time
> > to detect the change to me.
> >
> > Detecting faster might be nice, but I don't have a strong opinion about
> > it and I don't see why it necessarily needs to happen before this patch
> > goes in.
>
> I think it would be better to do it before we allow subscription
> owners to be non-superusers.
I think it would be better not to ever do it at any time.
It seems like a really bad idea to me to change the run-as user in the
middle of a transaction. That seems prone to producing all sorts of
confusing behavior that's hard to understand, and hard to test. So
what are we to do if a change occurs mid-transaction? I think we can
either finish replicating the current transaction and then switch to
the new owner for the next transaction, or we could abort the current
attempt to replicate the transaction and retry the whole transaction
with the new run-as user. My guess is that most users would prefer the
former behavior to the latter.
--
Robert Haas
EDB: http://www.enterprisedb.com
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 18:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-18 10:50 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-18 15:33 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-19 09:44 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-19 15:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-20 00:45 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-25 00:30 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-25 04:21 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-25 20:06 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-29 04:13 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-29 19:26 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-30 11:55 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-12-09 15:41 ` Re: Non-superuser subscription owners Robert Haas <[email protected]>
@ 2021-12-09 17:22 ` Mark Dilger <[email protected]>
2021-12-10 04:15 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
0 siblings, 1 reply; 68+ messages in thread
From: Mark Dilger @ 2021-12-09 17:22 UTC (permalink / raw)
To: Robert Haas <[email protected]>; +Cc: Amit Kapila <[email protected]>; Jeff Davis <[email protected]>; Andrew Dunstan <[email protected]>; pgsql-hackers
> On Dec 9, 2021, at 7:41 AM, Robert Haas <[email protected]> wrote:
>
> On Tue, Nov 30, 2021 at 6:55 AM Amit Kapila <[email protected]> wrote:
>>> This patch does detect ownership changes more quickly (at the
>>> transaction boundary) than the current code (only when it reloads for
>>> some other reason). Transaction boundary seems like a reasonable time
>>> to detect the change to me.
>>>
>>> Detecting faster might be nice, but I don't have a strong opinion about
>>> it and I don't see why it necessarily needs to happen before this patch
>>> goes in.
>>
>> I think it would be better to do it before we allow subscription
>> owners to be non-superusers.
>
> I think it would be better not to ever do it at any time.
>
> It seems like a really bad idea to me to change the run-as user in the
> middle of a transaction.
I agree. We allow SET ROLE inside transactions, but faking one on the subscriber seems odd. No such role change was performed on the publisher side, nor is there a principled reason for assuming the old run-as role has membership in the new run-as role, so we'd be pretending to do something that might otherwise be impossible.
There was some discussion off-list about having the apply worker take out a lock on its subscription, thereby blocking ownership changes mid-transaction. I coded that and it seems to work fine, but I have a hard time seeing how the lock traffic would be worth expending. Between (a) changing roles mid-transaction, and (b) locking the subscription for each transaction, I'd prefer to do neither, but (b) seems far better than (a). Thoughts?
—
Mark Dilger
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 18:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-18 10:50 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-18 15:33 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-19 09:44 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-19 15:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-20 00:45 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-25 00:30 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-25 04:21 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-25 20:06 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-29 04:13 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-29 19:26 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-30 11:55 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-12-09 15:41 ` Re: Non-superuser subscription owners Robert Haas <[email protected]>
2021-12-09 17:22 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
@ 2021-12-10 04:15 ` Amit Kapila <[email protected]>
2021-12-10 14:09 ` Re: Non-superuser subscription owners Robert Haas <[email protected]>
0 siblings, 1 reply; 68+ messages in thread
From: Amit Kapila @ 2021-12-10 04:15 UTC (permalink / raw)
To: Mark Dilger <[email protected]>; +Cc: Robert Haas <[email protected]>; Jeff Davis <[email protected]>; Andrew Dunstan <[email protected]>; pgsql-hackers
On Thu, Dec 9, 2021 at 10:52 PM Mark Dilger
<[email protected]> wrote:
>
> > On Dec 9, 2021, at 7:41 AM, Robert Haas <[email protected]> wrote:
> >
> > On Tue, Nov 30, 2021 at 6:55 AM Amit Kapila <[email protected]> wrote:
> >>> This patch does detect ownership changes more quickly (at the
> >>> transaction boundary) than the current code (only when it reloads for
> >>> some other reason). Transaction boundary seems like a reasonable time
> >>> to detect the change to me.
> >>>
> >>> Detecting faster might be nice, but I don't have a strong opinion about
> >>> it and I don't see why it necessarily needs to happen before this patch
> >>> goes in.
> >>
> >> I think it would be better to do it before we allow subscription
> >> owners to be non-superusers.
> >
> > I think it would be better not to ever do it at any time.
> >
> > It seems like a really bad idea to me to change the run-as user in the
> > middle of a transaction.
>
> I agree. We allow SET ROLE inside transactions, but faking one on the subscriber seems odd. No such role change was performed on the publisher side, nor is there a principled reason for assuming the old run-as role has membership in the new run-as role, so we'd be pretending to do something that might otherwise be impossible.
>
> There was some discussion off-list about having the apply worker take out a lock on its subscription, thereby blocking ownership changes mid-transaction. I coded that and it seems to work fine, but I have a hard time seeing how the lock traffic would be worth expending. Between (a) changing roles mid-transaction, and (b) locking the subscription for each transaction, I'd prefer to do neither, but (b) seems far better than (a). Thoughts?
>
Yeah, to me also (b) sounds better than (a). However, a few points
that we might want to consider in that regard are as follows: 1.
locking the subscription for each transaction will add new blocking
areas considering we acquire AccessExclusiveLock to change any
property of subscription. But as Alter Subscription won't be that
frequent operation it might be acceptable. 2. It might lead to adding
some cost to small transactions but not sure if that will be
noticeable. 3. Tomorrow, if we want to make the apply-process parallel
(IIRC, we do have the patch for that somewhere in archives) especially
for large in-progress transactions then this locking will have
additional blocking w.r.t Altering Subscription. But again, this also
might be acceptable.
--
With Regards,
Amit Kapila.
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 18:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-18 10:50 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-18 15:33 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-19 09:44 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-19 15:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-20 00:45 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-25 00:30 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-25 04:21 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-25 20:06 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-29 04:13 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-29 19:26 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-30 11:55 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-12-09 15:41 ` Re: Non-superuser subscription owners Robert Haas <[email protected]>
2021-12-09 17:22 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-12-10 04:15 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
@ 2021-12-10 14:09 ` Robert Haas <[email protected]>
2021-12-10 15:20 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-12-11 04:55 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
0 siblings, 2 replies; 68+ messages in thread
From: Robert Haas @ 2021-12-10 14:09 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: Mark Dilger <[email protected]>; Jeff Davis <[email protected]>; Andrew Dunstan <[email protected]>; pgsql-hackers
On Thu, Dec 9, 2021 at 11:15 PM Amit Kapila <[email protected]> wrote:
> Yeah, to me also (b) sounds better than (a). However, a few points
> that we might want to consider in that regard are as follows: 1.
> locking the subscription for each transaction will add new blocking
> areas considering we acquire AccessExclusiveLock to change any
> property of subscription. But as Alter Subscription won't be that
> frequent operation it might be acceptable.
The problem isn't the cost of the locks taken by ALTER SUBSCRIPTION.
It's the cost of locking and unlocking the relation for every
transaction we apply. Suppose it's a pgbench-type workload with a
single UPDATE per transaction. You've just limited the maximum
possible apply speed to about, I think, 30,000 transactions per second
no matter how many parallel workers you use, because that's how fast
the lock manager is (or was, unless newer hardware or newer PG
versions have changed things in a way I don't know about). That seems
like a poor idea. There's nothing wrong with noticing changes at the
next transaction boundary, as long as we document it. So why would we
incur a possibly-significant performance cost to provide a stricter
guarantee?
I bet users wouldn't even like this behavior. It would mean that if
you are replicating a long-running transaction, an ALTER SUBSCRIPTION
command might block for a long time until replication of that
transaction completes. I have a hard time understanding why anyone
would consider that an improvement.
--
Robert Haas
EDB: http://www.enterprisedb.com
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 18:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-18 10:50 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-18 15:33 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-19 09:44 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-19 15:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-20 00:45 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-25 00:30 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-25 04:21 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-25 20:06 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-29 04:13 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-29 19:26 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-30 11:55 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-12-09 15:41 ` Re: Non-superuser subscription owners Robert Haas <[email protected]>
2021-12-09 17:22 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-12-10 04:15 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-12-10 14:09 ` Re: Non-superuser subscription owners Robert Haas <[email protected]>
@ 2021-12-10 15:20 ` Andrew Dunstan <[email protected]>
1 sibling, 0 replies; 68+ messages in thread
From: Andrew Dunstan @ 2021-12-10 15:20 UTC (permalink / raw)
To: Robert Haas <[email protected]>; Amit Kapila <[email protected]>; +Cc: Mark Dilger <[email protected]>; Jeff Davis <[email protected]>; pgsql-hackers
On 12/10/21 09:09, Robert Haas wrote:
> On Thu, Dec 9, 2021 at 11:15 PM Amit Kapila <[email protected]> wrote:
>> Yeah, to me also (b) sounds better than (a). However, a few points
>> that we might want to consider in that regard are as follows: 1.
>> locking the subscription for each transaction will add new blocking
>> areas considering we acquire AccessExclusiveLock to change any
>> property of subscription. But as Alter Subscription won't be that
>> frequent operation it might be acceptable.
> The problem isn't the cost of the locks taken by ALTER SUBSCRIPTION.
> It's the cost of locking and unlocking the relation for every
> transaction we apply. Suppose it's a pgbench-type workload with a
> single UPDATE per transaction. You've just limited the maximum
> possible apply speed to about, I think, 30,000 transactions per second
> no matter how many parallel workers you use, because that's how fast
> the lock manager is (or was, unless newer hardware or newer PG
> versions have changed things in a way I don't know about). That seems
> like a poor idea. There's nothing wrong with noticing changes at the
> next transaction boundary, as long as we document it. So why would we
> incur a possibly-significant performance cost to provide a stricter
> guarantee?
>
> I bet users wouldn't even like this behavior. It would mean that if
> you are replicating a long-running transaction, an ALTER SUBSCRIPTION
> command might block for a long time until replication of that
> transaction completes. I have a hard time understanding why anyone
> would consider that an improvement.
>
+1
I think noticing changes at the transaction boundary is perfectly
acceptable.
cheers
andrew
--
Andrew Dunstan
EDB: https://www.enterprisedb.com
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 18:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-18 10:50 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-18 15:33 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-19 09:44 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-19 15:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-20 00:45 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-25 00:30 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-25 04:21 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-25 20:06 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-29 04:13 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-29 19:26 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-30 11:55 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-12-09 15:41 ` Re: Non-superuser subscription owners Robert Haas <[email protected]>
2021-12-09 17:22 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-12-10 04:15 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-12-10 14:09 ` Re: Non-superuser subscription owners Robert Haas <[email protected]>
@ 2021-12-11 04:55 ` Amit Kapila <[email protected]>
1 sibling, 0 replies; 68+ messages in thread
From: Amit Kapila @ 2021-12-11 04:55 UTC (permalink / raw)
To: Robert Haas <[email protected]>; +Cc: Mark Dilger <[email protected]>; Jeff Davis <[email protected]>; Andrew Dunstan <[email protected]>; pgsql-hackers
On Fri, Dec 10, 2021 at 7:39 PM Robert Haas <[email protected]> wrote:
>
> On Thu, Dec 9, 2021 at 11:15 PM Amit Kapila <[email protected]> wrote:
> > Yeah, to me also (b) sounds better than (a). However, a few points
> > that we might want to consider in that regard are as follows: 1.
> > locking the subscription for each transaction will add new blocking
> > areas considering we acquire AccessExclusiveLock to change any
> > property of subscription. But as Alter Subscription won't be that
> > frequent operation it might be acceptable.
>
> The problem isn't the cost of the locks taken by ALTER SUBSCRIPTION.
> It's the cost of locking and unlocking the relation for every
> transaction we apply.
>
This point is not clear to me as we are already locking the relation
while applying changes. I think here additional cost is to lock a
particular subscription as well in addition to the relation on which
we are going to perform apply. I agree that has a cost and that is why
I mentioned it as one of the points above and then also the
concurrency effect as you also noted could make this idea moot.
> Suppose it's a pgbench-type workload with a
> single UPDATE per transaction. You've just limited the maximum
> possible apply speed to about, I think, 30,000 transactions per second
> no matter how many parallel workers you use, because that's how fast
> the lock manager is (or was, unless newer hardware or newer PG
> versions have changed things in a way I don't know about). That seems
> like a poor idea. There's nothing wrong with noticing changes at the
> next transaction boundary, as long as we document it.
>
If we want to just document this then I think we should also keep in
mind that these could be N transactions as well if say tomorrow we
have N parallel apply workers applying the N transactions in parallel.
I think it might also be possible that RLS policies won't be applied
for initial table sync whereas those will be applied for later changes
even though the ownership has changed before both operations and one
of those happens to miss it. If that is possible, then it might be
better to avoid the same as it could appear inconsistent as mentioned
by Mark [1] as well. Now, it might be possible to avoid this by
implementation or we can say that we don't care about this or just
document it. But it seems to me that if we have some way to detect the
change of ownership at each operation level then no such possibilities
would arise.
The other alternative we discussed was to allow a change of ownership
on disabled subscriptions that way the apply behavior will always be
predictable.
There is clearly a merit in noticing the change of ownership at
transaction boundary but just wanted to consider other possibilities.
It could be that detecting at transaction-boundary is the best we can
do but I think there is no harm in considering other possibilities.
> So why would we
> incur a possibly-significant performance cost to provide a stricter
> guarantee?
>
> I bet users wouldn't even like this behavior. It would mean that if
> you are replicating a long-running transaction, an ALTER SUBSCRIPTION
> command might block for a long time until replication of that
> transaction completes.
>
Agreed and if we decide to lock the subscription during the initial
table sync phase then that could also take a long time for which again
users might not be happy.
[1] - https://www.postgresql.org/message-id/FE7D7024-6723-4ACB-82AB-94F6A194BE0D%40enterprisedb.com
--
With Regards,
Amit Kapila.
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 18:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-18 10:50 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-18 15:33 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-19 09:44 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-19 15:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-20 00:45 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-25 00:30 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
@ 2021-11-27 18:05 ` Mark Dilger <[email protected]>
2021-11-29 05:56 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2 siblings, 1 reply; 68+ messages in thread
From: Mark Dilger @ 2021-11-27 18:05 UTC (permalink / raw)
To: Jeff Davis <[email protected]>; +Cc: Amit Kapila <[email protected]>; Andrew Dunstan <[email protected]>; pgsql-hackers; Robert Haas <[email protected]>
> On Nov 24, 2021, at 4:30 PM, Jeff Davis <[email protected]> wrote:
>
> We need to do permission checking for WITH CHECK OPTION and RLS. The
> patch right now allows the subscription to write data that an RLS
> policy forbids.
Thanks for reviewing and for this observation! I can verify that RLS is not being honored on the subscriber side. I agree this is a problem for subscriptions owned by non-superusers.
The implementation of the table sync worker uses COPY FROM, which makes this problem hard to fix, because COPY FROM does not support row level security. We could do some work to honor the RLS policies during the apply workers' INSERT statements, but then some data would circumvent RLS during table sync and other data would honor RLS during worker apply, which would make the implementation not only wrong but inconsistently so.
I think a more sensible approach for v15 is to raise an ERROR if a non-superuser owned subscription is trying to replicate into a table which has RLS enabled. We might try to be more clever and check whether the RLS policies could possibly reject the operation (by comparing the TO and FOR clauses of the policies against the role and operation type) but that seems like a partial re-implementation of RLS. It would be simpler and more likely correct if we just unconditionally reject replicating into tables which have RLS enabled.
What do you think?
> A couple other points:
>
> * We shouldn't refer to the behavior of previous versions in the docs
> unless there's a compelling reason
Fair enough.
> * Do we need to be smarter about partitioned tables, where an insert
> can turn into an update?
Do you mean an INSERT statement with an ON CONFLICT DO UPDATE clause that is running against a partitioned table? If so, I don't think we need to handle that on the subscriber side under the current logical replication design. I would expect the plain INSERT or UPDATE that ultimately executes on the publisher to be what gets replicated to the subscriber, and not the original INSERT .. ON CONFLICT DO UPDATE statement.
> * Should we refactor to borrow logic from ExecInsert so that it's less
> likely that we miss something in the future?
Hooking into the executor at a higher level, possibly ExecInsert or ExecModifyTable would do a lot more than what logical replication currently does. If we also always used INSERT/UPDATE/DELETE statements and never COPY FROM statements, we might solve several problems at once, including honoring RLS policies and honoring rules defined for the target table on the subscriber side.
Doing this would clearly be a major design change, and possibly one we do not want. Can we consider this out of scope?
—
Mark Dilger
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 18:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-18 10:50 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-18 15:33 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-19 09:44 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-19 15:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-20 00:45 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-25 00:30 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-27 18:05 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
@ 2021-11-29 05:56 ` Amit Kapila <[email protected]>
2021-11-29 16:26 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
0 siblings, 1 reply; 68+ messages in thread
From: Amit Kapila @ 2021-11-29 05:56 UTC (permalink / raw)
To: Mark Dilger <[email protected]>; +Cc: Jeff Davis <[email protected]>; Andrew Dunstan <[email protected]>; pgsql-hackers; Robert Haas <[email protected]>
On Sat, Nov 27, 2021 at 11:37 PM Mark Dilger
<[email protected]> wrote:
>
>
>
> > On Nov 24, 2021, at 4:30 PM, Jeff Davis <[email protected]> wrote:
> >
> > We need to do permission checking for WITH CHECK OPTION and RLS. The
> > patch right now allows the subscription to write data that an RLS
> > policy forbids.
>
> Thanks for reviewing and for this observation! I can verify that RLS is not being honored on the subscriber side. I agree this is a problem for subscriptions owned by non-superusers.
>
...
>
> > A couple other points:
> >
>
> > * Do we need to be smarter about partitioned tables, where an insert
> > can turn into an update?
>
> Do you mean an INSERT statement with an ON CONFLICT DO UPDATE clause that is running against a partitioned table? If so, I don't think we need to handle that on the subscriber side under the current logical replication design. I would expect the plain INSERT or UPDATE that ultimately executes on the publisher to be what gets replicated to the subscriber, and not the original INSERT .. ON CONFLICT DO UPDATE statement.
>
Yeah, that is correct but I think the update case is more relevant
here. In ExecUpdate(), we convert Update to DELETE+INSERT when the
partition constraint is failed whereas, on the subscriber-side, it
will simply fail in this case. It is not clear to me how that is
directly related to this patch but surely it will be a good
improvement on its own and might help if that requires us to change
some infrastructure here like hooking into executor at a higher level.
> > * Should we refactor to borrow logic from ExecInsert so that it's less
> > likely that we miss something in the future?
>
> Hooking into the executor at a higher level, possibly ExecInsert or ExecModifyTable would do a lot more than what logical replication currently does. If we also always used INSERT/UPDATE/DELETE statements and never COPY FROM statements, we might solve several problems at once, including honoring RLS policies and honoring rules defined for the target table on the subscriber side.
>
> Doing this would clearly be a major design change, and possibly one we do not want. Can we consider this out of scope?
>
I agree that if we want to do all of this then that would require a
lot of changes. However, giving an error for RLS-enabled tables might
also be too restrictive. The few alternatives could be that (a) we
allow subscription owners to be either have "bypassrls" attribute or
they could be superusers. (b) don't allow initial table_sync for rls
enabled tables. (c) evaluate/analyze what is required to allow Copy
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 18:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-18 10:50 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-18 15:33 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-19 09:44 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-19 15:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-20 00:45 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-25 00:30 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-27 18:05 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-29 05:56 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
@ 2021-11-29 16:26 ` Mark Dilger <[email protected]>
2021-11-29 18:22 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
0 siblings, 1 reply; 68+ messages in thread
From: Mark Dilger @ 2021-11-29 16:26 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: Jeff Davis <[email protected]>; Andrew Dunstan <[email protected]>; pgsql-hackers; Robert Haas <[email protected]>
> On Nov 28, 2021, at 9:56 PM, Amit Kapila <[email protected]> wrote:
>
> In ExecUpdate(), we convert Update to DELETE+INSERT when the
> partition constraint is failed whereas, on the subscriber-side, it
> will simply fail in this case. It is not clear to me how that is
> directly related to this patch but surely it will be a good
> improvement on its own and might help if that requires us to change
> some infrastructure here like hooking into executor at a higher level.
I would rather get a fix for non-superuser subscription owners committed than expand the scope of work and have this patch linger until the v16 development cycle. This particular DELETE+INSERT problem sounds important but unrelated and out of scope.
> I agree that if we want to do all of this then that would require a
> lot of changes. However, giving an error for RLS-enabled tables might
> also be too restrictive. The few alternatives could be that (a) we
> allow subscription owners to be either have "bypassrls" attribute or
> they could be superusers. (b) don't allow initial table_sync for rls
> enabled tables. (c) evaluate/analyze what is required to allow Copy
> From to start respecting RLS policies. (d) reject replicating any
> changes to tables that have RLS enabled.
>
> I see that you are favoring (d) which clearly has merits like lesser
> code/design change but not sure if that is the best way forward or we
> can do something better than that either by following one of (a), (b),
> (c), or something less restrictive than (d).
I was favoring option (d) only when RLS policies exist for one or more of the target relations.
Skipping the table_sync step while replicating tables that have RLS policies for subscriptions that are owned by users who lack bypassrls is interesting. If we make that work, it will be a more complete solution than option (d).
—
Mark Dilger
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 18:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-18 10:50 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-18 15:33 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-19 09:44 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-19 15:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-20 00:45 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-25 00:30 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-27 18:05 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-29 05:56 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-29 16:26 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
@ 2021-11-29 18:22 ` Jeff Davis <[email protected]>
2021-11-30 11:49 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
0 siblings, 1 reply; 68+ messages in thread
From: Jeff Davis @ 2021-11-29 18:22 UTC (permalink / raw)
To: Mark Dilger <[email protected]>; Amit Kapila <[email protected]>; +Cc: Andrew Dunstan <[email protected]>; pgsql-hackers; Robert Haas <[email protected]>
On Mon, 2021-11-29 at 08:26 -0800, Mark Dilger wrote:
> > On Nov 28, 2021, at 9:56 PM, Amit Kapila <[email protected]>
> > wrote:
> >
> > In ExecUpdate(), we convert Update to DELETE+INSERT when the
> > partition constraint is failed whereas, on the subscriber-side, it
> > will simply fail in this case.
Thank you, yes, that's the more important case.
> This particular DELETE+INSERT problem sounds important but unrelated
> and out of scope.
+1
> > I agree that if we want to do all of this then that would require a
> > lot of changes. However, giving an error for RLS-enabled tables
> > might
> > also be too restrictive. The few alternatives could be that (a) we
> > allow subscription owners to be either have "bypassrls" attribute
> > or
> > they could be superusers. (b) don't allow initial table_sync for
> > rls
> > enabled tables. (c) evaluate/analyze what is required to allow Copy
> > From to start respecting RLS policies. (d) reject replicating any
> > changes to tables that have RLS enabled.
Maybe a combination?
Allow subscriptions with copy_data=true iff the subscription owner is
bypassrls or superuser. And then enforce RLS+WCO during
insert/update/delete.
I don't think it's a big change (correct me if I'm wrong), and it
allows good functionality now, and room to improve in the future if we
want to bring in more of ExecInsert into logical replication.
Regards,
Jeff Davis
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 18:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-18 10:50 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-18 15:33 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-19 09:44 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-19 15:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-20 00:45 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-25 00:30 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-27 18:05 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-29 05:56 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-29 16:26 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-29 18:22 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
@ 2021-11-30 11:49 ` Amit Kapila <[email protected]>
0 siblings, 0 replies; 68+ messages in thread
From: Amit Kapila @ 2021-11-30 11:49 UTC (permalink / raw)
To: Jeff Davis <[email protected]>; +Cc: Mark Dilger <[email protected]>; Andrew Dunstan <[email protected]>; pgsql-hackers; Robert Haas <[email protected]>
On Mon, Nov 29, 2021 at 11:52 PM Jeff Davis <[email protected]> wrote:
>
> On Mon, 2021-11-29 at 08:26 -0800, Mark Dilger wrote:
>
> > > I agree that if we want to do all of this then that would require a
> > > lot of changes. However, giving an error for RLS-enabled tables
> > > might
> > > also be too restrictive. The few alternatives could be that (a) we
> > > allow subscription owners to be either have "bypassrls" attribute
> > > or
> > > they could be superusers. (b) don't allow initial table_sync for
> > > rls
> > > enabled tables. (c) evaluate/analyze what is required to allow Copy
> > > From to start respecting RLS policies. (d) reject replicating any
> > > changes to tables that have RLS enabled.
>
> Maybe a combination?
>
> Allow subscriptions with copy_data=true iff the subscription owner is
> bypassrls or superuser. And then enforce RLS+WCO during
> insert/update/delete.
>
Yeah, that sounds reasonable to me.
> I don't think it's a big change (correct me if I'm wrong),
>
Yeah, I also don't think it should be a big change.
--
With Regards,
Amit Kapila.
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 18:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-18 10:50 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-18 15:33 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-19 09:44 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-19 15:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-20 00:45 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-25 00:30 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
@ 2021-12-15 20:23 ` Mark Dilger <[email protected]>
2 siblings, 0 replies; 68+ messages in thread
From: Mark Dilger @ 2021-12-15 20:23 UTC (permalink / raw)
To: Jeff Davis <[email protected]>; +Cc: Amit Kapila <[email protected]>; Andrew Dunstan <[email protected]>; pgsql-hackers; Robert Haas <[email protected]>
> On Nov 24, 2021, at 4:30 PM, Jeff Davis <[email protected]> wrote:
>
> We need to do permission checking for WITH CHECK OPTION and RLS. The
> patch right now allows the subscription to write data that an RLS
> policy forbids.
Version 4 of the patch, attached, no longer allows RLS to be circumvented, but does so in a course-grained fashion. If the target table has row-level security policies which are enforced against the subscription owner, the replication draws an error, much as with a permissions failure. This seems sufficient for now, as superusers, roles with bypassrls, and target table owners should be able to replicate as before. We may want to revisit this later, perhaps if/when we address your ExecInsert question, below.
>
> A couple other points:
>
> * We shouldn't refer to the behavior of previous versions in the docs
> unless there's a compelling reason
Fixed.
> * Do we need to be smarter about partitioned tables, where an insert
> can turn into an update?
Indeed, the logic of apply_handle_tuple_routing() required a bit of refactoring. Fixed in v4.
> * Should we refactor to borrow logic from ExecInsert so that it's less
> likely that we miss something in the future?
Let's just punt on this for now.
—
Mark Dilger
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
Attachments:
[application/octet-stream] v4-0001-Respect-permissions-within-logical-replication.patch (25.9K, ../../[email protected]/2-v4-0001-Respect-permissions-within-logical-replication.patch)
download | inline diff:
From 03ee011cc72768efbdd3e69eb2dcac7ed21ca0c7 Mon Sep 17 00:00:00 2001
From: Mark Dilger <[email protected]>
Date: Fri, 19 Nov 2021 16:08:40 -0800
Subject: [PATCH v4] Respect permissions within logical replication
Prevent logical replication workers from performing insert, update,
delete, truncate, or copy commands on tables unless the subscription
owner has permission to do so.
Prevent subscription owners from circumventing row-level security by
forbidding replication into tables with row-level security policies
which the subscription owner is subject to, without regard to
whether the policy would ordinary allow the INSERT, UPDATE, DELETE
or TRUNCATE which is being replicated. This seems sufficient for
now, as superusers, roles with bypassrls, and target table owners
should still be able to replicate despite RLS policies. We can
revisit the question of applying row-level security policies on a
per-row basis if this restriction proves too severe in practice.
---
doc/src/sgml/logical-replication.sgml | 36 +-
src/backend/commands/subscriptioncmds.c | 2 +
src/backend/replication/logical/tablesync.c | 28 ++
src/backend/replication/logical/worker.c | 42 +++
src/test/perl/PostgreSQL/Test/Cluster.pm | 36 ++
src/test/subscription/t/027_nosuperuser.pl | 363 ++++++++++++++++++++
6 files changed, 499 insertions(+), 8 deletions(-)
create mode 100644 src/test/subscription/t/027_nosuperuser.pl
diff --git a/doc/src/sgml/logical-replication.sgml b/doc/src/sgml/logical-replication.sgml
index 45b2e1e28f..4f70b1f4b8 100644
--- a/doc/src/sgml/logical-replication.sgml
+++ b/doc/src/sgml/logical-replication.sgml
@@ -330,6 +330,19 @@
will simply be skipped.
</para>
+ <para>
+ Logical replication operations are performed with the privileges of the role
+ which owns the subscription. Permissions failures on target tables will
+ cause replication conflicts, as will enabled
+ <link linkend="ddl-rowsecurity">row-level security</link> on target tables
+ that the subscription owner is subject to, without regard to whether any
+ policy would ordinary reject the <command>INSERT</command>,
+ <command>UPDATE</command>, <command>DELETE</command> or
+ <command>TRUNCATE</command> which is being replicated. This restriction on
+ row-level security may be lifted in a future version of
+ <productname>PostgreSQL</productname>.
+ </para>
+
<para>
A conflict will produce an error and will stop the replication; it must be
resolved manually by the user. Details about the conflict can be found in
@@ -337,7 +350,7 @@
</para>
<para>
- The resolution can be done either by changing data on the subscriber so
+ The resolution can be done either by changing data or permissions on the subscriber so
that it does not conflict with the incoming change or by skipping the
transaction that conflicts with the existing data. The transaction can be
skipped by calling the <link linkend="pg-replication-origin-advance">
@@ -530,9 +543,9 @@
<para>
A user able to modify the schema of subscriber-side tables can execute
- arbitrary code as a superuser. Limit ownership
- and <literal>TRIGGER</literal> privilege on such tables to roles that
- superusers trust. Moreover, if untrusted users can create tables, use only
+ arbitrary code as the role which owns any subscription which modifies those tables. Limit ownership
+ and <literal>TRIGGER</literal> privilege on such tables to trusted roles.
+ Moreover, if untrusted users can create tables, use only
publications that list tables explicitly. That is to say, create a
subscription <literal>FOR ALL TABLES</literal> or
<literal>FOR ALL TABLES IN SCHEMA</literal> only when superusers trust
@@ -576,13 +589,20 @@
<para>
The subscription apply process will run in the local database with the
- privileges of a superuser.
+ privileges of the subscription owner.
+ </para>
+
+ <para>
+ On the publisher, privileges are only checked once at the start of a
+ replication connection and are not re-checked as each change record is read.
</para>
<para>
- Privileges are only checked once at the start of a replication connection.
- They are not re-checked as each change record is read from the publisher,
- nor are they re-checked for each change when applied.
+ On the subscriber, the subscription owner's privileges are re-checked for
+ each transaction when applied. If a worker is in the process of applying a
+ transaction when the ownership of the subscription is changed by a
+ concurrent transaction, the application of the current transaction will
+ continue under the old owner's privileges.
</para>
</sect1>
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index 2b658080fe..e33f26e6cf 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -1481,6 +1481,8 @@ AlterSubscriptionOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
InvokeObjectPostAlterHook(SubscriptionRelationId,
form->oid, 0);
+
+ ApplyLauncherWakeupAtCommit();
}
/*
diff --git a/src/backend/replication/logical/tablesync.c b/src/backend/replication/logical/tablesync.c
index f07983a43c..d44ccdc0de 100644
--- a/src/backend/replication/logical/tablesync.c
+++ b/src/backend/replication/logical/tablesync.c
@@ -111,9 +111,11 @@
#include "replication/origin.h"
#include "storage/ipc.h"
#include "storage/lmgr.h"
+#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
+#include "utils/rls.h"
#include "utils/snapmgr.h"
#include "utils/syscache.h"
@@ -924,6 +926,7 @@ LogicalRepSyncTableStart(XLogRecPtr *origin_startpos)
char relstate;
XLogRecPtr relstate_lsn;
Relation rel;
+ AclResult aclresult;
WalRcvExecResult *res;
char originname[NAMEDATALEN];
RepOriginId originid;
@@ -1042,6 +1045,31 @@ LogicalRepSyncTableStart(XLogRecPtr *origin_startpos)
*/
rel = table_open(MyLogicalRepWorker->relid, RowExclusiveLock);
+ /*
+ * Check that our table sync worker has permission to insert into the
+ * target table.
+ */
+ aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(),
+ ACL_INSERT);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult,
+ get_relkind_objtype(rel->rd_rel->relkind),
+ RelationGetRelationName(rel));
+
+ /*
+ * COPY FROM does not honor RLS policies. That is not a problem for
+ * subscriptions owned by roles with BYPASSRLS privilege (or superuser, who
+ * has it implicitly), but other roles should not be able to circumvent
+ * RLS. Disallow logical replication into RLS enabled relations for such
+ * roles.
+ */
+ if (check_enable_rls(RelationGetRelid(rel), InvalidOid, false) == RLS_ENABLED)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("\"%s\" cannot replicate into relation with row-level security enabled: \"%s\"",
+ GetUserNameFromId(GetUserId(), true),
+ RelationGetRelationName(rel))));
+
/*
* Start a transaction in the remote node in REPEATABLE READ mode. This
* ensures that both the replication slot we create (see below) and the
diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c
index 2e79302a48..188eeb80aa 100644
--- a/src/backend/replication/logical/worker.c
+++ b/src/backend/replication/logical/worker.c
@@ -179,6 +179,7 @@
#include "storage/proc.h"
#include "storage/procarray.h"
#include "tcop/tcopprot.h"
+#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/catcache.h"
#include "utils/dynahash.h"
@@ -189,6 +190,7 @@
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/rel.h"
+#include "utils/rls.h"
#include "utils/syscache.h"
#include "utils/timeout.h"
@@ -1530,6 +1532,38 @@ GetRelationIdentityOrPK(Relation rel)
return idxoid;
}
+/*
+ * Check that we (the subscription owner) have sufficient privileges on the
+ * target relation to perform the given operation.
+ */
+static void
+TargetPrivilegesCheck(Relation rel, AclMode mode)
+{
+ Oid relid;
+ AclResult aclresult;
+
+ relid = RelationGetRelid(rel);
+ aclresult = pg_class_aclcheck(relid, GetUserId(), mode);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult,
+ get_relkind_objtype(rel->rd_rel->relkind),
+ get_rel_name(relid));
+
+ /*
+ * We lack the infrastructure to honor RLS policies. It might be possible
+ * to add such infrastructure here, but tablesync workers lack it, too, so
+ * we don't bother. RLS does not ordinarily apply to TRUNCATE commands,
+ * but it seems dangerous to replicate a TRUNCATE and then refuse to
+ * replicate subsequent INSERTs, so we forbid all commands the same.
+ */
+ if (check_enable_rls(relid, InvalidOid, false) == RLS_ENABLED)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("\"%s\" cannot replicate into relation with row-level security enabled: \"%s\"",
+ GetUserNameFromId(GetUserId(), true),
+ RelationGetRelationName(rel))));
+}
+
/*
* Handle INSERT message.
*/
@@ -1613,6 +1647,7 @@ apply_handle_insert_internal(ApplyExecutionData *edata,
ExecOpenIndices(relinfo, false);
/* Do the insert. */
+ TargetPrivilegesCheck(relinfo->ri_RelationDesc, ACL_INSERT);
ExecSimpleRelationInsert(relinfo, estate, remoteslot);
/* Cleanup. */
@@ -1796,6 +1831,7 @@ apply_handle_update_internal(ApplyExecutionData *edata,
EvalPlanQualSetSlot(&epqstate, remoteslot);
/* Do the actual update. */
+ TargetPrivilegesCheck(relinfo->ri_RelationDesc, ACL_UPDATE);
ExecSimpleRelationUpdate(relinfo, estate, &epqstate, localslot,
remoteslot);
}
@@ -1917,6 +1953,7 @@ apply_handle_delete_internal(ApplyExecutionData *edata,
EvalPlanQualSetSlot(&epqstate, localslot);
/* Do the actual delete. */
+ TargetPrivilegesCheck(relinfo->ri_RelationDesc, ACL_DELETE);
ExecSimpleRelationDelete(relinfo, estate, &epqstate, localslot);
}
else
@@ -2110,6 +2147,8 @@ apply_handle_tuple_routing(ApplyExecutionData *edata,
ExecOpenIndices(partrelinfo, false);
EvalPlanQualSetSlot(&epqstate, remoteslot_part);
+ TargetPrivilegesCheck(partrelinfo->ri_RelationDesc,
+ ACL_UPDATE);
ExecSimpleRelationUpdate(partrelinfo, estate, &epqstate,
localslot, remoteslot_part);
ExecCloseIndices(partrelinfo);
@@ -2236,6 +2275,7 @@ apply_handle_truncate(StringInfo s)
}
remote_rels = lappend(remote_rels, rel);
+ TargetPrivilegesCheck(rel->localrel, ACL_TRUNCATE);
rels = lappend(rels, rel->localrel);
relids = lappend_oid(relids, rel->localreloid);
if (RelationIsLogicallyLogged(rel->localrel))
@@ -2273,6 +2313,7 @@ apply_handle_truncate(StringInfo s)
continue;
}
+ TargetPrivilegesCheck(childrel, ACL_TRUNCATE);
rels = lappend(rels, childrel);
part_rels = lappend(part_rels, childrel);
relids = lappend_oid(relids, childrelid);
@@ -2915,6 +2956,7 @@ maybe_reread_subscription(void)
strcmp(newsub->slotname, MySubscription->slotname) != 0 ||
newsub->binary != MySubscription->binary ||
newsub->stream != MySubscription->stream ||
+ newsub->owner != MySubscription->owner ||
!equal(newsub->publications, MySubscription->publications))
{
ereport(LOG,
diff --git a/src/test/perl/PostgreSQL/Test/Cluster.pm b/src/test/perl/PostgreSQL/Test/Cluster.pm
index c061e850fb..6f38be031d 100644
--- a/src/test/perl/PostgreSQL/Test/Cluster.pm
+++ b/src/test/perl/PostgreSQL/Test/Cluster.pm
@@ -2599,6 +2599,42 @@ sub wait_for_slot_catchup
=pod
+=item $node->wait_for_log(regexp, offset)
+
+Waits for the contents of the server log file, starting at the given offset, to
+match the supplied regular expression. Checks the entire log if no offset is
+given. Times out after 180 seconds.
+
+If successful, returns the length of the entire log file, in bytes.
+
+=cut
+
+sub wait_for_log
+{
+ my ($self, $regexp, $offset) = @_;
+ $offset = 0 unless defined $offset;
+
+ my $max_attempts = 180 * 10;
+ my $attempts = 0;
+
+ while ($attempts < $max_attempts)
+ {
+ my $log = PostgreSQL::Test::Utils::slurp_file($self->logfile, $offset);
+
+ return $offset+length($log) if ($log =~ m/$regexp/);
+
+ # Wait 0.1 second before retrying.
+ usleep(100_000);
+
+ $attempts++;
+ }
+
+ # The logs didn't match within 180 seconds. Give up.
+ croak "timed out waiting for match: $regexp";
+}
+
+=pod
+
=item $node->query_hash($dbname, $query, @columns)
Execute $query on $dbname, replacing any appearance of the string __COLUMNS__
diff --git a/src/test/subscription/t/027_nosuperuser.pl b/src/test/subscription/t/027_nosuperuser.pl
new file mode 100644
index 0000000000..742a745cf7
--- /dev/null
+++ b/src/test/subscription/t/027_nosuperuser.pl
@@ -0,0 +1,363 @@
+
+# Copyright (c) 2021, PostgreSQL Global Development Group
+
+# Test that logical replication respects permissions
+use strict;
+use warnings;
+use PostgreSQL::Test::Cluster;
+use Test::More tests => 100;
+
+my ($node_publisher, $node_subscriber, $publisher_connstr, $result, $offset);
+$offset = 0;
+
+sub publish_insert($$)
+{
+ my ($tbl, $new_i) = @_;
+ $node_publisher->safe_psql('postgres', qq(
+ SET SESSION AUTHORIZATION regress_alice;
+ INSERT INTO $tbl (i) VALUES ($new_i);
+ ));
+}
+
+sub publish_update($$$)
+{
+ my ($tbl, $old_i, $new_i) = @_;
+ $node_publisher->safe_psql('postgres', qq(
+ SET SESSION AUTHORIZATION regress_alice;
+ UPDATE $tbl SET i = $new_i WHERE i = $old_i;
+ ));
+}
+
+sub publish_delete($$)
+{
+ my ($tbl, $old_i) = @_;
+ $node_publisher->safe_psql('postgres', qq(
+ SET SESSION AUTHORIZATION regress_alice;
+ DELETE FROM $tbl WHERE i = $old_i;
+ ));
+}
+
+sub expect_replication($$$$$)
+{
+ my ($tbl, $cnt, $min, $max, $testname) = @_;
+ $node_publisher->wait_for_catchup('admin_sub');
+ $result = $node_subscriber->safe_psql('postgres', qq(
+ SELECT COUNT(i), MIN(i), MAX(i) FROM $tbl));
+ is ($result, "$cnt|$min|$max", $testname);
+}
+
+sub expect_failure($$$$$$)
+{
+ my ($tbl, $cnt, $min, $max, $re, $testname) = @_;
+ $offset = $node_subscriber->wait_for_log($re, $offset);
+ $result = $node_subscriber->safe_psql('postgres', qq(
+ SELECT COUNT(i), MIN(i), MAX(i) FROM $tbl));
+ is ($result, "$cnt|$min|$max", $testname);
+}
+
+sub revoke_superuser($)
+{
+ my ($role) = @_;
+ $node_subscriber->safe_psql('postgres', qq(
+ ALTER ROLE $role NOSUPERUSER));
+}
+
+sub grant_superuser($)
+{
+ my ($role) = @_;
+ $node_subscriber->safe_psql('postgres', qq(
+ ALTER ROLE $role SUPERUSER));
+}
+
+sub revoke_bypassrls($)
+{
+ my ($role) = @_;
+ $node_subscriber->safe_psql('postgres', qq(
+ ALTER ROLE $role NOBYPASSRLS));
+}
+
+sub grant_bypassrls($)
+{
+ my ($role) = @_;
+ $node_subscriber->safe_psql('postgres', qq(
+ ALTER ROLE $role BYPASSRLS));
+}
+
+# Create publisher and subscriber nodes with schemas owned and published by
+# "regress_alice" but subscribed and replicated by different role
+# "regress_admin". For partitioned tables, layout the partitions differently
+# on the publisher than on the subscriber.
+#
+$node_publisher = PostgreSQL::Test::Cluster->new('publisher');
+$node_subscriber = PostgreSQL::Test::Cluster->new('subscriber');
+$node_publisher->init(allows_streaming => 'logical');
+$node_subscriber->init;
+$node_publisher->start;
+$node_subscriber->start;
+$publisher_connstr = $node_publisher->connstr . ' dbname=postgres';
+my %range_a = (
+ publisher => 'FROM (0) TO (15)',
+ subscriber => 'FROM (0) TO (5)');
+my %range_b = (
+ publisher => 'FROM (15) TO (30)',
+ subscriber => 'FROM (5) TO (30)');
+my %list_a = (
+ publisher => 'IN (1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29)',
+ subscriber => 'IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)',
+);
+my %list_b = (
+ publisher => 'IN (2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30)',
+ subscriber => 'IN (17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30)');
+my %remainder_a = (
+ publisher => 0,
+ subscriber => 1);
+my %remainder_b = (
+ publisher => 1,
+ subscriber => 0);
+
+for my $node ($node_publisher, $node_subscriber)
+{
+ my $range_a = $range_a{$node->name};
+ my $range_b = $range_b{$node->name};
+ my $list_a = $list_a{$node->name};
+ my $list_b = $list_b{$node->name};
+ my $remainder_a = $remainder_a{$node->name};
+ my $remainder_b = $remainder_b{$node->name};
+ $node->safe_psql('postgres', qq(
+ CREATE ROLE regress_admin SUPERUSER LOGIN;
+ CREATE ROLE regress_alice NOSUPERUSER LOGIN;
+ GRANT CREATE ON DATABASE postgres TO regress_alice;
+ SET SESSION AUTHORIZATION regress_alice;
+ CREATE SCHEMA alice;
+ GRANT USAGE ON SCHEMA alice TO regress_admin;
+
+ CREATE TABLE alice.unpartitioned (i INTEGER);
+ ALTER TABLE alice.unpartitioned REPLICA IDENTITY FULL;
+ GRANT SELECT ON TABLE alice.unpartitioned TO regress_admin;
+
+ CREATE TABLE alice.rangepart (i INTEGER) PARTITION BY RANGE (i);
+ ALTER TABLE alice.rangepart REPLICA IDENTITY FULL;
+ GRANT SELECT ON TABLE alice.rangepart TO regress_admin;
+ CREATE TABLE alice.rangepart_a PARTITION OF alice.rangepart
+ FOR VALUES $range_a;
+ ALTER TABLE alice.rangepart_a REPLICA IDENTITY FULL;
+ CREATE TABLE alice.rangepart_b PARTITION OF alice.rangepart
+ FOR VALUES $range_b;
+ ALTER TABLE alice.rangepart_b REPLICA IDENTITY FULL;
+
+ CREATE TABLE alice.listpart (i INTEGER) PARTITION BY LIST (i);
+ ALTER TABLE alice.listpart REPLICA IDENTITY FULL;
+ GRANT SELECT ON TABLE alice.listpart TO regress_admin;
+ CREATE TABLE alice.listpart_a PARTITION OF alice.listpart
+ FOR VALUES $list_a;
+ ALTER TABLE alice.listpart_a REPLICA IDENTITY FULL;
+ CREATE TABLE alice.listpart_b PARTITION OF alice.listpart
+ FOR VALUES $list_b;
+ ALTER TABLE alice.listpart_b REPLICA IDENTITY FULL;
+
+ CREATE TABLE alice.hashpart (i INTEGER) PARTITION BY HASH (i);
+ ALTER TABLE alice.hashpart REPLICA IDENTITY FULL;
+ GRANT SELECT ON TABLE alice.hashpart TO regress_admin;
+ CREATE TABLE alice.hashpart_a PARTITION OF alice.hashpart
+ FOR VALUES WITH (MODULUS 2, REMAINDER $remainder_a);
+ ALTER TABLE alice.hashpart_a REPLICA IDENTITY FULL;
+ CREATE TABLE alice.hashpart_b PARTITION OF alice.hashpart
+ FOR VALUES WITH (MODULUS 2, REMAINDER $remainder_b);
+ ALTER TABLE alice.hashpart_b REPLICA IDENTITY FULL;
+ ));
+}
+$node_publisher->safe_psql('postgres', qq(
+SET SESSION AUTHORIZATION regress_alice;
+
+CREATE PUBLICATION alice
+ FOR TABLE alice.unpartitioned, alice.rangepart, alice.listpart, alice.hashpart
+ WITH (publish_via_partition_root = true);
+));
+$node_subscriber->safe_psql('postgres', qq(
+SET SESSION AUTHORIZATION regress_admin;
+CREATE SUBSCRIPTION admin_sub CONNECTION '$publisher_connstr' PUBLICATION alice;
+));
+
+# Verify that "regress_admin" can replicate into the tables
+#
+my @tbl = (qw(unpartitioned rangepart listpart hashpart));
+for my $tbl (@tbl)
+{
+ publish_insert("alice.$tbl", 1);
+ publish_insert("alice.$tbl", 3);
+ publish_insert("alice.$tbl", 5);
+ expect_replication(
+ "alice.$tbl", 3, 1, 5,
+ "superuser admin replicates insert into $tbl");
+ publish_update("alice.$tbl", 1 => 7);
+ expect_replication(
+ "alice.$tbl", 3, 3, 7,
+ "superuser admin replicates update into $tbl");
+ publish_delete("alice.$tbl", 3);
+ expect_replication(
+ "alice.$tbl", 2, 5, 7,
+ "superuser admin replicates delete into $tbl");
+}
+
+# Repeatedly revoke and restore superuser privilege for "regress_admin", verifying
+# that replication fails while superuser privilege is missing, but works again and
+# catches up once superuser is restored.
+#
+for my $tbl (@tbl)
+{
+ revoke_superuser("regress_admin");
+ publish_insert("alice.$tbl", 3);
+ expect_failure("alice.$tbl", 2, 5, 7,
+ qr/ERROR: permission denied for table $tbl/msi,
+ "non-superuser admin fails to replicate insert");
+ grant_superuser("regress_admin");
+ expect_replication("alice.$tbl", 3, 3, 7,
+ "admin with restored superuser privilege replicates insert");
+
+ revoke_superuser("regress_admin");
+ publish_update("alice.$tbl", 3 => 9);
+ expect_failure("alice.$tbl", 3, 3, 7,
+ qr/ERROR: permission denied for table $tbl/msi,
+ "non-superuser admin fails to replicate update");
+ grant_superuser("regress_admin");
+ expect_replication("alice.$tbl", 3, 5, 9,
+ "admin with restored superuser privilege replicates update");
+
+ revoke_superuser("regress_admin");
+ publish_delete("alice.$tbl", 5);
+ expect_failure("alice.$tbl", 3, 5, 9,
+ qr/ERROR: permission denied for table $tbl/msi,
+ "non-superuser admin fails to replicate delete");
+ grant_superuser("regress_admin");
+ expect_replication("alice.$tbl", 2, 7, 9,
+ "admin with restored superuser privilege replicates delete");
+}
+
+# Grant privileges on the target tables to "regress_admin" so that superuser
+# privileges are not necessary for replication.
+#
+$node_subscriber->safe_psql('postgres', qq(
+ALTER ROLE regress_admin NOSUPERUSER;
+SET SESSION AUTHORIZATION regress_alice;
+GRANT ALL PRIVILEGES ON
+ alice.unpartitioned,
+ alice.rangepart, alice.rangepart_a, alice.rangepart_b,
+ alice.listpart, alice.listpart_a, alice.listpart_b,
+ alice.hashpart, alice.hashpart_a, alice.hashpart_b
+ TO regress_admin;
+));
+for my $tbl (@tbl)
+{
+ publish_insert("alice.$tbl", 11);
+ publish_update("alice.$tbl", 7 => 13);
+ publish_delete("alice.$tbl", 9);
+ expect_replication("alice.$tbl", 2, 11, 13,
+ "nosuperuser admin with all table privileges can replicate into $tbl");
+}
+
+# Enable RLS on the target tables and check that "regress_admin" can only
+# replicate into them when superuser. Note that RLS must be enabled on the
+# partitions, not the partitioned tables, since the partitions are the targets
+# of the replication.
+#
+$node_subscriber->safe_psql('postgres', qq(
+SET SESSION AUTHORIZATION regress_alice;
+ALTER TABLE alice.unpartitioned ENABLE ROW LEVEL SECURITY;
+ALTER TABLE alice.rangepart_a ENABLE ROW LEVEL SECURITY;
+ALTER TABLE alice.rangepart_b ENABLE ROW LEVEL SECURITY;
+ALTER TABLE alice.listpart_a ENABLE ROW LEVEL SECURITY;
+ALTER TABLE alice.listpart_b ENABLE ROW LEVEL SECURITY;
+ALTER TABLE alice.hashpart_a ENABLE ROW LEVEL SECURITY;
+ALTER TABLE alice.hashpart_b ENABLE ROW LEVEL SECURITY;
+));
+for my $tbl (@tbl)
+{
+ revoke_superuser("regress_admin");
+ publish_insert("alice.$tbl", 15);
+ expect_failure("alice.$tbl", 2, 11, 13,
+ qr/ERROR: "regress_admin" cannot replicate into relation with row-level security enabled: "$tbl\w*"/msi,
+ "non-superuser admin fails to replicate insert into rls enabled table");
+ grant_superuser("regress_admin");
+ expect_replication("alice.$tbl", 3, 11, 15,
+ "admin with restored superuser privilege replicates insert into rls enabled $tbl");
+
+ revoke_superuser("regress_admin");
+ publish_update("alice.$tbl", 11 => 17);
+ expect_failure("alice.$tbl", 3, 11, 15,
+ qr/ERROR: "regress_admin" cannot replicate into relation with row-level security enabled: "$tbl\w*"/msi,
+ "non-superuser admin fails to replicate update into rls enabled $tbl");
+
+ grant_superuser("regress_admin");
+ expect_replication("alice.$tbl", 3, 13, 17,
+ "admin with restored superuser privilege replicates update into rls enabled $tbl");
+
+ revoke_superuser("regress_admin");
+ publish_delete("alice.$tbl", 13);
+ expect_failure("alice.$tbl", 3, 13, 17,
+ qr/ERROR: "regress_admin" cannot replicate into relation with row-level security enabled: "$tbl\w*"/msi,
+ "non-superuser admin fails to replicate delete into rls enabled $tbl");
+ grant_superuser("regress_admin");
+ expect_replication("alice.$tbl", 2, 15, 17,
+ "admin with restored superuser privilege replicates delete into rls enabled $tbl");
+}
+
+# Revoke superuser from "regress_admin". Check that the admin can now only
+# replicate into alice's table when admin has the bypassrls privilege.
+#
+for my $tbl (@tbl)
+{
+ revoke_superuser("regress_admin");
+ revoke_bypassrls("regress_admin");
+ publish_insert("alice.$tbl", 19);
+ expect_failure("alice.$tbl", 2, 15, 17,
+ qr/ERROR: "regress_admin" cannot replicate into relation with row-level security enabled: "$tbl\w*"/msi,
+ "nobypassrls admin fails to replicate insert into rls enabled $tbl");
+ grant_bypassrls("regress_admin");
+ expect_replication("alice.$tbl", 3, 15, 19,
+ "admin with bypassrls privilege replicates insert into rls enabled $tbl");
+
+ revoke_bypassrls("regress_admin");
+ publish_update("alice.$tbl", 15 => 21);
+ expect_failure("alice.$tbl", 3, 15, 19,
+ qr/ERROR: "regress_admin" cannot replicate into relation with row-level security enabled: "$tbl\w*"/msi,
+ "nobypassrls admin fails to replicate update into rls enabled $tbl");
+
+ grant_bypassrls("regress_admin");
+ expect_replication("alice.$tbl", 3, 17, 21,
+ "admin with restored bypassrls privilege replicates update into rls enabled $tbl");
+
+ revoke_bypassrls("regress_admin");
+ publish_delete("alice.$tbl", 17);
+ expect_failure("alice.$tbl", 3, 17, 21,
+ qr/ERROR: "regress_admin" cannot replicate into relation with row-level security enabled: "$tbl\w*"/msi,
+ "nobypassrls admin fails to replicate delete into rls enabled $tbl");
+ grant_bypassrls("regress_admin");
+ expect_replication("alice.$tbl", 2, 19, 21,
+ "admin with restored bypassrls privilege replicates delete into rls enabled $tbl");
+}
+
+# Alter the subscription owner to "regress_alice". She has neither superuser
+# nor bypassrls, but as the table owner should be able to replicate.
+#
+$node_subscriber->safe_psql('postgres', qq(
+ALTER SUBSCRIPTION admin_sub DISABLE;
+ALTER ROLE regress_alice SUPERUSER;
+ALTER SUBSCRIPTION admin_sub OWNER TO regress_alice;
+ALTER ROLE regress_alice NOSUPERUSER;
+ALTER SUBSCRIPTION admin_sub ENABLE;
+));
+for my $tbl (@tbl)
+{
+ publish_insert("alice.$tbl", 23);
+ expect_replication(
+ "alice.$tbl", 3, 19, 23,
+ "nosuperuser nobypassrls table owner can replicate insert into $tbl despite rls");
+ publish_update("alice.$tbl", 19 => 25);
+ expect_replication(
+ "alice.$tbl", 3, 21, 25,
+ "nosuperuser nobypassrls table owner can replicate update into $tbl despite rls");
+ publish_delete("alice.$tbl", 21);
+ expect_replication(
+ "alice.$tbl", 2, 23, 25,
+ "nosuperuser nobypassrls table owner can replicate delete into $tbl despite rls");
+}
--
2.21.1 (Apple Git-122.3)
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
@ 2021-11-17 18:48 ` Mark Dilger <[email protected]>
2021-11-17 21:10 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
1 sibling, 1 reply; 68+ messages in thread
From: Mark Dilger @ 2021-11-17 18:48 UTC (permalink / raw)
To: Jeff Davis <[email protected]>; +Cc: Andrew Dunstan <[email protected]>; pgsql-hackers; Robert Haas <[email protected]>
> On Nov 17, 2021, at 9:33 AM, Jeff Davis <[email protected]> wrote:
>
> Is GRANT a better fit here? That would allow more than one user to
> REFRESH, or ENABLE/DISABLE the same subscription. It wouldn't allow
> RENAME, but I don't see why we'd separate privileges for
> CREATE/DROP/RENAME anyway.
I don't think I answered this directly in my last reply.
GRANT *might* be part of some solution, but it is unclear to me how best to do it. The various configuration parameters on subscriptions entail different security concerns. We might take a fine-grained approach and create a predefined role for each, or we might take a course-grained approach and create a single pg_manage_subscriptions role which can set any parameter on any subscription, or maybe just parameters on subscriptions that the role also owns, or we might do something else, like burn some privilege bits and define new privileges that can be granted per subscription rather than globally. (I think that last one is a non-starter, but just mention it as an example of another approach.)
—
Mark Dilger
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 18:48 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
@ 2021-11-17 21:10 ` Jeff Davis <[email protected]>
2021-11-17 23:07 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
0 siblings, 1 reply; 68+ messages in thread
From: Jeff Davis @ 2021-11-17 21:10 UTC (permalink / raw)
To: Mark Dilger <[email protected]>; +Cc: Andrew Dunstan <[email protected]>; pgsql-hackers; Robert Haas <[email protected]>
On Wed, 2021-11-17 at 10:48 -0800, Mark Dilger wrote:
> GRANT *might* be part of some solution, but it is unclear to me how
> best to do it. The various configuration parameters on subscriptions
> entail different security concerns. We might take a fine-grained
> approach and create a predefined role for each
I think you misunderstood the idea: not using predefined roles, just
plain old ordinary GRANT on a subscription object to ordinary roles.
GRANT REFRESH ON SUBSCRIPTION sub1 TO nonsuper;
This should be easy enough because the subscription is a real object,
right?
Regards,
Jeff Davis
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 18:48 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 21:10 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
@ 2021-11-17 23:07 ` Mark Dilger <[email protected]>
2021-11-17 23:46 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
0 siblings, 1 reply; 68+ messages in thread
From: Mark Dilger @ 2021-11-17 23:07 UTC (permalink / raw)
To: Jeff Davis <[email protected]>; +Cc: Andrew Dunstan <[email protected]>; pgsql-hackers; Robert Haas <[email protected]>
> On Nov 17, 2021, at 1:10 PM, Jeff Davis <[email protected]> wrote:
>
> I think you misunderstood the idea: not using predefined roles, just
> plain old ordinary GRANT on a subscription object to ordinary roles.
>
> GRANT REFRESH ON SUBSCRIPTION sub1 TO nonsuper;
>
> This should be easy enough because the subscription is a real object,
> right?
/*
* Grantable rights are encoded so that we can OR them together in a bitmask.
* The present representation of AclItem limits us to 16 distinct rights,
* even though AclMode is defined as uint32. See utils/acl.h.
*
* Caution: changing these codes breaks stored ACLs, hence forces initdb.
*/
typedef uint32 AclMode; /* a bitmask of privilege bits */
#define ACL_INSERT (1<<0) /* for relations */
#define ACL_SELECT (1<<1)
#define ACL_UPDATE (1<<2)
#define ACL_DELETE (1<<3)
#define ACL_TRUNCATE (1<<4)
#define ACL_REFERENCES (1<<5)
#define ACL_TRIGGER (1<<6)
#define ACL_EXECUTE (1<<7) /* for functions */
#define ACL_USAGE (1<<8) /* for languages, namespaces, FDWs, and
* servers */
#define ACL_CREATE (1<<9) /* for namespaces and databases */
#define ACL_CREATE_TEMP (1<<10) /* for databases */
#define ACL_CONNECT (1<<11) /* for databases */
We only have 4 values left in the bitmask, and I doubt that burning those slots for multiple new types of rights that only have meaning for subscriptions is going to be accepted. For full disclosure, I'm proposing adding ACL_SET and ACL_ALTER_SYSTEM in another patch and my proposal there could get shot down for the same reasons, but I think your argument would be even harder to defend. Maybe others feel differently.
—
Mark Dilger
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 18:48 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 21:10 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 23:07 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
@ 2021-11-17 23:46 ` Jeff Davis <[email protected]>
0 siblings, 0 replies; 68+ messages in thread
From: Jeff Davis @ 2021-11-17 23:46 UTC (permalink / raw)
To: Mark Dilger <[email protected]>; +Cc: Andrew Dunstan <[email protected]>; pgsql-hackers; Robert Haas <[email protected]>
On Wed, 2021-11-17 at 15:07 -0800, Mark Dilger wrote:
> We only have 4 values left in the bitmask, and I doubt that burning
> those slots for multiple new types of rights that only have meaning
> for subscriptions is going to be accepted. For full disclosure, I'm
> proposing adding ACL_SET and ACL_ALTER_SYSTEM in another patch and my
> proposal there could get shot down for the same reasons, but I think
> your argument would be even harder to defend. Maybe others feel
> differently.
Why not overload ACL_USAGE again, and say:
GRANT USAGE ON SUBSCRIPTION sub1 TO nonsuper;
would allow ENABLE/DISABLE and REFRESH.
Again, I don't really understand the use case behind "can use a
subscription but not create one", so I'm not making a proposal. But
assuming that the use case exists, GRANT seems like a much better
approach.
(Aside: for me to commit something like this I'd want to understand the
"can use a subscription but not create one" use case better.)
Regards,
Jeff Davis
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
@ 2021-11-18 11:37 ` Amit Kapila <[email protected]>
2021-11-18 15:45 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2 siblings, 1 reply; 68+ messages in thread
From: Amit Kapila @ 2021-11-18 11:37 UTC (permalink / raw)
To: Mark Dilger <[email protected]>; +Cc: Andrew Dunstan <[email protected]>; pgsql-hackers; Robert Haas <[email protected]>
On Thu, Nov 4, 2021 at 1:20 AM Mark Dilger <[email protected]> wrote:
>
> > On Nov 1, 2021, at 10:58 AM, Mark Dilger <[email protected]> wrote:
> >
> > ALTER SUBSCRIPTION..[ENABLE | DISABLE] do not synchronously start or stop subscription workers. The ALTER command updates the catalog's subenabled field, but workers only lazily respond to that. Disabling and enabling the subscription as part of the OWNER TO would not reliably accomplish anything.
>
> I have rethought my prior analysis. The problem in the previous patch was that the subscription apply workers did not check for a change in ownership the way they checked for other changes, instead only picking up the new ownership information when the worker restarted for some other reason. This next patch set fixes that. The application of a change record may continue under the old ownership permissions when a concurrent command changes the ownership of the subscription, but the worker will pick up the new permissions before applying the next record.
>
Are you talking about the below change in the above paragraph?
@@ -2912,6 +2941,7 @@ maybe_reread_subscription(void)
strcmp(newsub->slotname, MySubscription->slotname) != 0 ||
newsub->binary != MySubscription->binary ||
newsub->stream != MySubscription->stream ||
+ newsub->owner != MySubscription->owner ||
!equal(newsub->publications, MySubscription->publications))
{
If so, I am not sure how it will ensure that we check the ownership
change before applying each change? I think this will be invoked at
each transaction boundary, so, if there is a transaction with a large
number of changes, all the changes will be processed under the
previous owner.
--
With Regards,
Amit Kapila.
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-18 11:37 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
@ 2021-11-18 15:45 ` Mark Dilger <[email protected]>
2021-11-19 09:56 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
0 siblings, 1 reply; 68+ messages in thread
From: Mark Dilger @ 2021-11-18 15:45 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: Andrew Dunstan <[email protected]>; pgsql-hackers; Robert Haas <[email protected]>
> On Nov 18, 2021, at 3:37 AM, Amit Kapila <[email protected]> wrote:
>
>> I have rethought my prior analysis. The problem in the previous patch was that the subscription apply workers did not check for a change in ownership the way they checked for other changes, instead only picking up the new ownership information when the worker restarted for some other reason. This next patch set fixes that. The application of a change record may continue under the old ownership permissions when a concurrent command changes the ownership of the subscription, but the worker will pick up the new permissions before applying the next record.
>>
>
> Are you talking about the below change in the above paragraph?
>
> @@ -2912,6 +2941,7 @@ maybe_reread_subscription(void)
> strcmp(newsub->slotname, MySubscription->slotname) != 0 ||
> newsub->binary != MySubscription->binary ||
> newsub->stream != MySubscription->stream ||
> + newsub->owner != MySubscription->owner ||
> !equal(newsub->publications, MySubscription->publications))
> {
>
> If so, I am not sure how it will ensure that we check the ownership
> change before applying each change? I think this will be invoked at
> each transaction boundary, so, if there is a transaction with a large
> number of changes, all the changes will be processed under the
> previous owner.
Yes, your analysis appears correct. I was sloppy to say "before applying the next record". It will pick up the change before applying the next transaction.
The prior version of the patch only picked up the change if it happened to start a new worker, but could process multiple transactions without noticing the change. Now, it is limited to finishing the current transaction. Would you prefer that the worker noticed the change in ownership and aborted the transaction on the subscriber side? Or should the ALTER SUBSCRIPTION..OWNER TO block? I don't see much advantage to either of those options, but I also don't think I have any knock-down argument for my approach either. What do you think?
—
Mark Dilger
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-18 11:37 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-18 15:45 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
@ 2021-11-19 09:56 ` Amit Kapila <[email protected]>
2021-11-19 15:47 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
0 siblings, 1 reply; 68+ messages in thread
From: Amit Kapila @ 2021-11-19 09:56 UTC (permalink / raw)
To: Mark Dilger <[email protected]>; +Cc: Andrew Dunstan <[email protected]>; pgsql-hackers; Robert Haas <[email protected]>
On Thu, Nov 18, 2021 at 9:15 PM Mark Dilger
<[email protected]> wrote:
>
> The prior version of the patch only picked up the change if it happened to start a new worker, but could process multiple transactions without noticing the change. Now, it is limited to finishing the current transaction. Would you prefer that the worker noticed the change in ownership and aborted the transaction on the subscriber side? Or should the ALTER SUBSCRIPTION..OWNER TO block? I don't see much advantage to either of those options, but I also don't think I have any knock-down argument for my approach either. What do you think?
>
How about allowing to change ownership only for disabled
subscriptions? Basically, users need to first disable the subscription
and then change its ownership. Now, disabling is an asynchronous
operation but we won't allow the ownership change command to proceed
unless the subscription is marked disabled and all the apply/sync
workers are not running. After the ownership is changed, users can
enable it. We already have 'slot_name' parameter's dependency on
whether the subscription is marked enabled or not.
This will add some steps in changing the ownership of a subscription
but I think it will be predictable.
--
With Regards,
Amit Kapila.
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-18 11:37 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-18 15:45 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-19 09:56 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
@ 2021-11-19 15:47 ` Mark Dilger <[email protected]>
0 siblings, 0 replies; 68+ messages in thread
From: Mark Dilger @ 2021-11-19 15:47 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; Jeff Davis <[email protected]>; +Cc: Andrew Dunstan <[email protected]>; pgsql-hackers; Robert Haas <[email protected]>
> On Nov 19, 2021, at 1:56 AM, Amit Kapila <[email protected]> wrote:
>
> How about allowing to change ownership only for disabled
> subscriptions? Basically, users need to first disable the subscription
> and then change its ownership.
There are some open issues about non-superuser owners that Jeff would like to address before allowing transfers of ownership to non-superusers. Your proposal about requiring the subscription to be disabled seems reasonable to me, but I'd like to see how it would interact with whatever Jeff proposes. So I think I will change the patch as you suggest, but consider it a WIP patch until then.
—
Mark Dilger
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
@ 2021-11-16 18:08 ` Jeff Davis <[email protected]>
2021-11-16 18:12 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2 siblings, 1 reply; 68+ messages in thread
From: Jeff Davis @ 2021-11-16 18:08 UTC (permalink / raw)
To: Mark Dilger <[email protected]>; Andrew Dunstan <[email protected]>; +Cc: pgsql-hackers
On Mon, 2021-11-01 at 10:58 -0700, Mark Dilger wrote:
> It is unclear that I can make ALTER SUBSCRIPTION..OWNER TO
> synchronous without redesigning the way workers respond to
> pg_subscription catalog updates generally. That may be a good
> project to eventually tackle, but I don't see that it is more
> important to close the race condition in an OWNER TO than for a
> DISABLE.
>
> Thoughts?
What if we just say that OWNER TO must be done by a superuser, changing
from one superuser to another, just like today? That would preserve
backwards compatibility, but people with non-superuser subscriptions
would need to drop/recreate them.
When we eventually do tackle the problem, we can lift the restriction.
Regards,
Jeff Davis
^ permalink raw reply [nested|flat] 68+ messages in thread
* Re: Non-superuser subscription owners
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-16 18:08 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
@ 2021-11-16 18:12 ` Mark Dilger <[email protected]>
0 siblings, 0 replies; 68+ messages in thread
From: Mark Dilger @ 2021-11-16 18:12 UTC (permalink / raw)
To: Jeff Davis <[email protected]>; +Cc: Andrew Dunstan <[email protected]>; pgsql-hackers
> On Nov 16, 2021, at 10:08 AM, Jeff Davis <[email protected]> wrote:
>
> On Mon, 2021-11-01 at 10:58 -0700, Mark Dilger wrote:
>> It is unclear .....
>>
>> Thoughts?
>
> What if we just say that OWNER TO must be done by a superuser, changing
> from one superuser to another, just like today? That would preserve
> backwards compatibility, but people with non-superuser subscriptions
> would need to drop/recreate them.
The paragraph I wrote on 11/01 and you are responding to is no longer relevant. The patch submission on 11/03 tackled the problem. Have you had a chance to take a look at the new design?
—
Mark Dilger
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
^ permalink raw reply [nested|flat] 68+ messages in thread
end of thread, other threads:[~2021-12-15 20:23 UTC | newest]
Thread overview: 68+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2020-02-29 18:47 [PATCH] Add object names to partition errors Chris Bandy <[email protected]>
2021-10-20 18:40 Non-superuser subscription owners Mark Dilger <[email protected]>
2021-10-25 07:26 ` Re: Non-superuser subscription owners Ronan Dunklau <[email protected]>
2021-11-01 14:18 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-01 17:58 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-01 22:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-02 15:17 ` Re: Non-superuser subscription owners Robert Haas <[email protected]>
2021-11-03 19:50 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-16 20:06 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-16 20:08 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-16 20:40 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-17 20:26 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-11-17 04:11 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 15:44 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 17:33 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 18:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 21:06 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-18 00:17 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-18 18:29 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-19 10:23 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-19 16:12 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-18 18:50 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-18 10:50 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-18 15:33 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-19 09:44 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-19 15:25 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-20 00:45 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-25 00:30 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-25 04:21 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-25 20:06 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-29 04:13 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-29 19:26 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-30 11:55 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-30 20:42 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-12-01 13:36 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-12-01 19:21 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-12-02 09:29 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-12-03 13:31 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-12-06 10:19 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-12-06 15:56 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-12-07 09:39 ` Re: Non-superuser subscription owners Ronan Dunklau <[email protected]>
2021-12-07 10:29 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-12-07 14:55 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-12-09 04:58 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-12-09 15:47 ` Re: Non-superuser subscription owners Robert Haas <[email protected]>
2021-12-09 17:48 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-12-09 15:41 ` Re: Non-superuser subscription owners Robert Haas <[email protected]>
2021-12-09 17:22 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-12-10 04:15 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-12-10 14:09 ` Re: Non-superuser subscription owners Robert Haas <[email protected]>
2021-12-10 15:20 ` Re: Non-superuser subscription owners Andrew Dunstan <[email protected]>
2021-12-11 04:55 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-27 18:05 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-29 05:56 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-29 16:26 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-29 18:22 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-30 11:49 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-12-15 20:23 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 18:48 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 21:10 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-17 23:07 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-17 23:46 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-18 11:37 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-18 15:45 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-19 09:56 ` Re: Non-superuser subscription owners Amit Kapila <[email protected]>
2021-11-19 15:47 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
2021-11-16 18:08 ` Re: Non-superuser subscription owners Jeff Davis <[email protected]>
2021-11-16 18:12 ` Re: Non-superuser subscription owners Mark Dilger <[email protected]>
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox