aboutsummaryrefslogtreecommitdiff
path: root/src/backend/replication/logical/tablesync.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/replication/logical/tablesync.c')
-rw-r--r--src/backend/replication/logical/tablesync.c64
1 files changed, 39 insertions, 25 deletions
diff --git a/src/backend/replication/logical/tablesync.c b/src/backend/replication/logical/tablesync.c
index c56d42dcd2c..abae8d44dfc 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;
@@ -1252,7 +1253,9 @@ LogicalRepSyncTableStart(XLogRecPtr *origin_startpos)
WalRcvExecResult *res;
char originname[NAMEDATALEN];
RepOriginId originid;
+ UserContext ucxt;
bool must_use_password;
+ bool run_as_owner;
/* Check the state of the table synchronization. */
StartTransactionCommand();
@@ -1375,31 +1378,6 @@ 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("user \"%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
* COPY are consistent with each other.
@@ -1456,6 +1434,39 @@ 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);
+
+ /*
+ * 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("user \"%s\" cannot replicate into relation with row-level security enabled: \"%s\"",
+ GetUserNameFromId(GetUserId(), true),
+ RelationGetRelationName(rel))));
+
/* 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. */