Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion .schema/pgdog.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@
"tls_client_required": false,
"tls_private_key": null,
"tls_server_ca_certificate": null,
"tls_server_certificate": null,
"tls_server_private_key": null,
"tls_verify": "prefer",
"two_phase_commit": false,
"two_phase_commit_auto": null,
Expand Down Expand Up @@ -189,7 +191,7 @@
"$ref": "#/$defs/Plugin"
}
},
"query_parser": {
"query_parsers": {
"description": "Query parser levels per-database.",
"type": "array",
"default": [],
Expand Down Expand Up @@ -1181,6 +1183,20 @@
"null"
]
},
"tls_server_certificate": {
"description": "Path to the TLS certificate PgDog presents to upstream Postgres servers,\nenabling mutual TLS (client authentication) on the server connection.\n\nhttps://docs.pgdog.dev/configuration/pgdog.toml/general/#tls_server_certificate",
"type": [
"string",
"null"
]
},
"tls_server_private_key": {
"description": "Path to the TLS private key for the certificate configured in\n`tls_server_certificate`.\n\nhttps://docs.pgdog.dev/configuration/pgdog.toml/general/#tls_server_private_key",
"type": [
"string",
"null"
]
},
"tls_verify": {
"description": "How to handle TLS connections to Postgres servers.\n\n_Default:_ `prefer`\n\nhttps://docs.pgdog.dev/configuration/pgdog.toml/general/#tls_verify",
"$ref": "#/$defs/TlsVerifyMode",
Expand Down
6 changes: 6 additions & 0 deletions example.pgdog.toml
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,12 @@ tls_verify = "disabled"
# Path to PEM-encoded certificate bundle to use for Postgres server
# certificate validation.
# tls_server_ca_certificate = "relative/or/absolute/path/to/certificate.pem"
# Path to PEM-encoded TLS certificate PgDog presents to Postgres servers for
# mutual TLS (client authentication on the server connection). Requires
# tls_server_private_key to also be set.
# tls_server_certificate = "relative/or/absolute/path/to/certificate.pem"
# Path to the PEM-encoded private key for tls_server_certificate.
# tls_server_private_key = "relative/or/absolute/path/to/private_key.pem"
# How long to wait for active connections to finish transactions
# when shutting down PgDog.
#
Expand Down
38 changes: 38 additions & 0 deletions pgdog-config/src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -744,6 +744,44 @@ column = "tenant_id"
assert_eq!(config.multi_tenant.unwrap().column, "tenant_id");
}

#[test]
fn test_upstream_client_cert_config_parses() {
let source = r#"
[general]
tls_verify = "verify_full"
tls_server_ca_certificate = "/certs/ca.pem"
tls_server_certificate = "/certs/client.pem"
tls_server_private_key = "/certs/client.key"

[[databases]]
name = "production"
host = "127.0.0.1"
database_name = "postgres"
"#;

let config: Config = toml::from_str(source).unwrap();
assert_eq!(config.general.tls_verify, TlsVerifyMode::VerifyFull);
assert_eq!(
config.general.tls_server_certificate.as_deref(),
Some(std::path::Path::new("/certs/client.pem"))
);
assert_eq!(
config.general.tls_server_private_key.as_deref(),
Some(std::path::Path::new("/certs/client.key"))
);

// Both keys are optional: omitting them leaves the fields unset.
let without = r#"
[[databases]]
name = "production"
host = "127.0.0.1"
database_name = "postgres"
"#;
let config: Config = toml::from_str(without).unwrap();
assert!(config.general.tls_server_certificate.is_none());
assert!(config.general.tls_server_private_key.is_none());
}

#[test]
fn test_prepared_statements_disabled_in_session_mode() {
let mut config = ConfigAndUsers::default();
Expand Down
22 changes: 22 additions & 0 deletions pgdog-config/src/general.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,18 @@ pub struct General {
/// https://docs.pgdog.dev/configuration/pgdog.toml/general/#tls_server_ca_certificate
pub tls_server_ca_certificate: Option<PathBuf>,

/// Path to the TLS certificate PgDog presents to upstream Postgres servers,
/// enabling mutual TLS (client authentication) on the server connection.
///
/// https://docs.pgdog.dev/configuration/pgdog.toml/general/#tls_server_certificate
pub tls_server_certificate: Option<PathBuf>,

/// Path to the TLS private key for the certificate configured in
/// `tls_server_certificate`.
///
/// https://docs.pgdog.dev/configuration/pgdog.toml/general/#tls_server_private_key
pub tls_server_private_key: Option<PathBuf>,

/// Path to a certificate bundle used to validate the client certificate on TLS connection creation.
///
/// https://docs.pgdog.dev/configuration/pgdog.toml/general/#tls_client_ca_certificate
Expand Down Expand Up @@ -834,6 +846,8 @@ impl Default for General {
tls_client_required: bool::default(),
tls_verify: Self::default_tls_verify(),
tls_server_ca_certificate: Self::tls_server_ca_certificate(),
tls_server_certificate: Self::tls_server_certificate(),
tls_server_private_key: Self::tls_server_private_key(),
tls_client_ca_certificate: Self::tls_client_ca_certificate(),
shutdown_timeout: Self::default_shutdown_timeout(),
shutdown_termination_timeout: Self::default_shutdown_termination_timeout(),
Expand Down Expand Up @@ -1227,6 +1241,14 @@ impl General {
Self::env_option_string("PGDOG_TLS_SERVER_CA_CERTIFICATE").map(PathBuf::from)
}

fn tls_server_certificate() -> Option<PathBuf> {
Self::env_option_string("PGDOG_TLS_SERVER_CERTIFICATE").map(PathBuf::from)
}

fn tls_server_private_key() -> Option<PathBuf> {
Self::env_option_string("PGDOG_TLS_SERVER_PRIVATE_KEY").map(PathBuf::from)
}

fn tls_client_ca_certificate() -> Option<PathBuf> {
Self::env_option_string("PGDOG_TLS_CLIENT_CA_CERTIFICATE").map(PathBuf::from)
}
Expand Down
2 changes: 2 additions & 0 deletions pgdog/src/backend/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,8 @@ impl Server {
let connector = connector_with_verify_mode(
tls_mode,
config.config.general.tls_server_ca_certificate.as_ref(),
config.config.general.tls_server_certificate.as_ref(),
config.config.general.tls_server_private_key.as_ref(),
)?;
let plain = stream.take()?;

Expand Down
Loading