From f8a8c9c91c223eb6f954028fe79e3787a58b1622 Mon Sep 17 00:00:00 2001 From: Daniel Mach Date: Wed, 7 Sep 2022 16:10:55 +0200 Subject: [PATCH] Print user and apiurl when prompting for a password It's not a good idea to send a password to a different server than it belongs. Now the server identity is obvious. --- osc/conf.py | 2 +- osc/credentials.py | 29 +++++++++++++++++------------ 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/osc/conf.py b/osc/conf.py index 48176a37..61cf715a 100644 --- a/osc/conf.py +++ b/osc/conf.py @@ -794,7 +794,7 @@ def get_config(override_conffile=None, user = _extract_user_compat(cp, url, creds_mgr) if user is None: raise oscerr.ConfigMissingCredentialsError('No user found in section %s' % url, conffile, url) - password = creds_mgr.get_password(url, user, defer=True) + password = creds_mgr.get_password(url, user, defer=True, apiurl=apiurl) if password is None: raise oscerr.ConfigMissingCredentialsError('No password found in section %s' % url, conffile, url) diff --git a/osc/credentials.py b/osc/credentials.py index 47fc9886..61924e67 100644 --- a/osc/credentials.py +++ b/osc/credentials.py @@ -80,14 +80,14 @@ class AbstractCredentialsManager: def create(cls, cp, options): return cls(cp, options) - def _get_password(self, url, user): + def _get_password(self, url, user, apiurl=None): raise NotImplementedError() - def get_password(self, url, user, defer=True): + def get_password(self, url, user, defer=True, apiurl=None): if defer: - return _LazyPassword(lambda: self._get_password(url, user)) + return _LazyPassword(lambda: self._get_password(url, user, apiurl=apiurl)) else: - return self._get_password(url, user) + return self._get_password(url, user, apiurl=apiurl) def set_password(self, url, user, password): raise NotImplementedError() @@ -103,7 +103,7 @@ class AbstractCredentialsManager: class PlaintextConfigFileCredentialsManager(AbstractCredentialsManager): - def get_password(self, url, user, defer=True): + def get_password(self, url, user, defer=True, apiurl=None): return self._cp.get(url, 'pass', raw=True) def set_password(self, url, user, password): @@ -132,13 +132,12 @@ class PlaintextConfigFileDescriptor(AbstractCredentialsManagerDescriptor): return PlaintextConfigFileCredentialsManager(cp, None) -class ObfuscatedConfigFileCredentialsManager( - PlaintextConfigFileCredentialsManager): - def get_password(self, url, user, defer=True): +class ObfuscatedConfigFileCredentialsManager(PlaintextConfigFileCredentialsManager): + def get_password(self, url, user, defer=True, apiurl=None): if self._cp.has_option(url, 'passx', proper=True): passwd = self._cp.get(url, 'passx', raw=True) else: - passwd = super(self.__class__, self).get_password(url, user) + passwd = super(self.__class__, self).get_password(url, user, apiurl=apiurl) return self.decode_password(passwd) def set_password(self, url, user, password): @@ -182,9 +181,15 @@ class TransientCredentialsManager(AbstractCredentialsManager): if options is not None: raise RuntimeError('options must be None') - def _get_password(self, url, user): + def _get_password(self, url, user, apiurl=None): if self._password is None: - self._password = getpass.getpass('Password: ') + if apiurl: + # strip scheme from apiurl because we don't want to display it to the user + apiurl_no_scheme = urlsplit(apiurl)[1] + msg = f'Password [{user}@{apiurl_no_scheme}]: ' + else: + msg = 'Password: ' + self._password = getpass.getpass(msg) return self._password def set_password(self, url, user, password): @@ -229,7 +234,7 @@ class KeyringCredentialsManager(AbstractCredentialsManager): return None return super(cls, cls).create(cp, options) - def _get_password(self, url, user): + def _get_password(self, url, user, apiurl=None): self._load_backend() return keyring.get_password(urlsplit(url)[1], user)