diff --git a/pgxn/neon/libpagestore.c b/pgxn/neon/libpagestore.c index 64d38e7913..ae22589397 100644 --- a/pgxn/neon/libpagestore.c +++ b/pgxn/neon/libpagestore.c @@ -81,6 +81,23 @@ static int neon_compute_mode = 0; static int max_reconnect_attempts = 60; static int stripe_size; +static char *pageserver_sslcert = NULL; +static char *pageserver_sslcertmode = NULL; +static char *pageserver_sslcompression = NULL; +static char *pageserver_sslcrl = NULL; +static char *pageserver_sslcrldir = NULL; +static char *pageserver_sslkey = NULL; +static char *pageserver_sslmode = NULL; +static char *pageserver_sslpassword = NULL; +static char *pageserver_sslrootcert = NULL; +static char *pageserver_sslsni = NULL; +static char *pageserver_ssl_min_protocol_version = NULL; +static char *pageserver_ssl_max_protocol_version = NULL; + +#if PG_MAJORVERSION_NUM >= 17 +static char *pageserver_sslnegotiation = NULL; +#endif + static int pageserver_response_log_timeout = 10000; /* 2.5 minutes. A bit higher than highest default TCP retransmission timeout */ static int pageserver_response_disconnect_timeout = 150000; @@ -127,7 +144,7 @@ static uint64 pagestore_local_counter = 0; typedef enum PSConnectionState { PS_Disconnected, /* no connection yet */ PS_Connecting_Startup, /* connection starting up */ - PS_Connecting_PageStream, /* negotiating pagestream */ + PS_Connecting_PageStream, /* negotiating pagestream */ PS_Connected, /* connected, pagestream established */ } PSConnectionState; @@ -362,7 +379,7 @@ get_shard_number(BufferTag *tag) } static inline void -CLEANUP_AND_DISCONNECT(PageServer *shard) +CLEANUP_AND_DISCONNECT(PageServer *shard) { if (shard->wes_read) { @@ -384,7 +401,7 @@ CLEANUP_AND_DISCONNECT(PageServer *shard) * complete the connection (e.g. due to receiving an earlier cancellation * during connection start). * Returns true if successfully connected; false if the connection failed. - * + * * Throws errors in unrecoverable situations, or when this backend's query * is canceled. */ @@ -407,8 +424,8 @@ pageserver_connect(shardno_t shard_no, int elevel) { case PS_Disconnected: { - const char *keywords[5]; - const char *values[5]; + const char *keywords[17]; + const char *values[17]; char pid_str[16] = { 0 }; char endpoint_str[36] = { 0 }; int n_pgsql_params; @@ -482,6 +499,92 @@ pageserver_connect(shardno_t shard_no, int elevel) n_pgsql_params++; } + if (pageserver_sslcertmode) + { + keywords[n_pgsql_params] = "sslcertmode"; + values[n_pgsql_params] = pageserver_sslcertmode; + n_pgsql_params++; + } + + if (pageserver_sslcompression) + { + keywords[n_pgsql_params] = "sslcompression"; + values[n_pgsql_params] = pageserver_sslcompression; + n_pgsql_params++; + } + + if (pageserver_sslcrl) + { + keywords[n_pgsql_params] = "sslcrl"; + values[n_pgsql_params] = pageserver_sslcrl; + n_pgsql_params++; + } + + if (pageserver_sslcrldir) + { + keywords[n_pgsql_params] = "sslcrldir"; + values[n_pgsql_params] = pageserver_sslcrldir; + n_pgsql_params++; + } + + if (pageserver_sslkey) + { + keywords[n_pgsql_params] = "sslkey"; + values[n_pgsql_params] = pageserver_sslkey; + n_pgsql_params++; + } + + if (pageserver_sslmode) + { + keywords[n_pgsql_params] = "sslmode"; + values[n_pgsql_params] = pageserver_sslmode; + n_pgsql_params++; + } + +#if PG_MAJORVERSION_NUM >= 17 + if (pageserver_sslnegotiation) + { + keywords[n_pgsql_params] = "sslnegotiation"; + values[n_pgsql_params] = pageserver_sslnegotiation; + n_pgsql_params++; + } +#endif + + if (pageserver_sslpassword) + { + keywords[n_pgsql_params] = "sslpassword"; + values[n_pgsql_params] = pageserver_sslpassword; + n_pgsql_params++; + } + + if (pageserver_sslrootcert) + { + keywords[n_pgsql_params] = "sslrootcert"; + values[n_pgsql_params] = pageserver_sslrootcert; + n_pgsql_params++; + } + + if (pageserver_sslsni) + { + keywords[n_pgsql_params] = "sslsni"; + values[n_pgsql_params] = pageserver_sslsni; + n_pgsql_params++; + } + + if (pageserver_ssl_max_protocol_version) + { + keywords[n_pgsql_params] = "ssl_max_protocol_version"; + values[n_pgsql_params] = pageserver_ssl_max_protocol_version; + n_pgsql_params++; + } + + if (pageserver_ssl_min_protocol_version) + { + keywords[n_pgsql_params] = "ssl_min_protocol_version"; + values[n_pgsql_params] = pageserver_ssl_min_protocol_version; + n_pgsql_params++; + } + { bool param_set = false; switch (neon_compute_mode) @@ -1477,6 +1580,125 @@ pg_init_libpagestore(void) PGC_POSTMASTER, 0, NULL, NULL, NULL); + DefineCustomStringVariable( + "neon.pageserver_sslcert", + "SSL certificate path", + "Refer to the Postgres documentation on libpq's sslcert keyword.", + &pageserver_sslcert, + NULL, + PGC_POSTMASTER, + 0, + NULL, NULL, NULL); + DefineCustomStringVariable( + "neon.pageserver_sslcertmode", + "SSL certificate mode", + "Refer to the Postgres documentation on libpq's sslcertmode keyword.", + &pageserver_sslcertmode, + NULL, + PGC_POSTMASTER, + 0, + NULL, NULL, NULL); + DefineCustomStringVariable( + "neon.pageserver_sslcrl", + "Path to the SSL server certificate revocation list", + "Refer to the Postgres documentation on libpq's sslcrl keyword.", + &pageserver_sslcrl, + NULL, + PGC_POSTMASTER, + 0, + NULL, NULL, NULL); + DefineCustomStringVariable( + "neon.pageserver_sslcrldir", + "Path to the directory of the SSL server certificate revocation list", + "Refer to the Postgres documentation on libpq's sslcrldir keyword.", + &pageserver_sslcrldir, + NULL, + PGC_POSTMASTER, + 0, + NULL, NULL, NULL); + DefineCustomStringVariable( + "neon.pageserver_sslcompression", + "SSL compression", + "Refer to the Postgres documentation on libpq's sslcompression keyword.", + &pageserver_sslcompression, + NULL, + PGC_POSTMASTER, + 0, + NULL, NULL, NULL); + DefineCustomStringVariable( + "neon.pageserver_sslkey", + "SSL key", + "Refer to the Postgres documentation on libpq's sslkey keyword.", + &pageserver_sslkey, + NULL, + PGC_POSTMASTER, + 0, + NULL, NULL, NULL); + DefineCustomStringVariable( + "neon.pageserver_sslmode", + "SSL mode", + "Refer to the Postgres documentation on libpq's sslmode keyword.", + &pageserver_sslmode, + NULL, + PGC_POSTMASTER, + 0, + NULL, NULL, NULL); +#if PG_MAJORVERSION_NUM >= 17 + DefineCustomStringVariable( + "neon.pageserver_sslnegotiation", + "SSL negotiation", + "Refer to the Postgres documentation on libpq's sslnegotiation keyword.", + &pageserver_sslnegotiation, + NULL, + PGC_POSTMASTER, + 0, + NULL, NULL, NULL); +#endif + DefineCustomStringVariable( + "neon.pageserver_sslpassword", + "SSL passphrase", + "Refer to the Postgres documentation on libpq's sslpassword keyword.", + &pageserver_sslpassword, + NULL, + PGC_POSTMASTER, + 0, + NULL, NULL, NULL); + DefineCustomStringVariable( + "neon.pageserver_sslrootcert", + "SSL root certificate", + "Refer to the Postgres documentation on libpq's sslrootcert keyword.", + &pageserver_sslrootcert, + NULL, + PGC_POSTMASTER, + 0, + NULL, NULL, NULL); + DefineCustomStringVariable( + "neon.pageserver_sslsni", + "TLS SNI extension", + "Refer to the Postgres documentation on libpq's sslsni keyword.", + &pageserver_sslsni, + NULL, + PGC_POSTMASTER, + 0, + NULL, NULL, NULL); + DefineCustomStringVariable( + "neon.pageserver_ssl_max_protocol_version", + "SSL maxiumum protocol version", + "Refer to the Postgres documentation on libpq's ssl_max_protocol_version keyword.", + &pageserver_ssl_max_protocol_version, + NULL, + PGC_POSTMASTER, + 0, + NULL, NULL, NULL); + DefineCustomStringVariable( + "neon.pageserver_ssl_min_protocol_version", + "SSL minimum protocol version", + "Refer to the Postgres documentation on libpq's ssl_min_protocol_version keyword.", + &pageserver_ssl_min_protocol_version, + NULL, + PGC_POSTMASTER, + 0, + NULL, NULL, NULL); relsize_hash_init(); diff --git a/pgxn/neon/walproposer_pg.c b/pgxn/neon/walproposer_pg.c index a061639815..d334472013 100644 --- a/pgxn/neon/walproposer_pg.c +++ b/pgxn/neon/walproposer_pg.c @@ -64,6 +64,22 @@ char *wal_acceptors_list = ""; int wal_acceptor_reconnect_timeout = 1000; int wal_acceptor_connection_timeout = 10000; int safekeeper_proto_version = 2; +static char *safekeeper_sslcert = NULL; +static char *safekeeper_sslcertmode = NULL; +static char *safekeeper_sslcompression = NULL; +static char *safekeeper_sslcrl = NULL; +static char *safekeeper_sslcrldir = NULL; +static char *safekeeper_sslkey = NULL; +static char *safekeeper_sslmode = NULL; +static char *safekeeper_sslpassword = NULL; +static char *safekeeper_sslrootcert = NULL; +static char *safekeeper_sslsni = NULL; +static char *safekeeper_ssl_min_protocol_version = NULL; +static char *safekeeper_ssl_max_protocol_version = NULL; + +#if PG_MAJORVERSION_NUM >= 17 +static char *safekeeper_sslnegotiation = NULL; +#endif /* Set to true in the walproposer bgw. */ static bool am_walproposer; @@ -232,6 +248,125 @@ nwp_register_gucs(void) PGC_POSTMASTER, 0, NULL, NULL, NULL); + DefineCustomStringVariable( + "neon.safekeeper_sslcert", + "SSL certificate path", + "Refer to the Postgres documentation on libpq's sslcert keyword.", + &safekeeper_sslcert, + NULL, + PGC_POSTMASTER, + 0, + NULL, NULL, NULL); + DefineCustomStringVariable( + "neon.safekeeper_sslcertmode", + "SSL certificate mode", + "Refer to the Postgres documentation on libpq's sslcertmode keyword.", + &safekeeper_sslcertmode, + NULL, + PGC_POSTMASTER, + 0, + NULL, NULL, NULL); + DefineCustomStringVariable( + "neon.safekeeper_sslcrl", + "Path to the SSL server certificate revocation list", + "Refer to the Postgres documentation on libpq's sslcrl keyword.", + &safekeeper_sslcrl, + NULL, + PGC_POSTMASTER, + 0, + NULL, NULL, NULL); + DefineCustomStringVariable( + "neon.safekeeper_sslcrldir", + "Path to the directory of the SSL server certificate revocation list", + "Refer to the Postgres documentation on libpq's sslcrldir keyword.", + &safekeeper_sslcrldir, + NULL, + PGC_POSTMASTER, + 0, + NULL, NULL, NULL); + DefineCustomStringVariable( + "neon.safekeeper_sslcompression", + "SSL compression", + "Refer to the Postgres documentation on libpq's sslcompression keyword.", + &safekeeper_sslcompression, + NULL, + PGC_POSTMASTER, + 0, + NULL, NULL, NULL); + DefineCustomStringVariable( + "neon.safekeeper_sslkey", + "SSL key", + "Refer to the Postgres documentation on libpq's sslkey keyword.", + &safekeeper_sslkey, + NULL, + PGC_POSTMASTER, + 0, + NULL, NULL, NULL); + DefineCustomStringVariable( + "neon.safekeeper_sslmode", + "SSL mode", + "Refer to the Postgres documentation on libpq's sslmode keyword.", + &safekeeper_sslmode, + NULL, + PGC_POSTMASTER, + 0, + NULL, NULL, NULL); +#if PG_MAJORVERSION_NUM >= 17 + DefineCustomStringVariable( + "neon.safekeeper_sslnegotiation", + "SSL negotiation", + "Refer to the Postgres documentation on libpq's sslnegotiation keyword.", + &safekeeper_sslnegotiation, + NULL, + PGC_POSTMASTER, + 0, + NULL, NULL, NULL); +#endif + DefineCustomStringVariable( + "neon.safekeeper_sslpassword", + "SSL passphrase", + "Refer to the Postgres documentation on libpq's sslpassword keyword.", + &safekeeper_sslpassword, + NULL, + PGC_POSTMASTER, + 0, + NULL, NULL, NULL); + DefineCustomStringVariable( + "neon.safekeeper_sslrootcert", + "SSL root certificate", + "Refer to the Postgres documentation on libpq's sslrootcert keyword.", + &safekeeper_sslrootcert, + NULL, + PGC_POSTMASTER, + 0, + NULL, NULL, NULL); + DefineCustomStringVariable( + "neon.safekeeper_sslsni", + "TLS SNI extension", + "Refer to the Postgres documentation on libpq's sslsni keyword.", + &safekeeper_sslsni, + NULL, + PGC_POSTMASTER, + 0, + NULL, NULL, NULL); + DefineCustomStringVariable( + "neon.safekeeper_ssl_max_protocol_version", + "SSL maxiumum protocol version", + "Refer to the Postgres documentation on libpq's ssl_max_protocol_version keyword.", + &safekeeper_ssl_max_protocol_version, + NULL, + PGC_POSTMASTER, + 0, + NULL, NULL, NULL); + DefineCustomStringVariable( + "neon.safekeeper_ssl_min_protocol_version", + "SSL minimum protocol version", + "Refer to the Postgres documentation on libpq's ssl_min_protocol_version keyword.", + &safekeeper_ssl_min_protocol_version, + NULL, + PGC_POSTMASTER, + 0, + NULL, NULL, NULL); } @@ -843,15 +978,13 @@ walprop_status(Safekeeper *sk) WalProposerConn * libpqwp_connect_start(char *conninfo) { - PGconn *pg_conn; WalProposerConn *conn; - const char *keywords[3]; - const char *values[3]; + const char *keywords[16]; + const char *values[16]; int n; char *password = neon_auth_token; - /* * Connect using the given connection string. If the NEON_AUTH_TOKEN * environment variable was set, use that as the password. @@ -871,9 +1004,90 @@ libpqwp_connect_start(char *conninfo) keywords[n] = "dbname"; values[n] = conninfo; n++; + if (safekeeper_sslcert) + { + keywords[n] = "sslcert"; + values[n] = safekeeper_sslcert; + n++; + } + if (safekeeper_sslcertmode) + { + keywords[n] = "sslcertmode"; + values[n] = safekeeper_sslcertmode; + n++; + } + if (safekeeper_sslcompression) + { + keywords[n] = "sslcompression"; + values[n] = safekeeper_sslcompression; + n++; + } + if (safekeeper_sslcrl) + { + keywords[n] = "sslcrl"; + values[n] = safekeeper_sslcrl; + n++; + } + if (safekeeper_sslcrldir) + { + keywords[n] = "sslcrldir"; + values[n] = safekeeper_sslcrldir; + n++; + } + if (safekeeper_sslkey) + { + keywords[n] = "sslkey"; + values[n] = safekeeper_sslkey; + n++; + } + if (safekeeper_sslmode) + { + keywords[n] = "sslmode"; + values[n] = safekeeper_sslmode; + n++; + } +#if PG_MAJORVERSION_NUM >= 17 + if (safekeeper_sslnegotiation) + { + keywords[n] = "sslnegotiation"; + values[n] = safekeeper_sslnegotiation; + n++; + } +#endif + if (safekeeper_sslpassword) + { + keywords[n] = "sslpassword"; + values[n] = safekeeper_sslpassword; + n++; + } + if (safekeeper_sslrootcert) + { + keywords[n] = "sslrootcert"; + values[n] = safekeeper_sslrootcert; + n++; + } + if (safekeeper_sslsni) + { + keywords[n] = "sslsni"; + values[n] = safekeeper_sslsni; + n++; + } + if (safekeeper_ssl_max_protocol_version) + { + keywords[n] = "ssl_max_protocol_version"; + values[n] = safekeeper_ssl_max_protocol_version; + n++; + } + if (safekeeper_ssl_min_protocol_version) + { + keywords[n] = "ssl_min_protocol_version"; + values[n] = safekeeper_ssl_min_protocol_version; + n++; + } keywords[n] = NULL; values[n] = NULL; n++; + pg_conn = PQconnectStartParams(keywords, values, 1); /*