Move the auth plugins abstract base class out of core
This patch moves the auth plugins abstract base class out of core and into plugins/base.py This removes dependencies where backend code references code in the core. The reasoning being that the core should know about the backend interface, but the backends should not know anything about the core (separation of concerns). And part of the risk here is a potential for circular dependencies. Partial-Bug: #1563101 Change-Id: I4413ef01523d02c30af97e306069229252cb4971
This commit is contained in:
parent
5f7377f5ab
commit
5d707d510d
@ -325,7 +325,7 @@ How to Implement an Authentication Plugin
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
All authentication plugins must extend the
|
||||
:class:`keystone.auth.core.AuthMethodHandler` class and implement the
|
||||
:class:`keystone.auth.plugins.base.AuthMethodHandler` class and implement the
|
||||
``authenticate()`` method. The ``authenticate()`` method expects the following
|
||||
parameters.
|
||||
|
||||
|
@ -13,4 +13,3 @@
|
||||
# under the License.
|
||||
|
||||
from keystone.auth import controllers # noqa
|
||||
from keystone.auth.core import * # noqa
|
||||
|
@ -12,83 +12,15 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import abc
|
||||
from oslo_log import versionutils
|
||||
|
||||
import six
|
||||
|
||||
from keystone import exception
|
||||
from keystone.auth.plugins import base
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class AuthMethodHandler(object):
|
||||
"""Abstract base class for an authentication plugin."""
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def authenticate(self, context, auth_payload, auth_context):
|
||||
"""Authenticate user and return an authentication context.
|
||||
|
||||
:param context: keystone's request context
|
||||
:param auth_payload: the content of the authentication for a given
|
||||
method
|
||||
:param auth_context: user authentication context, a dictionary shared
|
||||
by all plugins. It contains "method_names" and
|
||||
"extras" by default. "method_names" is a list and
|
||||
"extras" is a dictionary.
|
||||
|
||||
If successful, plugin must set ``user_id`` in ``auth_context``.
|
||||
``method_name`` is used to convey any additional authentication methods
|
||||
in case authentication is for re-scoping. For example, if the
|
||||
authentication is for re-scoping, plugin must append the previous
|
||||
method names into ``method_names``. Also, plugin may add any additional
|
||||
information into ``extras``. Anything in ``extras`` will be conveyed in
|
||||
the token's ``extras`` attribute. Here's an example of ``auth_context``
|
||||
on successful authentication::
|
||||
|
||||
{
|
||||
"extras": {},
|
||||
"methods": [
|
||||
"password",
|
||||
"token"
|
||||
],
|
||||
"user_id": "abc123"
|
||||
}
|
||||
|
||||
Plugins are invoked in the order in which they are specified in the
|
||||
``methods`` attribute of the ``identity`` object. For example,
|
||||
``custom-plugin`` is invoked before ``password``, which is invoked
|
||||
before ``token`` in the following authentication request::
|
||||
|
||||
{
|
||||
"auth": {
|
||||
"identity": {
|
||||
"custom-plugin": {
|
||||
"custom-data": "sdfdfsfsfsdfsf"
|
||||
},
|
||||
"methods": [
|
||||
"custom-plugin",
|
||||
"password",
|
||||
"token"
|
||||
],
|
||||
"password": {
|
||||
"user": {
|
||||
"id": "s23sfad1",
|
||||
"password": "secrete"
|
||||
}
|
||||
},
|
||||
"token": {
|
||||
"id": "sdfafasdfsfasfasdfds"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:returns: None if authentication is successful.
|
||||
Authentication payload in the form of a dictionary for the
|
||||
next authentication step if this is a multi step
|
||||
authentication.
|
||||
:raises keystone.exception.Unauthorized: for authentication failure
|
||||
"""
|
||||
raise exception.Unauthorized()
|
||||
@versionutils.deprecated(
|
||||
versionutils.deprecated.NEWTON,
|
||||
what='keystone.auth.AuthMethodHandler',
|
||||
in_favor_of='keystone.auth.plugins.base.AuthMethodHandler',
|
||||
remove_in=+1)
|
||||
class AuthMethodHandler(base.AuthMethodHandler):
|
||||
pass
|
||||
|
94
keystone/auth/plugins/base.py
Normal file
94
keystone/auth/plugins/base.py
Normal file
@ -0,0 +1,94 @@
|
||||
# Copyright 2013 OpenStack Foundation
|
||||
#
|
||||
# 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.
|
||||
|
||||
import abc
|
||||
|
||||
import six
|
||||
|
||||
from keystone import exception
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class AuthMethodHandler(object):
|
||||
"""Abstract base class for an authentication plugin."""
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def authenticate(self, context, auth_payload, auth_context):
|
||||
"""Authenticate user and return an authentication context.
|
||||
|
||||
:param context: keystone's request context
|
||||
:param auth_payload: the content of the authentication for a given
|
||||
method
|
||||
:param auth_context: user authentication context, a dictionary shared
|
||||
by all plugins. It contains "method_names" and
|
||||
"extras" by default. "method_names" is a list and
|
||||
"extras" is a dictionary.
|
||||
|
||||
If successful, plugin must set ``user_id`` in ``auth_context``.
|
||||
``method_name`` is used to convey any additional authentication methods
|
||||
in case authentication is for re-scoping. For example, if the
|
||||
authentication is for re-scoping, plugin must append the previous
|
||||
method names into ``method_names``. Also, plugin may add any additional
|
||||
information into ``extras``. Anything in ``extras`` will be conveyed in
|
||||
the token's ``extras`` attribute. Here's an example of ``auth_context``
|
||||
on successful authentication::
|
||||
|
||||
{
|
||||
"extras": {},
|
||||
"methods": [
|
||||
"password",
|
||||
"token"
|
||||
],
|
||||
"user_id": "abc123"
|
||||
}
|
||||
|
||||
Plugins are invoked in the order in which they are specified in the
|
||||
``methods`` attribute of the ``identity`` object. For example,
|
||||
``custom-plugin`` is invoked before ``password``, which is invoked
|
||||
before ``token`` in the following authentication request::
|
||||
|
||||
{
|
||||
"auth": {
|
||||
"identity": {
|
||||
"custom-plugin": {
|
||||
"custom-data": "sdfdfsfsfsdfsf"
|
||||
},
|
||||
"methods": [
|
||||
"custom-plugin",
|
||||
"password",
|
||||
"token"
|
||||
],
|
||||
"password": {
|
||||
"user": {
|
||||
"id": "s23sfad1",
|
||||
"password": "secrete"
|
||||
}
|
||||
},
|
||||
"token": {
|
||||
"id": "sdfafasdfsfasfasdfds"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:returns: None if authentication is successful.
|
||||
Authentication payload in the form of a dictionary for the
|
||||
next authentication step if this is a multi step
|
||||
authentication.
|
||||
:raises keystone.exception.Unauthorized: for authentication failure
|
||||
"""
|
||||
raise exception.Unauthorized()
|
@ -18,7 +18,7 @@ import abc
|
||||
|
||||
import six
|
||||
|
||||
from keystone import auth
|
||||
from keystone.auth.plugins import base
|
||||
from keystone.common import dependency
|
||||
import keystone.conf
|
||||
from keystone import exception
|
||||
@ -29,7 +29,7 @@ CONF = keystone.conf.CONF
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class Base(auth.AuthMethodHandler):
|
||||
class Base(base.AuthMethodHandler):
|
||||
def authenticate(self, request, auth_info, auth_context):
|
||||
"""Use REMOTE_USER to look up the user in the identity backend.
|
||||
|
||||
|
@ -15,8 +15,8 @@ import functools
|
||||
from pycadf import cadftaxonomy as taxonomy
|
||||
from six.moves.urllib import parse
|
||||
|
||||
from keystone import auth
|
||||
from keystone.auth import plugins as auth_plugins
|
||||
from keystone.auth.plugins import base
|
||||
from keystone.common import dependency
|
||||
from keystone import exception
|
||||
from keystone.federation import constants as federation_constants
|
||||
@ -31,7 +31,7 @@ METHOD_NAME = 'mapped'
|
||||
|
||||
@dependency.requires('federation_api', 'identity_api',
|
||||
'resource_api', 'token_provider_api')
|
||||
class Mapped(auth.AuthMethodHandler):
|
||||
class Mapped(base.AuthMethodHandler):
|
||||
|
||||
def _get_token_ref(self, auth_payload):
|
||||
token_id = auth_payload['id']
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
from oslo_utils import timeutils
|
||||
|
||||
from keystone import auth
|
||||
from keystone.auth.plugins import base
|
||||
from keystone.common import controller
|
||||
from keystone.common import dependency
|
||||
from keystone import exception
|
||||
@ -24,7 +24,7 @@ from keystone.oauth1 import validator
|
||||
|
||||
|
||||
@dependency.requires('oauth_api')
|
||||
class OAuth(auth.AuthMethodHandler):
|
||||
class OAuth(base.AuthMethodHandler):
|
||||
def authenticate(self, request, auth_info, auth_context):
|
||||
"""Turn a signed request with an access key into a keystone token."""
|
||||
oauth_headers = oauth.get_oauth_headers(request.headers)
|
||||
|
@ -12,8 +12,8 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from keystone import auth
|
||||
from keystone.auth import plugins as auth_plugins
|
||||
from keystone.auth.plugins import base
|
||||
from keystone.common import dependency
|
||||
from keystone import exception
|
||||
from keystone.i18n import _
|
||||
@ -23,7 +23,7 @@ METHOD_NAME = 'password'
|
||||
|
||||
|
||||
@dependency.requires('identity_api')
|
||||
class Password(auth.AuthMethodHandler):
|
||||
class Password(base.AuthMethodHandler):
|
||||
|
||||
def authenticate(self, request, auth_payload, auth_context):
|
||||
"""Try to authenticate against the identity backend."""
|
||||
|
@ -15,7 +15,7 @@
|
||||
from oslo_log import log
|
||||
import six
|
||||
|
||||
from keystone import auth
|
||||
from keystone.auth.plugins import base
|
||||
from keystone.auth.plugins import mapped
|
||||
from keystone.common import dependency
|
||||
from keystone.common import wsgi
|
||||
@ -31,7 +31,7 @@ CONF = keystone.conf.CONF
|
||||
|
||||
|
||||
@dependency.requires('federation_api', 'identity_api', 'token_provider_api')
|
||||
class Token(auth.AuthMethodHandler):
|
||||
class Token(base.AuthMethodHandler):
|
||||
|
||||
def _get_token_ref(self, auth_payload):
|
||||
token_id = auth_payload['id']
|
||||
|
@ -31,8 +31,8 @@ from oslo_log import log
|
||||
from oslo_utils import timeutils
|
||||
import six
|
||||
|
||||
from keystone import auth
|
||||
from keystone.auth import plugins
|
||||
from keystone.auth.plugins import base
|
||||
from keystone.common import dependency
|
||||
from keystone import exception
|
||||
from keystone.i18n import _
|
||||
@ -66,7 +66,7 @@ def _generate_totp_passcode(secret):
|
||||
|
||||
|
||||
@dependency.requires('credential_api')
|
||||
class TOTP(auth.AuthMethodHandler):
|
||||
class TOTP(base.AuthMethodHandler):
|
||||
|
||||
def authenticate(self, request, auth_payload, auth_context):
|
||||
"""Try to authenticate using TOTP."""
|
||||
|
@ -17,6 +17,7 @@ import uuid
|
||||
import mock
|
||||
|
||||
from keystone import auth
|
||||
from keystone.auth.plugins import base
|
||||
from keystone import exception
|
||||
from keystone.tests import unit
|
||||
from keystone.tests.unit.ksfixtures import auth_plugins
|
||||
@ -32,7 +33,7 @@ EXPECTED_RESPONSE = uuid.uuid4().hex
|
||||
DEMO_USER_ID = uuid.uuid4().hex
|
||||
|
||||
|
||||
class SimpleChallengeResponse(auth.AuthMethodHandler):
|
||||
class SimpleChallengeResponse(base.AuthMethodHandler):
|
||||
def authenticate(self, context, auth_payload, user_context):
|
||||
if 'response' in auth_payload:
|
||||
if auth_payload['response'] != EXPECTED_RESPONSE:
|
||||
|
Loading…
Reference in New Issue
Block a user