def setup_connection(endpoint, auth_data, resolved_node_definition): """ Setup the connection to the Nova endpoint. """ project_id = resolved_node_definition['resource'].get('project_id', None) user_domain_name = resolved_node_definition['resource'].get( 'user_domain_name', 'Default') region_name = resolved_node_definition['resource'].get('region_name', None) auth_type = auth_data.get('type', None) if auth_type is None: user = auth_data['username'] password = auth_data['password'] auth = v3.Password(auth_url=endpoint, username=user, password=password, project_id=project_id, user_domain_name=user_domain_name) sess = session.Session(auth=auth) elif auth_type == 'application_credential': cred_id = auth_data['id'] cred_secret = auth_data['secret'] auth = v3.ApplicationCredential( auth_url=endpoint, application_credential_secret=cred_secret, application_credential_id=cred_id) sess = session.Session(auth=auth) else: raise NodeCreationError( None, 'Unknown authentication type provided: "%s"' % auth_type) os = connection.Connection(session=sess, region_name=region_name) return os
def _get_auth(self): if self.cloud_auth["domain_name"]: if self.cloud_auth["auth_type"] == 'password': kwargs = { 'auth_url': self.cloud_auth["auth_url"], 'username': self.cloud_auth["username"], 'password': self.cloud_auth["password"], 'user_domain_name': self.cloud_auth["domain_name"] } if self.unscoped: kwargs['unscoped'] = self.unscoped else: kwargs['project_id'] = self.cloud_auth["project_id"] return v3.Password(**kwargs) else: access_key = \ self.cloud_auth.application_credential_secret access_key_id = \ self.cloud_auth.application_credential_id kwargs = { 'auth_url': self.cloud_auth.auth_url, 'application_credential_secret': access_key, 'application_credential_id': access_key_id } return v3.ApplicationCredential(**kwargs) else: kwargs = { 'auth_url': self.cloud_auth.auth_url, 'username': self.cloud_auth.username, 'password': self.cloud_auth.password, 'tenant_id': self.cloud_auth.project_id } return v2.Password(**kwargs)
def _get_new_session(self): try: auth = keystoneidentity.ApplicationCredential( auth_url=self.auth_url, application_credential_secret=self.app_secret, application_credential_id=self.app_id, ) except KeyError as err: logging.error( "Error reading application credentials: {}".format(err)) return None return keystonesession.Session(auth=auth, timeout=self.DEFAULT_TIMEOUT)
def test_application_credential_method(self): self.stub_auth(json=self.TEST_APP_CRED_TOKEN_RESPONSE) ac = v3.ApplicationCredential( self.TEST_URL, application_credential_id=self.TEST_APP_CRED_ID, application_credential_secret=self.TEST_APP_CRED_SECRET) req = {'auth': {'identity': {'methods': ['application_credential'], 'application_credential': { 'id': self.TEST_APP_CRED_ID, 'secret': self.TEST_APP_CRED_SECRET}}}} s = session.Session(auth=ac) self.assertEqual({'X-Auth-Token': self.TEST_TOKEN}, s.get_auth_headers()) self.assertRequestBodyIs(json=req) self.assertEqual(s.auth.auth_ref.auth_token, self.TEST_TOKEN)
def get_connection(self, auth_url, region_name, project_id, user_domain_name): """Create OpenStack connection. Args: auth_url (string): Authentication URL for the NOVA resource. region_name (string, optional): Name of the region resource. Defaults to None. project_id (string, optional): ID of the project resource. Defaults to None. user_domain_name (string, optional): Define the user_domain_name. Defaults to 'Default' Raises: Exception: Project ID missing Returns: tuple: OpenStackSDK connection, and nova_client Connection """ auth_data = self.get_credentials() if auth_data[2]: app_cred_id = auth_data[0] app_cred_secret = auth_data[1] auth = v3.ApplicationCredential( auth_url, application_credential_id=app_cred_id, application_credential_secret=app_cred_secret) else: if project_id is None: raise Exception('Project ID is missing!') user = auth_data[0] password = auth_data[1] auth = v3.Password(auth_url=auth_url, username=user, password=password, user_domain_name=user_domain_name, project_id=project_id) sess = session.Session(auth=auth) return connection.Connection( region_name=region_name, session=sess, compute_api_version='2', identity_interface='public'), nova_client.Client( 2, session=sess, region_name=region_name)
def join(): """Authorize a client node and return relevant config.""" # Retrieve an API version from the request - it is a mandatory # header for this API. request_version = request.headers.get('API-Version') if request_version is None: logger.debug('The client has not specified the API-version header.') raise APIVersionMissing() else: try: api_version = semantic_version.Version(request_version) except ValueError: logger.debug('The client has specified an invalid API version.' f': {request_version}') raise APIVersionInvalid() # Compare the API version used by the clustering service with the # one specified in the request and return an appropriate response. if api_version.major > API_VERSION.major: logger.debug('The client requested a version that is not' f' supported yet: {api_version}.') raise APIVersionNotImplemented() elif api_version.major < API_VERSION.major: logger.debug('The client request version is no longer supported' f': {api_version}.') raise APIVersionDropped() else: # Flask raises a BadRequest if the JSON content is invalid and # returns None if the Content-Type header is missing or not set # to application/json. try: req_json = request.json except BadRequest: logger.debug('The client has POSTed an invalid JSON' ' in the request.') raise InvalidJSONInRequest() if req_json is None: logger.debug('The client has not specified the application/json' ' content type in the request.') raise IncorrectContentType() # So far we don't have any minor versions with backwards-compatible # changes so just assume that all data will be present or error out. credential_id = req_json.get('credential-id') credential_secret = req_json.get('credential-secret') if not credential_id or not credential_secret: logger.debug('The client has not specified the required' ' authentication data in the request.') return MissingAuthDataInRequest() # TODO: handle https here when TLS termination support is added. keystone_base_url = 'http://localhost:5000/v3' # In an unlikely event of failing to construct an auth object # treat it as if invalid data got passed in terms of responding # to the client. try: auth = v3.ApplicationCredential( auth_url=keystone_base_url, application_credential_id=credential_id, application_credential_secret=credential_secret) except Exception: logger.exception('An exception has occurred while trying to build' ' an auth object for an application credential' ' passed from the clustering client.') raise InvalidAuthDataInRequest() try: # Use the auth object with the app credential to create a session # which the Keystone client will use. sess = session.Session(auth=auth) except Exception: logger.exception('An exception has occurred while trying to build' ' a Session object with auth data' ' passed from the clustering client.') raise UnexpectedError() try: keystone_client = v3client.Client(session=sess) except Exception: logger.exception('An exception has occurred while trying to build' ' a Keystone Client object with auth data' ' passed from the clustering client.') raise UnexpectedError() try: # The add-compute command creates application credentials that # allow access to /v3/auth/catalog with an expiration time. # Authorization failures occur after an app credential expires # in which case an error is returned to the client. keystone_client.get(f'{keystone_base_url}/auth/catalog') except (kc_exceptions.AuthorizationFailure, kc_exceptions.Unauthorized): logger.exception('Failed to get a Keystone token' ' with the application credentials' ' passed from the clustering client.') raise AuthorizationFailed() except ValueError: logger.exception('Insufficient amount of parameters were' ' used in the request to Keystone.') raise UnexpectedError() except kc_exceptions.ConnectionError: logger.exception('Failed to connect to Keystone') raise UnexpectedError() except kc_exceptions.SSLError: logger.exception('A TLS-related error has occurred while' ' connecting to Keystone') raise UnexpectedError() # We were able to authenticate against Keystone using the # application credential and verify that it has not expired # so the information for a compute node to join the cluster can # now be returned. return json.dumps(join_info())