Updated parsing of catalog to handle bad format

Don't assume that the service catalog is well-formed, added code
to safely parsing the catalog.

Parsing of region from service catalog has been fixed as well.
'region' has been deprecated in the Keystone V3 catalog in favor of
'region_id'. Fix how region is extracted by checking 'region_id' then
fallback to 'region'.

Change-Id: I7b649a8b90e20caa2d04fdd3f79b5b1ac775237c
Closes-Bug: #1424825
This commit is contained in:
lin-hua-cheng 2015-02-25 16:33:22 -08:00
parent 09611a3d3c
commit 7ec44e898b
3 changed files with 45 additions and 22 deletions

View File

@ -215,11 +215,19 @@ class KeystoneBackend(object):
# when supported by Keystone. # when supported by Keystone.
role_perms = set(["openstack.roles.%s" % role['name'].lower() role_perms = set(["openstack.roles.%s" % role['name'].lower()
for role in user.roles]) for role in user.roles])
service_perms = set(["openstack.services.%s" % service['type'].lower()
for service in user.service_catalog services = []
if user.services_region in for service in user.service_catalog:
[endpoint.get('region', None) for endpoint try:
in service.get('endpoints', [])]]) service_type = service['type']
except KeyError:
continue
service_regions = [utils.get_endpoint_region(endpoint) for endpoint
in service.get('endpoints', [])]
if user.services_region in service_regions:
services.append(service_type.lower())
service_perms = set(["openstack.services.%s" % service
for service in services])
return role_perms | service_perms return role_perms | service_perms
def has_perm(self, user, perm, obj=None): def has_perm(self, user, perm, obj=None):

View File

@ -113,10 +113,7 @@ class Token(object):
else: else:
self.roles = auth_ref.get('roles', []) self.roles = auth_ref.get('roles', [])
if utils.get_keystone_version() < 3: self.serviceCatalog = auth_ref.service_catalog.get_data()
self.serviceCatalog = auth_ref.get('serviceCatalog', [])
else:
self.serviceCatalog = auth_ref.get('catalog', [])
class User(models.AnonymousUser): class User(models.AnonymousUser):
@ -331,11 +328,13 @@ class User(models.AnonymousUser):
regions = [] regions = []
if self.service_catalog: if self.service_catalog:
for service in self.service_catalog: for service in self.service_catalog:
if service['type'] == 'identity': service_type = service.get('type')
if service_type is None or service_type == 'identity':
continue continue
for endpoint in service['endpoints']: for endpoint in service.get('endpoints', []):
if endpoint['region'] not in regions: region = utils.get_endpoint_region(endpoint)
regions.append(endpoint['region']) if region not in regions:
regions.append(region)
return regions return regions
def save(*args, **kwargs): def save(*args, **kwargs):

View File

@ -260,20 +260,24 @@ def default_services_region(service_catalog, request=None):
Extracted from the service catalog. Extracted from the service catalog.
""" """
if service_catalog: if service_catalog:
available_regions = [endpoint['region'] for service available_regions = [get_endpoint_region(endpoint) for service
in service_catalog for endpoint in service_catalog for endpoint
in service['endpoints'] in service.get('endpoints', [])
if service['type'] != 'identity'] if (service.get('type') is not None
and service.get('type') != 'identity')]
if not available_regions: if not available_regions:
# this is very likely an incomplete keystone setup # this is very likely an incomplete keystone setup
LOG.warning('No regions could be found excluding identity.') LOG.warning('No regions could be found excluding identity.')
available_regions = [endpoint['region'] for service available_regions = [get_endpoint_region(endpoint) for service
in service_catalog for endpoint in service_catalog for endpoint
in service['endpoints']] in service.get('endpoints', [])]
if not available_regions:
# this is a critical problem and it's not clear how this occurs if not available_regions:
LOG.error('No regions can be found in the service catalog.') # if there are no region setup for any service endpoint,
return None # this is a critical problem and it's not clear how this occurs
LOG.error('No regions can be found in the service catalog.')
return None
selected_region = None selected_region = None
if request: if request:
selected_region = request.COOKIES.get('services_region', selected_region = request.COOKIES.get('services_region',
@ -297,6 +301,18 @@ def set_response_cookie(response, cookie_name, cookie_value):
response.set_cookie(cookie_name, cookie_value, expires=expire_date) response.set_cookie(cookie_name, cookie_value, expires=expire_date)
def get_endpoint_region(endpoint):
"""Common function for getting the region from endpoint.
In Keystone V3, region has been deprecated in favor of
region_id.
This method provides a way to get region that works for both
Keystone V2 and V3.
"""
return endpoint.get('region_id') or endpoint.get('region')
if django.VERSION < (1, 7): if django.VERSION < (1, 7):
try: try:
from importlib import import_module from importlib import import_module