Joe Heck f1cc3cfc42 removing repeat attempt at authorization in client
blueprint solidify-python-api

* extended and updated documentation strings
* updated README.rst with latest options
* made debug a pass-through value, optionally set on client (instead of
  just being pulled from environment variable)
* adding AccessInfo object and associated tests
  (access.AccessInfo meant to be a cacheable object external to client
  and ultimately to replace service_catalog and it's existing functionality)
* extending authtoken to support lists of endpoints
* maintaining a single entity for client.management_url with first from
  list of possible endpoints
* create project_name and project_id synonyms to match tenant_name and
  tenant_id
* replacing authenticate call to a pure method, not overloading the
  resource/manager path that confuses base URL concepts.
* throw AuthorizationFailure if client attempts to access keystone
  resources before it has a management url
* special case listing tenant using auth_url for unscoped tokens authorized
  through client
* special case listing tokens.authenticate for Dashboard to allow unscoped
  tokens to hand back parity information to dashboard

Change-Id: I4bb3a1b6a5ce2c4b3fbcebeb59116286cac8b2e3
2012-11-09 00:02:41 +00:00

145 lines
4.7 KiB
Python

# Copyright 2012 Nebula, Inc.
#
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
class AccessInfo(dict):
"""An object for encapsulating a raw authentication token from keystone
and helper methods for extracting useful values from that token."""
def __init__(self, *args, **kwargs):
dict.__init__(self, *args, **kwargs)
@property
def auth_token(self):
""" Returns the token_id associated with the auth request, to be used
in headers for authenticating OpenStack API requests.
:returns: str
"""
return self['token'].get('id', None)
@property
def username(self):
""" Returns the username associated with the authentication request.
Follows the pattern defined in the V2 API of first looking for 'name',
returning that if available, and falling back to 'username' if name
is unavailable.
:returns: str
"""
name = self['user'].get('name', None)
if name:
return name
else:
return self['user'].get('username', None)
@property
def user_id(self):
""" Returns the user id associated with the authentication request.
:returns: str
"""
return self['user'].get('id', None)
@property
def tenant_name(self):
""" Returns the tenant (project) name associated with the
authentication request.
:returns: str
"""
tenant_dict = self['token'].get('tenant', None)
if tenant_dict:
return tenant_dict.get('name', None)
return None
@property
def project_name(self):
""" Synonym for tenant_name """
return self.tenant_name
@property
def scoped(self):
""" Returns true if the authorization token was scoped to a tenant
(project), and contains a populated service catalog.
:returns: bool
"""
if ('serviceCatalog' in self
and self['serviceCatalog']
and 'tenant' in self['token']):
return True
return False
@property
def tenant_id(self):
""" Returns the tenant (project) id associated with the authentication
request, or None if the authentication request wasn't scoped to a
tenant (project).
:returns: str
"""
tenant_dict = self['token'].get('tenant', None)
if tenant_dict:
return tenant_dict.get('id', None)
return None
@property
def project_id(self):
""" Synonym for project_id """
return self.tenant_id
@property
def auth_url(self):
""" Returns a tuple of URLs from publicURL and adminURL for the service
'identity' from the service catalog associated with the authorization
request. If the authentication request wasn't scoped to a tenant
(project), this property will return None.
:returns: tuple of urls
"""
return_list = []
if 'serviceCatalog' in self and self['serviceCatalog']:
identity_services = [x for x in self['serviceCatalog']
if x['type'] == 'identity']
for svc in identity_services:
for endpoint in svc['endpoints']:
if 'publicURL' in endpoint:
return_list.append(endpoint['publicURL'])
if len(return_list) > 0:
return tuple(return_list)
return None
@property
def management_url(self):
""" Returns the first adminURL for 'identity' from the service catalog
associated with the authorization request, or None if the
authentication request wasn't scoped to a tenant (project).
:returns: tuple of urls
"""
return_list = []
if 'serviceCatalog' in self and self['serviceCatalog']:
identity_services = [x for x in self['serviceCatalog']
if x['type'] == 'identity']
for svc in identity_services:
for endpoint in svc['endpoints']:
if 'adminURL' in endpoint:
return_list.append(endpoint['adminURL'])
if len(return_list) > 0:
return tuple(return_list)
return None