Added url_path_replace and has_in_url_path methods

utils.py, views.py and backend.py were using .replace('v3', 'v2.0') and
.replace('v2.0', 'v3') methods on url strings.
This is BAD because if you have v3 in your url's domain it brakes it.

A new url_path_replace method now only performs the replaces in the url path
and leaves the domain unchanged.

Some checks where performed to test if a substring was in the url path but the
tests where performed on the whole url and could return a false positive if the
substring exists in the domain name or in the query string.
The new has_in_url_path method checks only if the substring is in the path of
the url.

Change-Id: I030d928d83e5c91cf26101221649a299d146747d
Closes-Bug: 1324948
This commit is contained in:
Yves-Gwenael Bourhis 2014-05-30 16:12:49 +02:00
parent abfb9359d2
commit b7bf43c730
3 changed files with 29 additions and 6 deletions

View File

@ -77,11 +77,11 @@ class KeystoneBackend(object):
# keystone client v3 does not support logging in on the v2 url any more
if utils.get_keystone_version() >= 3:
if auth_url.find("v2.0") >= 0:
if utils.has_in_url_path(auth_url, "/v2.0"):
LOG.warning("The settings.py file points to a v2.0 keystone "
"endpoint, but v3 is specified as the API version "
"to use. Using v3 endpoint for authentication.")
auth_url = auth_url.replace('v2.0', 'v3')
auth_url = utils.url_path_replace(auth_url, "/v2.0", "/v3", 1)
keystone_client = utils.get_keystone_client()
try:

View File

@ -141,15 +141,38 @@ def get_keystone_client():
return client_v3
def has_in_url_path(url, sub):
"""Test if the `sub` string is in the `url` path."""
scheme, netloc, path, query, fragment = urlparse.urlsplit(url)
return sub in path
def url_path_replace(url, old, new, count=None):
"""Return a copy of url with replaced path.
Return a copy of url with all occurrences of old replaced by new in the url
path. If the optional argument count is given, only the first count
occurrences are replaced.
"""
args = []
scheme, netloc, path, query, fragment = urlparse.urlsplit(url)
if count is not None:
args.append(count)
return urlparse.urlunsplit((
scheme, netloc, path.replace(old, new, *args), query, fragment))
@memoize_by_keyword_arg(_PROJECT_CACHE, ('token', ))
def get_project_list(*args, **kwargs):
if get_keystone_version() < 3:
auth_url = kwargs.get('auth_url', '').replace('v3', 'v2.0')
auth_url = url_path_replace(
kwargs.get('auth_url', ''), '/v3', '/v2.0', 1)
kwargs['auth_url'] = auth_url
client = get_keystone_client().Client(*args, **kwargs)
projects = client.tenants.list()
else:
auth_url = kwargs.get('auth_url', '').replace('v2.0', 'v3')
auth_url = url_path_replace(
kwargs.get('auth_url', ''), '/v2.0', '/v3', 1)
kwargs['auth_url'] = auth_url
client = get_keystone_client().Client(*args, **kwargs)
client.management_url = auth_url

View File

@ -149,8 +149,8 @@ def switch(request, tenant_id, redirect_field_name=auth.REDIRECT_FIELD_NAME):
endpoint = request.user.endpoint
try:
if utils.get_keystone_version() >= 3:
if 'v3' not in endpoint:
endpoint = endpoint.replace('v2.0', 'v3')
if not utils.has_in_url_path(endpoint, '/v3'):
endpoint = utils.url_path_replace(endpoint, '/v2.0', '/v3', 1)
client = utils.get_keystone_client().Client(
tenant_id=tenant_id,
token=request.user.token.id,