Skip to content

Ensuring that a provider based on the one built-in is used #1920

Closed
@stormshield-gt

Description

@stormshield-gt

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions