From b7bf43c73001651b13adae2668a12565b38c7a8f Mon Sep 17 00:00:00 2001 From: Yves-Gwenael Bourhis Date: Fri, 30 May 2014 16:12:49 +0200 Subject: [PATCH] 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 --- openstack_auth/backend.py | 4 ++-- openstack_auth/utils.py | 27 +++++++++++++++++++++++++-- openstack_auth/views.py | 4 ++-- 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/openstack_auth/backend.py b/openstack_auth/backend.py index 3cbd91f0..88121d58 100644 --- a/openstack_auth/backend.py +++ b/openstack_auth/backend.py @@ -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: diff --git a/openstack_auth/utils.py b/openstack_auth/utils.py index f6da16d1..a8c2ff50 100644 --- a/openstack_auth/utils.py +++ b/openstack_auth/utils.py @@ -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 diff --git a/openstack_auth/views.py b/openstack_auth/views.py index 4ce09b7f..361d22f8 100644 --- a/openstack_auth/views.py +++ b/openstack_auth/views.py @@ -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,