diff --git a/openstack_auth/backend.py b/openstack_auth/backend.py index 362855cb..46c32d40 100644 --- a/openstack_auth/backend.py +++ b/openstack_auth/backend.py @@ -215,11 +215,19 @@ class KeystoneBackend(object): # when supported by Keystone. role_perms = set(["openstack.roles.%s" % role['name'].lower() for role in user.roles]) - service_perms = set(["openstack.services.%s" % service['type'].lower() - for service in user.service_catalog - if user.services_region in - [endpoint.get('region', None) for endpoint - in service.get('endpoints', [])]]) + + services = [] + for service in user.service_catalog: + try: + 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 def has_perm(self, user, perm, obj=None): diff --git a/openstack_auth/user.py b/openstack_auth/user.py index 43336e55..811fe846 100644 --- a/openstack_auth/user.py +++ b/openstack_auth/user.py @@ -113,10 +113,7 @@ class Token(object): else: self.roles = auth_ref.get('roles', []) - if utils.get_keystone_version() < 3: - self.serviceCatalog = auth_ref.get('serviceCatalog', []) - else: - self.serviceCatalog = auth_ref.get('catalog', []) + self.serviceCatalog = auth_ref.service_catalog.get_data() class User(models.AnonymousUser): @@ -331,11 +328,13 @@ class User(models.AnonymousUser): regions = [] if 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 - for endpoint in service['endpoints']: - if endpoint['region'] not in regions: - regions.append(endpoint['region']) + for endpoint in service.get('endpoints', []): + region = utils.get_endpoint_region(endpoint) + if region not in regions: + regions.append(region) return regions def save(*args, **kwargs): diff --git a/openstack_auth/utils.py b/openstack_auth/utils.py index 198c8a08..d8610104 100644 --- a/openstack_auth/utils.py +++ b/openstack_auth/utils.py @@ -260,20 +260,24 @@ def default_services_region(service_catalog, request=None): Extracted from the 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['endpoints'] - if service['type'] != 'identity'] + in service.get('endpoints', []) + if (service.get('type') is not None + and service.get('type') != 'identity')] if not available_regions: # this is very likely an incomplete keystone setup 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['endpoints']] - if not available_regions: - # 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 + in service.get('endpoints', [])] + + if not available_regions: + # if there are no region setup for any service endpoint, + # 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 if request: 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) +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): try: from importlib import import_module