-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Update redirect implementation to handle more cases and be more testable #13754
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update redirect implementation to handle more cases and be more testable #13754
Conversation
|
|
||
| /// Allows credentials to be propagated on cross-origin redirects. | ||
| /// | ||
| /// WARNING: This should only be available for tests. In production code, propagating credentials |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added this same warning in a few places to make sure this invariant isn't broken in the future.
9f19ed9 to
e312789
Compare
| /// uv currently fails to look up keyring credentials on a cross-origin redirect. | ||
| #[tokio::test] | ||
| async fn add_redirect_with_keyring() -> Result<()> { | ||
| async fn add_redirect_with_keyring_cross_origin() -> Result<()> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On a cross-origin request (which is what happens with the mock server here), no username is propagated. It would be possible to use reqwest_middleware Extensions to do this and special-case the handling of a username propagated in that way, but we have decided to avoid the complexity around this refactor for now. Currently, this means that uv will not successfully find credentials in the keyring for cross-origin requests.
a5e9cdc to
1cc0e69
Compare
4c08337 to
b593d30
Compare
8b77039 to
edf9395
Compare
b593d30 to
fc162d6
Compare
edf9395 to
faca251
Compare
fc162d6 to
416ffe0
Compare
konstin
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a table to the description showing what behaviors we have on main and how they are with the two PRs for the relevant cases? This makes easier to follow along what we're changing and that we're handling everything we want to handle.
I've added a table |
8ac696c to
07df848
Compare
416ffe0 to
3b11243
Compare
07df848 to
0ad2529
Compare
3b11243 to
ea48ef9
Compare
0ad2529 to
97183db
Compare
ea48ef9 to
ae6b69c
Compare
a5e0fcc to
8a85667
Compare
7cded92 to
c9c44e3
Compare
|
Thanks for the confirmation @jenshnielsen! |
|
EDIT: Both ways worked great. No issues. I checked out the PR, cd'd into a new folder, added a The (really cool looking!) uvx command gets stuck on the last compilation step. EDIT: It finished, just took quite a bit longer than compiling it myself. I then created a new folder for it, ran |
|
Thanks @thomasaarholt! Yeah that command can be slow, but also nice to have. |
8a85667 to
77960e9
Compare
c9c44e3 to
6852cfd
Compare
This is mostly restoring #13215. It also includes a one-line fix for #13208 (which resulted from that PR). In particular, Azure was returning 303s which were not being correctly handled. I have also opened another PR (#13754) that refactors and improves the redirect handling here. It also supersedes the fix here. There are some tests failing here but they all pass there. This PR depends on #13615, which adds a script for testing against registries. The test fails for Azure when running against the restored #13215 alone and passes with the fix. It also passes for AWS CodeArtifact, GCP Artifact Registry, JFrog Artifactory, GitLab, and Gemfury in both cases. I also plan to test against Cloudsmith and Nexus.
6852cfd to
9c54824
Compare
This is mostly restoring #13215. It also includes a one-line fix for #13208 (which resulted from that PR). In particular, Azure was returning 303s which were not being correctly handled. I have also opened another PR (#13754) that refactors and improves the redirect handling here. It also supersedes the fix here. There are some tests failing here but they all pass there. This PR depends on #13615, which adds a script for testing against registries. The test fails for Azure when running against the restored #13215 alone and passes with the fix. It also passes for AWS CodeArtifact, GCP Artifact Registry, JFrog Artifactory, GitLab, and Gemfury in both cases. I also plan to test against Cloudsmith and Nexus.
…ble (#13754) This PR factors out and updates the redirect handling logic from #13595. It handles a few new cases: * If a 303 redirect is received for any method other than GET or HEAD, converts it to a GET. Unlike `reqwest`, it does not do this conversion for 301s or 302s (which is not required by RFC 7231 and was not the original intention of the spec). * If the original request did not have a Referer header, does not include a Referer header in the redirect request. * If the redirect is a cross-origin request, removes sensitive headers to avoid leaking credentials to untrusted domains. * * This change had the side effect of breaking mock server tests that redirected from `localhost` to `pypi-proxy.fly.dev`. I have added a `CrossOriginCredentialsPolicy` enum with a `#[cfg(test)]`-only `Insecure` variant. This allows existing tests to continue to work while still making it impossible to propagate credentials on cross-origin requests outside of tests. * * I've updated the main redirect integration test to check if cross-origin requests fail (there is, by design, no way to configure an insecure cross-origin policy from the command line). But critically, netrc credentials for the new location can still be successfully fetched on a cross-origin redirect (tested in `pip_install_redirect_with_netrc_cross_origin`). * One of the goals of the refactor was to make the redirect handling logic unit-testable. This PR adds a number of unit tests checking things like proper propagation of credentials on redirects on the same domain (and removal on cross-origin) and HTTP 303 POST-to-GET conversion. The following table illustrates the different behaviors on current `main`, the initial (reverted) redirect handling PR (#12920), the PR that restores #12920 and fixes the 303s bug (#13595), and this PR (#13754). We want to propagate credentials on same-origin but not cross-origin redirects, and we want to look up netrc credentials on redirects. | Behavior | main | reverted #12920 | fix #13595 | update #13754 | |---------------------------------------|------|--------------|-------------|----------------| | Propagate credentials on same-origin redirects | No | Yes | Yes | Yes | | Propagate credentials on cross-origin redirects | No | Yes | Yes | No | | Look up netrc credentials on redirects | No | Yes | Yes | Yes | | Handle 303s without failing | Yes | No | Yes | Yes | Depends on #13595.
This is mostly restoring #13215. It also includes a one-line fix for #13208 (which resulted from that PR). In particular, Azure was returning 303s which were not being correctly handled. I have also opened another PR (#13754) that refactors and improves the redirect handling here. It also supersedes the fix here. There are some tests failing here but they all pass there. This PR depends on #13615, which adds a script for testing against registries. The test fails for Azure when running against the restored #13215 alone and passes with the fix. It also passes for AWS CodeArtifact, GCP Artifact Registry, JFrog Artifactory, GitLab, and Gemfury in both cases. I also plan to test against Cloudsmith and Nexus.
…ble (#13754) This PR factors out and updates the redirect handling logic from #13595. It handles a few new cases: * If a 303 redirect is received for any method other than GET or HEAD, converts it to a GET. Unlike `reqwest`, it does not do this conversion for 301s or 302s (which is not required by RFC 7231 and was not the original intention of the spec). * If the original request did not have a Referer header, does not include a Referer header in the redirect request. * If the redirect is a cross-origin request, removes sensitive headers to avoid leaking credentials to untrusted domains. * * This change had the side effect of breaking mock server tests that redirected from `localhost` to `pypi-proxy.fly.dev`. I have added a `CrossOriginCredentialsPolicy` enum with a `#[cfg(test)]`-only `Insecure` variant. This allows existing tests to continue to work while still making it impossible to propagate credentials on cross-origin requests outside of tests. * * I've updated the main redirect integration test to check if cross-origin requests fail (there is, by design, no way to configure an insecure cross-origin policy from the command line). But critically, netrc credentials for the new location can still be successfully fetched on a cross-origin redirect (tested in `pip_install_redirect_with_netrc_cross_origin`). * One of the goals of the refactor was to make the redirect handling logic unit-testable. This PR adds a number of unit tests checking things like proper propagation of credentials on redirects on the same domain (and removal on cross-origin) and HTTP 303 POST-to-GET conversion. The following table illustrates the different behaviors on current `main`, the initial (reverted) redirect handling PR (#12920), the PR that restores #12920 and fixes the 303s bug (#13595), and this PR (#13754). We want to propagate credentials on same-origin but not cross-origin redirects, and we want to look up netrc credentials on redirects. | Behavior | main | reverted #12920 | fix #13595 | update #13754 | |---------------------------------------|------|--------------|-------------|----------------| | Propagate credentials on same-origin redirects | No | Yes | Yes | Yes | | Propagate credentials on cross-origin redirects | No | Yes | Yes | No | | Look up netrc credentials on redirects | No | Yes | Yes | Yes | | Handle 303s without failing | Yes | No | Yes | Yes | Depends on #13595.
This is mostly restoring #13215. It also includes a one-line fix for #13208 (which resulted from that PR). In particular, Azure was returning 303s which were not being correctly handled. I have also opened another PR (#13754) that refactors and improves the redirect handling here. It also supersedes the fix here. There are some tests failing here but they all pass there. This PR depends on #13615, which adds a script for testing against registries. The test fails for Azure when running against the restored #13215 alone and passes with the fix. It also passes for AWS CodeArtifact, GCP Artifact Registry, JFrog Artifactory, GitLab, and Gemfury in both cases. I also plan to test against Cloudsmith and Nexus.
…ble (#13754) This PR factors out and updates the redirect handling logic from #13595. It handles a few new cases: * If a 303 redirect is received for any method other than GET or HEAD, converts it to a GET. Unlike `reqwest`, it does not do this conversion for 301s or 302s (which is not required by RFC 7231 and was not the original intention of the spec). * If the original request did not have a Referer header, does not include a Referer header in the redirect request. * If the redirect is a cross-origin request, removes sensitive headers to avoid leaking credentials to untrusted domains. * * This change had the side effect of breaking mock server tests that redirected from `localhost` to `pypi-proxy.fly.dev`. I have added a `CrossOriginCredentialsPolicy` enum with a `#[cfg(test)]`-only `Insecure` variant. This allows existing tests to continue to work while still making it impossible to propagate credentials on cross-origin requests outside of tests. * * I've updated the main redirect integration test to check if cross-origin requests fail (there is, by design, no way to configure an insecure cross-origin policy from the command line). But critically, netrc credentials for the new location can still be successfully fetched on a cross-origin redirect (tested in `pip_install_redirect_with_netrc_cross_origin`). * One of the goals of the refactor was to make the redirect handling logic unit-testable. This PR adds a number of unit tests checking things like proper propagation of credentials on redirects on the same domain (and removal on cross-origin) and HTTP 303 POST-to-GET conversion. The following table illustrates the different behaviors on current `main`, the initial (reverted) redirect handling PR (#12920), the PR that restores #12920 and fixes the 303s bug (#13595), and this PR (#13754). We want to propagate credentials on same-origin but not cross-origin redirects, and we want to look up netrc credentials on redirects. | Behavior | main | reverted #12920 | fix #13595 | update #13754 | |---------------------------------------|------|--------------|-------------|----------------| | Propagate credentials on same-origin redirects | No | Yes | Yes | Yes | | Propagate credentials on cross-origin redirects | No | Yes | Yes | No | | Look up netrc credentials on redirects | No | Yes | Yes | Yes | | Handle 303s without failing | Yes | No | Yes | Yes | Depends on #13595.
…ts (#14126) This PR is a combination of #12920 and #13754. Prior to these changes, following a redirect when searching indexes would bypass our authentication middleware. This PR updates uv to support propagating credentials through our middleware on same-origin redirects and to support netrc credentials for both same- and cross-origin redirects. It does not handle the case described in #11097 where the redirect location itself includes credentials (e.g., `https://user:pass@redirect-location.com`). That will be addressed in follow-up work. This includes unit tests for the new redirect logic and integration tests for credential propagation. The automated external registries test is also passing for AWS CodeArtifact, Azure Artifacts, GCP Artifact Registry, JFrog Artifactory, GitLab, Cloudsmith, and Gemfury.
This PR factors out and updates the redirect handling logic from #13595. It handles a few new cases:
reqwest, it does not do this conversion for 301s or 302s (which is not required by RFC 7231 and was not the original intention of the spec).localhosttopypi-proxy.fly.dev. I have added aCrossOriginCredentialsPolicyenum with a#[cfg(test)]-onlyInsecurevariant. This allows existing tests to continue to work while still making it impossible to propagate credentials on cross-origin requests outside of tests.pip_install_redirect_with_netrc_cross_origin).The following table illustrates the different behaviors on current
main, the initial (reverted) redirect handling PR (#12920), the PR that restores #12920 and fixes the 303s bug (#13595), and this PR (#13754). We want to propagate credentials on same-origin but not cross-origin redirects, and we want to look up netrc credentials on redirects.Depends on #13595.