Skip to content

Add client certificates option to cargo registries #10641

@ETKNeil

Description

@ETKNeil

Problem

Currently when using a private registry, it will pull down the assets via http(s) from a public facing registry, however in the context of a company we don't want such public facing registry to be left unauthentificated.

One way to mitigate the problem is to implement what is call mutual TLS or client certificate. The client come with a certificate which is derived from a CA known to the server and the proxy such as NGINX, Apache, Haproxy or squid will serve either a 403 or the registry.

Proposed Solution

Fortunately for us curl (the backend used by cargo to make its request) already support client ssl certificates. Such certificates are composed of 2(3) parts, a certificate (public key), a private key and optionally a password protecting the private key.

I propose to use the curl::easy::Easy::ssl_cert curl::easy::Easy::ssl_key and curl::easy::Easy::key_password which are well tested methods in curl source code :

I would then expose those options inside the [http] section of the $HOME/.cargo/config.toml :

[http]
client-ssl-cert = "/etc/ssl/client.pem"
client-ssl-key = "/etc/ssl/key.pem"
client-ssl-key-password = "<password>"

Here is the PR : #10630

Notes

The certificate public and private key must be accessible by the user, so anyone accessing this user account has access to those information, we can optionally encrypt the private key with a password, this mitigate such broad access however here we would store it as plain text.

The password will be stored as plain text, the issue could be that it can then be read by anyone, but let me remind you that the registry token is also stored as plain text inside credentials.toml in the .cargo home directory.
We can not securely store it as asking it each time that you make a request to the registry would be counter productive for the user. In my threat model I assumed that the user would have the specific config with the plain password only in its home directory and that the home security would be assumed by the user.

Testing such real world scenario would need a mocking framework for a server with a client certificate authentication, however as these options are well tested in libcurl, I don't see the point of testing such feature. A regression in such area would likely mean also that all TLS exchange are broken as well.

In the PR, I set the key type to PEM, however it's already the default : https://github.com/curl/curl/blob/master/docs/libcurl/opts/CURLOPT_SSLKEYTYPE.3#L44 , I made this change so its explicit and fixed from an usage perspective. We could also provide the option to support DER format but since changing from DER to PEM is a one liner, having it as a constant would help to fix it once and for all.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-networkingArea: networking issues, curl, etc.A-registriesArea: registriesA-registry-authenticationArea: registry authentication and authorization (authn authz)C-feature-requestCategory: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted`S-triageStatus: This issue is waiting on initial triage.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions