uv: `uv pip install` returning 403 from private pypi cloud instance backed by s3
I am using a private pypi cloud instance backed by s3 (with no auth on my end). Public packages are resolved normally, but uv pip
cannot resolve packages hosted on the private cloud instance.
pip3 install my-private-package --index-url https://my-pip-instance.example.com/
succeeded with no problems.- Running
uv pip install
with the--no-cache
option did not change the result. - I can retrieve the artifact from the url that uv pip was trying to fetch. This URL returns a 302 to the url that is giving me a 403
$ uv pip install my-private-package --index-url https://my-pip-instance.example.com/
error: Failed to build editables
Caused by: Failed to build editable: file:///Users/phil/repos/philiplinden/scratch
Caused by: Failed to install requirements from build-system.requires (resolve)
Caused by: No solution found when resolving: setuptools
Caused by: Failed to download: setuptools==69.1.1
Caused by: HTTP status client error (403 Forbidden) for url (https://s3-url.amazonaws.com/example/setuptools-69.1.1-py3-none-any.whl?AWSAccessKeyId=xxx&Signature=xxx%3D&Expires=1709153725](https://s3-url.amazonaws.com/ffdf/setuptools/setuptools-69.1.1-py3-none-any.whl?AWSAccessKeyId=xxx&Signature=xxx%3D&Expires=1709153725)))
Relates to https://github.com/astral-sh/uv/issues/1709 and https://github.com/astral-sh/uv/pull/1902
Version: 0.1.6
, 0.1.11
Verbose output (anonymized)
uv_client::flat_index::from_entries
uv_installer::downloader::build_editables
0.355282s 0ms DEBUG uv_distribution::source Building (editable) file:///Users/phil/repos/philiplinden/scratch
uv_dispatch::setup_build package_id="file:///Users/phil/repos/philiplinden/scratch", subdirectory=None
uv_resolver::resolver::solve
0.361346s 0ms DEBUG uv_resolver::resolver Solving with target Python version 3.11.6
uv_resolver::resolver::choose_version package=root
uv_resolver::resolver::get_dependencies package=root, version=0a0.dev0
0.361500s 0ms DEBUG uv_resolver::resolver Adding direct dependency: setuptools*
uv_resolver::resolver::choose_version package=setuptools
uv_resolver::resolver::package_wait package_name=setuptools
uv_resolver::resolver::process_request request=Versions setuptools
uv_client::registry_client::simple_api package=setuptools
uv_client::cached_client::get_cacheable
uv_client::cached_client::read_and_parse_cache file=/Users/phil/Library/Caches/uv/simple-v1/8aba338bd0495f93/setuptools.rkyv
uv_resolver::resolver::process_request request=Prefetch setuptools *
0.366930s 5ms DEBUG uv_client::cached_client Found stale response for: https://my-pip-instance.example.com/simple/setuptools/
0.366959s 5ms DEBUG uv_client::cached_client Sending revalidation request for: https://my-pip-instance.example.com/setuptools/
uv_client::cached_client::revalidation_request url="https://my-pip-instance.example.com/setuptools/"
1.016439s 654ms DEBUG uv_client::cached_client Found modified response for: https://my-pip-instance.example.com/simple/setuptools/
uv_client::cached_client::new_cache file=/Users/phil/Library/Caches/uv/simple-v1/8aba338bd0495f93/setuptools.rkyv
uv_client::registry_client::parse_simple_api package=setuptools
uv_client::html::parse url=https://my-pip-instance.example.com/setuptools/
uv_resolver::version_map::from_metadata
uv_distribution::distribution_database::get_or_build_wheel_metadata dist=setuptools==69.1.1
uv_client::registry_client::wheel_metadata built_dist=setuptools==69.1.1
uv_client::cached_client::get_serde
uv_client::cached_client::get_cacheable
uv_client::cached_client::read_and_parse_cache file=/Users/phil/Library/Caches/uv/wheels-v0/index/8aba338bd0495f93/setuptools/setuptools-69.1.1-py3-none-any.msgpack
1.322675s 961ms DEBUG uv_resolver::resolver Searching for a compatible version of setuptools (*)
1.322694s 961ms DEBUG uv_resolver::resolver Selecting: setuptools==69.1.1 (setuptools-69.1.1-py3-none-any.whl)
uv_resolver::resolver::get_dependencies package=setuptools, version=69.1.1
uv_resolver::resolver::distributions_wait package_id=setuptools-69.1.1
1.322754s 0ms DEBUG uv_client::cached_client No cache entry for: https://my-pip-instance.example.com/api/package/setuptools/setuptools-69.1.1-py3-none-any.whl#sha256=02fa291a0471b3a18b2b2481ed902af520c69e8ae0919c13da936542754b4c56
uv_client::cached_client::fresh_request url="https://my-pip-instance.example.com/api/package/setuptools/setuptools-69.1.1-py3-none-any.whl#sha256=02fa291a0471b3a18b2b2481ed902af520c69e8ae0919c13da936542754b4c56"
error: Failed to build editables
Caused by: Failed to build editable: file:///Users/phil/repos/philiplinden/scratch
Caused by: Failed to install requirements from build-system.requires (resolve)
Caused by: No solution found when resolving: setuptools
Caused by: Failed to download: setuptools==69.1.1
Caused by: HTTP status client error (403 Forbidden) for url (https://my-pip-instance.amazonaws.com/ffdf/setuptools/setuptools-69.1.1-py3-none-any.whl?AWSAccessKeyId=xxx&Signature=xxx&Expires=1709157923)
About this issue
- Original URL
- State: open
- Created 4 months ago
- Comments: 25 (15 by maintainers)
I made a proof-of-concept PR to work around the issue. I do that by passing a modified
response
to the range reader so that it uses the “original” (gemfury) link and not the 302-redirected S3 link. Works for my local repro test case 😄I emailed Gemfury.
We are experiencing the same issue. I wonder if it’s because we have an older Gemfury account. This option is enabled under our organization settings:
I don’t remember opting into that explicitly. Is that disabled in your account?
EDIT: Disabling this option changed the package source to a
https://gemfury.s3-accelerate.dualstack.amazonaws.com/gems/...
CDN URL instead of S3, but I still get the same error.Yep, you’re right, @charliermarsh. I just tried hard-coding in my credentials at that point in the code, and then I got a “Request already has an authorization header” error instead. My clue was not a clue after all 😢
But yes, I can reproduce. I believe I have the same issue as @amarckal, which is that when I use curl against pypi.fury.io to fetch my private package, I get a 302 redirect to a url like this:
https://s3.amazonaws.com/gemfury/gems/<redacted-path>/sdxp_0_7_3_py3_none_any_whl?x-acct=<redacted-acct>&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=<redacted-cred>%2F20240404%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20240404T180859Z&X-Amz-Expires=900&X-Amz-SignedHeaders=host&X-Amz-Signature=<redacted-sig>
(I put
<redacted-[whatever]>
in places that could be sensitive).When I run
./target/debug/uv pip install -vv --no-cache --extra-index-url https://{$GEMFURY_READ_TOKEN}@pypi.fury.io/oda/ sdxp==0.7.3
, the last part of the output is (with some<redacted-[whatevers]>
here as well:If I isolate just the url in this output, there’s another possible clue:
https://s3.amazonaws.com/gemfury/gems/<redacted-path>/sdxp_0_7_3_py3_none_any_whl?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=<redacted-cred>%2F20240404%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20240404T181433Z&X-Amz-Expires=900&X-Amz-SignedHeaders=host&X-Amz-Signature=<redacted-sig>
(<-- this is theuv
one)compared with the curl one from above:
https://s3.amazonaws.com/gemfury/gems/<redacted-path>/sdxp_0_7_3_py3_none_any_whl?x-acct=<redacted-acct>&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=<redacted-cred>%2F20240404%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20240404T180859Z&X-Amz-Expires=900&X-Amz-SignedHeaders=host&X-Amz-Signature=<redacted-sig>
(<-- this is the curl one)The
curl
url has ax-acct=<stuff>
query param, while theuv
one doesn’t. I have no idea why…