Open
Conversation
added 12 commits
April 23, 2026 17:32
Covers TLS for pg_doorman-to-PostgreSQL connections: five SSL modes (disable/prefer/require/verify-ca/verify-full), mutual TLS, TLS-aware cancel requests, and per-pool configuration with global defaults.
What was needed: A foundational enum representing the five TLS modes for backend (server-facing) connections — disable, prefer, require, verify-ca, verify-full — so that later tasks can wire up server-side TLS config and connection logic. Summary: Clients can now refer to ServerTlsMode when connecting to PostgreSQL backends. The enum defaults to Prefer, parses from/renders to the canonical lowercase string forms, and exposes three helper predicates: requires_ca, sends_ssl_request, and requires_tls.
Что требовалось: нужна структура, инкапсулирующая режим TLS и готовый коннектор для исходящих соединений с сервером БД. Суть: пул теперь может получить предсобранный TlsConnector при загрузке конфигурации, вместо того чтобы строить его при каждом подключении.
The old boolean fields were parsed by serde but the TLS connection code returned an error when the server accepted TLS, making them non-functional. Replace with string-based server_tls_mode (prefer/require/disable/verify-full) and optional certificate path fields (server_tls_ca_cert, server_tls_certificate, server_tls_private_key). Pool fields are Option<String> to inherit from General via unwrap_or(). Server backend uses false/false stubs pending full TLS wiring.
What was needed: server-facing TLS fields had no validation, so misconfigured cert paths, mismatched cert/key pairs, and missing CA certs for verify modes would only fail at runtime. Summary: Startup now rejects invalid server TLS configurations eagerly and logs the effective server TLS mode and cert paths alongside the existing frontend TLS info.
Each Address now carries a resolved Arc<ServerTlsConfig> built once at pool creation time, so Server::startup() can consume it directly without re-reading global config on every connection. build_server_tls_for_pool() merges pool-level TLS overrides with general defaults. Dynamic pools (auth_query passthrough) call the same helper. Test construction sites use struct-update syntax to stay forward-compatible.
What was needed: server-side TLS support in the connection pooler requires StreamInner to handle encrypted TCP connections alongside plain TCP and Unix sockets. What changed: StreamInner now has a TCPTls variant wrapping TlsStream<TcpStream>. create_tcp_stream_inner accepts ServerTlsConfig instead of bare booleans and performs SSLRequest/handshake negotiation based on the configured TLS mode — connecting with TLS when the server supports it, falling back to plain TCP when the mode allows it, or failing when TLS is required but unavailable.
What was needed: cancel requests to PostgreSQL must use TLS when the main pooled connection was established over TLS. Essence: Server::startup() now uses per-address TLS config, ClientServerMap stores TLS info alongside connection details, and cancel requests reuse the same TLS configuration as the original connection.
The old server_tls (bool) and verify_server_certificate (bool) fields were replaced with server_tls_mode, server_tls_ca_cert, server_tls_certificate, and server_tls_private_key, but fields.yaml and the reference configs were not updated — breaking 9 tests in src/app/generate/. Updated fields.yaml for both general and pool sections and regenerated pg_doorman.toml and pg_doorman.yaml from the new field definitions.
…e, per-pool)
New step "PostgreSQL SSL certificates are generated" creates a full PKI
(CA + server cert with SAN + client cert + wrong CA) so feature scenarios
can start PostgreSQL with SSL enabled and point pg_doorman at the certs
via placeholder substitution.
Placeholder substitution is now also applied to the PostgreSQL options
string, allowing ${PG_SSL_CERT} / ${PG_SSL_KEY} inside pg_ctl -o flags.
| info!("Server TLS CA cert: {ca}"); | ||
| } | ||
| if let Some(ref cert) = self.general.server_tls_certificate { | ||
| info!("Server TLS certificate: {cert}"); |
|
|
||
| match mode { | ||
| ServerTlsMode::Prefer | ServerTlsMode::Require => { | ||
| builder.danger_accept_invalid_certs(true); |
| match mode { | ||
| ServerTlsMode::Prefer | ServerTlsMode::Require => { | ||
| builder.danger_accept_invalid_certs(true); | ||
| builder.danger_accept_invalid_hostnames(true); |
| let ca = load_certificate(ca_path)?; | ||
| builder.add_root_certificate(ca); | ||
| } | ||
| builder.danger_accept_invalid_hostnames(true); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
disable,prefer(default),require,verify-ca,verify-full[general]Breaking config change
Old non-functional fields
server_tlsandverify_server_certificateare removed. They were parsed but never worked —stream.rsreturned an error when the server accepted TLS. Replacement:server_tls_mode(string) +server_tls_ca_cert,server_tls_certificate,server_tls_private_key(paths).Configuration example
Test plan
cargo fmtcleancargo clippy -- --deny "warnings"cleanmake test-bdd TAGS=@server-tls) — prefer, require, verify-ca, verify-ca-wrong-CA, disable, per-pool override🤖 Generated with Claude Code