Add support for --trusted-host (#6591)

## Summary

This PR revives https://github.com/astral-sh/uv/pull/4944, which I think
was a good start towards adding `--trusted-host`. Last night, I tried to
add `--trusted-host` with a custom verifier, but we had to vendor a lot
of `reqwest` code and I eventually hit some private APIs. I'm not
confident that I can implement it correctly with that mechanism, and
since this is security, correctness is the priority.

So, instead, we now use two clients and multiplex between them.

Closes https://github.com/astral-sh/uv/issues/1339.

## Test Plan

Created self-signed certificate, and ran `python3 -m http.server --bind
127.0.0.1 4443 --directory . --certfile cert.pem --keyfile key.pem` from
the packse index directory.

Verified that `cargo run pip install
transitive-yanked-and-unyanked-dependency-a-0abad3b6 --index-url
https://127.0.0.1:8443/simple-html` failed with:

```
error: Request failed after 3 retries
  Caused by: error sending request for url (https://127.0.0.1:8443/simple-html/transitive-yanked-and-unyanked-dependency-a-0abad3b6/)
  Caused by: client error (Connect)
  Caused by: invalid peer certificate: Other(OtherError(CaUsedAsEndEntity))
```

Verified that `cargo run pip install
transitive-yanked-and-unyanked-dependency-a-0abad3b6 --index-url
'https://127.0.0.1:8443/simple-html' --trusted-host '127.0.0.1:8443'`
failed with the expected error (invalid resolution) and made valid
requests.

Verified that `cargo run pip install
transitive-yanked-and-unyanked-dependency-a-0abad3b6 --index-url
'https://127.0.0.1:8443/simple-html' --trusted-host '127.0.0.2' -n` also
failed.
This commit is contained in:
Charlie Marsh 2024-08-27 09:36:50 -04:00 committed by GitHub
parent ce749591de
commit d86075fc1e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
31 changed files with 808 additions and 125 deletions

View file

@ -1118,7 +1118,7 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
.git()
.fetch(
resource.git,
client.unmanaged.uncached_client().client(),
client.unmanaged.uncached_client(resource.url).clone(),
self.build_context.cache().bucket(CacheBucket::Git),
self.reporter.clone().map(Facade::from),
)
@ -1188,7 +1188,7 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
.git()
.fetch(
resource.git,
client.unmanaged.uncached_client().client(),
client.unmanaged.uncached_client(resource.url).clone(),
self.build_context.cache().bucket(CacheBucket::Git),
self.reporter.clone().map(Facade::from),
)
@ -1589,7 +1589,7 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
/// Returns a GET [`reqwest::Request`] for the given URL.
fn request(url: Url, client: &RegistryClient) -> Result<reqwest::Request, reqwest::Error> {
client
.uncached_client()
.uncached_client(&url)
.get(url)
.header(
// `reqwest` defaults to accepting compressed responses.