Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita83edea

Browse files
Honor run_as_owner option in tablesync worker.
Commit4826759 introduced "run_as_owner" subscription option so thatsubscription runs with either the permissions of the subscriptionowner or the permission of the table owner. However, tablesync workersdid not use this option for the initial data copy.With this change, tablesync workers run with appropriate permissionsbased on "run_as_owner" option.Ajin Cherian, with changes and regression tests added by me.Reported-By: Amit KapilaAuthor: Ajin Cherian, Masahiko SawadaReviewed-by: Ajin Cherian, Amit KapilaDiscussion:https://postgr.es/m/CAA4eK1L=qzRHPEn+qeMoKQGFBzqGoLBzt_ov0A89iFFiut+ppA@mail.gmail.com
1 parent26eaf82 commita83edea

File tree

2 files changed

+75
-27
lines changed

2 files changed

+75
-27
lines changed

‎src/backend/replication/logical/tablesync.c

Lines changed: 39 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@
120120
#include"utils/rls.h"
121121
#include"utils/snapmgr.h"
122122
#include"utils/syscache.h"
123+
#include"utils/usercontext.h"
123124

124125
staticbooltable_states_valid= false;
125126
staticList*table_states_not_ready=NIL;
@@ -1252,7 +1253,9 @@ LogicalRepSyncTableStart(XLogRecPtr *origin_startpos)
12521253
WalRcvExecResult*res;
12531254
charoriginname[NAMEDATALEN];
12541255
RepOriginIdoriginid;
1256+
UserContextucxt;
12551257
boolmust_use_password;
1258+
boolrun_as_owner;
12561259

12571260
/* Check the state of the table synchronization. */
12581261
StartTransactionCommand();
@@ -1374,31 +1377,6 @@ LogicalRepSyncTableStart(XLogRecPtr *origin_startpos)
13741377
*/
13751378
rel=table_open(MyLogicalRepWorker->relid,RowExclusiveLock);
13761379

1377-
/*
1378-
* Check that our table sync worker has permission to insert into the
1379-
* target table.
1380-
*/
1381-
aclresult=pg_class_aclcheck(RelationGetRelid(rel),GetUserId(),
1382-
ACL_INSERT);
1383-
if (aclresult!=ACLCHECK_OK)
1384-
aclcheck_error(aclresult,
1385-
get_relkind_objtype(rel->rd_rel->relkind),
1386-
RelationGetRelationName(rel));
1387-
1388-
/*
1389-
* COPY FROM does not honor RLS policies. That is not a problem for
1390-
* subscriptions owned by roles with BYPASSRLS privilege (or superuser,
1391-
* who has it implicitly), but other roles should not be able to
1392-
* circumvent RLS. Disallow logical replication into RLS enabled
1393-
* relations for such roles.
1394-
*/
1395-
if (check_enable_rls(RelationGetRelid(rel),InvalidOid, false)==RLS_ENABLED)
1396-
ereport(ERROR,
1397-
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1398-
errmsg("user \"%s\" cannot replicate into relation with row-level security enabled: \"%s\"",
1399-
GetUserNameFromId(GetUserId(), true),
1400-
RelationGetRelationName(rel))));
1401-
14021380
/*
14031381
* Start a transaction in the remote node in REPEATABLE READ mode. This
14041382
* ensures that both the replication slot we create (see below) and the
@@ -1456,6 +1434,39 @@ LogicalRepSyncTableStart(XLogRecPtr *origin_startpos)
14561434
originname)));
14571435
}
14581436

1437+
/*
1438+
* Make sure that the copy command runs as the table owner, unless
1439+
* the user has opted out of that behaviour.
1440+
*/
1441+
run_as_owner=MySubscription->runasowner;
1442+
if (!run_as_owner)
1443+
SwitchToUntrustedUser(rel->rd_rel->relowner,&ucxt);
1444+
1445+
/*
1446+
* Check that our table sync worker has permission to insert into the
1447+
* target table.
1448+
*/
1449+
aclresult=pg_class_aclcheck(RelationGetRelid(rel),GetUserId(),
1450+
ACL_INSERT);
1451+
if (aclresult!=ACLCHECK_OK)
1452+
aclcheck_error(aclresult,
1453+
get_relkind_objtype(rel->rd_rel->relkind),
1454+
RelationGetRelationName(rel));
1455+
1456+
/*
1457+
* COPY FROM does not honor RLS policies. That is not a problem for
1458+
* subscriptions owned by roles with BYPASSRLS privilege (or superuser,
1459+
* who has it implicitly), but other roles should not be able to
1460+
* circumvent RLS. Disallow logical replication into RLS enabled
1461+
* relations for such roles.
1462+
*/
1463+
if (check_enable_rls(RelationGetRelid(rel),InvalidOid, false)==RLS_ENABLED)
1464+
ereport(ERROR,
1465+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1466+
errmsg("user \"%s\" cannot replicate into relation with row-level security enabled: \"%s\"",
1467+
GetUserNameFromId(GetUserId(), true),
1468+
RelationGetRelationName(rel))));
1469+
14591470
/* Now do the initial data copy */
14601471
PushActiveSnapshot(GetTransactionSnapshot());
14611472
copy_table(rel);
@@ -1469,6 +1480,9 @@ LogicalRepSyncTableStart(XLogRecPtr *origin_startpos)
14691480
res->err)));
14701481
walrcv_clear_result(res);
14711482

1483+
if(!run_as_owner)
1484+
RestoreUserContext(&ucxt);
1485+
14721486
table_close(rel,NoLock);
14731487

14741488
/* Make the copy visible. */

‎src/test/subscription/t/033_run_as_table_owner.pl

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@ sub revoke_superuser
7070

7171
# Create publisher and subscriber nodes with schemas owned and published by
7272
# "regress_alice" but subscribed and replicated by different role
73-
# "regress_admin".For partitioned tables, layout the partitions differently
74-
# on the publisher than on the subscriber.
73+
# "regress_admin" and "regress_admin2".For partitioned tables, layout the
74+
#partitions differentlyon the publisher than on the subscriber.
7575
#
7676
$node_publisher = PostgreSQL::Test::Cluster->new('publisher');
7777
$node_subscriber = PostgreSQL::Test::Cluster->new('subscriber');
@@ -86,6 +86,7 @@ sub revoke_superuser
8686
$node->safe_psql(
8787
'postgres',qq(
8888
CREATE ROLE regress_admin SUPERUSER LOGIN;
89+
CREATE ROLE regress_admin2 SUPERUSER LOGIN;
8990
CREATE ROLE regress_alice NOSUPERUSER LOGIN;
9091
GRANT CREATE ON DATABASE postgres TO regress_alice;
9192
SET SESSION AUTHORIZATION regress_alice;
@@ -192,4 +193,37 @@ sub revoke_superuser
192193
expect_replication("alice.unpartitioned", 3, 7, 13,
193194
"with INHERIT but not SET ROLE can replicate");
194195

196+
# Remove the subscrition and truncate the table for the initial data sync
197+
# tests.
198+
$node_subscriber->safe_psql(
199+
'postgres',qq(
200+
DROP SUBSCRIPTION admin_sub;
201+
TRUNCATE alice.unpartitioned;
202+
));
203+
204+
# Create a new subscription "admin_sub" owned by regress_admin2. It's
205+
# disabled so that we revoke superuser privilege after creation.
206+
$node_subscriber->safe_psql(
207+
'postgres',qq(
208+
SET SESSION AUTHORIZATION regress_admin2;
209+
CREATE SUBSCRIPTION admin_sub CONNECTION '$publisher_connstr' PUBLICATION alice
210+
WITH (run_as_owner = false, password_required = false, copy_data = true, enabled = false);
211+
));
212+
213+
# Revoke superuser privilege for "regress_admin2", and give it the
214+
# ability to SET ROLE. Then enable the subscription "admin_sub".
215+
revoke_superuser("regress_admin2");
216+
$node_subscriber->safe_psql(
217+
'postgres',qq(
218+
GRANT regress_alice TO regress_admin2 WITH INHERIT FALSE, SET TRUE;
219+
ALTER SUBSCRIPTION admin_sub ENABLE;
220+
));
221+
222+
# Because the initial data sync is working as the table owner, all
223+
# data should be copied.
224+
$node_subscriber->wait_for_subscription_sync($node_publisher,
225+
'admin_sub');
226+
expect_replication("alice.unpartitioned", 3, 7, 13,
227+
"table owner can do the initial data copy");
228+
195229
done_testing();

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp