Convert authentication into a plugin
Extract all the information that is related to auth and make it into a keystoneclient auth plugin. This will make it easier later to substitute this auth plugin for another auth plugin. Blueprint: pluggable-auth Change-Id: Ibf9bc1dbf26f396bac09a96398a6467afc30f529
This commit is contained in:
parent
365b3ea1d9
commit
f21ccea42c
|
@ -169,6 +169,7 @@ import tempfile
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from keystoneclient import access
|
from keystoneclient import access
|
||||||
|
from keystoneclient import auth
|
||||||
from keystoneclient.auth.identity import base as base_identity
|
from keystoneclient.auth.identity import base as base_identity
|
||||||
from keystoneclient.auth.identity import v2
|
from keystoneclient.auth.identity import v2
|
||||||
from keystoneclient.auth import token_endpoint
|
from keystoneclient.auth import token_endpoint
|
||||||
|
@ -213,33 +214,12 @@ from keystonemiddleware.openstack.common import memorycache
|
||||||
# options via CONF.
|
# options via CONF.
|
||||||
|
|
||||||
_OPTS = [
|
_OPTS = [
|
||||||
cfg.StrOpt('auth_admin_prefix',
|
|
||||||
default='',
|
|
||||||
help='Prefix to prepend at the beginning of the path. '
|
|
||||||
'Deprecated, use identity_uri.'),
|
|
||||||
cfg.StrOpt('auth_host',
|
|
||||||
default='127.0.0.1',
|
|
||||||
help='Host providing the admin Identity API endpoint. '
|
|
||||||
'Deprecated, use identity_uri.'),
|
|
||||||
cfg.IntOpt('auth_port',
|
|
||||||
default=35357,
|
|
||||||
help='Port of the admin Identity API endpoint. '
|
|
||||||
'Deprecated, use identity_uri.'),
|
|
||||||
cfg.StrOpt('auth_protocol',
|
|
||||||
default='https',
|
|
||||||
help='Protocol of the admin Identity API endpoint '
|
|
||||||
'(http or https). Deprecated, use identity_uri.'),
|
|
||||||
cfg.StrOpt('auth_uri',
|
cfg.StrOpt('auth_uri',
|
||||||
default=None,
|
default=None,
|
||||||
# FIXME(dolph): should be default='http://127.0.0.1:5000/v2.0/',
|
# FIXME(dolph): should be default='http://127.0.0.1:5000/v2.0/',
|
||||||
# or (depending on client support) an unversioned, publicly
|
# or (depending on client support) an unversioned, publicly
|
||||||
# accessible identity endpoint (see bug 1207517)
|
# accessible identity endpoint (see bug 1207517)
|
||||||
help='Complete public Identity API endpoint.'),
|
help='Complete public Identity API endpoint.'),
|
||||||
cfg.StrOpt('identity_uri',
|
|
||||||
default=None,
|
|
||||||
help='Complete admin Identity API endpoint. This should '
|
|
||||||
'specify the unversioned root endpoint '
|
|
||||||
'e.g. https://localhost:35357/'),
|
|
||||||
cfg.StrOpt('auth_version',
|
cfg.StrOpt('auth_version',
|
||||||
default=None,
|
default=None,
|
||||||
help='API version of the admin Identity API endpoint.'),
|
help='API version of the admin Identity API endpoint.'),
|
||||||
|
@ -256,23 +236,6 @@ _OPTS = [
|
||||||
default=3,
|
default=3,
|
||||||
help='How many times are we trying to reconnect when'
|
help='How many times are we trying to reconnect when'
|
||||||
' communicating with Identity API Server.'),
|
' communicating with Identity API Server.'),
|
||||||
cfg.StrOpt('admin_token',
|
|
||||||
secret=True,
|
|
||||||
help='This option is deprecated and may be removed in a future'
|
|
||||||
' release. Single shared secret with the Keystone configuration'
|
|
||||||
' used for bootstrapping a Keystone installation, or otherwise'
|
|
||||||
' bypassing the normal authentication process. This option'
|
|
||||||
' should not be used, use `admin_user` and `admin_password`'
|
|
||||||
' instead.'),
|
|
||||||
cfg.StrOpt('admin_user',
|
|
||||||
help='Keystone account username.'),
|
|
||||||
cfg.StrOpt('admin_password',
|
|
||||||
secret=True,
|
|
||||||
help='Keystone account password.'),
|
|
||||||
cfg.StrOpt('admin_tenant_name',
|
|
||||||
default='admin',
|
|
||||||
help='Keystone service account tenant name to validate'
|
|
||||||
' user tokens.'),
|
|
||||||
cfg.StrOpt('cache',
|
cfg.StrOpt('cache',
|
||||||
default=None,
|
default=None,
|
||||||
help='Env key for the swift cache.'),
|
help='Env key for the swift cache.'),
|
||||||
|
@ -376,9 +339,9 @@ _OPTS = [
|
||||||
' should be set to a single value for better performance.'),
|
' should be set to a single value for better performance.'),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
_AUTHTOKEN_GROUP = 'keystone_authtoken'
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
CONF.register_opts(_OPTS, group='keystone_authtoken')
|
CONF.register_opts(_OPTS, group=_AUTHTOKEN_GROUP)
|
||||||
|
|
||||||
_LIST_OF_VERSIONS_TO_ATTEMPT = ['v3.0', 'v2.0']
|
_LIST_OF_VERSIONS_TO_ATTEMPT = ['v3.0', 'v2.0']
|
||||||
|
|
||||||
_HEADER_TEMPLATE = {
|
_HEADER_TEMPLATE = {
|
||||||
|
@ -541,6 +504,121 @@ class _MiniResp(object):
|
||||||
self.headers.append(('Content-type', 'text/plain'))
|
self.headers.append(('Content-type', 'text/plain'))
|
||||||
|
|
||||||
|
|
||||||
|
class _AuthTokenPlugin(auth.BaseAuthPlugin):
|
||||||
|
|
||||||
|
def __init__(self, auth_host, auth_port, auth_protocol, auth_admin_prefix,
|
||||||
|
admin_user, admin_password, admin_tenant_name, admin_token,
|
||||||
|
identity_uri, log):
|
||||||
|
# NOTE(jamielennox): it does appear here that our default arguments
|
||||||
|
# are backwards. We need to do it this way so that we can handle the
|
||||||
|
# same deprecation strategy for CONF and the conf variable.
|
||||||
|
if not identity_uri:
|
||||||
|
log.warning('Configuring admin URI using auth fragments. '
|
||||||
|
'This is deprecated, use \'identity_uri\''
|
||||||
|
' instead.')
|
||||||
|
|
||||||
|
if ':' in auth_host:
|
||||||
|
# Note(dzyu) it is an IPv6 address, so it needs to be wrapped
|
||||||
|
# with '[]' to generate a valid IPv6 URL, based on
|
||||||
|
# http://www.ietf.org/rfc/rfc2732.txt
|
||||||
|
auth_host = '[%s]' % auth_host
|
||||||
|
|
||||||
|
identity_uri = '%s://%s:%s' % (auth_protocol,
|
||||||
|
auth_host,
|
||||||
|
auth_port)
|
||||||
|
|
||||||
|
if auth_admin_prefix:
|
||||||
|
identity_uri = '%s/%s' % (identity_uri,
|
||||||
|
auth_admin_prefix.strip('/'))
|
||||||
|
|
||||||
|
self._identity_uri = identity_uri.rstrip('/')
|
||||||
|
|
||||||
|
# FIXME(jamielennox): Yes. This is wrong. We should be determining the
|
||||||
|
# plugin to use based on a combination of discovery and inputs. Much
|
||||||
|
# of this can be changed when we get keystoneclient 0.10. For now this
|
||||||
|
# hardcoded path is EXACTLY the same as the original auth_token did.
|
||||||
|
auth_url = '%s/v2.0' % self._identity_uri
|
||||||
|
|
||||||
|
if admin_token:
|
||||||
|
log.warning(
|
||||||
|
"The admin_token option in the auth_token middleware is "
|
||||||
|
"deprecated and should not be used. The admin_user and "
|
||||||
|
"admin_password options should be used instead. The "
|
||||||
|
"admin_token option may be removed in a future release.")
|
||||||
|
self._plugin = token_endpoint.Token(auth_url, admin_token)
|
||||||
|
else:
|
||||||
|
self._plugin = v2.Password(auth_url,
|
||||||
|
username=admin_user,
|
||||||
|
password=admin_password,
|
||||||
|
tenant_name=admin_tenant_name)
|
||||||
|
|
||||||
|
self._LOG = log
|
||||||
|
|
||||||
|
def get_token(self, *args, **kwargs):
|
||||||
|
return self._plugin.get_token(*args, **kwargs)
|
||||||
|
|
||||||
|
def get_endpoint(self, session, interface=None, **kwargs):
|
||||||
|
# FIXME(jamielennox) for now the paths are always set up such that they
|
||||||
|
# expect the unversioned endpoint to be returned as the base. This will
|
||||||
|
# change shortly.
|
||||||
|
|
||||||
|
return self._identity_uri
|
||||||
|
|
||||||
|
def invalidate(self):
|
||||||
|
return self._plugin.invalidate()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_options(cls):
|
||||||
|
options = super(_AuthTokenPlugin, cls).get_options()
|
||||||
|
|
||||||
|
options.extend([
|
||||||
|
cfg.StrOpt('auth_admin_prefix',
|
||||||
|
default='',
|
||||||
|
help='Prefix to prepend at the beginning of the path. '
|
||||||
|
'Deprecated, use identity_uri.'),
|
||||||
|
cfg.StrOpt('auth_host',
|
||||||
|
default='127.0.0.1',
|
||||||
|
help='Host providing the admin Identity API endpoint. '
|
||||||
|
'Deprecated, use identity_uri.'),
|
||||||
|
cfg.IntOpt('auth_port',
|
||||||
|
default=35357,
|
||||||
|
help='Port of the admin Identity API endpoint. '
|
||||||
|
'Deprecated, use identity_uri.'),
|
||||||
|
cfg.StrOpt('auth_protocol',
|
||||||
|
default='https',
|
||||||
|
help='Protocol of the admin Identity API endpoint '
|
||||||
|
'(http or https). Deprecated, use identity_uri.'),
|
||||||
|
cfg.StrOpt('identity_uri',
|
||||||
|
default=None,
|
||||||
|
help='Complete admin Identity API endpoint. This '
|
||||||
|
'should specify the unversioned root endpoint '
|
||||||
|
'e.g. https://localhost:35357/'),
|
||||||
|
cfg.StrOpt('admin_token',
|
||||||
|
secret=True,
|
||||||
|
help='This option is deprecated and may be removed in '
|
||||||
|
'a future release. Single shared secret with the '
|
||||||
|
'Keystone configuration used for bootstrapping a '
|
||||||
|
'Keystone installation, or otherwise bypassing '
|
||||||
|
'the normal authentication process. This option '
|
||||||
|
'should not be used, use `admin_user` and '
|
||||||
|
'`admin_password` instead.'),
|
||||||
|
cfg.StrOpt('admin_user',
|
||||||
|
help='Keystone account username.'),
|
||||||
|
cfg.StrOpt('admin_password',
|
||||||
|
secret=True,
|
||||||
|
help='Keystone account password.'),
|
||||||
|
cfg.StrOpt('admin_tenant_name',
|
||||||
|
default='admin',
|
||||||
|
help='Keystone service account tenant name to validate'
|
||||||
|
' user tokens.'),
|
||||||
|
])
|
||||||
|
|
||||||
|
return options
|
||||||
|
|
||||||
|
|
||||||
|
_AuthTokenPlugin.register_conf_options(CONF, _AUTHTOKEN_GROUP)
|
||||||
|
|
||||||
|
|
||||||
class _UserAuthPlugin(base_identity.BaseIdentityPlugin):
|
class _UserAuthPlugin(base_identity.BaseIdentityPlugin):
|
||||||
"""The incoming authentication credentials.
|
"""The incoming authentication credentials.
|
||||||
|
|
||||||
|
@ -591,38 +669,6 @@ class AuthProtocol(object):
|
||||||
(True, 'true', 't', '1', 'on', 'yes', 'y')
|
(True, 'true', 't', '1', 'on', 'yes', 'y')
|
||||||
)
|
)
|
||||||
|
|
||||||
self._identity_uri = self._conf_get('identity_uri')
|
|
||||||
|
|
||||||
# NOTE(jamielennox): it does appear here that our default arguments
|
|
||||||
# are backwards. We need to do it this way so that we can handle the
|
|
||||||
# same deprecation strategy for CONF and the conf variable.
|
|
||||||
if not self._identity_uri:
|
|
||||||
self._LOG.warning('Configuring admin URI using auth fragments. '
|
|
||||||
'This is deprecated, use \'identity_uri\''
|
|
||||||
' instead.')
|
|
||||||
|
|
||||||
auth_host = self._conf_get('auth_host')
|
|
||||||
auth_port = int(self._conf_get('auth_port'))
|
|
||||||
auth_protocol = self._conf_get('auth_protocol')
|
|
||||||
auth_admin_prefix = self._conf_get('auth_admin_prefix')
|
|
||||||
|
|
||||||
if ':' in auth_host:
|
|
||||||
# Note(dzyu) it is an IPv6 address, so it needs to be wrapped
|
|
||||||
# with '[]' to generate a valid IPv6 URL, based on
|
|
||||||
# http://www.ietf.org/rfc/rfc2732.txt
|
|
||||||
auth_host = '[%s]' % auth_host
|
|
||||||
|
|
||||||
self._identity_uri = '%s://%s:%s' % (auth_protocol,
|
|
||||||
auth_host,
|
|
||||||
auth_port)
|
|
||||||
|
|
||||||
if auth_admin_prefix:
|
|
||||||
self._identity_uri = '%s/%s' % (self._identity_uri,
|
|
||||||
auth_admin_prefix.strip('/'))
|
|
||||||
|
|
||||||
else:
|
|
||||||
self._identity_uri = self._identity_uri.rstrip('/')
|
|
||||||
|
|
||||||
self._session = self._session_factory()
|
self._session = self._session_factory()
|
||||||
|
|
||||||
self._http_request_max_retries = self._conf_get(
|
self._http_request_max_retries = self._conf_get(
|
||||||
|
@ -1217,6 +1263,10 @@ class AuthProtocol(object):
|
||||||
# NOTE(hrybacki): This and subsequent factory functions are part of a
|
# NOTE(hrybacki): This and subsequent factory functions are part of a
|
||||||
# cleanup and better organization effort of AuthProtocol.
|
# cleanup and better organization effort of AuthProtocol.
|
||||||
def _session_factory(self):
|
def _session_factory(self):
|
||||||
|
# NOTE(jamielennox): Loading Session here should be exactly the
|
||||||
|
# same as calling Session.load_from_conf_options(CONF, GROUP)
|
||||||
|
# however we can't do that because we have to use _conf_get to support
|
||||||
|
# the paste.ini options.
|
||||||
sess = session.Session.construct(dict(
|
sess = session.Session.construct(dict(
|
||||||
cert=self._conf_get('certfile'),
|
cert=self._conf_get('certfile'),
|
||||||
key=self._conf_get('keyfile'),
|
key=self._conf_get('keyfile'),
|
||||||
|
@ -1224,26 +1274,23 @@ class AuthProtocol(object):
|
||||||
insecure=self._conf_get('insecure'),
|
insecure=self._conf_get('insecure'),
|
||||||
timeout=self._conf_get('http_connect_timeout')
|
timeout=self._conf_get('http_connect_timeout')
|
||||||
))
|
))
|
||||||
# FIXME(jamielennox): Yes. This is wrong. We should be determining the
|
|
||||||
# plugin to use based on a combination of discovery and inputs. Much
|
|
||||||
# of this can be changed when we get keystoneclient 0.10. For now this
|
|
||||||
# hardcoded path is EXACTLY the same as the original auth_token did.
|
|
||||||
auth_url = '%s/v2.0' % self._identity_uri
|
|
||||||
|
|
||||||
admin_token = self._conf_get('admin_token')
|
# NOTE(jamielennox): Loading AuthTokenPlugin here should be exactly the
|
||||||
if admin_token:
|
# same as calling _AuthTokenPlugin.load_from_conf_options(CONF, GROUP)
|
||||||
self._LOG.warning(
|
# however we can't do that because we have to use _conf_get to support
|
||||||
"The admin_token option in the auth_token middleware is "
|
# the paste.ini options.
|
||||||
"deprecated and should not be used. The admin_user and "
|
sess.auth = _AuthTokenPlugin.load_from_options(
|
||||||
"admin_password options should be used instead. The "
|
auth_host=self._conf_get('auth_host'),
|
||||||
"admin_token option may be removed in a future release.")
|
auth_port=int(self._conf_get('auth_port')),
|
||||||
sess.auth = token_endpoint.Token(auth_url, admin_token)
|
auth_protocol=self._conf_get('auth_protocol'),
|
||||||
else:
|
auth_admin_prefix=self._conf_get('auth_admin_prefix'),
|
||||||
sess.auth = v2.Password(
|
admin_user=self._conf_get('admin_user'),
|
||||||
auth_url,
|
admin_password=self._conf_get('admin_password'),
|
||||||
username=self._conf_get('admin_user'),
|
admin_tenant_name=self._conf_get('admin_tenant_name'),
|
||||||
password=self._conf_get('admin_password'),
|
admin_token=self._conf_get('admin_token'),
|
||||||
tenant_name=self._conf_get('admin_tenant_name'))
|
identity_uri=self._conf_get('identity_uri'),
|
||||||
|
log=self._LOG)
|
||||||
|
|
||||||
return sess
|
return sess
|
||||||
|
|
||||||
def _identity_server_factory(self):
|
def _identity_server_factory(self):
|
||||||
|
@ -1251,7 +1298,6 @@ class AuthProtocol(object):
|
||||||
self._LOG,
|
self._LOG,
|
||||||
self._session,
|
self._session,
|
||||||
include_service_catalog=self._include_service_catalog,
|
include_service_catalog=self._include_service_catalog,
|
||||||
identity_uri=self._identity_uri,
|
|
||||||
auth_uri=self._conf_get('auth_uri'),
|
auth_uri=self._conf_get('auth_uri'),
|
||||||
http_request_max_retries=self._http_request_max_retries,
|
http_request_max_retries=self._http_request_max_retries,
|
||||||
auth_version=self._conf_get('auth_version'))
|
auth_version=self._conf_get('auth_version'))
|
||||||
|
@ -1351,19 +1397,14 @@ class _IdentityServer(object):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
def __init__(self, log, session, include_service_catalog=None,
|
def __init__(self, log, session, include_service_catalog=None,
|
||||||
identity_uri=None, auth_uri=None,
|
auth_uri=None, http_request_max_retries=None,
|
||||||
http_request_max_retries=None, auth_version=None):
|
auth_version=None):
|
||||||
self._LOG = log
|
self._LOG = log
|
||||||
self._include_service_catalog = include_service_catalog
|
self._include_service_catalog = include_service_catalog
|
||||||
self._req_auth_version = auth_version
|
self._req_auth_version = auth_version
|
||||||
|
|
||||||
# where to find the auth service (we use this to validate tokens)
|
|
||||||
self._identity_uri = identity_uri
|
|
||||||
self.auth_uri = auth_uri
|
|
||||||
|
|
||||||
self._session = session
|
self._session = session
|
||||||
|
|
||||||
if self.auth_uri is None:
|
if auth_uri is None:
|
||||||
self._LOG.warning(
|
self._LOG.warning(
|
||||||
'Configuring auth_uri to point to the public identity '
|
'Configuring auth_uri to point to the public identity '
|
||||||
'endpoint is required; clients may not be able to '
|
'endpoint is required; clients may not be able to '
|
||||||
|
@ -1371,11 +1412,15 @@ class _IdentityServer(object):
|
||||||
|
|
||||||
# FIXME(dolph): drop support for this fallback behavior as
|
# FIXME(dolph): drop support for this fallback behavior as
|
||||||
# documented in bug 1207517.
|
# documented in bug 1207517.
|
||||||
# NOTE(jamielennox): we urljoin '/' to get just the base URI as
|
auth_uri = session.get_endpoint(interface=auth.AUTH_INTERFACE)
|
||||||
# this is the original behaviour.
|
|
||||||
self.auth_uri = urllib.parse.urljoin(self._identity_uri, '/')
|
|
||||||
self.auth_uri = self.auth_uri.rstrip('/')
|
|
||||||
|
|
||||||
|
# NOTE(jamielennox): This weird stripping of the prefix hack is
|
||||||
|
# only relevant to the legacy case. We urljoin '/' to get just the
|
||||||
|
# base URI as this is the original behaviour.
|
||||||
|
if isinstance(session.auth, _AuthTokenPlugin):
|
||||||
|
auth_uri = urllib.parse.urljoin(auth_uri, '/').rstrip('/')
|
||||||
|
|
||||||
|
self.auth_uri = auth_uri
|
||||||
self._auth_version = None
|
self._auth_version = None
|
||||||
self._http_request_max_retries = http_request_max_retries
|
self._http_request_max_retries = http_request_max_retries
|
||||||
|
|
||||||
|
@ -1519,13 +1564,16 @@ class _IdentityServer(object):
|
||||||
:raise ServerError when unable to communicate with keystone
|
:raise ServerError when unable to communicate with keystone
|
||||||
|
|
||||||
"""
|
"""
|
||||||
url = '%s/%s' % (self._identity_uri, path.lstrip('/'))
|
|
||||||
|
|
||||||
RETRIES = self._http_request_max_retries
|
RETRIES = self._http_request_max_retries
|
||||||
retry = 0
|
retry = 0
|
||||||
|
|
||||||
|
endpoint_filter = kwargs.setdefault('endpoint_filter', {})
|
||||||
|
endpoint_filter.setdefault('service_type', 'identity')
|
||||||
|
endpoint_filter.setdefault('interface', 'admin')
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
response = self._session.request(url, method, **kwargs)
|
response = self._session.request(path, method, **kwargs)
|
||||||
break
|
break
|
||||||
except exceptions.HTTPError:
|
except exceptions.HTTPError:
|
||||||
# NOTE(hrybacki): unlike the requests library that return
|
# NOTE(hrybacki): unlike the requests library that return
|
||||||
|
|
|
@ -22,7 +22,9 @@ import keystonemiddleware.auth_token
|
||||||
|
|
||||||
|
|
||||||
auth_token_opts = [
|
auth_token_opts = [
|
||||||
('keystone_authtoken', keystonemiddleware.auth_token._OPTS)
|
(keystonemiddleware.auth_token._AUTHTOKEN_GROUP,
|
||||||
|
keystonemiddleware.auth_token._OPTS +
|
||||||
|
keystonemiddleware.auth_token._AuthTokenPlugin.get_options())
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
import calendar
|
import calendar
|
||||||
import datetime
|
import datetime
|
||||||
import json
|
import json
|
||||||
|
import logging
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
import stat
|
import stat
|
||||||
|
@ -24,6 +25,7 @@ import uuid
|
||||||
|
|
||||||
import fixtures
|
import fixtures
|
||||||
from keystoneclient import access
|
from keystoneclient import access
|
||||||
|
from keystoneclient import auth
|
||||||
from keystoneclient.common import cms
|
from keystoneclient.common import cms
|
||||||
from keystoneclient import exceptions
|
from keystoneclient import exceptions
|
||||||
from keystoneclient import fixture
|
from keystoneclient import fixture
|
||||||
|
@ -633,7 +635,7 @@ class GeneralAuthTokenMiddlewareTest(BaseAuthTokenMiddlewareTest,
|
||||||
middleware._token_revocation_list_cache_timeout)
|
middleware._token_revocation_list_cache_timeout)
|
||||||
self.assertEqual(False, middleware._include_service_catalog)
|
self.assertEqual(False, middleware._include_service_catalog)
|
||||||
self.assertEqual('https://keystone.example.com:1234',
|
self.assertEqual('https://keystone.example.com:1234',
|
||||||
middleware._identity_uri)
|
middleware._session.auth._identity_uri)
|
||||||
self.assertEqual('0', middleware._conf['nonexsit_option'])
|
self.assertEqual('0', middleware._conf['nonexsit_option'])
|
||||||
|
|
||||||
def test_conf_values_type_convert_with_wrong_value(self):
|
def test_conf_values_type_convert_with_wrong_value(self):
|
||||||
|
@ -2407,5 +2409,85 @@ class v3CompositeAuthTests(BaseAuthTokenMiddlewareTest,
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
class DefaultAuthPluginTests(testtools.TestCase):
|
||||||
|
|
||||||
|
def new_plugin(self, auth_host=None, auth_port=None, auth_protocol=None,
|
||||||
|
auth_admin_prefix=None, admin_user=None,
|
||||||
|
admin_password=None, admin_tenant_name=None,
|
||||||
|
admin_token=None, identity_uri=None, log=None):
|
||||||
|
if not log:
|
||||||
|
log = self.logger
|
||||||
|
|
||||||
|
return auth_token._AuthTokenPlugin.load_from_options(
|
||||||
|
auth_host=auth_host,
|
||||||
|
auth_port=auth_port,
|
||||||
|
auth_protocol=auth_protocol,
|
||||||
|
auth_admin_prefix=auth_admin_prefix,
|
||||||
|
admin_user=admin_user,
|
||||||
|
admin_password=admin_password,
|
||||||
|
admin_tenant_name=admin_tenant_name,
|
||||||
|
admin_token=admin_token,
|
||||||
|
identity_uri=identity_uri,
|
||||||
|
log=log)
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(DefaultAuthPluginTests, self).setUp()
|
||||||
|
|
||||||
|
self.stream = six.StringIO()
|
||||||
|
self.logger = logging.getLogger(__name__)
|
||||||
|
self.session = session.Session()
|
||||||
|
self.requests = self.useFixture(rm_fixture.Fixture())
|
||||||
|
|
||||||
|
def test_auth_uri_from_fragments(self):
|
||||||
|
auth_protocol = 'http'
|
||||||
|
auth_host = 'testhost'
|
||||||
|
auth_port = 8888
|
||||||
|
auth_admin_prefix = 'admin'
|
||||||
|
|
||||||
|
expected = '%s://%s:%d/admin' % (auth_protocol, auth_host, auth_port)
|
||||||
|
|
||||||
|
plugin = self.new_plugin(auth_host=auth_host,
|
||||||
|
auth_protocol=auth_protocol,
|
||||||
|
auth_port=auth_port,
|
||||||
|
auth_admin_prefix=auth_admin_prefix)
|
||||||
|
|
||||||
|
self.assertEqual(expected,
|
||||||
|
plugin.get_endpoint(self.session,
|
||||||
|
interface=auth.AUTH_INTERFACE))
|
||||||
|
|
||||||
|
def test_identity_uri_overrides_fragments(self):
|
||||||
|
identity_uri = 'http://testhost:8888/admin'
|
||||||
|
plugin = self.new_plugin(identity_uri=identity_uri,
|
||||||
|
auth_host='anotherhost',
|
||||||
|
auth_port=9999,
|
||||||
|
auth_protocol='ftp')
|
||||||
|
|
||||||
|
self.assertEqual(identity_uri,
|
||||||
|
plugin.get_endpoint(self.session,
|
||||||
|
interface=auth.AUTH_INTERFACE))
|
||||||
|
|
||||||
|
def test_with_admin_token(self):
|
||||||
|
token = uuid.uuid4().hex
|
||||||
|
plugin = self.new_plugin(identity_uri='http://testhost:8888/admin',
|
||||||
|
admin_token=token)
|
||||||
|
self.assertEqual(token, plugin.get_token(self.session))
|
||||||
|
|
||||||
|
def test_with_user_pass(self):
|
||||||
|
base_uri = 'http://testhost:8888/admin'
|
||||||
|
token = fixture.V2Token()
|
||||||
|
admin_tenant_name = uuid.uuid4().hex
|
||||||
|
|
||||||
|
self.requests.register_uri('POST',
|
||||||
|
base_uri + '/v2.0/tokens',
|
||||||
|
json=token)
|
||||||
|
|
||||||
|
plugin = self.new_plugin(identity_uri=base_uri,
|
||||||
|
admin_user=uuid.uuid4().hex,
|
||||||
|
admin_password=uuid.uuid4().hex,
|
||||||
|
admin_tenant_name=admin_tenant_name)
|
||||||
|
|
||||||
|
self.assertEqual(token.token_id, plugin.get_token(self.session))
|
||||||
|
|
||||||
|
|
||||||
def load_tests(loader, tests, pattern):
|
def load_tests(loader, tests, pattern):
|
||||||
return testresources.OptimisingTestSuite(tests)
|
return testresources.OptimisingTestSuite(tests)
|
||||||
|
|
Loading…
Reference in New Issue