def get_endpoint(self, session, interface=None, version=None, **kwargs): """Return an endpoint for the client. There are no required keyword arguments to ``get_endpoint`` as a plugin implementation should use best effort with the information available to determine the endpoint. :param session: The session object that the auth_plugin belongs to. :type session: keystoneauth1.session.Session :param version: The version number required for this endpoint. :type version: tuple or str :param str interface: what visibility the endpoint should have. :returns: The base URL that will be used to talk to the required service or None if not available. :rtype: string """ if interface == plugin.AUTH_INTERFACE: return self._identity_uri if not version: # NOTE(jamielennox): This plugin can only be used within auth_token # and auth_token will always provide version= with requests. return None if not self._discover: self._discover = discover.Discover(session, url=self._identity_uri, authenticated=False) if not self._discover.url_for(version): # NOTE(jamielennox): The requested version is not supported by the # identity server. return None # NOTE(jamielennox): for backwards compatibility here we don't # actually use the URL from discovery we hack it up instead. :( # NOTE(blk-u): Normalizing the version is a workaround for bug 1450272. # This can be removed once that's fixed. Also fix the docstring for the # version parameter to be just "tuple". version = discover.normalize_version_number(version) if discover.version_match((2, 0), version): return '%s/v2.0' % self._identity_uri elif discover.version_match((3, 0), version): return '%s/v3' % self._identity_uri # NOTE(jamielennox): This plugin will only get called from auth_token # middleware. The middleware should never request a version that the # plugin doesn't know how to handle. msg = _('Invalid version asked for in auth_token plugin') raise NotImplementedError(msg)
def pick_microversion(session, required): """Get a new microversion if it is higher than session's default. :param session: The session to use for making this request. :type session: :class:`~keystoneauth1.adapter.Adapter` :param required: Version that is required for an action. :type required: String or tuple or None. :return: ``required`` as a string if the ``session``'s default is too low, the ``session``'s default otherwise. Returns ``None`` of both are ``None``. :raises: TypeError if ``required`` is invalid. """ if required is not None: required = discover.normalize_version_number(required) if session.default_microversion is not None: default = discover.normalize_version_number( session.default_microversion) if required is None: required = default else: required = (default if discover.version_match(required, default) else required) if required is not None: return discover.version_to_string(required)
def version_data(self): """Get an endpoint with its versions""" all_version_data = [] if not self.endpoint_with_versions: return None else: for endpoint in self.endpoint_with_versions: if not endpoint: continue for version in endpoint: if not self.desired_version: if 'version' in version and version['version']: all_version_data.append(version) elif 'id' in version: all_version_data.append(version) else: if 'version' in version and version['version']: if self.exact_match: if version['version'] == str( self.desired_version): all_version_data.append(version) else: current_micro_version = normalize_version_number( version['version']) required_micro_version = normalize_version_number( str(self.desired_version)) if version_match(required_micro_version, current_micro_version): all_version_data.append(version) elif 'id' in version and version["id"]: if self.exact_match: if version['id'] == 'v' + str( self.desired_version): all_version_data.append(version) else: current_version = normalize_version_number( version['id']) required_version = normalize_version_number( str(self.desired_version)) if version_match(required_version, current_version): all_version_data.append(version) return all_version_data
def _do_create_plugin(self, session): plugin = None try: disc = self.get_discovery(session, self.auth_url, authenticated=False) except (exceptions.DiscoveryFailure, exceptions.HttpError, exceptions.ConnectionError): LOG.warning('Discovering versions from the identity service ' 'failed when creating the password plugin. ' 'Attempting to determine version from URL.') url_parts = urlparse.urlparse(self.auth_url) path = url_parts.path.lower() if path.startswith('/v2.0'): if self._has_domain_scope: raise exceptions.DiscoveryFailure( 'Cannot use v2 authentication with domain scope') plugin = self.create_plugin(session, (2, 0), self.auth_url) elif path.startswith('/v3'): plugin = self.create_plugin(session, (3, 0), self.auth_url) else: disc_data = disc.version_data() v2_with_domain_scope = False for data in disc_data: version = data['version'] if (discover.version_match((2,), version) and self._has_domain_scope): # NOTE(jamielennox): if there are domain parameters there # is no point even trying against v2 APIs. v2_with_domain_scope = True continue plugin = self.create_plugin(session, version, data['url'], raw_status=data['raw_status']) if plugin: break if not plugin and v2_with_domain_scope: raise exceptions.DiscoveryFailure( 'Cannot use v2 authentication with domain scope') if plugin: return plugin # so there were no URLs that i could use for auth of any version. raise exceptions.DiscoveryFailure('Could not determine a suitable URL ' 'for the plugin')
def create_plugin(self, session, version, url, raw_status=None): if discover.version_match((2,), version): if self._user_domain_id or self._user_domain_name: raise exceptions.DiscoveryFailure( 'Cannot use v2 authentication with domain scope') return v2.Password(auth_url=url, user_id=self._user_id, username=self._username, password=self._password, **self._v2_params) elif discover.version_match((3,), version): return v3.Password(auth_url=url, user_id=self._user_id, username=self._username, user_domain_id=self._user_domain_id, user_domain_name=self._user_domain_name, password=self._password, **self._v3_params)
def create_plugin(self, session, version, url, raw_status=None): if discover.version_match((2, ), version): if self._user_domain_id or self._user_domain_name: raise exceptions.DiscoveryFailure( 'Cannot use v2 authentication with domain scope') return v2.Password(auth_url=url, user_id=self._user_id, username=self._username, password=self._password, **self._v2_params) elif discover.version_match((3, ), version): return v3.Password(auth_url=url, user_id=self._user_id, username=self._username, user_domain_id=self._user_domain_id, user_domain_name=self._user_domain_name, password=self._password, **self._v3_params)
def create_plugin(self, session, version, url, raw_status=None): if discover.version_match((2,), version): if self._user_domain_id or self._user_domain_name: # If you specify any domain parameters it won't work so quit. return None return v2.Password(auth_url=url, user_id=self._user_id, username=self._username, password=self._password, **self._v2_params) elif discover.version_match((3,), version): return v3.Password(auth_url=url, user_id=self._user_id, username=self._username, user_domain_id=self._user_domain_id, user_domain_name=self._user_domain_name, password=self._password, **self._v3_params)
def create_plugin(self, session, version, url, raw_status=None): if discover.version_match((2,), version): if self._user_domain_id or self._user_domain_name: return None return v2.Password(auth_url=url, user_id=self._user_id, username=self._username, password=self._password, **self._v2_params) elif discover.version_match((3,), version): u_domain_id = self._user_domain_id or self._default_domain_id u_domain_name = self._user_domain_name or self._default_domain_name return v3.Password(auth_url=url, user_id=self._user_id, username=self._username, user_domain_id=u_domain_id, user_domain_name=u_domain_name, password=self._password, **self._v3_params)
def create_plugin(self, session, version, url, raw_status=None): if discover.version_match((2, ), version): if self._user_domain_id or self._user_domain_name: return None return v2.Password(auth_url=url, user_id=self._user_id, username=self._username, password=self._password, **self._v2_params) elif discover.version_match((3, ), version): u_domain_id = self._user_domain_id or self._default_domain_id u_domain_name = self._user_domain_name or self._default_domain_name return v3.Password(auth_url=url, user_id=self._user_id, username=self._username, user_domain_id=u_domain_id, user_domain_name=u_domain_name, password=self._password, **self._v3_params)
def supports_microversion(adapter, microversion, raise_exception=False): """Determine if the given adapter supports the given microversion. Checks the min and max microversion asserted by the service and checks to make sure that ``min <= microversion <= max``. Current default microversion is taken into consideration if set and verifies that ``microversion <= default``. :param adapter: :class:`~keystoneauth1.adapter.Adapter` instance. :param str microversion: String containing the desired microversion. :param bool raise_exception: Raise exception when requested microversion is not supported be the server side or is higher than the current default microversion. :returns: True if the service supports the microversion. :rtype: bool :raises: :class:`~openstack.exceptions.SDKException` when requested microversion is not supported. """ endpoint_data = adapter.get_endpoint_data() if (endpoint_data.min_microversion and endpoint_data.max_microversion and discover.version_between( endpoint_data.min_microversion, endpoint_data.max_microversion, microversion)): if adapter.default_microversion is not None: # If default_microversion is set - evaluate # whether it match the expectation candidate = discover.normalize_version_number( adapter.default_microversion) required = discover.normalize_version_number(microversion) supports = discover.version_match(required, candidate) if raise_exception and not supports: raise exceptions.SDKException( 'Required microversion {ver} is higher than currently ' 'selected {curr}'.format( ver=microversion, curr=adapter.default_microversion)) return supports return True if raise_exception: raise exceptions.SDKException( 'Required microversion {ver} is not supported ' 'by the server side'.format(ver=microversion)) return False
def _get_strategy_class(self): if self._requested_auth_version: # A specific version was requested. if discover.version_match(_V3RequestStrategy.AUTH_VERSION, self._requested_auth_version): return _V3RequestStrategy # The version isn't v3 so we don't know what to do. Just assume V2. return _V2RequestStrategy # Specific version was not requested then we fall through to # discovering available versions from the server for klass in _REQUEST_STRATEGIES: if self._adapter.get_endpoint(version=klass.AUTH_VERSION): self._LOG.debug("Auth Token confirmed use of %s apis", self._requested_auth_version) return klass versions = ["v%d.%d" % s.AUTH_VERSION for s in _REQUEST_STRATEGIES] self._LOG.error(_LE("No attempted versions [%s] supported by server"), ", ".join(versions)) msg = _("No compatible apis supported by server") raise ksm_exceptions.ServiceError(msg)
def _get_strategy_class(self): if self._requested_auth_version: if not discover.version_match(_V3RequestStrategy.AUTH_VERSION, self._requested_auth_interface): self._LOG.info('A version other than v3 was requested: %s', self._requested_auth_interface) # Return v3, even if the request is unknown return _V3RequestStrategy # Specific version was not requested then we fall through to # discovering available versions from the server for klass in _REQUEST_STRATEGIES: if self._adapter.get_endpoint(version=klass.AUTH_VERSION): self._LOG.debug('Auth Token confirmed use of %s apis', klass.AUTH_VERSION) return klass versions = ['v%d.%d' % s.AUTH_VERSION for s in _REQUEST_STRATEGIES] self._LOG.error('No attempted versions [%s] supported by server', ', '.join(versions)) msg = _('No compatible apis supported by server') raise ksm_exceptions.ServiceError(msg)
def _get_strategy_class(self): if self._requested_auth_version: # A specific version was requested. if discover.version_match(_V3RequestStrategy.AUTH_VERSION, self._requested_auth_version): return _V3RequestStrategy # The version isn't v3 so we don't know what to do. Just assume V2. return _V2RequestStrategy # Specific version was not requested then we fall through to # discovering available versions from the server for klass in _REQUEST_STRATEGIES: if self._adapter.get_endpoint(version=klass.AUTH_VERSION): self._LOG.debug('Auth Token confirmed use of %s apis', self._requested_auth_version) return klass versions = ['v%d.%d' % s.AUTH_VERSION for s in _REQUEST_STRATEGIES] self._LOG.error(_LE('No attempted versions [%s] supported by server'), ', '.join(versions)) msg = _('No compatible apis supported by server') raise ksm_exceptions.ServiceError(msg)
def _do_create_plugin(self, session): plugin = None try: disc = self.get_discovery(session, self.auth_url, authenticated=False) except (exceptions.DiscoveryFailure, exceptions.HttpError, exceptions.ConnectionError): LOG.warning('Discovering versions from the identity service ' 'failed when creating the password plugin. ' 'Attempting to determine version from URL.') url_parts = urlparse.urlparse(self.auth_url) path = url_parts.path.lower() if path.startswith('/v2.0'): if self._has_domain_scope: raise exceptions.DiscoveryFailure( 'Cannot use v2 authentication with domain scope') plugin = self.create_plugin(session, (2, 0), self.auth_url) elif path.startswith('/v3'): plugin = self.create_plugin(session, (3, 0), self.auth_url) else: # NOTE(jamielennox): version_data is always in oldest to newest # order. This is fine normally because we explicitly skip v2 below # if there is domain data present. With default_domain params # though we want a v3 plugin if available and fall back to v2 so we # have to process in reverse order. FIXME(jamielennox): if we ever # go for another version we should reverse this logic as we always # want to favour the newest available version. reverse = self._default_domain_id or self._default_domain_name disc_data = disc.version_data(reverse=bool(reverse)) v2_with_domain_scope = False for data in disc_data: version = data['version'] if (discover.version_match((2,), version) and self._has_domain_scope): # NOTE(jamielennox): if there are domain parameters there # is no point even trying against v2 APIs. v2_with_domain_scope = True continue plugin = self.create_plugin(session, version, data['url'], raw_status=data['raw_status']) if plugin: break if not plugin and v2_with_domain_scope: raise exceptions.DiscoveryFailure( 'Cannot use v2 authentication with domain scope') if plugin: return plugin # so there were no URLs that i could use for auth of any version. raise exceptions.DiscoveryFailure('Could not determine a suitable URL ' 'for the plugin')
def create_plugin(self, session, version, url, raw_status=None): if discover.version_match((2,), version): return v2.Token(url, self._token, **self._v2_params) elif discover.version_match((3,), version): return v3.Token(url, self._token, **self._v3_params)
def create_plugin(self, session, version, url, raw_status=None): if discover.version_match((2, ), version): return v2.Token(url, self._token, **self._v2_params) elif discover.version_match((3, ), version): return v3.Token(url, self._token, **self._v3_params)