Poetry silently fails to save basic-auth creds, leading to failure to install private deps
See original GitHub issue-
I am on the latest Poetry version.
-
I have searched the issues of this repo and believe that this is not a duplicate.
-
If an exception occurs when executing a command, I executed it again in debug mode (
-vvv
option). -
OS version and name:
python:3.7
base Docker image -
Poetry version: 1.0.0b5
-
Link of a Gist with the contents of your pyproject.toml file: https://gist.github.com/tsiq-oliver/bb36a0c705459ab85197ec71de580a24
Issue
When install
-ing a dep from a private repo with basic auth, Poetry non-deterministically fails (you can assume the env vars in the first line are set appropriately):
poetry config http-basic.my-private-repo "${REPO_USERNAME}" "${REPO_PASSWORD}"
poetry install --no-dev --no-interaction -vvv
Skipping virtualenv creation, as specified in config file.
Installing dependencies from lock file
Package operations: XXX installs, XXX updates, 0 removals, XXX skipped
[...]
- Installing myprivatepackage (0.0.6081)
[TypeError]
quote_from_bytes() expected bytes
Traceback (most recent call last):
File "/root/.poetry/lib/poetry/_vendor/py3.7/clikit/console_application.py", line 131, in run
status_code = command.handle(parsed_args, io)
File "/root/.poetry/lib/poetry/_vendor/py3.7/clikit/api/command/command.py", line 120, in handle
status_code = self._do_handle(args, io)
File "/root/.poetry/lib/poetry/_vendor/py3.7/clikit/api/command/command.py", line 171, in _do_handle
return getattr(handler, handler_method)(args, io, self)
File "/root/.poetry/lib/poetry/_vendor/py3.7/cleo/commands/command.py", line 92, in wrap_handle
return self.handle()
File "/root/.poetry/lib/poetry/console/commands/install.py", line 63, in handle
return_code = installer.run()
File "/root/.poetry/lib/poetry/installation/installer.py", line 74, in run
self._do_install(local_repo)
File "/root/.poetry/lib/poetry/installation/installer.py", line 286, in _do_install
self._execute(op)
File "/root/.poetry/lib/poetry/installation/installer.py", line 302, in _execute
getattr(self, '_execute_{}'.format(method))(operation)
File "/root/.poetry/lib/poetry/installation/installer.py", line 327, in _execute_install
self._installer.install(operation.package)
File "/root/.poetry/lib/poetry/installation/pip_installer.py", line 63, in install
index_url = repository.authenticated_url
File "/root/.poetry/lib/poetry/repositories/legacy_repository.py", line 224, in authenticated_url
password=quote(self._auth.auth.password),
File "/usr/local/lib/python3.7/urllib/parse.py", line 834, in quote
return quote_from_bytes(string, safe)
File "/usr/local/lib/python3.7/urllib/parse.py", line 859, in quote_from_bytes
raise TypeError('quote_from_bytes() expected bytes')
Having looked through the code, we identified a couple of issues that combine to cause this.
-
Due to this
keyring
issue,poetry config
can non-deterministically silently fail to save the password at all.Inside a container, there are only two backends -
fail
andchainer
. Iffail
is chosen thenkeyring
fails loudly with aRuntimeError
, andpoetry
falls back to writing to its own config. However ifchainer
is chosen thenkeyring
fails silently, and the password is saved nowhere. -
poetry
silently swallowskeyring
issues when trying to retrieve the password (no matter which backendkeyring
non-deterministically selects).This means that
None
is propagated all the way up toLegacyRepository
, which then unconditionally attempts to pass it intourllib.quote
which raises the exception in the trace above.
Suggested mitigations
-
Use the workaround described in the
keyring
issue - installkeyrings.alt
. -
Fail loudly on
poetry config
if the password is not actually set - i.e. fail as early as possible in the workfow. -
Fail loudly on password retrieval if
keyring
returnsNone
- this is definitely (?) an error situation. -
Give the user more control over where they expect the password to be written. (The silent fallback from keyring to plain-text file would already be a security risk in some scenarios, so may need re-designing.)
Issue Analytics
- State:
- Created 4 years ago
- Reactions:20
- Comments:8 (3 by maintainers)
Top GitHub Comments
As a workaround, I have this in some CI scripts:
It then gets removed after
poetry install
To add to the suggestions, please also fail loudly if credentials are wrong for a private repository.
Current pre-release
1.0.0b8
appears to fail silently if it does not have correct creds for a private repo, so poetry instead fails with a solver error when the package is expected to be in the private repo instead of PyPi. You can imagine this combined with the silent failures mentioned in the issue make for a frustrating debugging dive.Since private repos have been and still are quite error prone I’d appreciate at least loud errors so I can find workarounds.