Use keyring --mode creds when authenticate = "always" (#12316)

Previously, we required a username to perform a fetch from the keyring
because the `keyring` CLI only supported fetching password for a given
service and username. Unfortunately, this is different from the keyring
Python API which supported fetching a username _and_ password for a
given service. We can't (easily) use the Python API because we don't
expect `keyring` to be installed in a specific environment during
network requests. This means that we did not have parity with `pip`.

Way back in https://github.com/jaraco/keyring/pull/678 we got a `--mode
creds` flag added to `keyring`'s CLI which supports parity with the
Python API. Since `keyring` is expensive to invoke and we cannot be
certain that users are on the latest version of keyring, we've not added
support for invoking keyring with this flag. However, now that we have a
mode that says authentication is _required_ for an index (#11896), we
might as well _try_ to invoke keyring with `--mode creds` when there is
no username. This will address use-cases where the username is
non-constant and move us closer to `pip` parity.
This commit is contained in:
Zanie Blue
2025-03-19 16:30:32 -05:00
committed by GitHub
parent 011a6de6dc
commit 37c25f2a9d
7 changed files with 417 additions and 108 deletions
@@ -2,7 +2,7 @@ import json
import os
import sys
from keyring import backend
from keyring import backend, credentials
class KeyringTest(backend.KeyringBackend):
@@ -10,8 +10,8 @@ class KeyringTest(backend.KeyringBackend):
def get_password(self, service, username):
print(f"Request for {username}@{service}", file=sys.stderr)
credentials = json.loads(os.environ.get("KEYRING_TEST_CREDENTIALS", "{}"))
return credentials.get(service, {}).get(username)
entries = json.loads(os.environ.get("KEYRING_TEST_CREDENTIALS", "{}"))
return entries.get(service, {}).get(username)
def set_password(self, service, username, password):
raise NotImplementedError()
@@ -20,4 +20,15 @@ class KeyringTest(backend.KeyringBackend):
raise NotImplementedError()
def get_credential(self, service, username):
raise NotImplementedError()
print(f"Request for {service}", file=sys.stderr)
entries = json.loads(os.environ.get("KEYRING_TEST_CREDENTIALS", "{}"))
service_entries = entries.get(service, {})
if not service_entries:
return None
if username:
password = service_entries.get(username)
if not password:
return None
return credentials.SimpleCredential(username, password)
else:
return credentials.SimpleCredential(*list(service_entries.items())[0])