Rev 3758: Add credential stores plugging. in file:///v/home/vila/src/bzr/experimental/pluggable-auth-conf/
Vincent Ladeuil
v.ladeuil+lp at free.fr
Sun Oct 5 22:32:01 BST 2008
At file:///v/home/vila/src/bzr/experimental/pluggable-auth-conf/
------------------------------------------------------------
revno: 3758
revision-id: v.ladeuil+lp at free.fr-20081005213200-tbgbnnhq6rjabnlz
parent: pqm at pqm.ubuntu.com-20081001123103-9powbklax4nmw09j
committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
branch nick: pluggable-auth-conf
timestamp: Sun 2008-10-05 23:32:00 +0200
message:
Add credential stores plugging.
* tests/test_config.py:
(TestAuthenticationConfigFile.test_unknown_password_encoding):
Test that the user get a meaningful error on typos or installation
problems.
(TestCredentialStoreRegistry): Basic tests for the registry.
(TestPlainTextCredentialStore): Test plain text credential store.
* config.py:
(AuthenticationConfig.decode_password): Go through the credential
store registry to decode the password.
(CredentialStoreRegistry): New registry for credential stores.
(CredentialStore): Abstract base class for credential stores.
(PlainTextCredentialStore): Default, plain text, credential store,
using authentication.conf file itself as storage(i.e actual
behavior).
-------------- next part --------------
=== modified file 'bzrlib/config.py'
--- a/bzrlib/config.py 2008-09-08 12:59:00 +0000
+++ b/bzrlib/config.py 2008-10-05 21:32:00 +0000
@@ -78,6 +78,7 @@
errors,
mail_client,
osutils,
+ registry,
symbol_versioning,
trace,
ui,
@@ -1131,9 +1132,57 @@
return password
def decode_password(self, credentials, encoding):
+ try:
+ cs = credential_store_registry.get_credential_store(encoding)
+ except KeyError:
+ raise ValueError('%r is not a known password_encoding' % encoding)
+ credentials['password'] = cs.decode_password(credentials)
return credentials
+class CredentialStoreRegistry(registry.Registry):
+ """A class that registers credential stores.
+
+ A credential store provides access to credentials via the password_encoding
+ field in authentication.conf sections.
+
+ Except for stores provided by bzr itself,most stores are expected to be
+ provided by plugins that will therefore use
+ register_lazy(password_encoding, module_name, member_name, help=help,
+ info=info) to install themselves.
+ """
+
+ def get_credential_store(self, encoding=None):
+ cs = self.get(encoding)
+ if callable(cs):
+ cs = cs()
+ return cs
+
+
+credential_store_registry = CredentialStoreRegistry()
+
+
+class CredentialStore(object):
+ """An abstract class to implement storage for credentials"""
+
+ def decode_password(self, credentials):
+ """Returns a password for the provided credentials in clear text."""
+ raise NotImplementedError(self.decode_password)
+
+
+class PlainTextCredentialStore(CredentialStore):
+ """Plain text credential store for the authentication.conf file."""
+
+ def decode_password(self, credentials):
+ """See CredentialStore.decode_password."""
+ return credentials['password']
+
+
+credential_store_registry.register('plain', PlainTextCredentialStore,
+ help=PlainTextCredentialStore.__doc__)
+credential_store_registry.default_key = 'plain'
+
+
class BzrDirConfig(object):
def __init__(self, transport):
=== modified file 'bzrlib/tests/test_config.py'
--- a/bzrlib/tests/test_config.py 2008-08-10 11:26:50 +0000
+++ b/bzrlib/tests/test_config.py 2008-10-05 21:32:00 +0000
@@ -1263,6 +1263,16 @@
"""))
self.assertRaises(ValueError, conf.get_credentials, 'ftp', 'foo.net')
+ def test_unknown_password_encoding(self):
+ conf = config.AuthenticationConfig(_file=StringIO(
+ """[broken]
+scheme=ftp
+user=joe
+password_encoding=unknown
+"""))
+ self.assertRaises(ValueError, conf.get_password,
+ 'ftp', 'foo.net', 'joe')
+
def test_credentials_for_scheme_host(self):
conf = config.AuthenticationConfig(_file=StringIO(
"""# Identity on foo.net
@@ -1500,6 +1510,32 @@
'password ignored in section \[ssh with password\]')
+class TestCredentialStoreRegistry(tests.TestCase):
+
+ def _get_cs_registry(self):
+ return config.credential_store_registry
+
+ def test_default_credential_store(self):
+ r = self._get_cs_registry()
+ default = r.get_credential_store(None)
+ self.assertIsInstance(default, config.PlainTextCredentialStore)
+
+ def test_unknown_credential_store(self):
+ r = self._get_cs_registry()
+ # It's hard to imagine someone creating a credential store named
+ # 'unknown' so we use that as an never registered key.
+ self.assertRaises(KeyError, r.get_credential_store, 'unknown')
+
+
+class TestPlainTextCredentialStore(tests.TestCase):
+
+ def test_decode_password(self):
+ r = config.credential_store_registry
+ plain_text = r.get_credential_store()
+ decoded = plain_text.decode_password(dict(password='secret'))
+ self.assertEquals('secret', decoded)
+
+
# FIXME: Once we have a way to declare authentication to all test servers, we
# can implement generic tests.
# test_user_password_in_url
More information about the bazaar-commits
mailing list