From fc95d25544a0f14e886810ab53c689909b22cad9 Mon Sep 17 00:00:00 2001 From: Colleen Murphy Date: Thu, 26 May 2016 12:01:59 -0700 Subject: [PATCH] Make the kerberos plugin loadable This patch adds a BaseLoader class for the Kerberos plugin and an entry point in setup.cfg. Since the plugin file is being renamed, also fix the comment that refers to the library as 'keystoneauth' - it is called 'keystoneauth1' and trying to install 'keystoneauth' will cause the outdated version of the library to be installed and kerberos will not work. To make sure the plugin was loadable, this was tested using a version of python-openstackclient that had been migrated to keystoneauth[1]. [1] https://review.openstack.org/#/c/276350/ Change-Id: Id339295c795f6bf1b428dac8fc9f79d2f5fb453f Closes-bug: #1567257 Partial-bug: #1567260 --- .../{kerberos.py => kerberos/__init__.py} | 26 +++++++++++++-- keystoneauth1/extras/kerberos/_loading.py | 25 ++++++++++++++ .../extras/kerberos/test_kerberos_loading.py | 33 +++++++++++++++++++ .../tests/unit/extras/kerberos/test_mapped.py | 17 ++-------- .../tests/unit/extras/kerberos/test_v3.py | 18 ++-------- .../tests/unit/extras/kerberos/utils.py | 3 ++ setup.cfg | 1 + 7 files changed, 89 insertions(+), 34 deletions(-) rename keystoneauth1/extras/{kerberos.py => kerberos/__init__.py} (78%) create mode 100644 keystoneauth1/extras/kerberos/_loading.py create mode 100644 keystoneauth1/tests/unit/extras/kerberos/test_kerberos_loading.py diff --git a/keystoneauth1/extras/kerberos.py b/keystoneauth1/extras/kerberos/__init__.py similarity index 78% rename from keystoneauth1/extras/kerberos.py rename to keystoneauth1/extras/kerberos/__init__.py index 5a4c4f47..1092910c 100644 --- a/keystoneauth1/extras/kerberos.py +++ b/keystoneauth1/extras/kerberos/__init__.py @@ -18,11 +18,13 @@ not installed by default. Without the extra package an import error will occur. The extra package can be installed using:: - $ pip install keystoneauth['kerberos'] - + $ pip install keystoneauth1[kerberos] """ -import requests_kerberos +try: + import requests_kerberos +except ImportError: + requests_kerberos = None from keystoneauth1 import access from keystoneauth1.identity import v3 @@ -37,10 +39,24 @@ def _requests_auth(): mutual_authentication=requests_kerberos.OPTIONAL) +def _dependency_check(): + if requests_kerberos is None: + raise ImportError(""" +Using the kerberos authentication plugin requires installation of additional +packages. These can be installed with:: + + $ pip install keystoneauth1[kerberos] +""") + + class KerberosMethod(v3.AuthMethod): _method_parameters = [] + def __init__(self, *args, **kwargs): + _dependency_check() + super(KerberosMethod, self).__init__(*args, **kwargs) + def get_auth_data(self, session, auth, headers, request_kwargs, **kwargs): # NOTE(jamielennox): request_kwargs is passed as a kwarg however it is # required and always present when called from keystoneclient. @@ -59,6 +75,10 @@ class MappedKerberos(federation.FederationBaseAuth): use the standard keystone auth process to scope that to any given project. """ + def __init__(self, *args, **kwargs): + _dependency_check() + super(MappedKerberos, self).__init__(*args, **kwargs) + def get_unscoped_auth_ref(self, session, **kwargs): resp = session.get(self.federated_token_url, requests_auth=_requests_auth(), diff --git a/keystoneauth1/extras/kerberos/_loading.py b/keystoneauth1/extras/kerberos/_loading.py new file mode 100644 index 00000000..b66c9880 --- /dev/null +++ b/keystoneauth1/extras/kerberos/_loading.py @@ -0,0 +1,25 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from keystoneauth1.extras import kerberos +from keystoneauth1 import loading + + +class Kerberos(loading.BaseV3Loader): + + @property + def plugin_class(self): + return kerberos.Kerberos + + @property + def available(self): + return kerberos.kerberos_requests is not None diff --git a/keystoneauth1/tests/unit/extras/kerberos/test_kerberos_loading.py b/keystoneauth1/tests/unit/extras/kerberos/test_kerberos_loading.py new file mode 100644 index 00000000..e4da3070 --- /dev/null +++ b/keystoneauth1/tests/unit/extras/kerberos/test_kerberos_loading.py @@ -0,0 +1,33 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from keystoneauth1 import loading +from keystoneauth1.tests.unit import utils as test_utils + + +class KerberosLoadingTests(test_utils.TestCase): + + def test_options(self): + opts = [o.name for o in + loading.get_plugin_loader('v3kerberos').get_options()] + + allowed_opts = ['domain-id', + 'domain-name', + 'project-id', + 'project-name', + 'project-domain-id', + 'project-domain-name', + 'trust-id', + 'auth-url', + ] + + self.assertItemsEqual(allowed_opts, opts) diff --git a/keystoneauth1/tests/unit/extras/kerberos/test_mapped.py b/keystoneauth1/tests/unit/extras/kerberos/test_mapped.py index 9ba7fbbb..a5fa41c7 100644 --- a/keystoneauth1/tests/unit/extras/kerberos/test_mapped.py +++ b/keystoneauth1/tests/unit/extras/kerberos/test_mapped.py @@ -12,29 +12,16 @@ import uuid -import six - +from keystoneauth1.extras import kerberos from keystoneauth1 import fixture as ks_fixture from keystoneauth1 import session from keystoneauth1.tests.unit.extras.kerberos import base -try: - # Until requests_kerberos gets py3 support, this is going to fail to import - from keystoneauth1.extras import kerberos - -except ImportError: - if six.PY2: - # requests_kerberos is expected to be there on py2, so don't ignore. - raise - - # requests_kerberos isn't available - kerberos = False - class TestMappedAuth(base.TestCase): def setUp(self): - if not kerberos: + if kerberos.requests_kerberos is None: self.skipTest("Kerberos support isn't available.") super(TestMappedAuth, self).setUp() diff --git a/keystoneauth1/tests/unit/extras/kerberos/test_v3.py b/keystoneauth1/tests/unit/extras/kerberos/test_v3.py index 40df22f7..1d6e5e91 100644 --- a/keystoneauth1/tests/unit/extras/kerberos/test_v3.py +++ b/keystoneauth1/tests/unit/extras/kerberos/test_v3.py @@ -10,29 +10,15 @@ # License for the specific language governing permissions and limitations # under the License. - -import six - +from keystoneauth1.extras import kerberos from keystoneauth1 import session from keystoneauth1.tests.unit.extras.kerberos import base -try: - # Until requests_kerberos gets py3 support, this is going to fail to import - from keystoneauth1.extras import kerberos - -except ImportError: - if six.PY2: - # requests_kerberos is expected to be there on py2, so don't ignore. - raise - - # requests_kerberos isn't available - kerberos = None - class TestKerberosAuth(base.TestCase): def setUp(self): - if not kerberos: + if kerberos.requests_kerberos is None: self.skipTest("Kerberos support isn't available.") super(TestKerberosAuth, self).setUp() diff --git a/keystoneauth1/tests/unit/extras/kerberos/utils.py b/keystoneauth1/tests/unit/extras/kerberos/utils.py index 8c35292f..f955cc8e 100644 --- a/keystoneauth1/tests/unit/extras/kerberos/utils.py +++ b/keystoneauth1/tests/unit/extras/kerberos/utils.py @@ -36,6 +36,9 @@ class KerberosMock(fixtures.Fixture): def setUp(self): super(KerberosMock, self).setUp() + if requests_kerberos is None: + return + m = mockpatch.PatchObject(requests_kerberos.HTTPKerberosAuth, 'generate_request_header', self._generate_request_header) diff --git a/setup.cfg b/setup.cfg index 06cb522e..827c8dae 100644 --- a/setup.cfg +++ b/setup.cfg @@ -48,6 +48,7 @@ keystoneauth1.plugin = v3oidcauthcode = keystoneauth1.loading._plugins.identity.v3:OpenIDConnectAuthorizationCode v3oidcaccesstoken = keystoneauth1.loading._plugins.identity.v3:OpenIDConnectAccessToken v3oauth1 = keystoneauth1.extras.oauth1._loading:V3OAuth1 + v3kerberos = keystoneauth1.extras.kerberos._loading:Kerberos [build_sphinx] source-dir = doc/source