sqlx icon indicating copy to clipboard operation
sqlx copied to clipboard

[PostgreSQL] Must TLS configuration parameters mirror what's available in `libpq`?

Open LukeMathWalker opened this issue 2 months ago • 5 comments

I have found these related issues/pull requests

Description

The current PgConfig definition seems to mirror quite closely, for TLS, the corresponding options in libpq: sslmode, sslrootcert, sslcert, sslkey.

I'm currently trying to build an application that uses a unified TLS policy across all its clients. In particular, a consistent set of trusted root certificates. I'm struggling to get sqlx to fit. As far as I understand, these are my options:

  • I can specify sslrootcert, but this requires me to manually "bundle" all my certs into a single PEM bundle
  • I can use tls-rustls-native-roots to get the certs trusted by the OS (soon via rustls-plaftorm-verifier)

There is no way for me to say: I want the certs trusted by the OS as well as these other N roots. Something equivalent to Verifier::new_with_extra_roots.

Prefered solution

I can see various options to solve the problem:

  • Move away from mirroring libpq when it comes to TLS configuration, using a more expressive set of options for server certificate verification
  • Allow the user to pass a preconfigured rustls::Config (although that'd have semver implications)

and probably others I haven't thought about. But I'd like to first understand if there is an interest in tackling the problem.

Is this a breaking change? Why or why not?

It'd most likely be a breaking change.

LukeMathWalker avatar Oct 03 '25 13:10 LukeMathWalker

We can add options beyond what libpq supports, that's not a problem. We just used libpq as a baseline.

However, I'm leaning towards letting the user specify a custom rustls::ClientConfig since it has plenty of other use-cases as well, like #4044.

It could be a SemVer hazard, but we could just mark that API as SemVer-exempt. However, Rustls has been on the 0.23 release for at least a year and 0.24 seems to be a ways off still, so that's possibly a non-issue.

abonander avatar Oct 03 '25 21:10 abonander

However, I'm leaning towards letting the user specify a custom rustls::ClientConfig since it has plenty of other use-cases as well, like #4044.

How do you envision that working? A method along the lines of reqwest::ClientBuilder::use_preconfigured_tls on PgConnectOptions (and, I assume, all other database drivers)?

It could be a SemVer hazard, but we could just mark that API as SemVer-exempt. However, Rustls has been on the 0.23 release for at least a year and 0.24 seems to be a ways off still, so that's possibly a non-issue.

Yes, I don't think 0.24.x is coming out any time soon.

LukeMathWalker avatar Oct 04 '25 08:10 LukeMathWalker

I'd just have a method that takes rustls::ClientConfig and one that takes... I dunno, probably a native_tls::TlsConnector.

If we wanted to support it in the same method then we'd need to create a common trait to implement for both types. Which is possible, I'm just not sure what the value is. I guess that would allow third-party implementations, which could be useful.

As for the SemVer issue, we could just try using a range when Rustls 0.24 releases. I think that's less hazardous than taking dyn Any because if Cargo fails to constrain the version correctly it'll error at compile time instead of runtime.

abonander avatar Oct 05 '25 00:10 abonander

I'd just have a method that takes rustls::ClientConfig and one that takes... I dunno, probably a native_tls::TlsConnector.

I've started to sketch the design in https://github.com/launchbadge/sqlx/pull/4051. There are some open questions that would benefit from your input, before I go further with the implementation work.

If we wanted to support it in the same method then we'd need to create a common trait to implement for both types. Which is possible, I'm just not sure what the value is. I guess that would allow third-party implementations, which could be useful.

That's something that could be added later on, if desired, in a backwards-compatible manner. E.g. it'd allow sqlx to support multiple versions of rustls, if desired.

LukeMathWalker avatar Oct 05 '25 13:10 LukeMathWalker

I'm leaning towards letting the user specify a custom rustls::ClientConfig since it has plenty of other use-cases as well, like #4044.

@abonander Would it be okay to have #4044 in the meantime, or do you want to go directly for the support of custom rustls::ClientConfig?

While not crucial, it will enable us to rely on a single TLS implementation.

manifest avatar Oct 25 '25 09:10 manifest