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

Package gir1.2-secret-1 changes behaviour #558

Open
ziima opened this issue Jan 10, 2022 · 7 comments
Open

Package gir1.2-secret-1 changes behaviour #558

ziima opened this issue Jan 10, 2022 · 7 comments

Comments

@ziima
Copy link

ziima commented Jan 10, 2022

Describe the bug
I ran into an error which prevented me from using devpi, cause by the presence of gir1.2-secret-1 package. devpi ended up in error

$ devpi login vzima
Traceback (most recent call last):
  File "/home/vzima/.local/bin/devpi", line 8, in <module>
    sys.exit(main())
  File "/home/vzima/.local/lib/python3.9/site-packages/devpi/main.py", line 36, in main
    return method(hub, hub.args)
  File "/home/vzima/.local/lib/python3.9/site-packages/devpi/login.py", line 13, in main
    password = hub.hook.devpiclient_get_password(
  File "/home/vzima/.local/lib/python3.9/site-packages/pluggy/hooks.py", line 286, in __call__
    return self._hookexec(self, self.get_hookimpls(), kwargs)
  File "/home/vzima/.local/lib/python3.9/site-packages/pluggy/manager.py", line 93, in _hookexec
    return self._inner_hookexec(hook, methods, kwargs)
  File "/home/vzima/.local/lib/python3.9/site-packages/pluggy/manager.py", line 84, in <lambda>
    self._inner_hookexec = lambda hook, methods, kwargs: hook.multicall(
  File "/home/vzima/.local/lib/python3.9/site-packages/pluggy/callers.py", line 208, in _multicall
    return outcome.get_result()
  File "/home/vzima/.local/lib/python3.9/site-packages/pluggy/callers.py", line 80, in get_result
    raise ex[1].with_traceback(ex[2])
  File "/home/vzima/.local/lib/python3.9/site-packages/pluggy/callers.py", line 187, in _multicall
    res = hook_impl.function(*args)
  File "/usr/lib/python3/dist-packages/keyring/devpi_client.py", line 11, in devpiclient_get_password
    return keyring.get_password(url, username)
  File "/usr/lib/python3/dist-packages/keyring/core.py", line 55, in get_password
    return get_keyring().get_password(service_name, username)
  File "/usr/lib/python3/dist-packages/keyring/backends/chainer.py", line 51, in get_password
    password = keyring.get_password(service, username)
  File "/usr/lib/python3/dist-packages/keyring/backends/libsecret.py", line 62, in get_password
    items = Secret.password_search_sync(
gi.repository.GLib.GError: g-dbus-error-quark: The name org.freedesktop.secrets was not provided by any .service files (2)

although the gnome-keyring is not installed and there is no backend for the keyring available (that I'm aware of). Anyway the uninstallation of gir1.2-secret-1 resolved the problem. The issue may be related to #19.

To Reproduce
I wan able to reproduce the issue using docker:
Dockerfile

FROM debian:testing-slim

# Install build dependencies from debian
RUN apt-get update \
    && apt-get install --yes --no-install-recommends \
        gir1.2-secret-1 \
        python3-gi \
        python3-keyring \
        python3-pip \
    && rm -rf /var/lib/apt/lists/* \
    # And a devpi client
    && /usr/bin/pip install devpi-client

WORKDIR /app
docker build -t devpi-test .
docker run --privileged -ti --rm devpi-test:latest /bin/bash -c "dbus-run-session -- python3 -c 'from keyring.devpi_client import devpiclient_get_password; devpiclient_get_password(\"http://example.org/\", \"username\")'"

This produces the error same as above

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/lib/python3/dist-packages/keyring/devpi_client.py", line 11, in devpiclient_get_password
    return keyring.get_password(url, username)
  File "/usr/lib/python3/dist-packages/keyring/core.py", line 55, in get_password
    return get_keyring().get_password(service_name, username)
  File "/usr/lib/python3/dist-packages/keyring/backends/libsecret.py", line 62, in get_password
    items = Secret.password_search_sync(
gi.repository.GLib.GError: g-dbus-error-quark: The name org.freedesktop.secrets was not provided by any .service files (2)

but a different output if gir1.2-secret-1 is not installed:

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/lib/python3/dist-packages/keyring/devpi_client.py", line 11, in devpiclient_get_password
    return keyring.get_password(url, username)
  File "/usr/lib/python3/dist-packages/keyring/core.py", line 55, in get_password
    return get_keyring().get_password(service_name, username)
  File "/usr/lib/python3/dist-packages/keyring/backends/fail.py", line 25, in get_password
    raise NoKeyringError(msg)
keyring.errors.NoKeyringError: No recommended backend was available. Install a recommended 3rd party backend package; or, install the keyrings.alt package if you want to use the non-recommended backends. See https://pypi.org/project/keyring for details.

Expected behavior
Same behavior for cases when gir1.2-secret-1 is installed and when it isn't. In case of devpi login, it should result in devpi asking for password directly.

Environment

  • OS: Linux Debian testing
$ pip list | grep keyring
## Desktop
keyring                            23.3.0
keyrings.alt                       4.1.0
## Docker
keyring            23.5.0
...
$ keyring --list-backends
## Desktop
keyring.backends.chainer.ChainerBackend (priority: 10)
keyrings.alt.file.EncryptedKeyring (priority: 0.6)
keyring.backends.fail.Keyring (priority: 0)
keyrings.alt.file.PlaintextKeyring (priority: 0.5)
## Docker
keyring.backends.chainer.ChainerBackend (priority: -1)
keyring.backends.fail.Keyring (priority: 0)
keyring.backends.libsecret.Keyring (priority: 4.8)
...

Additional context
Add any other context about the problem here.

@jaraco
Copy link
Owner

jaraco commented Feb 12, 2022

It seems that something about installing girl.2-secret-1 is causing the libsecret.Keyring backend to become enabled, and that backend is failing with the reported error.

When you remove that library, Keyring detects that you have no viable backends, so falls back to the "fail" keyring, meaning it should fail when queried.

Same behavior for cases when gir1.2-secret-1 is installed and when it isn't.

I'm not sure your expectation can be met. Keyring specifically aims to infer from the user's environment the best set of backends to offer. If that library is changing the environment, making the libsecret backend viable, then that's working as intended, and you can expect different behavior depending on its presence. It may be a bug that libsecret is detected as viable but in fact can't resolve passwords.

As for without libsecret, the behavior is also working as intended:

keyring main $ docker run -it jaraco/multipy-tox pip-run -q keyring -- -c "import keyring; keyring.get_password('foo', 'bar')"
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/tmp/pip-run-c2u4za_5/keyring/core.py", line 55, in get_password
    return get_keyring().get_password(service_name, username)
  File "/tmp/pip-run-c2u4za_5/keyring/backends/fail.py", line 25, in get_password
    raise NoKeyringError(msg)
keyring.errors.NoKeyringError: No recommended backend was available. Install a recommended 3rd party backend package; or, install the keyrings.alt package if you want to use the non-recommended backends. See https://pypi.org/project/keyring for details.

(ignore the pip warning; it's just noise)

As you can see, it's expected that attempting to retrieve a password when no backends are present is meant to cause an error. You can work around this error by disabling keyring or by supplying a working backend.

@ziima
Copy link
Author

ziima commented Mar 4, 2022

If that library is changing the environment, making the libsecret backend viable, then that's working as intended, and you can expect different behavior depending on its presence.

Is there any other way to tell if the backend is actually viable, other than trying the imports? I believe that could be enough.

I guess that the GError raised on attempt to get the password is not specific enough to tell the keyring is not actually available.

It may be a bug that libsecret is detected as viable but in fact can't resolve passwords.

I can't deny that. Keyring library is as deep as I can debug the problem. Hope you can pass the bug to the libsecret.

As you can see, it's expected that attempting to retrieve a password when no backends are present is meant to cause an error. You can work around this error by disabling keyring or by supplying a working backend.

Actually I have multiple backends, but I can't use them. The libsecret has high priority and ends up in error preventing fallback to the next backends.

@jaraco
Copy link
Owner

jaraco commented Apr 4, 2022

Is there any other way to tell if the backend is actually viable, other than trying the imports? I believe that could be enough.

You can test if a given backend is viable by accessing that attribute:

>>> import keyring.backends.libsecret as libsecret
>>> libsecret.Keyring
<class 'keyring.backends.libsecret.Keyring'>
>>> libsecret.Keyring.viable
False

The viable property merely reflects if .priority does not raise an exception, so you can inspect that code in libsecret to ascertain why libsecret is apparently viable.

@jaraco
Copy link
Owner

jaraco commented Apr 4, 2022

I was also able to replicate the issue using the Dockerfile provided:

draft $ docker run -it @$(docker build -q .) bash -c "dbus-run-session python3 -c \"import keyring; keyring.get_password('foo', 'bar')\""
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/lib/python3/dist-packages/keyring/core.py", line 55, in get_password
    return get_keyring().get_password(service_name, username)
  File "/usr/lib/python3/dist-packages/keyring/backends/libsecret.py", line 62, in get_password
    items = Secret.password_search_sync(
gi.repository.GLib.GError: g-dbus-error-quark: The name org.freedesktop.secrets was not provided by any .service files (2)

@jaraco jaraco added the Linux label Apr 4, 2022
@jaraco
Copy link
Owner

jaraco commented Apr 4, 2022

I was able to replicate the issue using this command, not involving keyring:

draft $ docker run -it @$(docker build -q .) bash -c "dbus-run-session python3 -c \"import gi; gi.require_version('Secret', '1'); from gi.repository import Secret; schema = Secret.Schema.new('org.freedesktop.Secret.Generic', Secret.SchemaFlags.NONE, dict(application=Secret.SchemaAttributeType.STRING, service=Secret.SchemaAttributeType.STRING, username=Secret.SchemaAttributeType.STRING)); items = Secret.password_search_sync(schema, {}, Secret.SearchFlags.UNLOCK, None)\""
Traceback (most recent call last):
  File "<string>", line 1, in <module>
gi.repository.GLib.GError: g-dbus-error-quark: The name org.freedesktop.secrets was not provided by any .service files (2)

Now we just need someone to figure out what it is about girl.2-secret-1 that triggers that error and if there's something that keyring should be doing differently.

@mitya57
Copy link
Collaborator

mitya57 commented Apr 4, 2022

With libsecret backend, just like with Secret Service backend, you need to have gnome-keyring or another Secret Service server implementation installed and running.

Libsecret has a special mode when it works without server process, but it applies only to Flatpak applications.

@lazka
Copy link
Contributor

lazka commented Nov 5, 2022

Is this fixed by #603 ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants