public inbox for [email protected]help / color / mirror / Atom feed
[PATCH v34 4/7] Make archiver process an auxiliary process 8+ messages / 4 participants [nested] [flat]
* [PATCH v34 4/7] Make archiver process an auxiliary process @ 2020-03-13 07:59 Kyotaro Horiguchi <[email protected]> 0 siblings, 0 replies; 8+ messages in thread From: Kyotaro Horiguchi @ 2020-03-13 07:59 UTC (permalink / raw) This is a preliminary patch for shared-memory based stats collector. Archiver process must be a auxiliary process since it uses shared memory after stats data was moved into shared-memory. Make the process an auxiliary process in order to make it work. --- src/backend/access/transam/xlogarchive.c | 6 +- src/backend/bootstrap/bootstrap.c | 22 ++-- src/backend/postmaster/pgarch.c | 130 +++-------------------- src/backend/postmaster/postmaster.c | 50 +++++---- src/backend/storage/lmgr/proc.c | 1 + src/include/access/xlog.h | 3 + src/include/access/xlogarchive.h | 1 + src/include/miscadmin.h | 2 + src/include/postmaster/pgarch.h | 4 +- src/include/storage/pmsignal.h | 1 - src/include/storage/proc.h | 3 + 11 files changed, 69 insertions(+), 154 deletions(-) diff --git a/src/backend/access/transam/xlogarchive.c b/src/backend/access/transam/xlogarchive.c index cdd586fcfb..ee3444284b 100644 --- a/src/backend/access/transam/xlogarchive.c +++ b/src/backend/access/transam/xlogarchive.c @@ -29,7 +29,9 @@ #include "storage/fd.h" #include "storage/ipc.h" #include "storage/lwlock.h" +#include "storage/latch.h" #include "storage/pmsignal.h" +#include "storage/proc.h" /* * Attempt to retrieve the specified file from off-line archival storage. @@ -489,8 +491,8 @@ XLogArchiveNotify(const char *xlog) } /* Notify archiver that it's got something to do */ - if (IsUnderPostmaster) - SendPostmasterSignal(PMSIGNAL_WAKEN_ARCHIVER); + if (IsUnderPostmaster && ProcGlobal->archiverLatch) + SetLatch(ProcGlobal->archiverLatch); } /* diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c index 5480a024e0..d398ce6f03 100644 --- a/src/backend/bootstrap/bootstrap.c +++ b/src/backend/bootstrap/bootstrap.c @@ -319,6 +319,9 @@ AuxiliaryProcessMain(int argc, char *argv[]) case StartupProcess: MyBackendType = B_STARTUP; break; + case ArchiverProcess: + MyBackendType = B_ARCHIVER; + break; case BgWriterProcess: MyBackendType = B_BG_WRITER; break; @@ -439,30 +442,29 @@ AuxiliaryProcessMain(int argc, char *argv[]) proc_exit(1); /* should never return */ case StartupProcess: - /* don't set signals, startup process has its own agenda */ StartupProcessMain(); - proc_exit(1); /* should never return */ + proc_exit(1); + + case ArchiverProcess: + PgArchiverMain(); + proc_exit(1); case BgWriterProcess: - /* don't set signals, bgwriter has its own agenda */ BackgroundWriterMain(); - proc_exit(1); /* should never return */ + proc_exit(1); case CheckpointerProcess: - /* don't set signals, checkpointer has its own agenda */ CheckpointerMain(); - proc_exit(1); /* should never return */ + proc_exit(1); case WalWriterProcess: - /* don't set signals, walwriter has its own agenda */ InitXLOGAccess(); WalWriterMain(); - proc_exit(1); /* should never return */ + proc_exit(1); case WalReceiverProcess: - /* don't set signals, walreceiver has its own agenda */ WalReceiverMain(); - proc_exit(1); /* should never return */ + proc_exit(1); default: elog(PANIC, "unrecognized process type: %d", (int) MyAuxProcType); diff --git a/src/backend/postmaster/pgarch.c b/src/backend/postmaster/pgarch.c index 37be0e2bbb..063d1323ea 100644 --- a/src/backend/postmaster/pgarch.c +++ b/src/backend/postmaster/pgarch.c @@ -48,6 +48,7 @@ #include "storage/latch.h" #include "storage/pg_shmem.h" #include "storage/pmsignal.h" +#include "storage/procsignal.h" #include "utils/guc.h" #include "utils/ps_status.h" @@ -78,13 +79,11 @@ * Local data * ---------- */ -static time_t last_pgarch_start_time; static time_t last_sigterm_time = 0; /* * Flags set by interrupt handlers for later service in the main loop. */ -static volatile sig_atomic_t wakened = false; static volatile sig_atomic_t ready_to_stop = false; /* ---------- @@ -95,8 +94,6 @@ static volatile sig_atomic_t ready_to_stop = false; static pid_t pgarch_forkexec(void); #endif -NON_EXEC_STATIC void PgArchiverMain(int argc, char *argv[]) pg_attribute_noreturn(); -static void pgarch_waken(SIGNAL_ARGS); static void pgarch_waken_stop(SIGNAL_ARGS); static void pgarch_MainLoop(void); static void pgarch_ArchiverCopyLoop(void); @@ -110,75 +107,6 @@ static void pgarch_archiveDone(char *xlog); * ------------------------------------------------------------ */ -/* - * pgarch_start - * - * Called from postmaster at startup or after an existing archiver - * died. Attempt to fire up a fresh archiver process. - * - * Returns PID of child process, or 0 if fail. - * - * Note: if fail, we will be called again from the postmaster main loop. - */ -int -pgarch_start(void) -{ - time_t curtime; - pid_t pgArchPid; - - /* - * Do nothing if no archiver needed - */ - if (!XLogArchivingActive()) - return 0; - - /* - * Do nothing if too soon since last archiver start. This is a safety - * valve to protect against continuous respawn attempts if the archiver is - * dying immediately at launch. Note that since we will be re-called from - * the postmaster main loop, we will get another chance later. - */ - curtime = time(NULL); - if ((unsigned int) (curtime - last_pgarch_start_time) < - (unsigned int) PGARCH_RESTART_INTERVAL) - return 0; - last_pgarch_start_time = curtime; - -#ifdef EXEC_BACKEND - switch ((pgArchPid = pgarch_forkexec())) -#else - switch ((pgArchPid = fork_process())) -#endif - { - case -1: - ereport(LOG, - (errmsg("could not fork archiver: %m"))); - return 0; - -#ifndef EXEC_BACKEND - case 0: - /* in postmaster child ... */ - InitPostmasterChild(); - - /* Close the postmaster's sockets */ - ClosePostmasterPorts(false); - - /* Drop our connection to postmaster's shared memory, as well */ - dsm_detach_all(); - PGSharedMemoryDetach(); - - PgArchiverMain(0, NULL); - break; -#endif - - default: - return (int) pgArchPid; - } - - /* shouldn't get here */ - return 0; -} - /* ------------------------------------------------------------ * Local functions called by archiver follow * ------------------------------------------------------------ @@ -212,14 +140,9 @@ pgarch_forkexec(void) #endif /* EXEC_BACKEND */ -/* - * PgArchiverMain - * - * The argc/argv parameters are valid only in EXEC_BACKEND case. However, - * since we don't use 'em, it hardly matters... - */ -NON_EXEC_STATIC void -PgArchiverMain(int argc, char *argv[]) +/* Main entry point for archiver process */ +void +PgArchiverMain(void) { /* * Ignore all signals usually bound to some action in the postmaster, @@ -231,33 +154,26 @@ PgArchiverMain(int argc, char *argv[]) pqsignal(SIGQUIT, SignalHandlerForCrashExit); pqsignal(SIGALRM, SIG_IGN); pqsignal(SIGPIPE, SIG_IGN); - pqsignal(SIGUSR1, pgarch_waken); + pqsignal(SIGUSR1, procsignal_sigusr1_handler); pqsignal(SIGUSR2, pgarch_waken_stop); + /* Reset some signals that are accepted by postmaster but not here */ pqsignal(SIGCHLD, SIG_DFL); + + /* Unblock signals (they were blocked when the postmaster forked us) */ PG_SETMASK(&UnBlockSig); - MyBackendType = B_ARCHIVER; - init_ps_display(NULL); + /* + * Advertise our latch that backends can use to wake us up while we're + * sleeping. + */ + ProcGlobal->archiverLatch = &MyProc->procLatch; pgarch_MainLoop(); exit(0); } -/* SIGUSR1 signal handler for archiver process */ -static void -pgarch_waken(SIGNAL_ARGS) -{ - int save_errno = errno; - - /* set flag that there is work to be done */ - wakened = true; - SetLatch(MyLatch); - - errno = save_errno; -} - /* SIGUSR2 signal handler for archiver process */ static void pgarch_waken_stop(SIGNAL_ARGS) @@ -282,14 +198,6 @@ pgarch_MainLoop(void) pg_time_t last_copy_time = 0; bool time_to_stop; - /* - * We run the copy loop immediately upon entry, in case there are - * unarchived files left over from a previous database run (or maybe the - * archiver died unexpectedly). After that we wait for a signal or - * timeout before doing more. - */ - wakened = true; - /* * There shouldn't be anything for the archiver to do except to wait for a * signal ... however, the archiver exists to protect our data, so she @@ -328,12 +236,8 @@ pgarch_MainLoop(void) } /* Do what we're here for */ - if (wakened || time_to_stop) - { - wakened = false; - pgarch_ArchiverCopyLoop(); - last_copy_time = time(NULL); - } + pgarch_ArchiverCopyLoop(); + last_copy_time = time(NULL); /* * Sleep until a signal is received, or until a poll is forced by @@ -354,13 +258,9 @@ pgarch_MainLoop(void) WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH, timeout * 1000L, WAIT_EVENT_ARCHIVER_MAIN); - if (rc & WL_TIMEOUT) - wakened = true; if (rc & WL_POSTMASTER_DEATH) time_to_stop = true; } - else - wakened = true; } /* diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 160afe9f39..9de9396628 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -539,6 +539,7 @@ static void ShmemBackendArrayRemove(Backend *bn); #endif /* EXEC_BACKEND */ #define StartupDataBase() StartChildProcess(StartupProcess) +#define StartArchiver() StartChildProcess(ArchiverProcess) #define StartBackgroundWriter() StartChildProcess(BgWriterProcess) #define StartCheckpointer() StartChildProcess(CheckpointerProcess) #define StartWalWriter() StartChildProcess(WalWriterProcess) @@ -1785,7 +1786,7 @@ ServerLoop(void) /* If we have lost the archiver, try to start a new one. */ if (PgArchPID == 0 && PgArchStartupAllowed()) - PgArchPID = pgarch_start(); + PgArchPID = StartArchiver(); /* If we need to signal the autovacuum launcher, do so now */ if (avlauncher_needs_signal) @@ -3068,7 +3069,7 @@ reaper(SIGNAL_ARGS) if (!IsBinaryUpgrade && AutoVacuumingActive() && AutoVacPID == 0) AutoVacPID = StartAutoVacLauncher(); if (PgArchStartupAllowed() && PgArchPID == 0) - PgArchPID = pgarch_start(); + PgArchPID = StartArchiver(); if (PgStatPID == 0) PgStatPID = pgstat_start(); @@ -3203,20 +3204,16 @@ reaper(SIGNAL_ARGS) } /* - * Was it the archiver? If so, just try to start a new one; no need - * to force reset of the rest of the system. (If fail, we'll try - * again in future cycles of the main loop.). Unless we were waiting - * for it to shut down; don't restart it in that case, and - * PostmasterStateMachine() will advance to the next shutdown step. + * Was it the archiver? Normal exit can be ignored; we'll start a new + * one at the next iteration of the postmaster's main loop, if + * necessary. Any other exit condition is treated as a crash. */ if (pid == PgArchPID) { PgArchPID = 0; if (!EXIT_STATUS_0(exitstatus)) - LogChildExit(LOG, _("archiver process"), - pid, exitstatus); - if (PgArchStartupAllowed()) - PgArchPID = pgarch_start(); + HandleChildCrash(pid, exitstatus, + _("archiver process")); continue; } @@ -3464,7 +3461,7 @@ CleanupBackend(int pid, /* * HandleChildCrash -- cleanup after failed backend, bgwriter, checkpointer, - * walwriter, autovacuum, or background worker. + * walwriter, autovacuum, archiver or background worker. * * The objectives here are to clean up our local state about the child * process, and to signal all other remaining children to quickdie. @@ -3669,6 +3666,18 @@ HandleChildCrash(int pid, int exitstatus, const char *procname) signal_child(AutoVacPID, (SendStop ? SIGSTOP : SIGQUIT)); } + /* Take care of the archiver too */ + if (pid == PgArchPID) + PgArchPID = 0; + else if (PgArchPID != 0 && take_action) + { + ereport(DEBUG2, + (errmsg_internal("sending %s to process %d", + (SendStop ? "SIGSTOP" : "SIGQUIT"), + (int) PgArchPID))); + signal_child(PgArchPID, (SendStop ? SIGSTOP : SIGQUIT)); + } + /* * Force a power-cycle of the pgarch process too. (This isn't absolutely * necessary, but it seems like a good idea for robustness, and it @@ -3941,6 +3950,7 @@ PostmasterStateMachine(void) Assert(CheckpointerPID == 0); Assert(WalWriterPID == 0); Assert(AutoVacPID == 0); + Assert(PgArchPID == 0); /* syslogger is not considered here */ pmState = PM_NO_CHILDREN; } @@ -5216,7 +5226,7 @@ sigusr1_handler(SIGNAL_ARGS) */ Assert(PgArchPID == 0); if (XLogArchivingAlways()) - PgArchPID = pgarch_start(); + PgArchPID = StartArchiver(); /* * If we aren't planning to enter hot standby mode later, treat @@ -5259,16 +5269,6 @@ sigusr1_handler(SIGNAL_ARGS) if (StartWorkerNeeded || HaveCrashedWorker) maybe_start_bgworkers(); - if (CheckPostmasterSignal(PMSIGNAL_WAKEN_ARCHIVER) && - PgArchPID != 0) - { - /* - * Send SIGUSR1 to archiver process, to wake it up and begin archiving - * next WAL file. - */ - signal_child(PgArchPID, SIGUSR1); - } - /* Tell syslogger to rotate logfile if requested */ if (SysLoggerPID != 0) { @@ -5501,6 +5501,10 @@ StartChildProcess(AuxProcType type) ereport(LOG, (errmsg("could not fork startup process: %m"))); break; + case ArchiverProcess: + ereport(LOG, + (errmsg("could not fork archiver process: %m"))); + break; case BgWriterProcess: ereport(LOG, (errmsg("could not fork background writer process: %m"))); diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index f5eef6fa4e..46f0198510 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -187,6 +187,7 @@ InitProcGlobal(void) ProcGlobal->startupBufferPinWaitBufId = -1; ProcGlobal->walwriterLatch = NULL; ProcGlobal->checkpointerLatch = NULL; + ProcGlobal->archiverLatch = NULL; pg_atomic_init_u32(&ProcGlobal->procArrayGroupFirst, INVALID_PGPROCNO); pg_atomic_init_u32(&ProcGlobal->clogGroupFirst, INVALID_PGPROCNO); diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h index e917dfe92d..0783692c83 100644 --- a/src/include/access/xlog.h +++ b/src/include/access/xlog.h @@ -336,6 +336,9 @@ extern XLogRecPtr GetRedoRecPtr(void); extern XLogRecPtr GetInsertRecPtr(void); extern XLogRecPtr GetFlushRecPtr(void); extern XLogRecPtr GetLastImportantRecPtr(void); +extern void XLogArchiveWakeupStart(void); +extern void XLogArchiveWakeupEnd(void); +extern void XLogArchiveWakeup(void); extern void RemovePromoteSignalFiles(void); extern bool PromoteIsTriggered(void); diff --git a/src/include/access/xlogarchive.h b/src/include/access/xlogarchive.h index 1c67de2ede..54ce0b97d7 100644 --- a/src/include/access/xlogarchive.h +++ b/src/include/access/xlogarchive.h @@ -25,6 +25,7 @@ extern void ExecuteRecoveryCommand(const char *command, const char *commandName, extern void KeepFileRestoredFromArchive(const char *path, const char *xlogfname); extern void XLogArchiveNotify(const char *xlog); extern void XLogArchiveNotifySeg(XLogSegNo segno); +extern void XLogArchiveWakeup(void); extern void XLogArchiveForceDone(const char *xlog); extern bool XLogArchiveCheckDone(const char *xlog); extern bool XLogArchiveIsBusy(const char *xlog); diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h index 14fa127ab1..619b2f9c71 100644 --- a/src/include/miscadmin.h +++ b/src/include/miscadmin.h @@ -417,6 +417,7 @@ typedef enum BootstrapProcess, StartupProcess, BgWriterProcess, + ArchiverProcess, CheckpointerProcess, WalWriterProcess, WalReceiverProcess, @@ -429,6 +430,7 @@ extern AuxProcType MyAuxProcType; #define AmBootstrapProcess() (MyAuxProcType == BootstrapProcess) #define AmStartupProcess() (MyAuxProcType == StartupProcess) #define AmBackgroundWriterProcess() (MyAuxProcType == BgWriterProcess) +#define AmArchiverProcess() (MyAuxProcType == ArchiverProcess) #define AmCheckpointerProcess() (MyAuxProcType == CheckpointerProcess) #define AmWalWriterProcess() (MyAuxProcType == WalWriterProcess) #define AmWalReceiverProcess() (MyAuxProcType == WalReceiverProcess) diff --git a/src/include/postmaster/pgarch.h b/src/include/postmaster/pgarch.h index b3200874ca..e3ffc63f14 100644 --- a/src/include/postmaster/pgarch.h +++ b/src/include/postmaster/pgarch.h @@ -32,8 +32,6 @@ */ extern int pgarch_start(void); -#ifdef EXEC_BACKEND -extern void PgArchiverMain(int argc, char *argv[]) pg_attribute_noreturn(); -#endif +extern void PgArchiverMain(void) pg_attribute_noreturn(); #endif /* _PGARCH_H */ diff --git a/src/include/storage/pmsignal.h b/src/include/storage/pmsignal.h index 56c5ec4481..c691acf8cd 100644 --- a/src/include/storage/pmsignal.h +++ b/src/include/storage/pmsignal.h @@ -34,7 +34,6 @@ typedef enum { PMSIGNAL_RECOVERY_STARTED, /* recovery has started */ PMSIGNAL_BEGIN_HOT_STANDBY, /* begin Hot Standby */ - PMSIGNAL_WAKEN_ARCHIVER, /* send a NOTIFY signal to xlog archiver */ PMSIGNAL_ROTATE_LOGFILE, /* send SIGUSR1 to syslogger to rotate logfile */ PMSIGNAL_START_AUTOVAC_LAUNCHER, /* start an autovacuum launcher */ PMSIGNAL_START_AUTOVAC_WORKER, /* start an autovacuum worker */ diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h index 1ee9000b2b..8ab6d859bb 100644 --- a/src/include/storage/proc.h +++ b/src/include/storage/proc.h @@ -270,6 +270,9 @@ typedef struct PROC_HDR int startupProcPid; /* Buffer id of the buffer that Startup process waits for pin on, or -1 */ int startupBufferPinWaitBufId; + /* Archiver process's latch */ + Latch *archiverLatch; + /* Current shared estimate of appropriate spins_per_delay value */ } PROC_HDR; extern PGDLLIMPORT PROC_HDR *ProcGlobal; -- 2.18.2 ----Next_Part(Mon_Jun__1_18_00_01_2020_089)-- Content-Type: Text/X-Patch; charset=us-ascii Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="v34-0005-Shared-memory-based-stats-collector.patch" ^ permalink raw reply [nested|flat] 8+ messages in thread
* Add a new BGWORKER_BYPASS_ROLELOGINCHECK flag @ 2023-09-28 12:37 Drouvot, Bertrand <[email protected]> 0 siblings, 1 reply; 8+ messages in thread From: Drouvot, Bertrand @ 2023-09-28 12:37 UTC (permalink / raw) To: PostgreSQL Hackers <[email protected]> Hi hackers, Please find attached a patch proposal to $SUBJECT. This patch allows the role provided in BackgroundWorkerInitializeConnection() and BackgroundWorkerInitializeConnectionByOid() to lack login authorization. In InitPostgres(), in case of a background worker, authentication is not performed (PerformAuthentication() is not called), so having the role used to connect to the database lacking login authorization seems to make sense. With this new flag in place, one could give "high" privileges to the role used to initialize the background workers connections without any risk of seeing this role being used by a "normal user" to login. The attached patch: - adds the new flag - adds documentation - adds testing Looking forward to your feedback, Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com From 82ea53a81a5e9f5e8b680ec6de849a48a7222463 Mon Sep 17 00:00:00 2001 From: Bertrand Drouvot <[email protected]> Date: Wed, 20 Sep 2023 08:28:59 +0000 Subject: [PATCH v1] Allow background workers to bypass login check This adds a new flag value (BGWORKER_BYPASS_ROLELOGINCHECK) to the flags being used in BackgroundWorkerInitializeConnection() and BackgroundWorkerInitializeConnectionByOid(). This flag allows the background workers to bypass the login check done in InitializeSessionUserId(). --- doc/src/sgml/bgworker.sgml | 3 +- src/backend/bootstrap/bootstrap.c | 2 +- src/backend/postmaster/autovacuum.c | 4 +- src/backend/postmaster/postmaster.c | 4 +- src/backend/tcop/postgres.c | 2 +- src/backend/utils/init/miscinit.c | 4 +- src/backend/utils/init/postinit.c | 9 ++-- src/include/miscadmin.h | 5 +- src/include/postmaster/bgworker.h | 6 ++- .../modules/worker_spi/t/001_worker_spi.pl | 48 +++++++++++++++++++ src/test/modules/worker_spi/worker_spi.c | 25 +++++++++- 11 files changed, 95 insertions(+), 17 deletions(-) 6.9% doc/src/sgml/ 3.4% src/backend/bootstrap/ 10.6% src/backend/postmaster/ 16.8% src/backend/utils/init/ 7.2% src/include/postmaster/ 29.7% src/test/modules/worker_spi/t/ 21.1% src/test/modules/worker_spi/ 4.0% src/ diff --git a/doc/src/sgml/bgworker.sgml b/doc/src/sgml/bgworker.sgml index 9ad1146ba0..7335c02ed8 100644 --- a/doc/src/sgml/bgworker.sgml +++ b/doc/src/sgml/bgworker.sgml @@ -200,7 +200,8 @@ typedef struct BackgroundWorker <literal>InvalidOid</literal>, the process will run as the superuser created during <command>initdb</command>. If <literal>BGWORKER_BYPASS_ALLOWCONN</literal> is specified as <varname>flags</varname> it is possible to bypass the restriction - to connect to databases not allowing user connections. + to connect to databases not allowing user connections. If <literal>BGWORKER_BYPASS_ROLELOGINCHECK</literal> + is specified as <varname>flags</varname> it is possible to bypass the login check to connect to databases. A background worker can only call one of these two functions, and only once. It is not possible to switch databases. </para> diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c index 5810f8825e..d4b6425585 100644 --- a/src/backend/bootstrap/bootstrap.c +++ b/src/backend/bootstrap/bootstrap.c @@ -345,7 +345,7 @@ BootstrapModeMain(int argc, char *argv[], bool check_only) if (pg_link_canary_is_frontend()) elog(ERROR, "backend is incorrectly linked to frontend functions"); - InitPostgres(NULL, InvalidOid, NULL, InvalidOid, false, false, NULL); + InitPostgres(NULL, InvalidOid, NULL, InvalidOid, false, 0, NULL); /* Initialize stuff for bootstrap-file processing */ for (i = 0; i < MAXATTR; i++) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index ae9be9b911..dde83e76fb 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -488,7 +488,7 @@ AutoVacLauncherMain(int argc, char *argv[]) /* Early initialization */ BaseInit(); - InitPostgres(NULL, InvalidOid, NULL, InvalidOid, false, false, NULL); + InitPostgres(NULL, InvalidOid, NULL, InvalidOid, false, 0, NULL); SetProcessingMode(NormalProcessing); @@ -1706,7 +1706,7 @@ AutoVacWorkerMain(int argc, char *argv[]) * Note: if we have selected a just-deleted database (due to using * stale stats info), we'll fail and exit here. */ - InitPostgres(NULL, dbid, NULL, InvalidOid, false, false, + InitPostgres(NULL, dbid, NULL, InvalidOid, false, 0, dbname); SetProcessingMode(NormalProcessing); set_ps_display(dbname); diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 54e9bfb8c4..443b1c4725 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -5588,7 +5588,7 @@ BackgroundWorkerInitializeConnection(const char *dbname, const char *username, u InitPostgres(dbname, InvalidOid, /* database to connect to */ username, InvalidOid, /* role to connect as */ false, /* never honor session_preload_libraries */ - (flags & BGWORKER_BYPASS_ALLOWCONN) != 0, /* ignore datallowconn? */ + flags, NULL); /* no out_dbname */ /* it had better not gotten out of "init" mode yet */ @@ -5615,7 +5615,7 @@ BackgroundWorkerInitializeConnectionByOid(Oid dboid, Oid useroid, uint32 flags) InitPostgres(NULL, dboid, /* database to connect to */ NULL, useroid, /* role to connect as */ false, /* never honor session_preload_libraries */ - (flags & BGWORKER_BYPASS_ALLOWCONN) != 0, /* ignore datallowconn? */ + flags, NULL); /* no out_dbname */ /* it had better not gotten out of "init" mode yet */ diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 21b9763183..f5ef8f52a8 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -4210,7 +4210,7 @@ PostgresMain(const char *dbname, const char *username) InitPostgres(dbname, InvalidOid, /* database to connect to */ username, InvalidOid, /* role to connect as */ !am_walsender, /* honor session_preload_libraries? */ - false, /* don't ignore datallowconn */ + 0, NULL); /* no out_dbname */ /* diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c index 1e671c560c..182d666852 100644 --- a/src/backend/utils/init/miscinit.c +++ b/src/backend/utils/init/miscinit.c @@ -725,7 +725,7 @@ has_rolreplication(Oid roleid) * Initialize user identity during normal backend startup */ void -InitializeSessionUserId(const char *rolename, Oid roleid) +InitializeSessionUserId(const char *rolename, Oid roleid, bool bypass_login_check) { HeapTuple roleTup; Form_pg_authid rform; @@ -789,7 +789,7 @@ InitializeSessionUserId(const char *rolename, Oid roleid) /* * Is role allowed to login at all? */ - if (!rform->rolcanlogin) + if (!bypass_login_check && !rform->rolcanlogin) ereport(FATAL, (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION), errmsg("role \"%s\" is not permitted to log in", diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c index df4d15a50f..6ccedffd62 100644 --- a/src/backend/utils/init/postinit.c +++ b/src/backend/utils/init/postinit.c @@ -41,6 +41,7 @@ #include "miscadmin.h" #include "pgstat.h" #include "postmaster/autovacuum.h" +#include "postmaster/bgworker.h" #include "postmaster/postmaster.h" #include "replication/slot.h" #include "replication/walsender.h" @@ -718,10 +719,12 @@ void InitPostgres(const char *in_dbname, Oid dboid, const char *username, Oid useroid, bool load_session_libraries, - bool override_allow_connections, + uint32 flags, char *out_dbname) { bool bootstrap = IsBootstrapProcessingMode(); + bool override_allow_connections = (flags & BGWORKER_BYPASS_ALLOWCONN) != 0; + bool bypass_login_check = (flags & BGWORKER_BYPASS_ROLELOGINCHECK) != 0; bool am_superuser; char *fullpath; char dbname[NAMEDATALEN]; @@ -901,7 +904,7 @@ InitPostgres(const char *in_dbname, Oid dboid, } else { - InitializeSessionUserId(username, useroid); + InitializeSessionUserId(username, useroid, bypass_login_check); am_superuser = superuser(); } } @@ -910,7 +913,7 @@ InitPostgres(const char *in_dbname, Oid dboid, /* normal multiuser case */ Assert(MyProcPort != NULL); PerformAuthentication(MyProcPort); - InitializeSessionUserId(username, useroid); + InitializeSessionUserId(username, useroid, false); /* ensure that auth_method is actually valid, aka authn_id is not NULL */ if (MyClientConnectionInfo.authn_id) InitializeSystemUser(MyClientConnectionInfo.authn_id, diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h index 14bd574fc2..7e6ee415cb 100644 --- a/src/include/miscadmin.h +++ b/src/include/miscadmin.h @@ -364,7 +364,8 @@ extern bool InSecurityRestrictedOperation(void); extern bool InNoForceRLSOperation(void); extern void GetUserIdAndContext(Oid *userid, bool *sec_def_context); extern void SetUserIdAndContext(Oid userid, bool sec_def_context); -extern void InitializeSessionUserId(const char *rolename, Oid roleid); +extern void InitializeSessionUserId(const char *rolename, Oid roleid, + bool bypass_login_check); extern void InitializeSessionUserIdStandalone(void); extern void SetSessionAuthorization(Oid userid, bool is_superuser); extern Oid GetCurrentRoleId(void); @@ -468,7 +469,7 @@ extern void InitializeMaxBackends(void); extern void InitPostgres(const char *in_dbname, Oid dboid, const char *username, Oid useroid, bool load_session_libraries, - bool override_allow_connections, + uint32 flags, char *out_dbname); extern void BaseInit(void); diff --git a/src/include/postmaster/bgworker.h b/src/include/postmaster/bgworker.h index 7815507e3d..d7a5c1a946 100644 --- a/src/include/postmaster/bgworker.h +++ b/src/include/postmaster/bgworker.h @@ -150,9 +150,11 @@ extern void BackgroundWorkerInitializeConnectionByOid(Oid dboid, Oid useroid, ui * Flags to BackgroundWorkerInitializeConnection et al * * - * Allow bypassing datallowconn restrictions when connecting to database + * Allow bypassing datallowconn restrictions and login check when connecting + * to database */ -#define BGWORKER_BYPASS_ALLOWCONN 1 +#define BGWORKER_BYPASS_ALLOWCONN 0x0001 +#define BGWORKER_BYPASS_ROLELOGINCHECK 0x0002 /* Block/unblock signals in a background worker process */ diff --git a/src/test/modules/worker_spi/t/001_worker_spi.pl b/src/test/modules/worker_spi/t/001_worker_spi.pl index 2965acd789..ff8b72f5b5 100644 --- a/src/test/modules/worker_spi/t/001_worker_spi.pl +++ b/src/test/modules/worker_spi/t/001_worker_spi.pl @@ -93,4 +93,52 @@ ok( $node->poll_query_until( 'dynamic bgworkers all launched' ) or die "Timed out while waiting for dynamic bgworkers to be launched"; +# Check BGWORKER_BYPASS_ROLELOGINCHECK behaves as expected. + +# First create a role without login. +$node->safe_psql( + 'postgres', qq[ + CREATE ROLE nologrole with nologin; + ALTER ROLE nologrole with superuser; +]); + +my $log_start = get_log_size($node); + +# Ask the background workers to connect with this role. +$node->append_conf( + 'postgresql.conf', q{ +worker_spi.role = 'nologrole' +}); +$node->restart; + +# An error message should be issued. +ok( $node->log_contains( + "role \"nologrole\" is not permitted to log in", $log_start), + "nologrole not allowed to connect if BGWORKER_BYPASS_ROLELOGINCHECK is not set" +); + + +$log_start = get_log_size($node); + +# Ask the background workers to connect with this role with the flag in place. +$node->append_conf( + 'postgresql.conf', q{ +worker_spi.role = 'nologrole' +worker_spi.bypass_login_check = true +}); +$node->restart; + +# An error message should not be issued. +ok( !$node->log_contains( + "role \"nologrole\" is not permitted to log in", $log_start), + "nologrole allowed to connect if BGWORKER_BYPASS_ROLELOGINCHECK is set"); + done_testing(); + +# return the size of logfile of $node in bytes +sub get_log_size +{ + my ($node) = @_; + + return (stat $node->logfile)[7]; +} diff --git a/src/test/modules/worker_spi/worker_spi.c b/src/test/modules/worker_spi/worker_spi.c index 98f8d4194b..d2ca99f2c5 100644 --- a/src/test/modules/worker_spi/worker_spi.c +++ b/src/test/modules/worker_spi/worker_spi.c @@ -52,6 +52,8 @@ PGDLLEXPORT void worker_spi_main(Datum main_arg) pg_attribute_noreturn(); static int worker_spi_naptime = 10; static int worker_spi_total_workers = 2; static char *worker_spi_database = NULL; +static char *worker_spi_role = NULL; +static bool worker_spi_bypass_login_check = false; /* value cached, fetched from shared memory */ static uint32 worker_spi_wait_event_main = 0; @@ -152,7 +154,10 @@ worker_spi_main(Datum main_arg) BackgroundWorkerUnblockSignals(); /* Connect to our database */ - BackgroundWorkerInitializeConnection(worker_spi_database, NULL, 0); + if (worker_spi_bypass_login_check) + BackgroundWorkerInitializeConnection(worker_spi_database, worker_spi_role, BGWORKER_BYPASS_ROLELOGINCHECK); + else + BackgroundWorkerInitializeConnection(worker_spi_database, worker_spi_role, 0); elog(LOG, "%s initialized with %s.%s", MyBgworkerEntry->bgw_name, table->schema, table->name); @@ -316,6 +321,24 @@ _PG_init(void) 0, NULL, NULL, NULL); + DefineCustomStringVariable("worker_spi.role", + "Role to connect with.", + NULL, + &worker_spi_role, + NULL, + PGC_SIGHUP, + 0, + NULL, NULL, NULL); + + DefineCustomBoolVariable("worker_spi.bypass_login_check", + "Should BGW allows to connect with non login role.", + NULL, + &worker_spi_bypass_login_check, + false, + PGC_SIGHUP, + 0, + NULL, NULL, NULL); + if (!process_shared_preload_libraries_in_progress) return; -- 2.34.1 Attachments: [text/plain] v1-0001-Allow-background-workers-to-bypass-login-check.patch (12.9K, ../../[email protected]/2-v1-0001-Allow-background-workers-to-bypass-login-check.patch) download | inline diff: From 82ea53a81a5e9f5e8b680ec6de849a48a7222463 Mon Sep 17 00:00:00 2001 From: Bertrand Drouvot <[email protected]> Date: Wed, 20 Sep 2023 08:28:59 +0000 Subject: [PATCH v1] Allow background workers to bypass login check This adds a new flag value (BGWORKER_BYPASS_ROLELOGINCHECK) to the flags being used in BackgroundWorkerInitializeConnection() and BackgroundWorkerInitializeConnectionByOid(). This flag allows the background workers to bypass the login check done in InitializeSessionUserId(). --- doc/src/sgml/bgworker.sgml | 3 +- src/backend/bootstrap/bootstrap.c | 2 +- src/backend/postmaster/autovacuum.c | 4 +- src/backend/postmaster/postmaster.c | 4 +- src/backend/tcop/postgres.c | 2 +- src/backend/utils/init/miscinit.c | 4 +- src/backend/utils/init/postinit.c | 9 ++-- src/include/miscadmin.h | 5 +- src/include/postmaster/bgworker.h | 6 ++- .../modules/worker_spi/t/001_worker_spi.pl | 48 +++++++++++++++++++ src/test/modules/worker_spi/worker_spi.c | 25 +++++++++- 11 files changed, 95 insertions(+), 17 deletions(-) 6.9% doc/src/sgml/ 3.4% src/backend/bootstrap/ 10.6% src/backend/postmaster/ 16.8% src/backend/utils/init/ 7.2% src/include/postmaster/ 29.7% src/test/modules/worker_spi/t/ 21.1% src/test/modules/worker_spi/ 4.0% src/ diff --git a/doc/src/sgml/bgworker.sgml b/doc/src/sgml/bgworker.sgml index 9ad1146ba0..7335c02ed8 100644 --- a/doc/src/sgml/bgworker.sgml +++ b/doc/src/sgml/bgworker.sgml @@ -200,7 +200,8 @@ typedef struct BackgroundWorker <literal>InvalidOid</literal>, the process will run as the superuser created during <command>initdb</command>. If <literal>BGWORKER_BYPASS_ALLOWCONN</literal> is specified as <varname>flags</varname> it is possible to bypass the restriction - to connect to databases not allowing user connections. + to connect to databases not allowing user connections. If <literal>BGWORKER_BYPASS_ROLELOGINCHECK</literal> + is specified as <varname>flags</varname> it is possible to bypass the login check to connect to databases. A background worker can only call one of these two functions, and only once. It is not possible to switch databases. </para> diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c index 5810f8825e..d4b6425585 100644 --- a/src/backend/bootstrap/bootstrap.c +++ b/src/backend/bootstrap/bootstrap.c @@ -345,7 +345,7 @@ BootstrapModeMain(int argc, char *argv[], bool check_only) if (pg_link_canary_is_frontend()) elog(ERROR, "backend is incorrectly linked to frontend functions"); - InitPostgres(NULL, InvalidOid, NULL, InvalidOid, false, false, NULL); + InitPostgres(NULL, InvalidOid, NULL, InvalidOid, false, 0, NULL); /* Initialize stuff for bootstrap-file processing */ for (i = 0; i < MAXATTR; i++) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index ae9be9b911..dde83e76fb 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -488,7 +488,7 @@ AutoVacLauncherMain(int argc, char *argv[]) /* Early initialization */ BaseInit(); - InitPostgres(NULL, InvalidOid, NULL, InvalidOid, false, false, NULL); + InitPostgres(NULL, InvalidOid, NULL, InvalidOid, false, 0, NULL); SetProcessingMode(NormalProcessing); @@ -1706,7 +1706,7 @@ AutoVacWorkerMain(int argc, char *argv[]) * Note: if we have selected a just-deleted database (due to using * stale stats info), we'll fail and exit here. */ - InitPostgres(NULL, dbid, NULL, InvalidOid, false, false, + InitPostgres(NULL, dbid, NULL, InvalidOid, false, 0, dbname); SetProcessingMode(NormalProcessing); set_ps_display(dbname); diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 54e9bfb8c4..443b1c4725 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -5588,7 +5588,7 @@ BackgroundWorkerInitializeConnection(const char *dbname, const char *username, u InitPostgres(dbname, InvalidOid, /* database to connect to */ username, InvalidOid, /* role to connect as */ false, /* never honor session_preload_libraries */ - (flags & BGWORKER_BYPASS_ALLOWCONN) != 0, /* ignore datallowconn? */ + flags, NULL); /* no out_dbname */ /* it had better not gotten out of "init" mode yet */ @@ -5615,7 +5615,7 @@ BackgroundWorkerInitializeConnectionByOid(Oid dboid, Oid useroid, uint32 flags) InitPostgres(NULL, dboid, /* database to connect to */ NULL, useroid, /* role to connect as */ false, /* never honor session_preload_libraries */ - (flags & BGWORKER_BYPASS_ALLOWCONN) != 0, /* ignore datallowconn? */ + flags, NULL); /* no out_dbname */ /* it had better not gotten out of "init" mode yet */ diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 21b9763183..f5ef8f52a8 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -4210,7 +4210,7 @@ PostgresMain(const char *dbname, const char *username) InitPostgres(dbname, InvalidOid, /* database to connect to */ username, InvalidOid, /* role to connect as */ !am_walsender, /* honor session_preload_libraries? */ - false, /* don't ignore datallowconn */ + 0, NULL); /* no out_dbname */ /* diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c index 1e671c560c..182d666852 100644 --- a/src/backend/utils/init/miscinit.c +++ b/src/backend/utils/init/miscinit.c @@ -725,7 +725,7 @@ has_rolreplication(Oid roleid) * Initialize user identity during normal backend startup */ void -InitializeSessionUserId(const char *rolename, Oid roleid) +InitializeSessionUserId(const char *rolename, Oid roleid, bool bypass_login_check) { HeapTuple roleTup; Form_pg_authid rform; @@ -789,7 +789,7 @@ InitializeSessionUserId(const char *rolename, Oid roleid) /* * Is role allowed to login at all? */ - if (!rform->rolcanlogin) + if (!bypass_login_check && !rform->rolcanlogin) ereport(FATAL, (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION), errmsg("role \"%s\" is not permitted to log in", diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c index df4d15a50f..6ccedffd62 100644 --- a/src/backend/utils/init/postinit.c +++ b/src/backend/utils/init/postinit.c @@ -41,6 +41,7 @@ #include "miscadmin.h" #include "pgstat.h" #include "postmaster/autovacuum.h" +#include "postmaster/bgworker.h" #include "postmaster/postmaster.h" #include "replication/slot.h" #include "replication/walsender.h" @@ -718,10 +719,12 @@ void InitPostgres(const char *in_dbname, Oid dboid, const char *username, Oid useroid, bool load_session_libraries, - bool override_allow_connections, + uint32 flags, char *out_dbname) { bool bootstrap = IsBootstrapProcessingMode(); + bool override_allow_connections = (flags & BGWORKER_BYPASS_ALLOWCONN) != 0; + bool bypass_login_check = (flags & BGWORKER_BYPASS_ROLELOGINCHECK) != 0; bool am_superuser; char *fullpath; char dbname[NAMEDATALEN]; @@ -901,7 +904,7 @@ InitPostgres(const char *in_dbname, Oid dboid, } else { - InitializeSessionUserId(username, useroid); + InitializeSessionUserId(username, useroid, bypass_login_check); am_superuser = superuser(); } } @@ -910,7 +913,7 @@ InitPostgres(const char *in_dbname, Oid dboid, /* normal multiuser case */ Assert(MyProcPort != NULL); PerformAuthentication(MyProcPort); - InitializeSessionUserId(username, useroid); + InitializeSessionUserId(username, useroid, false); /* ensure that auth_method is actually valid, aka authn_id is not NULL */ if (MyClientConnectionInfo.authn_id) InitializeSystemUser(MyClientConnectionInfo.authn_id, diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h index 14bd574fc2..7e6ee415cb 100644 --- a/src/include/miscadmin.h +++ b/src/include/miscadmin.h @@ -364,7 +364,8 @@ extern bool InSecurityRestrictedOperation(void); extern bool InNoForceRLSOperation(void); extern void GetUserIdAndContext(Oid *userid, bool *sec_def_context); extern void SetUserIdAndContext(Oid userid, bool sec_def_context); -extern void InitializeSessionUserId(const char *rolename, Oid roleid); +extern void InitializeSessionUserId(const char *rolename, Oid roleid, + bool bypass_login_check); extern void InitializeSessionUserIdStandalone(void); extern void SetSessionAuthorization(Oid userid, bool is_superuser); extern Oid GetCurrentRoleId(void); @@ -468,7 +469,7 @@ extern void InitializeMaxBackends(void); extern void InitPostgres(const char *in_dbname, Oid dboid, const char *username, Oid useroid, bool load_session_libraries, - bool override_allow_connections, + uint32 flags, char *out_dbname); extern void BaseInit(void); diff --git a/src/include/postmaster/bgworker.h b/src/include/postmaster/bgworker.h index 7815507e3d..d7a5c1a946 100644 --- a/src/include/postmaster/bgworker.h +++ b/src/include/postmaster/bgworker.h @@ -150,9 +150,11 @@ extern void BackgroundWorkerInitializeConnectionByOid(Oid dboid, Oid useroid, ui * Flags to BackgroundWorkerInitializeConnection et al * * - * Allow bypassing datallowconn restrictions when connecting to database + * Allow bypassing datallowconn restrictions and login check when connecting + * to database */ -#define BGWORKER_BYPASS_ALLOWCONN 1 +#define BGWORKER_BYPASS_ALLOWCONN 0x0001 +#define BGWORKER_BYPASS_ROLELOGINCHECK 0x0002 /* Block/unblock signals in a background worker process */ diff --git a/src/test/modules/worker_spi/t/001_worker_spi.pl b/src/test/modules/worker_spi/t/001_worker_spi.pl index 2965acd789..ff8b72f5b5 100644 --- a/src/test/modules/worker_spi/t/001_worker_spi.pl +++ b/src/test/modules/worker_spi/t/001_worker_spi.pl @@ -93,4 +93,52 @@ ok( $node->poll_query_until( 'dynamic bgworkers all launched' ) or die "Timed out while waiting for dynamic bgworkers to be launched"; +# Check BGWORKER_BYPASS_ROLELOGINCHECK behaves as expected. + +# First create a role without login. +$node->safe_psql( + 'postgres', qq[ + CREATE ROLE nologrole with nologin; + ALTER ROLE nologrole with superuser; +]); + +my $log_start = get_log_size($node); + +# Ask the background workers to connect with this role. +$node->append_conf( + 'postgresql.conf', q{ +worker_spi.role = 'nologrole' +}); +$node->restart; + +# An error message should be issued. +ok( $node->log_contains( + "role \"nologrole\" is not permitted to log in", $log_start), + "nologrole not allowed to connect if BGWORKER_BYPASS_ROLELOGINCHECK is not set" +); + + +$log_start = get_log_size($node); + +# Ask the background workers to connect with this role with the flag in place. +$node->append_conf( + 'postgresql.conf', q{ +worker_spi.role = 'nologrole' +worker_spi.bypass_login_check = true +}); +$node->restart; + +# An error message should not be issued. +ok( !$node->log_contains( + "role \"nologrole\" is not permitted to log in", $log_start), + "nologrole allowed to connect if BGWORKER_BYPASS_ROLELOGINCHECK is set"); + done_testing(); + +# return the size of logfile of $node in bytes +sub get_log_size +{ + my ($node) = @_; + + return (stat $node->logfile)[7]; +} diff --git a/src/test/modules/worker_spi/worker_spi.c b/src/test/modules/worker_spi/worker_spi.c index 98f8d4194b..d2ca99f2c5 100644 --- a/src/test/modules/worker_spi/worker_spi.c +++ b/src/test/modules/worker_spi/worker_spi.c @@ -52,6 +52,8 @@ PGDLLEXPORT void worker_spi_main(Datum main_arg) pg_attribute_noreturn(); static int worker_spi_naptime = 10; static int worker_spi_total_workers = 2; static char *worker_spi_database = NULL; +static char *worker_spi_role = NULL; +static bool worker_spi_bypass_login_check = false; /* value cached, fetched from shared memory */ static uint32 worker_spi_wait_event_main = 0; @@ -152,7 +154,10 @@ worker_spi_main(Datum main_arg) BackgroundWorkerUnblockSignals(); /* Connect to our database */ - BackgroundWorkerInitializeConnection(worker_spi_database, NULL, 0); + if (worker_spi_bypass_login_check) + BackgroundWorkerInitializeConnection(worker_spi_database, worker_spi_role, BGWORKER_BYPASS_ROLELOGINCHECK); + else + BackgroundWorkerInitializeConnection(worker_spi_database, worker_spi_role, 0); elog(LOG, "%s initialized with %s.%s", MyBgworkerEntry->bgw_name, table->schema, table->name); @@ -316,6 +321,24 @@ _PG_init(void) 0, NULL, NULL, NULL); + DefineCustomStringVariable("worker_spi.role", + "Role to connect with.", + NULL, + &worker_spi_role, + NULL, + PGC_SIGHUP, + 0, + NULL, NULL, NULL); + + DefineCustomBoolVariable("worker_spi.bypass_login_check", + "Should BGW allows to connect with non login role.", + NULL, + &worker_spi_bypass_login_check, + false, + PGC_SIGHUP, + 0, + NULL, NULL, NULL); + if (!process_shared_preload_libraries_in_progress) return; -- 2.34.1 ^ permalink raw reply [nested|flat] 8+ messages in thread
* Re: Add a new BGWORKER_BYPASS_ROLELOGINCHECK flag @ 2023-09-29 06:19 Michael Paquier <[email protected]> parent: Drouvot, Bertrand <[email protected]> 0 siblings, 1 reply; 8+ messages in thread From: Michael Paquier @ 2023-09-29 06:19 UTC (permalink / raw) To: Drouvot, Bertrand <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]> On Thu, Sep 28, 2023 at 02:37:02PM +0200, Drouvot, Bertrand wrote: > This patch allows the role provided in BackgroundWorkerInitializeConnection() > and BackgroundWorkerInitializeConnectionByOid() to lack login authorization. Interesting. Yes, there would be use cases for that, I suppose. > + uint32 flags, > char *out_dbname) > { This may be more adapted with a bits32 for the flags. > +# Ask the background workers to connect with this role with the flag in place. > +$node->append_conf( > + 'postgresql.conf', q{ > +worker_spi.role = 'nologrole' > +worker_spi.bypass_login_check = true > +}); > +$node->restart; > + > +# An error message should not be issued. > +ok( !$node->log_contains( > + "role \"nologrole\" is not permitted to log in", $log_start), > + "nologrole allowed to connect if BGWORKER_BYPASS_ROLELOGINCHECK is set"); > + > done_testing(); It would be cheaper to use a dynamic background worker for such tests. Something that I've been tempted to do in this module is to extend the amount of data that's given to bgw_main_arg when launching a worker with worker_spi_launch(). How about extending the SQL function so as it is possible to give in input a role name (or a regrole), a database name (or a database OID) and a text[] for the flags? This would require a bit more refactoring, but this would be benefitial to show or one can pass down a full structure from the registration to the main() routine. On top of that, it would make the addition of the new GUCs worker_spi.bypass_login_check and worker_spi.role unnecessary. > +# return the size of logfile of $node in bytes > +sub get_log_size > +{ > + my ($node) = @_; > + > + return (stat $node->logfile)[7]; > +} Just use -s here. See other tests that want to check the contents of the logs from an offset. > - * Allow bypassing datallowconn restrictions when connecting to database > + * Allow bypassing datallowconn restrictions and login check when connecting > + * to database > */ > -#define BGWORKER_BYPASS_ALLOWCONN 1 > +#define BGWORKER_BYPASS_ALLOWCONN 0x0001 > +#define BGWORKER_BYPASS_ROLELOGINCHECK 0x0002 The structure of the patch is inconsistent. These flags are in bgworker.h, but they are used also by InitPostgres(). Perhaps a second boolean flag would be OK rather than a second set of flags for InitPostgres() mapping with the bgworker set. -- Michael Attachments: [application/pgp-signature] signature.asc (833B, ../../[email protected]/2-signature.asc) download ^ permalink raw reply [nested|flat] 8+ messages in thread
* Re: Add a new BGWORKER_BYPASS_ROLELOGINCHECK flag @ 2023-10-02 08:01 Drouvot, Bertrand <[email protected]> parent: Michael Paquier <[email protected]> 0 siblings, 1 reply; 8+ messages in thread From: Drouvot, Bertrand @ 2023-10-02 08:01 UTC (permalink / raw) To: Michael Paquier <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]> Hi, On 9/29/23 8:19 AM, Michael Paquier wrote: > On Thu, Sep 28, 2023 at 02:37:02PM +0200, Drouvot, Bertrand wrote: >> This patch allows the role provided in BackgroundWorkerInitializeConnection() >> and BackgroundWorkerInitializeConnectionByOid() to lack login authorization. > > Interesting. Yes, there would be use cases for that, I suppose. Thanks for looking at it! > >> + uint32 flags, >> char *out_dbname) >> { > > This may be more adapted with a bits32 for the flags. Done that way in v2 attached. > >> +# Ask the background workers to connect with this role with the flag in place. >> +$node->append_conf( >> + 'postgresql.conf', q{ >> +worker_spi.role = 'nologrole' >> +worker_spi.bypass_login_check = true >> +}); >> +$node->restart; >> + >> +# An error message should not be issued. >> +ok( !$node->log_contains( >> + "role \"nologrole\" is not permitted to log in", $log_start), >> + "nologrole allowed to connect if BGWORKER_BYPASS_ROLELOGINCHECK is set"); >> + >> done_testing(); > > It would be cheaper to use a dynamic background worker for such tests. > Something that I've been tempted to do in this module is to extend the > amount of data that's given to bgw_main_arg when launching a worker > with worker_spi_launch(). How about extending the SQL function so as > it is possible to give in input a role name (or a regrole), a database > name (or a database OID) and a text[] for the flags? This would > require a bit more refactoring, but this would be benefitial to show > or one can pass down a full structure from the registration to the > main() routine. On top of that, it would make the addition of the new > GUCs worker_spi.bypass_login_check and worker_spi.role unnecessary. > I think that would make sense to have more flexibility in the worker_spi module. I think that could be done in a dedicated patch though. I think it makes more sense to have the current patch "focusing" on this new flag (while adding a test about it without too much refactoring). What about doing the worker_spi module re-factoring as a follow up of this one? >> +# return the size of logfile of $node in bytes >> +sub get_log_size >> +{ >> + my ($node) = @_; >> + >> + return (stat $node->logfile)[7]; >> +} > > Just use -s here. Done in v2 attached. > See other tests that want to check the contents of > the logs from an offset. > Oh right, worth to modify 019_replslot_limit.pl, 002_corrupted.pl and 001_pg_controldata.pl in a separate patch for consistency? (they are using "(stat $node->logfile)[7]" or "(stat($pg_control))[7]"). >> - * Allow bypassing datallowconn restrictions when connecting to database >> + * Allow bypassing datallowconn restrictions and login check when connecting >> + * to database >> */ >> -#define BGWORKER_BYPASS_ALLOWCONN 1 >> +#define BGWORKER_BYPASS_ALLOWCONN 0x0001 >> +#define BGWORKER_BYPASS_ROLELOGINCHECK 0x0002 > > The structure of the patch is inconsistent. These flags are in > bgworker.h, but they are used also by InitPostgres(). Perhaps a > second boolean flag would be OK rather than a second set of flags for > InitPostgres() mapping with the bgworker set. I did not want initially to add an extra parameter to InitPostgres() but I agree it would make more sense. So done that way in v2. Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com From 59de41f3c305b009babfa6d05c054d8ae9e4d730 Mon Sep 17 00:00:00 2001 From: Bertrand Drouvot <[email protected]> Date: Wed, 20 Sep 2023 08:28:59 +0000 Subject: [PATCH v2] Allow background workers to bypass login check This adds a new flag value (BGWORKER_BYPASS_ROLELOGINCHECK) to the flags being used in BackgroundWorkerInitializeConnection() and BackgroundWorkerInitializeConnectionByOid(). This flag allows the background workers to bypass the login check done in InitializeSessionUserId(). --- doc/src/sgml/bgworker.sgml | 3 +- src/backend/bootstrap/bootstrap.c | 2 +- src/backend/postmaster/autovacuum.c | 5 +-- src/backend/postmaster/postmaster.c | 6 ++- src/backend/tcop/postgres.c | 1 + src/backend/utils/init/miscinit.c | 4 +- src/backend/utils/init/postinit.c | 5 ++- src/include/miscadmin.h | 4 +- src/include/postmaster/bgworker.h | 10 +++-- .../modules/worker_spi/t/001_worker_spi.pl | 40 +++++++++++++++++++ src/test/modules/worker_spi/worker_spi.c | 25 +++++++++++- 11 files changed, 88 insertions(+), 17 deletions(-) 7.6% doc/src/sgml/ 11.4% src/backend/postmaster/ 12.6% src/backend/utils/init/ 11.8% src/include/postmaster/ 29.2% src/test/modules/worker_spi/t/ 23.2% src/test/modules/worker_spi/ 4.0% src/ diff --git a/doc/src/sgml/bgworker.sgml b/doc/src/sgml/bgworker.sgml index 9ad1146ba0..7335c02ed8 100644 --- a/doc/src/sgml/bgworker.sgml +++ b/doc/src/sgml/bgworker.sgml @@ -200,7 +200,8 @@ typedef struct BackgroundWorker <literal>InvalidOid</literal>, the process will run as the superuser created during <command>initdb</command>. If <literal>BGWORKER_BYPASS_ALLOWCONN</literal> is specified as <varname>flags</varname> it is possible to bypass the restriction - to connect to databases not allowing user connections. + to connect to databases not allowing user connections. If <literal>BGWORKER_BYPASS_ROLELOGINCHECK</literal> + is specified as <varname>flags</varname> it is possible to bypass the login check to connect to databases. A background worker can only call one of these two functions, and only once. It is not possible to switch databases. </para> diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c index 5810f8825e..bdd005b66a 100644 --- a/src/backend/bootstrap/bootstrap.c +++ b/src/backend/bootstrap/bootstrap.c @@ -345,7 +345,7 @@ BootstrapModeMain(int argc, char *argv[], bool check_only) if (pg_link_canary_is_frontend()) elog(ERROR, "backend is incorrectly linked to frontend functions"); - InitPostgres(NULL, InvalidOid, NULL, InvalidOid, false, false, NULL); + InitPostgres(NULL, InvalidOid, NULL, InvalidOid, false, false, false, NULL); /* Initialize stuff for bootstrap-file processing */ for (i = 0; i < MAXATTR; i++) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index ae9be9b911..4686b81f68 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -488,7 +488,7 @@ AutoVacLauncherMain(int argc, char *argv[]) /* Early initialization */ BaseInit(); - InitPostgres(NULL, InvalidOid, NULL, InvalidOid, false, false, NULL); + InitPostgres(NULL, InvalidOid, NULL, InvalidOid, false, false, false, NULL); SetProcessingMode(NormalProcessing); @@ -1706,8 +1706,7 @@ AutoVacWorkerMain(int argc, char *argv[]) * Note: if we have selected a just-deleted database (due to using * stale stats info), we'll fail and exit here. */ - InitPostgres(NULL, dbid, NULL, InvalidOid, false, false, - dbname); + InitPostgres(NULL, dbid, NULL, InvalidOid, false, false, false, dbname); SetProcessingMode(NormalProcessing); set_ps_display(dbname); ereport(DEBUG1, diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 54e9bfb8c4..37f5b94469 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -5575,7 +5575,7 @@ MaxLivePostmasterChildren(void) * Connect background worker to a database. */ void -BackgroundWorkerInitializeConnection(const char *dbname, const char *username, uint32 flags) +BackgroundWorkerInitializeConnection(const char *dbname, const char *username, bits32 flags) { BackgroundWorker *worker = MyBgworkerEntry; @@ -5589,6 +5589,7 @@ BackgroundWorkerInitializeConnection(const char *dbname, const char *username, u username, InvalidOid, /* role to connect as */ false, /* never honor session_preload_libraries */ (flags & BGWORKER_BYPASS_ALLOWCONN) != 0, /* ignore datallowconn? */ + (flags & BGWORKER_BYPASS_ROLELOGINCHECK) != 0, /* bypass login check? */ NULL); /* no out_dbname */ /* it had better not gotten out of "init" mode yet */ @@ -5602,7 +5603,7 @@ BackgroundWorkerInitializeConnection(const char *dbname, const char *username, u * Connect background worker to a database using OIDs. */ void -BackgroundWorkerInitializeConnectionByOid(Oid dboid, Oid useroid, uint32 flags) +BackgroundWorkerInitializeConnectionByOid(Oid dboid, Oid useroid, bits32 flags) { BackgroundWorker *worker = MyBgworkerEntry; @@ -5616,6 +5617,7 @@ BackgroundWorkerInitializeConnectionByOid(Oid dboid, Oid useroid, uint32 flags) NULL, useroid, /* role to connect as */ false, /* never honor session_preload_libraries */ (flags & BGWORKER_BYPASS_ALLOWCONN) != 0, /* ignore datallowconn? */ + (flags & BGWORKER_BYPASS_ROLELOGINCHECK) != 0, /* bypass login check? */ NULL); /* no out_dbname */ /* it had better not gotten out of "init" mode yet */ diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 21b9763183..5c1e21b99d 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -4211,6 +4211,7 @@ PostgresMain(const char *dbname, const char *username) username, InvalidOid, /* role to connect as */ !am_walsender, /* honor session_preload_libraries? */ false, /* don't ignore datallowconn */ + false, /* don't bypass login check */ NULL); /* no out_dbname */ /* diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c index 1e671c560c..182d666852 100644 --- a/src/backend/utils/init/miscinit.c +++ b/src/backend/utils/init/miscinit.c @@ -725,7 +725,7 @@ has_rolreplication(Oid roleid) * Initialize user identity during normal backend startup */ void -InitializeSessionUserId(const char *rolename, Oid roleid) +InitializeSessionUserId(const char *rolename, Oid roleid, bool bypass_login_check) { HeapTuple roleTup; Form_pg_authid rform; @@ -789,7 +789,7 @@ InitializeSessionUserId(const char *rolename, Oid roleid) /* * Is role allowed to login at all? */ - if (!rform->rolcanlogin) + if (!bypass_login_check && !rform->rolcanlogin) ereport(FATAL, (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION), errmsg("role \"%s\" is not permitted to log in", diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c index df4d15a50f..dcfeb30832 100644 --- a/src/backend/utils/init/postinit.c +++ b/src/backend/utils/init/postinit.c @@ -719,6 +719,7 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username, Oid useroid, bool load_session_libraries, bool override_allow_connections, + bool bypass_login_check, char *out_dbname) { bool bootstrap = IsBootstrapProcessingMode(); @@ -901,7 +902,7 @@ InitPostgres(const char *in_dbname, Oid dboid, } else { - InitializeSessionUserId(username, useroid); + InitializeSessionUserId(username, useroid, bypass_login_check); am_superuser = superuser(); } } @@ -910,7 +911,7 @@ InitPostgres(const char *in_dbname, Oid dboid, /* normal multiuser case */ Assert(MyProcPort != NULL); PerformAuthentication(MyProcPort); - InitializeSessionUserId(username, useroid); + InitializeSessionUserId(username, useroid, false); /* ensure that auth_method is actually valid, aka authn_id is not NULL */ if (MyClientConnectionInfo.authn_id) InitializeSystemUser(MyClientConnectionInfo.authn_id, diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h index 14bd574fc2..f1d03f2df8 100644 --- a/src/include/miscadmin.h +++ b/src/include/miscadmin.h @@ -364,7 +364,8 @@ extern bool InSecurityRestrictedOperation(void); extern bool InNoForceRLSOperation(void); extern void GetUserIdAndContext(Oid *userid, bool *sec_def_context); extern void SetUserIdAndContext(Oid userid, bool sec_def_context); -extern void InitializeSessionUserId(const char *rolename, Oid roleid); +extern void InitializeSessionUserId(const char *rolename, Oid roleid, + bool bypass_login_check); extern void InitializeSessionUserIdStandalone(void); extern void SetSessionAuthorization(Oid userid, bool is_superuser); extern Oid GetCurrentRoleId(void); @@ -469,6 +470,7 @@ extern void InitPostgres(const char *in_dbname, Oid dboid, const char *username, Oid useroid, bool load_session_libraries, bool override_allow_connections, + bool bypass_login_check, char *out_dbname); extern void BaseInit(void); diff --git a/src/include/postmaster/bgworker.h b/src/include/postmaster/bgworker.h index 7815507e3d..0fdbfaf431 100644 --- a/src/include/postmaster/bgworker.h +++ b/src/include/postmaster/bgworker.h @@ -141,18 +141,20 @@ extern PGDLLIMPORT BackgroundWorker *MyBgworkerEntry; * If dbname is NULL, connection is made to no specific database; * only shared catalogs can be accessed. */ -extern void BackgroundWorkerInitializeConnection(const char *dbname, const char *username, uint32 flags); +extern void BackgroundWorkerInitializeConnection(const char *dbname, const char *username, bits32 flags); /* Just like the above, but specifying database and user by OID. */ -extern void BackgroundWorkerInitializeConnectionByOid(Oid dboid, Oid useroid, uint32 flags); +extern void BackgroundWorkerInitializeConnectionByOid(Oid dboid, Oid useroid, bits32 flags); /* * Flags to BackgroundWorkerInitializeConnection et al * * - * Allow bypassing datallowconn restrictions when connecting to database + * Allow bypassing datallowconn restrictions and login check when connecting + * to database */ -#define BGWORKER_BYPASS_ALLOWCONN 1 +#define BGWORKER_BYPASS_ALLOWCONN 0x0001 +#define BGWORKER_BYPASS_ROLELOGINCHECK 0x0002 /* Block/unblock signals in a background worker process */ diff --git a/src/test/modules/worker_spi/t/001_worker_spi.pl b/src/test/modules/worker_spi/t/001_worker_spi.pl index 2965acd789..dcf37606a4 100644 --- a/src/test/modules/worker_spi/t/001_worker_spi.pl +++ b/src/test/modules/worker_spi/t/001_worker_spi.pl @@ -93,4 +93,44 @@ ok( $node->poll_query_until( 'dynamic bgworkers all launched' ) or die "Timed out while waiting for dynamic bgworkers to be launched"; +# Check BGWORKER_BYPASS_ROLELOGINCHECK behaves as expected. + +# First create a role without login. +$node->safe_psql( + 'postgres', qq[ + CREATE ROLE nologrole with nologin; + ALTER ROLE nologrole with superuser; +]); + +my $log_start = -s $node->logfile; + +# Ask the background workers to connect with this role. +$node->append_conf( + 'postgresql.conf', q{ +worker_spi.role = 'nologrole' +}); +$node->restart; + +# An error message should be issued. +ok( $node->log_contains( + "role \"nologrole\" is not permitted to log in", $log_start), + "nologrole not allowed to connect if BGWORKER_BYPASS_ROLELOGINCHECK is not set" +); + + +$log_start = -s $node->logfile; + +# Ask the background workers to connect with this role with the flag in place. +$node->append_conf( + 'postgresql.conf', q{ +worker_spi.role = 'nologrole' +worker_spi.bypass_login_check = true +}); +$node->restart; + +# An error message should not be issued. +ok( !$node->log_contains( + "role \"nologrole\" is not permitted to log in", $log_start), + "nologrole allowed to connect if BGWORKER_BYPASS_ROLELOGINCHECK is set"); + done_testing(); diff --git a/src/test/modules/worker_spi/worker_spi.c b/src/test/modules/worker_spi/worker_spi.c index 98f8d4194b..d2ca99f2c5 100644 --- a/src/test/modules/worker_spi/worker_spi.c +++ b/src/test/modules/worker_spi/worker_spi.c @@ -52,6 +52,8 @@ PGDLLEXPORT void worker_spi_main(Datum main_arg) pg_attribute_noreturn(); static int worker_spi_naptime = 10; static int worker_spi_total_workers = 2; static char *worker_spi_database = NULL; +static char *worker_spi_role = NULL; +static bool worker_spi_bypass_login_check = false; /* value cached, fetched from shared memory */ static uint32 worker_spi_wait_event_main = 0; @@ -152,7 +154,10 @@ worker_spi_main(Datum main_arg) BackgroundWorkerUnblockSignals(); /* Connect to our database */ - BackgroundWorkerInitializeConnection(worker_spi_database, NULL, 0); + if (worker_spi_bypass_login_check) + BackgroundWorkerInitializeConnection(worker_spi_database, worker_spi_role, BGWORKER_BYPASS_ROLELOGINCHECK); + else + BackgroundWorkerInitializeConnection(worker_spi_database, worker_spi_role, 0); elog(LOG, "%s initialized with %s.%s", MyBgworkerEntry->bgw_name, table->schema, table->name); @@ -316,6 +321,24 @@ _PG_init(void) 0, NULL, NULL, NULL); + DefineCustomStringVariable("worker_spi.role", + "Role to connect with.", + NULL, + &worker_spi_role, + NULL, + PGC_SIGHUP, + 0, + NULL, NULL, NULL); + + DefineCustomBoolVariable("worker_spi.bypass_login_check", + "Should BGW allows to connect with non login role.", + NULL, + &worker_spi_bypass_login_check, + false, + PGC_SIGHUP, + 0, + NULL, NULL, NULL); + if (!process_shared_preload_libraries_in_progress) return; -- 2.34.1 Attachments: [text/plain] v2-0001-Allow-background-workers-to-bypass-login-check.patch (13.6K, ../../[email protected]/2-v2-0001-Allow-background-workers-to-bypass-login-check.patch) download | inline diff: From 59de41f3c305b009babfa6d05c054d8ae9e4d730 Mon Sep 17 00:00:00 2001 From: Bertrand Drouvot <[email protected]> Date: Wed, 20 Sep 2023 08:28:59 +0000 Subject: [PATCH v2] Allow background workers to bypass login check This adds a new flag value (BGWORKER_BYPASS_ROLELOGINCHECK) to the flags being used in BackgroundWorkerInitializeConnection() and BackgroundWorkerInitializeConnectionByOid(). This flag allows the background workers to bypass the login check done in InitializeSessionUserId(). --- doc/src/sgml/bgworker.sgml | 3 +- src/backend/bootstrap/bootstrap.c | 2 +- src/backend/postmaster/autovacuum.c | 5 +-- src/backend/postmaster/postmaster.c | 6 ++- src/backend/tcop/postgres.c | 1 + src/backend/utils/init/miscinit.c | 4 +- src/backend/utils/init/postinit.c | 5 ++- src/include/miscadmin.h | 4 +- src/include/postmaster/bgworker.h | 10 +++-- .../modules/worker_spi/t/001_worker_spi.pl | 40 +++++++++++++++++++ src/test/modules/worker_spi/worker_spi.c | 25 +++++++++++- 11 files changed, 88 insertions(+), 17 deletions(-) 7.6% doc/src/sgml/ 11.4% src/backend/postmaster/ 12.6% src/backend/utils/init/ 11.8% src/include/postmaster/ 29.2% src/test/modules/worker_spi/t/ 23.2% src/test/modules/worker_spi/ 4.0% src/ diff --git a/doc/src/sgml/bgworker.sgml b/doc/src/sgml/bgworker.sgml index 9ad1146ba0..7335c02ed8 100644 --- a/doc/src/sgml/bgworker.sgml +++ b/doc/src/sgml/bgworker.sgml @@ -200,7 +200,8 @@ typedef struct BackgroundWorker <literal>InvalidOid</literal>, the process will run as the superuser created during <command>initdb</command>. If <literal>BGWORKER_BYPASS_ALLOWCONN</literal> is specified as <varname>flags</varname> it is possible to bypass the restriction - to connect to databases not allowing user connections. + to connect to databases not allowing user connections. If <literal>BGWORKER_BYPASS_ROLELOGINCHECK</literal> + is specified as <varname>flags</varname> it is possible to bypass the login check to connect to databases. A background worker can only call one of these two functions, and only once. It is not possible to switch databases. </para> diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c index 5810f8825e..bdd005b66a 100644 --- a/src/backend/bootstrap/bootstrap.c +++ b/src/backend/bootstrap/bootstrap.c @@ -345,7 +345,7 @@ BootstrapModeMain(int argc, char *argv[], bool check_only) if (pg_link_canary_is_frontend()) elog(ERROR, "backend is incorrectly linked to frontend functions"); - InitPostgres(NULL, InvalidOid, NULL, InvalidOid, false, false, NULL); + InitPostgres(NULL, InvalidOid, NULL, InvalidOid, false, false, false, NULL); /* Initialize stuff for bootstrap-file processing */ for (i = 0; i < MAXATTR; i++) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index ae9be9b911..4686b81f68 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -488,7 +488,7 @@ AutoVacLauncherMain(int argc, char *argv[]) /* Early initialization */ BaseInit(); - InitPostgres(NULL, InvalidOid, NULL, InvalidOid, false, false, NULL); + InitPostgres(NULL, InvalidOid, NULL, InvalidOid, false, false, false, NULL); SetProcessingMode(NormalProcessing); @@ -1706,8 +1706,7 @@ AutoVacWorkerMain(int argc, char *argv[]) * Note: if we have selected a just-deleted database (due to using * stale stats info), we'll fail and exit here. */ - InitPostgres(NULL, dbid, NULL, InvalidOid, false, false, - dbname); + InitPostgres(NULL, dbid, NULL, InvalidOid, false, false, false, dbname); SetProcessingMode(NormalProcessing); set_ps_display(dbname); ereport(DEBUG1, diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 54e9bfb8c4..37f5b94469 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -5575,7 +5575,7 @@ MaxLivePostmasterChildren(void) * Connect background worker to a database. */ void -BackgroundWorkerInitializeConnection(const char *dbname, const char *username, uint32 flags) +BackgroundWorkerInitializeConnection(const char *dbname, const char *username, bits32 flags) { BackgroundWorker *worker = MyBgworkerEntry; @@ -5589,6 +5589,7 @@ BackgroundWorkerInitializeConnection(const char *dbname, const char *username, u username, InvalidOid, /* role to connect as */ false, /* never honor session_preload_libraries */ (flags & BGWORKER_BYPASS_ALLOWCONN) != 0, /* ignore datallowconn? */ + (flags & BGWORKER_BYPASS_ROLELOGINCHECK) != 0, /* bypass login check? */ NULL); /* no out_dbname */ /* it had better not gotten out of "init" mode yet */ @@ -5602,7 +5603,7 @@ BackgroundWorkerInitializeConnection(const char *dbname, const char *username, u * Connect background worker to a database using OIDs. */ void -BackgroundWorkerInitializeConnectionByOid(Oid dboid, Oid useroid, uint32 flags) +BackgroundWorkerInitializeConnectionByOid(Oid dboid, Oid useroid, bits32 flags) { BackgroundWorker *worker = MyBgworkerEntry; @@ -5616,6 +5617,7 @@ BackgroundWorkerInitializeConnectionByOid(Oid dboid, Oid useroid, uint32 flags) NULL, useroid, /* role to connect as */ false, /* never honor session_preload_libraries */ (flags & BGWORKER_BYPASS_ALLOWCONN) != 0, /* ignore datallowconn? */ + (flags & BGWORKER_BYPASS_ROLELOGINCHECK) != 0, /* bypass login check? */ NULL); /* no out_dbname */ /* it had better not gotten out of "init" mode yet */ diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 21b9763183..5c1e21b99d 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -4211,6 +4211,7 @@ PostgresMain(const char *dbname, const char *username) username, InvalidOid, /* role to connect as */ !am_walsender, /* honor session_preload_libraries? */ false, /* don't ignore datallowconn */ + false, /* don't bypass login check */ NULL); /* no out_dbname */ /* diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c index 1e671c560c..182d666852 100644 --- a/src/backend/utils/init/miscinit.c +++ b/src/backend/utils/init/miscinit.c @@ -725,7 +725,7 @@ has_rolreplication(Oid roleid) * Initialize user identity during normal backend startup */ void -InitializeSessionUserId(const char *rolename, Oid roleid) +InitializeSessionUserId(const char *rolename, Oid roleid, bool bypass_login_check) { HeapTuple roleTup; Form_pg_authid rform; @@ -789,7 +789,7 @@ InitializeSessionUserId(const char *rolename, Oid roleid) /* * Is role allowed to login at all? */ - if (!rform->rolcanlogin) + if (!bypass_login_check && !rform->rolcanlogin) ereport(FATAL, (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION), errmsg("role \"%s\" is not permitted to log in", diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c index df4d15a50f..dcfeb30832 100644 --- a/src/backend/utils/init/postinit.c +++ b/src/backend/utils/init/postinit.c @@ -719,6 +719,7 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username, Oid useroid, bool load_session_libraries, bool override_allow_connections, + bool bypass_login_check, char *out_dbname) { bool bootstrap = IsBootstrapProcessingMode(); @@ -901,7 +902,7 @@ InitPostgres(const char *in_dbname, Oid dboid, } else { - InitializeSessionUserId(username, useroid); + InitializeSessionUserId(username, useroid, bypass_login_check); am_superuser = superuser(); } } @@ -910,7 +911,7 @@ InitPostgres(const char *in_dbname, Oid dboid, /* normal multiuser case */ Assert(MyProcPort != NULL); PerformAuthentication(MyProcPort); - InitializeSessionUserId(username, useroid); + InitializeSessionUserId(username, useroid, false); /* ensure that auth_method is actually valid, aka authn_id is not NULL */ if (MyClientConnectionInfo.authn_id) InitializeSystemUser(MyClientConnectionInfo.authn_id, diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h index 14bd574fc2..f1d03f2df8 100644 --- a/src/include/miscadmin.h +++ b/src/include/miscadmin.h @@ -364,7 +364,8 @@ extern bool InSecurityRestrictedOperation(void); extern bool InNoForceRLSOperation(void); extern void GetUserIdAndContext(Oid *userid, bool *sec_def_context); extern void SetUserIdAndContext(Oid userid, bool sec_def_context); -extern void InitializeSessionUserId(const char *rolename, Oid roleid); +extern void InitializeSessionUserId(const char *rolename, Oid roleid, + bool bypass_login_check); extern void InitializeSessionUserIdStandalone(void); extern void SetSessionAuthorization(Oid userid, bool is_superuser); extern Oid GetCurrentRoleId(void); @@ -469,6 +470,7 @@ extern void InitPostgres(const char *in_dbname, Oid dboid, const char *username, Oid useroid, bool load_session_libraries, bool override_allow_connections, + bool bypass_login_check, char *out_dbname); extern void BaseInit(void); diff --git a/src/include/postmaster/bgworker.h b/src/include/postmaster/bgworker.h index 7815507e3d..0fdbfaf431 100644 --- a/src/include/postmaster/bgworker.h +++ b/src/include/postmaster/bgworker.h @@ -141,18 +141,20 @@ extern PGDLLIMPORT BackgroundWorker *MyBgworkerEntry; * If dbname is NULL, connection is made to no specific database; * only shared catalogs can be accessed. */ -extern void BackgroundWorkerInitializeConnection(const char *dbname, const char *username, uint32 flags); +extern void BackgroundWorkerInitializeConnection(const char *dbname, const char *username, bits32 flags); /* Just like the above, but specifying database and user by OID. */ -extern void BackgroundWorkerInitializeConnectionByOid(Oid dboid, Oid useroid, uint32 flags); +extern void BackgroundWorkerInitializeConnectionByOid(Oid dboid, Oid useroid, bits32 flags); /* * Flags to BackgroundWorkerInitializeConnection et al * * - * Allow bypassing datallowconn restrictions when connecting to database + * Allow bypassing datallowconn restrictions and login check when connecting + * to database */ -#define BGWORKER_BYPASS_ALLOWCONN 1 +#define BGWORKER_BYPASS_ALLOWCONN 0x0001 +#define BGWORKER_BYPASS_ROLELOGINCHECK 0x0002 /* Block/unblock signals in a background worker process */ diff --git a/src/test/modules/worker_spi/t/001_worker_spi.pl b/src/test/modules/worker_spi/t/001_worker_spi.pl index 2965acd789..dcf37606a4 100644 --- a/src/test/modules/worker_spi/t/001_worker_spi.pl +++ b/src/test/modules/worker_spi/t/001_worker_spi.pl @@ -93,4 +93,44 @@ ok( $node->poll_query_until( 'dynamic bgworkers all launched' ) or die "Timed out while waiting for dynamic bgworkers to be launched"; +# Check BGWORKER_BYPASS_ROLELOGINCHECK behaves as expected. + +# First create a role without login. +$node->safe_psql( + 'postgres', qq[ + CREATE ROLE nologrole with nologin; + ALTER ROLE nologrole with superuser; +]); + +my $log_start = -s $node->logfile; + +# Ask the background workers to connect with this role. +$node->append_conf( + 'postgresql.conf', q{ +worker_spi.role = 'nologrole' +}); +$node->restart; + +# An error message should be issued. +ok( $node->log_contains( + "role \"nologrole\" is not permitted to log in", $log_start), + "nologrole not allowed to connect if BGWORKER_BYPASS_ROLELOGINCHECK is not set" +); + + +$log_start = -s $node->logfile; + +# Ask the background workers to connect with this role with the flag in place. +$node->append_conf( + 'postgresql.conf', q{ +worker_spi.role = 'nologrole' +worker_spi.bypass_login_check = true +}); +$node->restart; + +# An error message should not be issued. +ok( !$node->log_contains( + "role \"nologrole\" is not permitted to log in", $log_start), + "nologrole allowed to connect if BGWORKER_BYPASS_ROLELOGINCHECK is set"); + done_testing(); diff --git a/src/test/modules/worker_spi/worker_spi.c b/src/test/modules/worker_spi/worker_spi.c index 98f8d4194b..d2ca99f2c5 100644 --- a/src/test/modules/worker_spi/worker_spi.c +++ b/src/test/modules/worker_spi/worker_spi.c @@ -52,6 +52,8 @@ PGDLLEXPORT void worker_spi_main(Datum main_arg) pg_attribute_noreturn(); static int worker_spi_naptime = 10; static int worker_spi_total_workers = 2; static char *worker_spi_database = NULL; +static char *worker_spi_role = NULL; +static bool worker_spi_bypass_login_check = false; /* value cached, fetched from shared memory */ static uint32 worker_spi_wait_event_main = 0; @@ -152,7 +154,10 @@ worker_spi_main(Datum main_arg) BackgroundWorkerUnblockSignals(); /* Connect to our database */ - BackgroundWorkerInitializeConnection(worker_spi_database, NULL, 0); + if (worker_spi_bypass_login_check) + BackgroundWorkerInitializeConnection(worker_spi_database, worker_spi_role, BGWORKER_BYPASS_ROLELOGINCHECK); + else + BackgroundWorkerInitializeConnection(worker_spi_database, worker_spi_role, 0); elog(LOG, "%s initialized with %s.%s", MyBgworkerEntry->bgw_name, table->schema, table->name); @@ -316,6 +321,24 @@ _PG_init(void) 0, NULL, NULL, NULL); + DefineCustomStringVariable("worker_spi.role", + "Role to connect with.", + NULL, + &worker_spi_role, + NULL, + PGC_SIGHUP, + 0, + NULL, NULL, NULL); + + DefineCustomBoolVariable("worker_spi.bypass_login_check", + "Should BGW allows to connect with non login role.", + NULL, + &worker_spi_bypass_login_check, + false, + PGC_SIGHUP, + 0, + NULL, NULL, NULL); + if (!process_shared_preload_libraries_in_progress) return; -- 2.34.1 ^ permalink raw reply [nested|flat] 8+ messages in thread
* Re: Add a new BGWORKER_BYPASS_ROLELOGINCHECK flag @ 2023-10-03 09:21 Bharath Rupireddy <[email protected]> parent: Drouvot, Bertrand <[email protected]> 0 siblings, 1 reply; 8+ messages in thread From: Bharath Rupireddy @ 2023-10-03 09:21 UTC (permalink / raw) To: Drouvot, Bertrand <[email protected]>; +Cc: Michael Paquier <[email protected]>; PostgreSQL Hackers <[email protected]> On Mon, Oct 2, 2023 at 4:58 PM Drouvot, Bertrand <[email protected]> wrote: > > On 9/29/23 8:19 AM, Michael Paquier wrote: > > On Thu, Sep 28, 2023 at 02:37:02PM +0200, Drouvot, Bertrand wrote: > >> This patch allows the role provided in BackgroundWorkerInitializeConnection() > >> and BackgroundWorkerInitializeConnectionByOid() to lack login authorization. > > > > Interesting. Yes, there would be use cases for that, I suppose. Correct. It allows the roles that don't have LOGIN capabilities to start and use bg workers. > > This may be more adapted with a bits32 for the flags. > > Done that way in v2 attached. While I like the idea of the flag to skip login checks for bg workers, I don't quite like the APIs being changes InitializeSessionUserId and InitPostgres (adding a new input parameter), BackgroundWorkerInitializeConnection and BackgroundWorkerInitializeConnectionByOid (changing of input parameter type) given that all of these functions are available for external modules and will break things for sure. What if BGWORKER_BYPASS_ROLELOGINCHECK be part of bgw_flags? With this, none of the API needs to be changed, so no compatibility problems as such for external modules and the InitializeSessionUserId can just do something like [1]. We might be tempted to add BGWORKER_BYPASS_ALLOWCONN also to bgw_flags, but I'd prefer not to do it for the same compatibility reasons. Thoughts? [1] diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c index 1e671c560c..27dcf052ab 100644 --- a/src/backend/utils/init/miscinit.c +++ b/src/backend/utils/init/miscinit.c @@ -786,10 +786,17 @@ InitializeSessionUserId(const char *rolename, Oid roleid) */ if (IsUnderPostmaster) { + bool skip_check = false; + + /* If asked, skip the role login check for background workers. */ + if (IsBackgroundWorker && + (MyBgworkerEntry->bgw_flags & BGWORKER_BYPASS_ROLELOGINCHECK) != 0) + skip_check = true; + /* * Is role allowed to login at all? */ - if (!rform->rolcanlogin) + if (!skip_check && !rform->rolcanlogin) ereport(FATAL, (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION), errmsg("role \"%s\" is not permitted to log in", -- Bharath Rupireddy PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com ^ permalink raw reply [nested|flat] 8+ messages in thread
* Re: Add a new BGWORKER_BYPASS_ROLELOGINCHECK flag @ 2023-10-03 12:15 Drouvot, Bertrand <[email protected]> parent: Bharath Rupireddy <[email protected]> 0 siblings, 1 reply; 8+ messages in thread From: Drouvot, Bertrand @ 2023-10-03 12:15 UTC (permalink / raw) To: Bharath Rupireddy <[email protected]>; +Cc: Michael Paquier <[email protected]>; PostgreSQL Hackers <[email protected]> Hi, On 10/3/23 11:21 AM, Bharath Rupireddy wrote: > On Mon, Oct 2, 2023 at 4:58 PM Drouvot, Bertrand > <[email protected]> wrote: >> >> On 9/29/23 8:19 AM, Michael Paquier wrote: >>> On Thu, Sep 28, 2023 at 02:37:02PM +0200, Drouvot, Bertrand wrote: >>>> This patch allows the role provided in BackgroundWorkerInitializeConnection() >>>> and BackgroundWorkerInitializeConnectionByOid() to lack login authorization. >>> >>> Interesting. Yes, there would be use cases for that, I suppose. > > Correct. It allows the roles that don't have LOGIN capabilities to > start and use bg workers. > >>> This may be more adapted with a bits32 for the flags. >> >> Done that way in v2 attached. > > While I like the idea of the flag to skip login checks for bg workers, > I don't quite like the APIs being changes InitializeSessionUserId and > InitPostgres (adding a new input parameter), > BackgroundWorkerInitializeConnection and > BackgroundWorkerInitializeConnectionByOid (changing of input parameter > type) given that all of these functions are available for external > modules and will break things for sure. > > What if BGWORKER_BYPASS_ROLELOGINCHECK be part of bgw_flags? With > this, none of the API needs to be changed, so no compatibility > problems as such for external modules and the InitializeSessionUserId > can just do something like [1]. We might be tempted to add > BGWORKER_BYPASS_ALLOWCONN also to bgw_flags, but I'd prefer not to do > it for the same compatibility reasons. > > Thoughts? > Thanks for looking at it! I did some research and BGWORKER_BYPASS_ALLOWCONN has been added in eed1ce72e1 and at that time the bgw_flags did already exist. In this the related thread [1], Tom mentioned: " We change exported APIs in new major versions all the time. As long as it's just a question of an added parameter, people can deal with it. " And I agree with that. Now, I understand your point but it looks to me that bgw_flags is more about the capabilities (Access to shared memory with BGWORKER_SHMEM_ACCESS or ability to establish database connection with BGWORKER_BACKEND_DATABASE_CONNECTION), While with BGWORKER_BYPASS_ROLELOGINCHECK (and BGWORKER_BYPASS_ALLOWCONN) it's more related to the BGW behavior once the capability is in place. So, I think I'm fine with the current proposal and don't see the need to move BGWORKER_BYPASS_ROLELOGINCHECK in bgw_flags. [1]: https://www.postgresql.org/message-id/22769.1519323861%40sss.pgh.pa.us Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com ^ permalink raw reply [nested|flat] 8+ messages in thread
* Re: Add a new BGWORKER_BYPASS_ROLELOGINCHECK flag @ 2023-10-03 13:32 Bharath Rupireddy <[email protected]> parent: Drouvot, Bertrand <[email protected]> 0 siblings, 1 reply; 8+ messages in thread From: Bharath Rupireddy @ 2023-10-03 13:32 UTC (permalink / raw) To: Drouvot, Bertrand <[email protected]>; +Cc: Michael Paquier <[email protected]>; PostgreSQL Hackers <[email protected]> On Tue, Oct 3, 2023 at 5:45 PM Drouvot, Bertrand <[email protected]> wrote: > > > While I like the idea of the flag to skip login checks for bg workers, > > I don't quite like the APIs being changes InitializeSessionUserId and > > InitPostgres (adding a new input parameter), > > BackgroundWorkerInitializeConnection and > > BackgroundWorkerInitializeConnectionByOid (changing of input parameter > > type) given that all of these functions are available for external > > modules and will break things for sure. > > > > What if BGWORKER_BYPASS_ROLELOGINCHECK be part of bgw_flags? With > > this, none of the API needs to be changed, so no compatibility > > problems as such for external modules and the InitializeSessionUserId > > can just do something like [1]. We might be tempted to add > > BGWORKER_BYPASS_ALLOWCONN also to bgw_flags, but I'd prefer not to do > > it for the same compatibility reasons. > > > > Thoughts? > > > > Thanks for looking at it! > > I did some research and BGWORKER_BYPASS_ALLOWCONN has been added in eed1ce72e1 and > at that time the bgw_flags did already exist. > > In this the related thread [1], Tom mentioned: > > " > We change exported APIs in new major versions all the time. As > long as it's just a question of an added parameter, people can deal > with it. > " It doesn't have to be always/all the time. If the case here is okay to change the bgw and other core functions API, I honestly feel that we must move BGWORKER_BYPASS_ALLOWCONN to bgw_flags. > Now, I understand your point but it looks to me that bgw_flags is more > about the capabilities (Access to shared memory with BGWORKER_SHMEM_ACCESS > or ability to establish database connection with BGWORKER_BACKEND_DATABASE_CONNECTION), > > While with BGWORKER_BYPASS_ROLELOGINCHECK (and BGWORKER_BYPASS_ALLOWCONN) it's more related to > the BGW behavior once the capability is in place. I look at the new flag as a capability of the bgw to connect with a role without login access. IMV, all are the same. > So, I think I'm fine with the current proposal and don't see the need to move > BGWORKER_BYPASS_ROLELOGINCHECK in bgw_flags. > > [1]: https://www.postgresql.org/message-id/22769.1519323861%40sss.pgh.pa.us I prefer to have it as bgw_flag, however, let's hear from others. -- Bharath Rupireddy PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com ^ permalink raw reply [nested|flat] 8+ messages in thread
* Re: Add a new BGWORKER_BYPASS_ROLELOGINCHECK flag @ 2023-10-03 23:17 Michael Paquier <[email protected]> parent: Bharath Rupireddy <[email protected]> 0 siblings, 0 replies; 8+ messages in thread From: Michael Paquier @ 2023-10-03 23:17 UTC (permalink / raw) To: Bharath Rupireddy <[email protected]>; +Cc: Drouvot, Bertrand <[email protected]>; PostgreSQL Hackers <[email protected]> On Tue, Oct 03, 2023 at 07:02:11PM +0530, Bharath Rupireddy wrote: > On Tue, Oct 3, 2023 at 5:45 PM Drouvot, Bertrand > <[email protected]> wrote: >> I did some research and BGWORKER_BYPASS_ALLOWCONN has been added in eed1ce72e1 and >> at that time the bgw_flags did already exist. >> >> In this the related thread [1], Tom mentioned: >> >> " >> We change exported APIs in new major versions all the time. As >> long as it's just a question of an added parameter, people can deal >> with it. >> " > > It doesn't have to be always/all the time. If the case here is okay to > change the bgw and other core functions API, I honestly feel that we > must move BGWORKER_BYPASS_ALLOWCONN to bgw_flags. I don't agree with this point. BackgroundWorkerInitializeConnection() and its other friend are designed to be called at the beginning of the main routine of a background worker, where bgw_flags is not accessible. There is much more happening before a bgworker initializes its connection, like signal handling and definitions of other states that depend on the GUCs loaded for the bgworker. >> Now, I understand your point but it looks to me that bgw_flags is more >> about the capabilities (Access to shared memory with BGWORKER_SHMEM_ACCESS >> or ability to establish database connection with BGWORKER_BACKEND_DATABASE_CONNECTION), >> >> While with BGWORKER_BYPASS_ROLELOGINCHECK (and BGWORKER_BYPASS_ALLOWCONN) it's more related to >> the BGW behavior once the capability is in place. > > I look at the new flag as a capability of the bgw to connect with a > role without login access. IMV, all are the same. Bertrand is arguing that the current code with its current split is OK, because both are different concepts: - bgw_flags is used by the postmaster to control how to launch the bgworkers. - The BGWORKER_* flags are used by the bgworkers themselves, once things are set up by the postmaster based on bgw_flags. -- Michael Attachments: [application/pgp-signature] signature.asc (833B, ../../[email protected]/2-signature.asc) download ^ permalink raw reply [nested|flat] 8+ messages in thread
end of thread, other threads:[~2023-10-03 23:17 UTC | newest] Thread overview: 8+ messages (download: mbox mbox.gz follow: Atom feed) -- links below jump to the message on this page -- 2020-03-13 07:59 [PATCH v34 4/7] Make archiver process an auxiliary process Kyotaro Horiguchi <[email protected]> 2023-09-28 12:37 Add a new BGWORKER_BYPASS_ROLELOGINCHECK flag Drouvot, Bertrand <[email protected]> 2023-09-29 06:19 ` Re: Add a new BGWORKER_BYPASS_ROLELOGINCHECK flag Michael Paquier <[email protected]> 2023-10-02 08:01 ` Re: Add a new BGWORKER_BYPASS_ROLELOGINCHECK flag Drouvot, Bertrand <[email protected]> 2023-10-03 09:21 ` Re: Add a new BGWORKER_BYPASS_ROLELOGINCHECK flag Bharath Rupireddy <[email protected]> 2023-10-03 12:15 ` Re: Add a new BGWORKER_BYPASS_ROLELOGINCHECK flag Drouvot, Bertrand <[email protected]> 2023-10-03 13:32 ` Re: Add a new BGWORKER_BYPASS_ROLELOGINCHECK flag Bharath Rupireddy <[email protected]> 2023-10-03 23:17 ` Re: Add a new BGWORKER_BYPASS_ROLELOGINCHECK flag Michael Paquier <[email protected]>
This inbox is served by agora; see mirroring instructions for how to clone and mirror all data and code used for this inbox