// Connection configuration and TLS policy for the PostgreSQL client package.
///|
/// Controls how the client negotiates TLS when opening a TCP connection.
///
/// The modes are intentionally strict:
/// plaintext is opt-in via `Disable`, while TLS-using callers choose between
/// certificate-chain verification with or without endpoint identity checks.
pub(all) enum SslMode {
/// Explicit plaintext mode.
///
/// The client skips PostgreSQL SSL negotiation, does not encrypt traffic,
/// and does not verify the server's identity.
Disable
/// Require TLS and verify the server certificate chain.
///
/// This mode never falls back to plaintext. It validates the certificate
/// chain against the configured trust roots, **but it does not verify that the
/// certificate matches the requested hostname or IP address!**
///
/// Its security can approach `VerifyFull` only when a private CA issues
/// certificates exclusively for the intended PostgreSQL endpoints.
VerifyCa
/// Require TLS, verify the certificate chain, and verify endpoint identity.
///
/// This mode never falls back to plaintext. It validates both the server
/// certificate chain and the requested hostname or IP address, and is the
/// default and recommended mode.
VerifyFull
} derive(Debug, Eq)
///|
/// Controls whether SCRAM channel binding is disabled, preferred, or required.
///
/// This setting controls whether the connection must complete SCRAM channel
/// binding. It does not enable TLS by itself.
/// It is also unrelated to TLS `sslmode`: this package still does not support
/// the removed libpq-style TLS aliases `sslmode=prefer` or `sslmode=require`.
///
/// `Disable` always uses plain `SCRAM-SHA-256`.
/// `Prefer` uses `SCRAM-SHA-256-PLUS` when the TLS transport exposes a
/// supported binding and the server advertises it, otherwise it falls back to
/// plain `SCRAM-SHA-256`.
/// `Require` insists on `SCRAM-SHA-256-PLUS` and fails when TLS or server
/// support is missing. Because non-SCRAM authentication methods cannot employ
/// PostgreSQL channel binding, `Require` rejects them before sending
/// authentication credentials.
pub(all) enum ChannelBinding {
Disable
Prefer
Require
} derive(Debug, Eq)
///|
/// Immutable configuration supplied to `Client::create`.
///
/// The returned `ClientExecutor::run` uses this value to establish a PostgreSQL
/// session. The client runtime retains it so that later features, such as
/// cancellation, can reopen a control connection with the exact same host and
/// port. Its `Debug` representation replaces a configured password with
/// ``.
pub struct Config {
/// Hostname used for TLS verification and default server-name handling.
host : String
/// Optional concrete address used for the TCP socket connection.
hostaddr : String?
/// TCP port for the PostgreSQL server.
port : Int32
/// Login role used during startup authentication.
user : String
/// Database selected in the startup packet.
database : String
/// Optional password consumed by password-based authentication methods.
/// PostgreSQL chooses the authentication method at startup; cleartext
/// password and SCRAM authentication require this field to be present.
password : String?
/// TLS negotiation policy.
ssl_mode : SslMode
/// Root certificate file used to verify the server certificate chain.
///
/// `None` keeps the platform default trust-store behavior. The special value
/// `"system"` also selects the platform trust store and requires
/// `ssl_mode == SslMode::VerifyFull`.
ssl_root_cert : String?
/// Channel-binding preference for SCRAM authentication.
channel_binding : ChannelBinding
/// Value sent as PostgreSQL `application_name`.
application_name : String
/// Optional PostgreSQL `options` startup parameter.
options : String?
/// Optional end-to-end connection timeout in milliseconds.
connect_timeout_ms : Int32?
/// Whether TCP keepalive should be enabled on the socket.
keepalives : Bool?
/// Idle time in seconds before the first TCP keepalive probe.
keepalives_idle_s : Int32?
} derive(Eq)
///|
/// Keep connection diagnostics useful without rendering the password.
pub impl @debug.Debug for Config with fn to_repr(self) {
let password : String? = if self.password is Some(_) {
Some("")
} else {
None
}
@debug.Repr::record({
"host": @debug.Repr(self.host),
"hostaddr": @debug.Repr(self.hostaddr),
"port": @debug.Repr(self.port),
"user": @debug.Repr(self.user),
"database": @debug.Repr(self.database),
"password": @debug.Repr(password),
"ssl_mode": @debug.Repr(self.ssl_mode),
"ssl_root_cert": @debug.Repr(self.ssl_root_cert),
"channel_binding": @debug.Repr(self.channel_binding),
"application_name": @debug.Repr(self.application_name),
"options": @debug.Repr(self.options),
"connect_timeout_ms": @debug.Repr(self.connect_timeout_ms),
"keepalives": @debug.Repr(self.keepalives),
"keepalives_idle_s": @debug.Repr(self.keepalives_idle_s),
})
}
///|
/// Build a configuration with PostgreSQL-friendly defaults.
///
/// Defaults are chosen to keep secure TLS on the main path: port `5432`,
/// `ssl_mode = SslMode::VerifyFull`, and database name equal to the user name.
/// Callers pass `application_name` explicitly.
pub fn Config::Config(
host : String,
hostaddr? : String,
port~ : Int32 = 5432,
user~ : String,
database~ : String = user,
password? : String,
ssl_mode~ : SslMode = VerifyFull,
ssl_root_cert? : String,
channel_binding~ : ChannelBinding = Disable,
application_name~ : String,
options? : String,
connect_timeout_ms? : Int32,
keepalives? : Bool,
keepalives_idle_s? : Int32,
) -> Config {
{
host,
hostaddr,
port,
user,
database,
password,
ssl_mode,
ssl_root_cert,
channel_binding,
application_name,
options,
connect_timeout_ms,
keepalives,
keepalives_idle_s,
}
}
///|
/// Internal constructor for a single PostgreSQL connection target.
///
/// Used by pgpool to build one client config per endpoint. Callers
/// supply every field explicitly; no defaults or validation are applied here.
#internal(internal, "for internal use only")
pub fn Config::new_internal(
host : String,
hostaddr : String?,
port : Int32,
user : String,
database : String,
password : String?,
ssl_mode : SslMode,
ssl_root_cert : String?,
channel_binding : ChannelBinding,
application_name : String,
options : String?,
connect_timeout_ms : Int32?,
keepalives : Bool?,
keepalives_idle_s : Int32?,
) -> Config {
{
host,
hostaddr,
port,
user,
database,
password,
ssl_mode,
ssl_root_cert,
channel_binding,
application_name,
options,
connect_timeout_ms,
keepalives,
keepalives_idle_s,
}
}