v2-0001-Fix-issue-where-the-copy-command-does-not-adhere-.patch
application/octet-stream
Filename: v2-0001-Fix-issue-where-the-copy-command-does-not-adhere-.patch
Type: application/octet-stream
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v2-0001
Subject: Fix issue where the "copy" command does not adhere to the run_as_owner setting.
| File | + | − |
|---|---|---|
| src/backend/replication/logical/tablesync.c | 14 | 0 |
| src/test/subscription/t/033_run_as_table_owner.pl | 64 | 0 |
From e5528f708fcd75135a46146da97d338d5c763843 Mon Sep 17 00:00:00 2001
From: Ajin Cherian <ajinc@fast.au.fujitsu.com>
Date: Mon, 15 May 2023 04:34:40 -0400
Subject: [PATCH v2] Fix issue where the "copy" command does not adhere to the
run_as_owner setting.
Make sure that "copy" command used during tablesync also respects the run_as_owner
setting.
---
src/backend/replication/logical/tablesync.c | 14 +++++
src/test/subscription/t/033_run_as_table_owner.pl | 64 +++++++++++++++++++++++
2 files changed, 78 insertions(+)
diff --git a/src/backend/replication/logical/tablesync.c b/src/backend/replication/logical/tablesync.c
index 0c71ae9..a8d3c47 100644
--- a/src/backend/replication/logical/tablesync.c
+++ b/src/backend/replication/logical/tablesync.c
@@ -120,6 +120,7 @@
#include "utils/rls.h"
#include "utils/snapmgr.h"
#include "utils/syscache.h"
+#include "utils/usercontext.h"
static bool table_states_valid = false;
static List *table_states_not_ready = NIL;
@@ -1253,6 +1254,8 @@ LogicalRepSyncTableStart(XLogRecPtr *origin_startpos)
char originname[NAMEDATALEN];
RepOriginId originid;
bool must_use_password;
+ UserContext ucxt;
+ bool run_as_owner;
/* Check the state of the table synchronization. */
StartTransactionCommand();
@@ -1456,6 +1459,14 @@ LogicalRepSyncTableStart(XLogRecPtr *origin_startpos)
originname)));
}
+ /*
+ * Make sure that the copy command runs as the table owner, unless
+ * the user has opted out of that behaviour.
+ */
+ run_as_owner = MySubscription->runasowner;
+ if (!run_as_owner)
+ SwitchToUntrustedUser(rel->rd_rel->relowner, &ucxt);
+
/* Now do the initial data copy */
PushActiveSnapshot(GetTransactionSnapshot());
copy_table(rel);
@@ -1469,6 +1480,9 @@ LogicalRepSyncTableStart(XLogRecPtr *origin_startpos)
res->err)));
walrcv_clear_result(res);
+ if(!run_as_owner)
+ RestoreUserContext(&ucxt);
+
table_close(rel, NoLock);
/* Make the copy visible. */
diff --git a/src/test/subscription/t/033_run_as_table_owner.pl b/src/test/subscription/t/033_run_as_table_owner.pl
index cabc8a7..91a95f8 100644
--- a/src/test/subscription/t/033_run_as_table_owner.pl
+++ b/src/test/subscription/t/033_run_as_table_owner.pl
@@ -68,6 +68,14 @@ sub revoke_superuser
ALTER ROLE $role NOSUPERUSER));
}
+sub grant_superuser
+{
+ my ($role) = @_;
+ $node_subscriber->safe_psql(
+ 'postgres', qq(
+ ALTER ROLE $role SUPERUSER));
+}
+
# 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
@@ -201,4 +209,60 @@ expect_replication("alice.unpartitioned", 3, 7, 13,
"with INHERIT but not SET ROLE can replicate"
);
+$node_subscriber->safe_psql(
+ 'postgres', qq(
+ DROP SUBSCRIPTION admin_sub;
+));
+
+grant_superuser("regress_admin");
+
+# When a SUBSCRIPTION is created with run_as_owner as false,
+# then replication runs as the owner of the table, and should not have
+# permission to access tables that are not accessible to the owner of the
+# table being replicated.
+# Create a table owned by regress_admin which regress_alice does not
+# have permission to access.
+$node_subscriber->safe_psql(
+ 'postgres', qq(
+SET SESSION AUTHORIZATION regress_admin;
+CREATE TABLE admin_audit (i integer);
+));
+
+# Create a trigger on table alice.unpartitioned that writes
+# to a table that regress_alice does not have permission.
+$node_subscriber->safe_psql(
+ 'postgres', qq(
+SET SESSION AUTHORIZATION regress_alice;
+CREATE OR REPLACE FUNCTION alice.alice_audit()
+RETURNS trigger AS
+\$\$
+ BEGIN
+ insert into public.admin_audit values(2);
+ RETURN NEW;
+ END;
+\$\$
+LANGUAGE 'plpgsql';
+CREATE TRIGGER ALICE_TRIGGER AFTER INSERT ON alice.unpartitioned FOR EACH ROW
+EXECUTE PROCEDURE alice.alice_audit();
+ALTER TABLE alice.unpartitioned ENABLE ALWAYS TRIGGER ALICE_TRIGGER;
+));
+
+# Create subscription with run_as_owner = false.
+$node_subscriber->safe_psql(
+ 'postgres', qq(
+SET SESSION AUTHORIZATION regress_admin;
+CREATE SUBSCRIPTION admin_sub CONNECTION '$publisher_connstr' PUBLICATION alice
+ WITH (run_as_owner = false, password_required = false);
+));
+
+# This should fail in the copy stage of the tablesync.
+expect_failure(
+ "admin_audit",
+ 0,
+ '',
+ '',
+ qr/ERROR: ( [A-Z0-9]+:)? permission denied for table admin_audit/msi,
+ "with run_as_owner false cannot access table without permission"
+);
+
done_testing();
--
1.8.3.1