120
120
#include "utils/rls.h"
121
121
#include "utils/snapmgr.h"
122
122
#include "utils/syscache.h"
123
+ #include "utils/usercontext.h"
123
124
124
125
static bool table_states_valid = false;
125
126
static List * table_states_not_ready = NIL ;
@@ -1252,7 +1253,9 @@ LogicalRepSyncTableStart(XLogRecPtr *origin_startpos)
1252
1253
WalRcvExecResult * res ;
1253
1254
char originname [NAMEDATALEN ];
1254
1255
RepOriginId originid ;
1256
+ UserContext ucxt ;
1255
1257
bool must_use_password ;
1258
+ bool run_as_owner ;
1256
1259
1257
1260
/* Check the state of the table synchronization. */
1258
1261
StartTransactionCommand ();
@@ -1374,31 +1377,6 @@ LogicalRepSyncTableStart(XLogRecPtr *origin_startpos)
1374
1377
*/
1375
1378
rel = table_open (MyLogicalRepWorker -> relid , RowExclusiveLock );
1376
1379
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
-
1402
1380
/*
1403
1381
* Start a transaction in the remote node in REPEATABLE READ mode. This
1404
1382
* ensures that both the replication slot we create (see below) and the
@@ -1456,6 +1434,39 @@ LogicalRepSyncTableStart(XLogRecPtr *origin_startpos)
1456
1434
originname )));
1457
1435
}
1458
1436
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
+
1459
1470
/* Now do the initial data copy */
1460
1471
PushActiveSnapshot (GetTransactionSnapshot ());
1461
1472
copy_table (rel );
@@ -1469,6 +1480,9 @@ LogicalRepSyncTableStart(XLogRecPtr *origin_startpos)
1469
1480
res -> err )));
1470
1481
walrcv_clear_result (res );
1471
1482
1483
+ if (!run_as_owner )
1484
+ RestoreUserContext (& ucxt );
1485
+
1472
1486
table_close (rel , NoLock );
1473
1487
1474
1488
/* Make the copy visible. */
0 commit comments