Skip to content
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

Regression: 403 Auth Failure for S3-hosted (Cloudfront) Private Repos #3303

Closed
3 tasks done
dvf opened this issue Oct 28, 2020 · 7 comments
Closed
3 tasks done

Regression: 403 Auth Failure for S3-hosted (Cloudfront) Private Repos #3303

dvf opened this issue Oct 28, 2020 · 7 comments
Labels
kind/bug Something isn't working as expected

Comments

@dvf
Copy link

dvf commented Oct 28, 2020

Issue

  • We noticed a regression from Poetry 1.0.3 to 1.1.4.
  • We're using a private PyPI repository hosted on S3 protected by Cloudfront using Basic Auth (we use s3pypi)

When we tried to install a new private dependency, or remove a non-private dependency (with common sub dependencies with a private dependency) we saw this error:

➜  project git:(master) poetry remove django-structlog
Updating dependencies
Resolving dependencies... (0.2s)

  RepositoryError

  403 Client Error: Forbidden for url: https://XXXXXXXXXXXXXXXX/pyjwt/

  at ~/.poetry/lib/poetry/repositories/legacy_repository.py:393 in _get
      389│             if response.status_code == 404:
      390│                 return
      391│             response.raise_for_status()
      392│         except requests.HTTPError as e:
    → 393│             raise RepositoryError(e)
      394│ 
      395│         if response.status_code in (401, 403):
      396│             self._log(
      397│                 "Authorization error accessing {url}".format(url=url), level="warn"

Hypothesis of why this is happening

By default, Cloudfront returns a 403 for non-existing files. This is a good security practice as it prevents leakage of information to unauthenticated parties. However, (from the above code) Poetry only falls back to public PyPI if it encounters a 404 when requesting a package.

Quick fix

The quick fix for this is to have your private repo (in our case Cloudfront) return a default error response code of 404.
Here are docs on how to do that: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/custom-error-pages-response-code.html

Recommendations

Poetry shouldn't fall back to the public repo on a 401/403/404 without first checking if it can successfully auth to the repo. And failing that, it should throw an appropriate error.

Thanks to @proxyroot and @vagelim for helping debug and fix.

@dvf dvf added kind/bug Something isn't working as expected status/triage This issue needs to be triaged labels Oct 28, 2020
@sschrijver
Copy link

sschrijver commented Nov 2, 2020

This is also an issue (but maybe slightly different, I receive a "Forbidden" error) with a private PyPI registry that stores packages on S3 (without cloudfront). It returns a s3 URL (with temp auth token) with the message that the request is forbidden, whilst copying the URL and pasting it in a new browser initiates the correct download.

Downgrading to 1.0.10 solved this error, this error happens from version 1.1.x

@abn
Copy link
Member

abn commented Nov 2, 2020

This block

if response.status_code in (401, 403):
self._log(
"Authorization error accessing {url}".format(url=url), level="warn"
)
return

Should move to before

response.raise_for_status()

@abn
Copy link
Member

abn commented Nov 2, 2020

@dvf thank you for the great issue report! 🎉

Regarding the fallback behaviour, I am reluctant to suggest we change at that at the moment since I think there are cases where authentication/authorsation is not available and a public package can still be added. Happy to discuss that and change behaviour in another issue. For this one, lets treat it as a bug and resolve it as such.

@abn abn added Good First Issue and removed status/triage This issue needs to be triaged labels Nov 2, 2020
@abn
Copy link
Member

abn commented Nov 2, 2020

This is also an issue (but maybe slightly different, I receive a "Forbidden" error) with a private PyPI registry that stores packages on S3 (without cloudfront). It returns a s3 URL (with temp auth token) with the message that the request is forbidden, whilst copying the URL and pasting it in a new browser initiates the correct download.

@sschrijver think this was reported elsewhere, the issue here is that we use basic authentication as configured along with those requests. The existence of an "Authorization" header the "authorised" url ends up failing on the server side. IIRC, this was an issue with PyPI cloud since it deviates from the defined/expected behaviour for an index. See #3041 (comment) for that bit. I have not looked into the comments after that one yet. Additionally, note that there is the issue that using "authorised" urls will have other side-effects when the token used expires as these are used in the lock file.

@cereblanco
Copy link
Contributor

hello! if no one started working on this yet, I can create the fix. 💭

@jeremysprofile
Copy link

This also affects Sonatype Nexus PyPI repositories when using poetry 1.1.4, and downgrading to 1.0.10 fixes the issue there as well.

Copy link

github-actions bot commented Mar 2, 2024

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 2, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
kind/bug Something isn't working as expected
Projects
None yet
Development

No branches or pull requests

5 participants