def keystone_auth(self, user, password, auth_url, service, tenant_name): """ Provides authentication via Keystone using v2 identity API. """ # Normalize URI to ensure /tokens is in it. if 'tokens' not in auth_url: auth_url = auth_url.rstrip('/') + '/tokens' creds = { 'auth': { 'passwordCredentials': { 'username': user, 'password': password, }, 'tenantName': tenant_name, } } headers = {'Content-Type': 'application/json'} body = json.dumps(creds) self._log_request('POST', auth_url, headers, body) resp, resp_body = self.http_obj.request(auth_url, 'POST', headers=headers, body=body) self._log_response(resp, resp_body) if resp.status == 200: try: auth_data = json.loads(resp_body)['access'] token = auth_data['token']['id'] except Exception as e: print("Failed to obtain token for user: %s" % e) raise mgmt_url = None for ep in auth_data['serviceCatalog']: if ep["type"] == service: for _ep in ep['endpoints']: if service in self.region and \ _ep['region'] == self.region[service]: mgmt_url = _ep[self.endpoint_url] if not mgmt_url: mgmt_url = ep['endpoints'][0][self.endpoint_url] break if mgmt_url is None: raise exceptions.EndpointNotFound(service) return token, mgmt_url elif resp.status == 401: raise exceptions.AuthenticationFailure(user=user, password=password, tenant=tenant_name) raise exceptions.IdentityError('Unexpected status code {0}'.format( resp.status))
def identity_auth_v3(self, user, password, auth_url, service, project_name, domain_id='default'): """Provides authentication using Identity API v3.""" req_url = auth_url.rstrip('/') + '/auth/tokens' creds = { "auth": { "identity": { "methods": ["password"], "password": { "user": { "name": user, "password": password, "domain": { "id": domain_id } } } }, "scope": { "project": { "domain": { "id": domain_id }, "name": project_name } } } } headers = {'Content-Type': 'application/json'} body = json.dumps(creds) resp, body = self.http_obj.request(req_url, 'POST', headers=headers, body=body) if resp.status == 201: try: token = resp['x-subject-token'] except Exception: self.LOG.exception("Failed to obtain token using V3" " authentication (auth URL is '%s')" % req_url) raise catalog = json.loads(body)['token']['catalog'] mgmt_url = None for service_info in catalog: if service_info['type'] != service: continue # this isn't the entry for us. endpoints = service_info['endpoints'] # Look for an endpoint in the region if configured. if service in self.region: region = self.region[service] for ep in endpoints: if ep['region'] != region: continue mgmt_url = ep['url'] # FIXME(blk-u): this isn't handling endpoint type # (public, internal, admin). break if not mgmt_url: # Didn't find endpoint for region, use the first. ep = endpoints[0] mgmt_url = ep['url'] # FIXME(blk-u): this isn't handling endpoint type # (public, internal, admin). break return token, mgmt_url elif resp.status == 401: raise exceptions.AuthenticationFailure(user=user, password=password) else: self.LOG.error("Failed to obtain token using V3 authentication" " (auth URL is '%s'), the response status is %s" % (req_url, resp.status)) raise exceptions.AuthenticationFailure(user=user, password=password)
class RestClient(object): TYPE = "json" LOG = logging.getLogger(__name__) def __init__(self, config, user, password, auth_url, tenant_name=None): self.config = config self.user = user self.password = password self.auth_url = auth_url self.tenant_name = tenant_name self.service = None self.token = None self.base_url = None self.region = {'compute': self.config.identity.region} self.endpoint_url = 'publicURL' self.strategy = self.config.identity.strategy self.headers = { 'Content-Type': 'application/%s' % self.TYPE, 'Accept': 'application/%s' % self.TYPE } self.build_interval = config.compute.build_interval self.build_timeout = config.compute.build_timeout self.general_header_lc = set( ('cache-control', 'connection', 'date', 'pragma', 'trailer', 'transfer-encoding', 'via', 'warning')) self.response_header_lc = set( ('accept-ranges', 'age', 'etag', 'location', 'proxy-authenticate', 'retry-after', 'server', 'vary', 'www-authenticate')) dscv = self.config.identity.disable_ssl_certificate_validation self.http_obj = httplib2.Http(disable_ssl_certificate_validation=dscv) def _set_auth(self): """ Sets the token and base_url used in requests based on the strategy type """ if self.strategy == 'keystone': self.token, self.base_url = self.keystone_auth( self.user, self.password, self.auth_url, self.service, self.tenant_name) else: self.token, self.base_url = self.basic_auth( self.user, self.password, self.auth_url) def clear_auth(self): """ Can be called to clear the token and base_url so that the next request will fetch a new token and base_url. """ self.token = None self.base_url = None def get_auth(self): """Returns the token of the current request or sets the token if none. """ if not self.token: self._set_auth() return self.token def basic_auth(self, user, password, auth_url): """ Provides authentication for the target API. """ params = {} params['headers'] = { 'User-Agent': 'Test-Client', 'X-Auth-User': user, 'X-Auth-Key': password } resp, body = self.http_obj.request(auth_url, 'GET', **params) try: return resp['x-auth-token'], resp['x-server-management-url'] except Exception: raise def keystone_auth(self, user, password, auth_url, service, tenant_name): """ Provides authentication via Keystone. """ # Normalize URI to ensure /tokens is in it. if 'tokens' not in auth_url: auth_url = auth_url.rstrip('/') + '/tokens' creds = { 'auth': { 'passwordCredentials': { 'username': user, 'password': password, }, 'tenantName': tenant_name, } } headers = {'Content-Type': 'application/json'} body = json.dumps(creds) self._log_request('POST', auth_url, headers, body) resp, resp_body = self.http_obj.request(auth_url, 'POST', headers=headers, body=body) self._log_response(resp, resp_body) if resp.status == 200: try: auth_data = json.loads(resp_body)['access'] token = auth_data['token']['id'] except Exception, e: print "Failed to obtain token for user: %s" % e raise mgmt_url = None for ep in auth_data['serviceCatalog']: if ep["type"] == service: for _ep in ep['endpoints']: if service in self.region and \ _ep['region'] == self.region[service]: mgmt_url = _ep[self.endpoint_url] if not mgmt_url: mgmt_url = ep['endpoints'][0][self.endpoint_url] break if mgmt_url is None: raise exceptions.EndpointNotFound(service) return token, mgmt_url elif resp.status == 401: raise exceptions.AuthenticationFailure(user=user, password=password)
class RestClient(object): def __init__(self, config, user, key, auth_url, tenant_name=None): self.config = config if self.config.env.authentication == 'keystone_v2': self.token, self.base_url = self.keystone_v2_auth( user, key, auth_url, tenant_name) else: self.token, self.base_url = self.basic_auth(user, key, auth_url) def basic_auth(self, user, api_key, auth_url): """ Provides authentication for the target API """ params = {} params['headers'] = { 'User-Agent': 'Test-Client', 'X-Auth-User': user, 'X-Auth-Key': api_key } self.http_obj = httplib2.Http() resp, body = self.http_obj.request(auth_url, 'GET', **params) try: return resp['x-auth-token'], resp['x-server-management-url'] except: raise def keystone_v2_auth(self, user, api_key, auth_url, tenant_name): """ Provides authentication via Keystone 2.0 """ creds = { 'auth': { 'passwordCredentials': { 'username': user, 'password': api_key, }, 'tenantName': tenant_name } } self.http_obj = httplib2.Http() headers = {'Content-Type': 'application/json'} body = json.dumps(creds) resp, body = self.http_obj.request(auth_url, 'POST', headers=headers, body=body) if resp.status == 200: try: auth_data = json.loads(body)['access'] token = auth_data['token']['id'] endpoints = auth_data['serviceCatalog'][0]['endpoints'] mgmt_url = endpoints[0]['publicURL'] #TODO (dwalleck): This is a horrible stopgap. #Need to join strings more cleanly temp = mgmt_url.rsplit('/') service_url = temp[0] + '//' + temp[2] + '/' + temp[3] + '/' management_url = service_url + tenant_name return token, management_url except Exception, e: print "Failed to authenticate user: %s" % e raise elif resp.status == 401: raise exceptions.AuthenticationFailure(user=user, password=api_key)
class RestClient(object): TYPE = "json" def __init__(self, config, user, password, auth_url, tenant_name=None): self.log = logging.getLogger(__name__) self.log.setLevel(getattr(logging, config.compute.log_level)) self.config = config self.user = user self.password = password self.auth_url = auth_url self.tenant_name = tenant_name self.service = None self.token = None self.base_url = None self.config = config self.region = 0 self.endpoint_url = 'publicURL' self.strategy = self.config.identity.strategy self.headers = { 'Content-Type': 'application/%s' % self.TYPE, 'Accept': 'application/%s' % self.TYPE } self.build_interval = config.compute.build_interval self.build_timeout = config.compute.build_timeout def _set_auth(self): """ Sets the token and base_url used in requests based on the strategy type """ if self.strategy == 'keystone': self.token, self.base_url = self.keystone_auth( self.user, self.password, self.auth_url, self.service, self.tenant_name) else: self.token, self.base_url = self.basic_auth( self.user, self.password, self.auth_url) def clear_auth(self): """ Can be called to clear the token and base_url so that the next request will fetch a new token and base_url """ self.token = None self.base_url = None def get_auth(self): """Returns the token of the current request or sets the token if none""" if not self.token: self._set_auth() return self.token def basic_auth(self, user, password, auth_url): """ Provides authentication for the target API """ params = {} params['headers'] = { 'User-Agent': 'Test-Client', 'X-Auth-User': user, 'X-Auth-Key': password } self.http_obj = httplib2.Http() resp, body = self.http_obj.request(auth_url, 'GET', **params) try: return resp['x-auth-token'], resp['x-server-management-url'] except: raise def keystone_auth(self, user, password, auth_url, service, tenant_name): """ Provides authentication via Keystone """ creds = { 'auth': { 'passwordCredentials': { 'username': user, 'password': password, }, 'tenantName': tenant_name } } self.http_obj = httplib2.Http() headers = {'Content-Type': 'application/json'} body = json.dumps(creds) resp, body = self.http_obj.request(auth_url, 'POST', headers=headers, body=body) if resp.status == 200: try: auth_data = json.loads(body)['access'] token = auth_data['token']['id'] except Exception, e: print "Failed to obtain token for user: %s" % e raise mgmt_url = None for ep in auth_data['serviceCatalog']: if ep["type"] == service: mgmt_url = ep['endpoints'][self.region][self.endpoint_url] tenant_id = auth_data['token']['tenant']['id'] break if mgmt_url == None: raise exceptions.EndpointNotFound(service) if service == 'network': # Keystone does not return the correct endpoint for # quantum. Handle this separately. mgmt_url = mgmt_url + self.config.network.api_version + \ "/tenants/" + tenant_id return token, mgmt_url elif resp.status == 401: raise exceptions.AuthenticationFailure(user=user, password=password)