Skip to content

Commit fe1513c

Browse files
authored
Add neon.safekeeper_conninfo_options GUC (neondatabase#11901)
In order to enable TLS connections between computes and safekeepers, we need to provide the control plane with a way to configure the various libpq keyword parameters, sslmode and sslrootcert. neon.safekeepers is a comma separated list of safekeepers formatted as host:port, so isn't available for extension in the same way that neon.pageserver_connstring is. This could be remedied in a future PR. Part-of: neondatabase/neon-archive-cloud#25823 Link: https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PARAMKEYWORDS Signed-off-by: Tristan Partin <[email protected]>
1 parent 3e86008 commit fe1513c

File tree

5 files changed

+27
-2
lines changed

5 files changed

+27
-2
lines changed

libs/walproposer/src/walproposer.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#![allow(clippy::todo)]
22

33
use std::ffi::CString;
4+
use std::str::FromStr;
45

56
use postgres_ffi::WAL_SEGMENT_SIZE;
67
use utils::id::TenantTimelineId;
@@ -173,6 +174,8 @@ pub struct Config {
173174
pub ttid: TenantTimelineId,
174175
/// List of safekeepers in format `host:port`
175176
pub safekeepers_list: Vec<String>,
177+
/// libpq connection info options
178+
pub safekeeper_conninfo_options: String,
176179
/// Safekeeper reconnect timeout in milliseconds
177180
pub safekeeper_reconnect_timeout: i32,
178181
/// Safekeeper connection timeout in milliseconds
@@ -202,13 +205,17 @@ impl Wrapper {
202205
.into_bytes_with_nul();
203206
assert!(safekeepers_list_vec.len() == safekeepers_list_vec.capacity());
204207
let safekeepers_list = safekeepers_list_vec.as_mut_ptr() as *mut std::ffi::c_char;
208+
let safekeeper_conninfo_options = CString::from_str(&config.safekeeper_conninfo_options)
209+
.unwrap()
210+
.into_raw();
205211

206212
let callback_data = Box::into_raw(Box::new(api)) as *mut ::std::os::raw::c_void;
207213

208214
let c_config = WalProposerConfig {
209215
neon_tenant,
210216
neon_timeline,
211217
safekeepers_list,
218+
safekeeper_conninfo_options,
212219
safekeeper_reconnect_timeout: config.safekeeper_reconnect_timeout,
213220
safekeeper_connection_timeout: config.safekeeper_connection_timeout,
214221
wal_segment_size: WAL_SEGMENT_SIZE as i32, // default 16MB
@@ -576,6 +583,7 @@ mod tests {
576583
let config = crate::walproposer::Config {
577584
ttid,
578585
safekeepers_list: vec!["localhost:5000".to_string()],
586+
safekeeper_conninfo_options: String::new(),
579587
safekeeper_reconnect_timeout: 1000,
580588
safekeeper_connection_timeout: 10000,
581589
sync_safekeepers: true,

pgxn/neon/walproposer.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,9 @@ WalProposerCreate(WalProposerConfig *config, walproposer_api api)
155155
int written = 0;
156156

157157
written = snprintf((char *) &sk->conninfo, MAXCONNINFO,
158-
"host=%s port=%s dbname=replication options='-c timeline_id=%s tenant_id=%s'",
159-
sk->host, sk->port, wp->config->neon_timeline, wp->config->neon_tenant);
158+
"%s host=%s port=%s dbname=replication options='-c timeline_id=%s tenant_id=%s'",
159+
wp->config->safekeeper_conninfo_options, sk->host, sk->port,
160+
wp->config->neon_timeline, wp->config->neon_tenant);
160161
if (written > MAXCONNINFO || written < 0)
161162
wp_log(FATAL, "could not create connection string for safekeeper %s:%s", sk->host, sk->port);
162163
}

pgxn/neon/walproposer.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,9 @@ typedef struct WalProposerConfig
714714
*/
715715
char *safekeepers_list;
716716

717+
/* libpq connection info options. */
718+
char *safekeeper_conninfo_options;
719+
717720
/*
718721
* WalProposer reconnects to offline safekeepers once in this interval.
719722
* Time is in milliseconds.

pgxn/neon/walproposer_pg.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ char *wal_acceptors_list = "";
6464
int wal_acceptor_reconnect_timeout = 1000;
6565
int wal_acceptor_connection_timeout = 10000;
6666
int safekeeper_proto_version = 3;
67+
char *safekeeper_conninfo_options = "";
6768

6869
/* Set to true in the walproposer bgw. */
6970
static bool am_walproposer;
@@ -119,6 +120,7 @@ init_walprop_config(bool syncSafekeepers)
119120
walprop_config.neon_timeline = neon_timeline;
120121
/* WalProposerCreate scribbles directly on it, so pstrdup */
121122
walprop_config.safekeepers_list = pstrdup(wal_acceptors_list);
123+
walprop_config.safekeeper_conninfo_options = pstrdup(safekeeper_conninfo_options);
122124
walprop_config.safekeeper_reconnect_timeout = wal_acceptor_reconnect_timeout;
123125
walprop_config.safekeeper_connection_timeout = wal_acceptor_connection_timeout;
124126
walprop_config.wal_segment_size = wal_segment_size;
@@ -203,6 +205,16 @@ nwp_register_gucs(void)
203205
* GUC_LIST_QUOTE */
204206
NULL, assign_neon_safekeepers, NULL);
205207

208+
DefineCustomStringVariable(
209+
"neon.safekeeper_conninfo_options",
210+
"libpq keyword parameters and values to apply to safekeeper connections",
211+
NULL,
212+
&safekeeper_conninfo_options,
213+
"",
214+
PGC_POSTMASTER,
215+
0,
216+
NULL, NULL, NULL);
217+
206218
DefineCustomIntVariable(
207219
"neon.safekeeper_reconnect_timeout",
208220
"Walproposer reconnects to offline safekeepers once in this interval.",

safekeeper/tests/walproposer_sim/simulation.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ impl WalProposer {
8787
let config = Config {
8888
ttid,
8989
safekeepers_list: addrs,
90+
safekeeper_conninfo_options: String::new(),
9091
safekeeper_reconnect_timeout: 1000,
9192
safekeeper_connection_timeout: 5000,
9293
sync_safekeepers,

0 commit comments

Comments
 (0)