Description
Checklist
- I've searched the issue tracker for similar requests
Is your feature request related to a problem? Please describe.
I work on a very big project with multiple applications that uses rustls and which dependencies also use rustls. We have a custom provider based on aws-lc-rs, that we want to be used by all of our crates.
Besides, some of our dependency relies on a static provider has been installed in the current process.
My problem is sometimes, when new codes that need tls is added, the original aws-lc-rs is silently used instead of our custom one.
For instance, if in a crate someone does rustls_platform_verifier::tls_config
without installing our custom provider before, no error will be thrown and this will use the classic aws-lc-rs provider
I thought how I could detect this with some tooling, like clippy or cargo deny and I didn't figure it out.
Describe the solution you'd like
I would like that ring and aws-lc-rs provider to be moved on a separate crate. They could still be added as dependency to ruslts under feature flag to keep the current behavior.
If aws-lc-rs provider were in a separated crate, I could use this crate directly for my custom provider. I could then deny the feature aws-lc-rs and ring with cargo deny
[[bans.features]]
name = "rustls"
deny = ["aws-lc-rs","aws_lc_rs", "ring"]
reason = "we use our own provider"
Then if somebody forgets to install the custom provider, it will be caught thanks to a panic in get_default_or_install_from_crate_features()
. This can work right now for providers that aren't based on ring or aws-lc-rs, but in my case I must activate the aws-lc-rs feature so I can base my custom provider on it.
Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.
Option A: force users to always use builder_with_provider
I can tell users to not use the process default provider and add this to my clippy.toml:
disallowed-methods = [
{ path = "rustls::ClientConfig::builder", reason = "can silently use a wrong provider" },
{ path = "rustls::ServerConfig::builder", reason = "can silently use a wrong provider" },
# But those methodes can also be called transitively..
{ path = "rustls_platform_verifier::tls_config", reason = "can silently use a wrong provider" },
]
The problem is that I must also scan dependencies that my use the default provider and so each time a new version is issued.
Besides we have a patched dependency which relies on the process default because it makes the patch a lot simpler.
Option B: reexport rustls and dependencies that use rustls under an inner crate
Another solution is to have an inner crate that has rustls has a private dependency and force use to use my crate with cargo deny
deny = [
{ crate = "rustls", reason = "must not be used directly", use-instead = "inner-crate", wrappers = ["inner-crate"]},
]
This requires less auditing of dependencies, because I only have to do a cargo tree to see the one that depends of rustls. In the clippy solution I would also have to check if they use ClientConfig::builder()
internally.
Additional context
I´m not a provider expert and maybe I missed something. If so I would be grateful if you can provide additional guidance. Otherwise the proposed solution, moving the providers to a crate, that I remember to have already been discussed, seems to be a reasonable option.