Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/pgactive.h
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,7 @@ extern int pgactive_init_node_parallel_jobs;
extern int pgactive_max_nodes;
extern bool pgactive_permit_node_identifier_getter_function_creation;
extern bool pgactive_debug_trace_connection_errors;
extern bool pgactive_apply_as_table_owner;

static const char *const pgactive_default_apply_connection_options =
"connect_timeout=30 "
Expand Down
11 changes: 11 additions & 0 deletions src/pgactive.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ int pgactive_init_node_parallel_jobs;
int pgactive_max_nodes;
bool pgactive_permit_node_identifier_getter_function_creation;
bool pgactive_debug_trace_connection_errors;
bool pgactive_apply_as_table_owner;

PG_MODULE_MAGIC;

Expand Down Expand Up @@ -1251,6 +1252,16 @@ _PG_init(void)
GUC_SUPERUSER_ONLY,
NULL, NULL, NULL);

DefineCustomBoolVariable("pgactive.apply_as_table_owner",
"Apply DML changes as the table owner instead of superuser.",
"When enabled, the apply worker switches to the table owner "
"before executing INSERT, UPDATE, or DELETE operations.",
&pgactive_apply_as_table_owner,
true,
PGC_POSTMASTER,
Comment thread
bdrouvotAWS marked this conversation as resolved.
0,
NULL, NULL, NULL);

EmitWarningsOnPlaceholders("pgactive");

/* Security label provider hook */
Expand Down
62 changes: 62 additions & 0 deletions src/pgactive_apply.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,30 @@
#include "utils/memutils.h"
#include "utils/snapmgr.h"

#if PG_VERSION_NUM >= 160000
#include "utils/usercontext.h"
#else
typedef struct UserContext
{
Oid save_userid;
int save_sec_context;
} UserContext;

static inline void
SwitchToUntrustedUser(Oid userid, UserContext *context)
{
GetUserIdAndSecContext(&context->save_userid, &context->save_sec_context);
SetUserIdAndSecContext(userid,
context->save_sec_context | SECURITY_RESTRICTED_OPERATION);
}

static inline void
RestoreUserContext(UserContext *context)
{
SetUserIdAndSecContext(context->save_userid, context->save_sec_context);
}
#endif

/*
* Useful for development:
* #define VERBOSE_INSERT
Expand Down Expand Up @@ -606,6 +630,7 @@ process_remote_insert(StringInfo s)
ItemPointerData conflicting_tid;
ErrorContextCallback errcallback;
struct ActionErrCallbackArg cbarg;
UserContext ucxt;

ItemPointerSetInvalid(&conflicting_tid);

Expand All @@ -623,6 +648,14 @@ process_remote_insert(StringInfo s)

rel = read_rel(s, RowExclusiveLock, &cbarg);

if (pgactive_apply_as_table_owner)
{
SwitchToUntrustedUser(rel->rel->rd_rel->relowner, &ucxt);
elog(DEBUG1, "pgactive apply INSERT as user %s on %s",
GetUserNameFromId(rel->rel->rd_rel->relowner, false),
RelationGetRelationName(rel->rel));
}

emit_replay_info(&cbarg);

action = pq_getmsgbyte(s);
Expand Down Expand Up @@ -842,6 +875,9 @@ process_remote_insert(StringInfo s)

PopActiveSnapshot();

if (pgactive_apply_as_table_owner)
RestoreUserContext(&ucxt);

ExecCloseIndices(relinfo);

check_pgactive_wakeups(rel);
Expand Down Expand Up @@ -933,6 +969,7 @@ process_remote_update(StringInfo s)
ErrorContextCallback errcallback;
struct ActionErrCallbackArg cbarg;
ResultRelInfo *relinfo = makeNode(ResultRelInfo);
UserContext ucxt;

xact_action_counter++;
memset(&cbarg, 0, sizeof(struct ActionErrCallbackArg));
Expand All @@ -946,6 +983,14 @@ process_remote_update(StringInfo s)

rel = read_rel(s, RowExclusiveLock, &cbarg);

if (pgactive_apply_as_table_owner)
{
SwitchToUntrustedUser(rel->rel->rd_rel->relowner, &ucxt);
elog(DEBUG1, "pgactive apply UPDATE as user %s on %s",
GetUserNameFromId(rel->rel->rd_rel->relowner, false),
RelationGetRelationName(rel->rel));
}

emit_replay_info(&cbarg);

action = pq_getmsgbyte(s);
Expand Down Expand Up @@ -1183,6 +1228,9 @@ process_remote_update(StringInfo s)

PopActiveSnapshot();

if (pgactive_apply_as_table_owner)
RestoreUserContext(&ucxt);

check_pgactive_wakeups(rel);

/* release locks upon commit */
Expand Down Expand Up @@ -1213,6 +1261,7 @@ process_remote_delete(StringInfo s)
ErrorContextCallback errcallback;
struct ActionErrCallbackArg cbarg;
ResultRelInfo *relinfo = makeNode(ResultRelInfo);
UserContext ucxt;

Assert(pgactive_apply_worker != NULL);

Expand All @@ -1228,6 +1277,14 @@ process_remote_delete(StringInfo s)

rel = read_rel(s, RowExclusiveLock, &cbarg);

if (pgactive_apply_as_table_owner)
{
SwitchToUntrustedUser(rel->rel->rd_rel->relowner, &ucxt);
elog(DEBUG1, "pgactive apply DELETE as user %s on %s",
GetUserNameFromId(rel->rel->rd_rel->relowner, false),
RelationGetRelationName(rel->rel));
}

emit_replay_info(&cbarg);

action = pq_getmsgbyte(s);
Expand All @@ -1238,6 +1295,8 @@ process_remote_delete(StringInfo s)
if (action == 'E')
{
elog(WARNING, "got delete without pkey");
if (pgactive_apply_as_table_owner)
RestoreUserContext(&ucxt);
pgactive_table_close(rel, NoLock);
return;
}
Expand Down Expand Up @@ -1367,6 +1426,9 @@ process_remote_delete(StringInfo s)

PopActiveSnapshot();

if (pgactive_apply_as_table_owner)
RestoreUserContext(&ucxt);

check_pgactive_wakeups(rel);

index_close(idxrel, NoLock);
Expand Down
Loading
Loading