def verify_token(self, user_token, retry=True): """Authenticate user token with identity server. :param user_token: user's token id :param retry: flag that forces the middleware to retry user authentication when an indeterminate response is received. Optional. :returns: access info received from identity server on success :rtype: :py:class:`keystoneauth1.access.AccessInfo` :raises exc.InvalidToken: if token is rejected :raises exc.ServiceError: if unable to authenticate token """ try: auth_ref = self._request_strategy.verify_token(user_token) except ksa_exceptions.NotFound as e: self._LOG.warning(_LW("Authorization failed for token")) self._LOG.warning(_LW("Identity response: %s"), e.response.text) raise ksm_exceptions.InvalidToken(_("Token authorization failed")) except ksa_exceptions.Unauthorized as e: self._LOG.info(_LI("Identity server rejected authorization")) self._LOG.warning(_LW("Identity response: %s"), e.response.text) if retry: self._LOG.info(_LI("Retrying validation")) return self.verify_token(user_token, False) msg = _("Identity server rejected authorization necessary to " "fetch token data") raise ksm_exceptions.ServiceError(msg) except ksa_exceptions.HttpError as e: self._LOG.error(_LE("Bad response code while validating token: %s"), e.http_status) self._LOG.warning(_LW("Identity response: %s"), e.response.text) msg = _("Failed to fetch token data from identity server") raise ksm_exceptions.ServiceError(msg) else: return auth_ref
def _get_token_expiration(data): if not data: raise exc.InvalidToken(_('Token authorization failed')) if _token_is_v2(data): return data['access']['token']['expires'] elif _token_is_v3(data): return data['token']['expires_at'] else: raise exc.InvalidToken(_('Token authorization failed'))
def fetch_revocation_list(self): try: data = self._request_strategy.fetch_revocation_list() except ksa_exceptions.HttpError as e: msg = _("Failed to fetch token revocation list: %d") raise ksm_exceptions.RevocationListError(msg % e.http_status) if "signed" not in data: msg = _("Revocation list improperly formatted.") raise ksm_exceptions.RevocationListError(msg) return data["signed"]
def fetch_revocation_list(self): try: data = self._request_strategy.fetch_revocation_list() except ksc_exceptions.HTTPError as e: msg = _('Failed to fetch token revocation list: %d') raise ksm_exceptions.RevocationListError(msg % e.http_status) if 'signed' not in data: msg = _('Revocation list improperly formatted.') raise ksm_exceptions.RevocationListError(msg) return data['signed']
def fetch_revocation_list(self): try: data = self._request_strategy.fetch_revocation_list() except ksa_exceptions.HttpError as e: msg = _('Failed to fetch token revocation list: %d') raise ksm_exceptions.RevocationListError(msg % e.http_status) if 'signed' not in data: msg = _('Revocation list improperly formatted.') raise ksm_exceptions.RevocationListError(msg) return data['signed']
def _cache_get(self, token_id): """Return token information from cache. If token is invalid raise exc.InvalidToken return token only if fresh (not expired). """ if not token_id: # Nothing to do return key, context = self._get_cache_key(token_id) with self._cache_pool.reserve() as cache: serialized = cache.get(key) if serialized is None: return None if isinstance(serialized, six.text_type): serialized = serialized.encode('utf8') data = self._deserialize(serialized, context) # Note that _INVALID_INDICATOR and (data, expires) are the only # valid types of serialized cache entries, so there is not # a collision with jsonutils.loads(serialized) == None. if not isinstance(data, six.string_types): data = data.decode('utf-8') cached = jsonutils.loads(data) if cached == self._INVALID_INDICATOR: self._LOG.debug('Cached Token is marked unauthorized') raise exc.InvalidToken(_('Token authorization failed')) data, expires = cached try: expires = timeutils.parse_isotime(expires) except ValueError: # Gracefully handle upgrade of expiration times from *nix # timestamps to ISO 8601 formatted dates by ignoring old cached # values. return expires = timeutils.normalize_time(expires) utcnow = timeutils.utcnow() if utcnow < expires: self._LOG.debug('Returning cached token') return data else: self._LOG.debug('Cached Token seems expired') raise exc.InvalidToken(_('Token authorization failed'))
def _split_path(path, minsegs=1, maxsegs=None, rest_with_last=False): """Validate and split the given HTTP request path. **Examples**:: ['a'] = _split_path('/a') ['a', None] = _split_path('/a', 1, 2) ['a', 'c'] = _split_path('/a/c', 1, 2) ['a', 'c', 'o/r'] = _split_path('/a/c/o/r', 1, 3, True) :param path: HTTP Request path to be split :param minsegs: Minimum number of segments to be extracted :param maxsegs: Maximum number of segments to be extracted :param rest_with_last: If True, trailing data will be returned as part of last segment. If False, and there is trailing data, raises ValueError. :returns: list of segments with a length of maxsegs (non-existent segments will return as None) :raises: ValueError if given an invalid path """ if not maxsegs: maxsegs = minsegs if minsegs > maxsegs: raise ValueError( _('minsegs > maxsegs: %(min)d > %(max)d)') % { 'min': minsegs, 'max': maxsegs }) if rest_with_last: segs = path.split('/', maxsegs) minsegs += 1 maxsegs += 1 count = len(segs) if (segs[0] or count < minsegs or count > maxsegs or '' in segs[1:minsegs]): raise ValueError(_('Invalid path: %s') % urllib.parse.quote(path)) else: minsegs += 1 maxsegs += 1 segs = path.split('/', maxsegs) count = len(segs) if (segs[0] or count < minsegs or count > maxsegs + 1 or '' in segs[1:minsegs] or (count == maxsegs + 1 and segs[maxsegs])): raise ValueError(_('Invalid path: %s') % urllib.parse.quote(path)) segs = segs[1:maxsegs] segs.extend([None] * (maxsegs - 1 - len(segs))) return segs
def _build_service_headers(self, token_info): """Convert token object into service headers. Build headers that represent authenticated user - see main doc info at start of file for details of headers to be defined. :param token_info: token object returned by identity server on authentication :raises exc.InvalidToken: when unable to parse token object """ auth_ref = access.AccessInfo.factory(body=token_info) if _token_is_v2(token_info) and not auth_ref.project_id: raise exc.InvalidToken(_('Unable to determine service tenancy.')) roles = ','.join(auth_ref.role_names) rval = { 'X-Service-Identity-Status': 'Confirmed', 'X-Service-Roles': roles, } header_type = '-Service' for header_tmplt, attr in six.iteritems(_HEADER_TEMPLATE): rval[header_tmplt % header_type] = getattr(auth_ref, attr) return rval
def _do_fetch_token(self, token, **kwargs): """Helper method to fetch a token and convert it into an AccessInfo.""" if self.kwargs_to_fetch_token: data = self.fetch_token(token, **kwargs) else: m = _('Implementations of auth_token must set ' 'kwargs_to_fetch_token this will be the required and ' 'assumed in Pike.') warnings.warn(m) data = self.fetch_token(token) try: return data, access.create(body=data, auth_token=token) except Exception: self.log.warning(_LW('Invalid token contents.'), exc_info=True) raise ksm_exceptions.InvalidToken(_('Token authorization failed'))
def _conf_values_type_convert(conf): """Convert conf values into correct type.""" if not conf: return {} opt_types = {} for o in (_OPTS + _auth.AuthTokenPlugin.get_options()): type_dest = (getattr(o, 'type', str), o.dest) opt_types[o.dest] = type_dest # Also add the deprecated name with the same type and dest. for d_o in o.deprecated_opts: opt_types[d_o.name] = type_dest opts = {} for k, v in six.iteritems(conf): dest = k try: if v is not None: type_, dest = opt_types[k] v = type_(v) except KeyError: # This option is not known to auth_token. pass except ValueError as e: raise exc.ConfigurationError( _('Unable to convert the value of %(key)s option into correct ' 'type: %(ex)s') % { 'key': k, 'ex': e }) opts[dest] = v return opts
def _conf_values_type_convert(conf): """Convert conf values into correct type.""" if not conf: return {} opt_types = {} for o in (_OPTS + _auth.AuthTokenPlugin.get_options()): type_dest = (getattr(o, 'type', str), o.dest) opt_types[o.dest] = type_dest # Also add the deprecated name with the same type and dest. for d_o in o.deprecated_opts: opt_types[d_o.name] = type_dest opts = {} for k, v in six.iteritems(conf): dest = k try: if v is not None: type_, dest = opt_types[k] v = type_(v) except KeyError: # This option is not known to auth_token. pass except ValueError as e: raise exc.ConfigurationError( _('Unable to convert the value of %(key)s option into correct ' 'type: %(ex)s') % {'key': k, 'ex': e}) opts[dest] = v return opts
def unprotect_data(keys, signed_data): """Given keys and cached string data, verifies the signature, decrypts if necessary, and returns the original serialized data. """ # cache backends return None when no data is found. We don't mind # that this particular special value is unsigned. if signed_data is None: return None # First we calculate the signature provided_mac = signed_data[:DIGEST_LENGTH_B64] calculated_mac = sign_data( keys['MAC'], signed_data[DIGEST_LENGTH_B64:]) # Then verify that it matches the provided value if not constant_time_compare(provided_mac, calculated_mac): raise InvalidMacError(_('Invalid MAC; data appears to be corrupted.')) data = base64.b64decode(signed_data[DIGEST_LENGTH_B64:]) # then if necessary decrypt the data if keys['strategy'] == b'ENCRYPT': data = decrypt_data(keys['ENCRYPTION'], data) return data
def unprotect_data(keys, signed_data): """De-serialize data given a dict of keys. Given keys and cached string data, verifies the signature, decrypts if necessary, and returns the original serialized data. """ # cache backends return None when no data is found. We don't mind # that this particular special value is unsigned. if signed_data is None: return None # First we calculate the signature provided_mac = signed_data[:DIGEST_LENGTH_B64] calculated_mac = sign_data(keys['MAC'], signed_data[DIGEST_LENGTH_B64:]) # Then verify that it matches the provided value if not constant_time_compare(provided_mac, calculated_mac): raise InvalidMacError(_('Invalid MAC; data appears to be corrupted.')) data = base64.b64decode(signed_data[DIGEST_LENGTH_B64:]) # then if necessary decrypt the data if keys['strategy'] == b'ENCRYPT': data = decrypt_data(keys['ENCRYPTION'], data) return data
def fetch_revocation_list(self): try: response, data = self._json_request( 'GET', '/tokens/revoked', authenticated=True, endpoint_filter={'version': (2, 0)}) except exceptions.HTTPError as e: msg = _('Failed to fetch token revocation list: %d') raise exc.RevocationListError(msg % e.http_status) if response.status_code != 200: msg = _('Unable to fetch token revocation list.') raise exc.RevocationListError(msg) if 'signed' not in data: msg = _('Revocation list improperly formatted.') raise exc.RevocationListError(msg) return data['signed']
def verify_token(self, token): auth_ref = self._client.tokens.validate_access_info(token) if not auth_ref: msg = _('Failed to fetch token data from identity server') raise ksm_exceptions.InvalidToken(msg) return {'access': auth_ref}
def verify_token(self, token): auth_ref = self._client.tokens.validate_access_info(token) if not auth_ref: msg = _('Failed to fetch token data from identity server') raise exc.InvalidToken(msg) return {'access': auth_ref}
def validate_allowed_request(self, request, token): self.log.debug("Validating token access rules against request") app_cred = token.get('application_credential') if not app_cred: return access_rules = app_cred.get('access_rules') if access_rules is None: return if hasattr(self, '_conf'): my_service_type = self._conf.get('service_type') else: my_service_type = self._service_type if not my_service_type: self.log.warning('Cannot validate request with restricted' ' access rules. Set service_type in' ' [keystone_authtoken] to allow access rule' ' validation.') raise ksm_exceptions.InvalidToken(_('Token authorization failed')) # token can always be validated regardless of access rules if (my_service_type == 'identity' and request.method == 'GET' and request.path.endswith('/v3/auth/tokens')): return catalog = token['catalog'] # validate service type is in catalog catalog_svcs = [s for s in catalog if s['type'] == my_service_type] if len(catalog_svcs) == 0: self.log.warning('Cannot validate request with restricted' ' access rules. service_type in' ' [keystone_authtoken] is not a valid service' ' type in the catalog.') raise ksm_exceptions.InvalidToken(_('Token authorization failed')) if request.service_token: # The request may not match an allowed request, but the presence # of the service token indicates this is a chain of requests and # hence this request was not user-facing return for access_rule in access_rules: method = access_rule['method'] path = access_rule['path'] service = access_rule['service'] if request.method == method and \ service == my_service_type and \ _path_matches(request.path, path): return raise ksm_exceptions.InvalidToken(_('Token authorization failed'))
def verify_token(self, token): auth_ref = self._client.tokens.validate(token, include_catalog=self._include_service_catalog) if not auth_ref: msg = _("Failed to fetch token data from identity server") raise ksm_exceptions.InvalidToken(msg) return {"token": auth_ref}
def _split_path(path, minsegs=1, maxsegs=None, rest_with_last=False): """Validate and split the given HTTP request path. **Examples**:: ['a'] = _split_path('/a') ['a', None] = _split_path('/a', 1, 2) ['a', 'c'] = _split_path('/a/c', 1, 2) ['a', 'c', 'o/r'] = _split_path('/a/c/o/r', 1, 3, True) :param path: HTTP Request path to be split :param minsegs: Minimum number of segments to be extracted :param maxsegs: Maximum number of segments to be extracted :param rest_with_last: If True, trailing data will be returned as part of last segment. If False, and there is trailing data, raises ValueError. :returns: list of segments with a length of maxsegs (non-existent segments will return as None) :raises: ValueError if given an invalid path """ if not maxsegs: maxsegs = minsegs if minsegs > maxsegs: raise ValueError(_('minsegs > maxsegs: %(min)d > %(max)d)') % {'min': minsegs, 'max': maxsegs}) if rest_with_last: segs = path.split('/', maxsegs) minsegs += 1 maxsegs += 1 count = len(segs) if (segs[0] or count < minsegs or count > maxsegs or '' in segs[1:minsegs]): raise ValueError(_('Invalid path: %s') % urllib.parse.quote(path)) else: minsegs += 1 maxsegs += 1 segs = path.split('/', maxsegs) count = len(segs) if (segs[0] or count < minsegs or count > maxsegs + 1 or '' in segs[1:minsegs] or (count == maxsegs + 1 and segs[maxsegs])): raise ValueError(_('Invalid path: %s') % urllib.parse.quote(path)) segs = segs[1:maxsegs] segs.extend([None] * (maxsegs - 1 - len(segs))) return segs
def verify_token(self, token, allow_expired=False): # NOTE(jamielennox): allow_expired is ignored on V2 auth_ref = self._client.tokens.validate_access_info(token) if not auth_ref: msg = _('Failed to fetch token data from identity server') raise ksm_exceptions.InvalidToken(msg) return {'access': auth_ref}
def _do_fetch_token(self, token): """Helper method to fetch a token and convert it into an AccessInfo""" data = self._fetch_token(token) try: return data, access.AccessInfo.factory(body=data, auth_token=token) except Exception: self.log.warning(_LW("Invalid token contents."), exc_info=True) raise exc.InvalidToken(_("Token authorization failed"))
def verify_token(self, token): auth_ref = self._client.tokens.validate( token, include_catalog=self._include_service_catalog) if not auth_ref: msg = _('Failed to fetch token data from identity server') raise exc.InvalidToken(msg) return {'token': auth_ref}
def _do_fetch_token(self, token): """Helper method to fetch a token and convert it into an AccessInfo""" data = self.fetch_token(token) try: return data, access.create(body=data, auth_token=token) except Exception: self.log.warning(_LW('Invalid token contents.'), exc_info=True) raise ksm_exceptions.InvalidToken(_('Token authorization failed'))
def _do_fetch_token(self, token): """Helper method to fetch a token and convert it into an AccessInfo""" data = self._fetch_token(token) try: return data, access.AccessInfo.factory(body=data, auth_token=token) except Exception: self.log.warning(_LW('Invalid token contents.'), exc_info=True) raise exc.InvalidToken(_('Token authorization failed'))
def _fetch_token(self, token): """Retrieve a token from either a PKI bundle or the identity server. :param str token: token id :raises exc.InvalidToken: if token is rejected """ data = None token_hashes = None try: token_hashes = self._token_hashes(token) cached = self._cache_get_hashes(token_hashes) if cached: data = cached if self._check_revocations_for_cached: # A token stored in Memcached might have been revoked # regardless of initial mechanism used to validate it, # and needs to be checked. self._revocations.check(token_hashes) else: data = self._validate_offline(token, token_hashes) if not data: data = self._identity_server.verify_token(token) self._token_cache.store(token_hashes[0], data) except (exceptions.ConnectionRefused, exceptions.RequestTimeout): self.log.debug("Token validation failure.", exc_info=True) self.log.warning(_LW("Authorization failed for token")) raise exc.InvalidToken(_("Token authorization failed")) except exc.ServiceError as e: self.log.critical(_LC("Unable to obtain admin token: %s"), e) raise webob.exc.HTTPServiceUnavailable() except Exception: self.log.debug("Token validation failure.", exc_info=True) if token_hashes: self._token_cache.store_invalid(token_hashes[0]) self.log.warning(_LW("Authorization failed for token")) raise exc.InvalidToken(_("Token authorization failed")) return data
def _fetch_token(self, token): """Retrieve a token from either a PKI bundle or the identity server. :param str token: token id :raises exc.InvalidToken: if token is rejected """ data = None token_hashes = None try: token_hashes = self._token_hashes(token) cached = self._cache_get_hashes(token_hashes) if cached: data = cached if self._check_revocations_for_cached: # A token stored in Memcached might have been revoked # regardless of initial mechanism used to validate it, # and needs to be checked. self._revocations.check(token_hashes) else: data = self._validate_offline(token, token_hashes) if not data: data = self._identity_server.verify_token(token) self._token_cache.store(token_hashes[0], data) except (exceptions.ConnectionRefused, exceptions.RequestTimeout): self.log.debug('Token validation failure.', exc_info=True) self.log.warning(_LW('Authorization failed for token')) raise exc.InvalidToken(_('Token authorization failed')) except exc.ServiceError as e: self.log.critical(_LC('Unable to obtain admin token: %s'), e) raise webob.exc.HTTPServiceUnavailable() except Exception: self.log.debug('Token validation failure.', exc_info=True) if token_hashes: self._token_cache.store_invalid(token_hashes[0]) self.log.warning(_LW('Authorization failed for token')) raise exc.InvalidToken(_('Token authorization failed')) return data
def _do_fetch_token(self, token, **kwargs): """Helper method to fetch a token and convert it into an AccessInfo.""" # NOTE(edmondsw): strip the token to remove any whitespace that may # have been passed along in the header per bug 1689468 token = token.strip() if self.kwargs_to_fetch_token: data = self.fetch_token(token, **kwargs) else: m = _('Implementations of auth_token must set ' 'kwargs_to_fetch_token this will be the required and ' 'assumed in Queens.') warnings.warn(m) data = self.fetch_token(token) try: return data, access.create(body=data, auth_token=token) except Exception: self.log.warning('Invalid token contents.', exc_info=True) raise ksm_exceptions.InvalidToken(_('Token authorization failed'))
def __init__(self, log, security_strategy, secret_key, **kwargs): super(SecureTokenCache, self).__init__(log, **kwargs) security_strategy = security_strategy.upper() if security_strategy not in ('MAC', 'ENCRYPT'): msg = _('memcache_security_strategy must be ENCRYPT or MAC') raise exc.ConfigurationError(msg) if not secret_key: msg = _('memcache_secret_key must be defined when a ' 'memcache_security_strategy is defined') raise exc.ConfigurationError(msg) if isinstance(security_strategy, six.string_types): security_strategy = security_strategy.encode('utf-8') if isinstance(secret_key, six.string_types): secret_key = secret_key.encode('utf-8') self._security_strategy = security_strategy self._secret_key = secret_key
def _validate_token(self, auth_ref): """Perform the validation steps on the token. :param auth_ref: The token data :type auth_ref: keystoneauth1.access.AccessInfo :raises exc.InvalidToken: if token is rejected """ # 0 seconds of validity means it is invalid right now if auth_ref.will_expire_soon(stale_duration=0): raise ksm_exceptions.InvalidToken(_('Token authorization failed'))
def _validate_token(self, auth_ref): """Perform the validation steps on the token. :param auth_ref: The token data :type auth_ref: keystoneclient.access.AccessInfo :raises exc.InvalidToken: if token is rejected """ # 0 seconds of validity means is it valid right now. if auth_ref.will_expire_soon(stale_duration=0): raise exc.InvalidToken(_('Token authorization failed'))
def verify_token(self, token, allow_expired=False): auth_ref = self._client.tokens.validate( token, include_catalog=self._include_service_catalog, allow_expired=allow_expired) if not auth_ref: msg = _('Failed to fetch token data from identity server') raise ksm_exceptions.InvalidToken(msg) return {'token': auth_ref}
def _validate_token(self, auth_ref, allow_expired=False): """Perform the validation steps on the token. :param auth_ref: The token data :type auth_ref: keystoneauth1.access.AccessInfo :raises exc.InvalidToken: if token is rejected """ # 0 seconds of validity means it is invalid right now if (not allow_expired) and auth_ref.will_expire_soon(stale_duration=0): raise ksm_exceptions.InvalidToken(_('Token authorization failed'))
def verify_token(self, user_token, retry=True): """Authenticate user token with identity server. :param user_token: user's token id :param retry: flag that forces the middleware to retry user authentication when an indeterminate response is received. Optional. :returns: token object received from identity server on success :raises exc.InvalidToken: if token is rejected :raises exc.ServiceError: if unable to authenticate token """ user_token = _utils.safe_quote(user_token) try: response, data = self._request_strategy.verify_token(user_token) except exceptions.NotFound as e: self._LOG.warning(_LW('Authorization failed for token')) self._LOG.warning(_LW('Identity response: %s'), e.response.text) raise exc.InvalidToken(_('Token authorization failed')) except exceptions.Unauthorized as e: self._LOG.info(_LI('Identity server rejected authorization')) self._LOG.warning(_LW('Identity response: %s'), e.response.text) if retry: self._LOG.info(_LI('Retrying validation')) return self.verify_token(user_token, False) msg = _('Identity server rejected authorization necessary to ' 'fetch token data') raise exc.ServiceError(msg) except exceptions.HttpError as e: self._LOG.error( _LE('Bad response code while validating token: %s'), e.http_status) self._LOG.warning(_LW('Identity response: %s'), e.response.text) msg = _('Failed to fetch token data from identity server') raise exc.ServiceError(msg) else: if response.status_code == 200: return data raise exc.InvalidToken()
def verify_token(self, user_token, retry=True, allow_expired=False): """Authenticate user token with identity server. :param user_token: user's token id :param retry: flag that forces the middleware to retry user authentication when an indeterminate response is received. Optional. :param allow_expired: Allow retrieving an expired token. :returns: access info received from identity server on success :rtype: :py:class:`keystoneauth1.access.AccessInfo` :raises exc.InvalidToken: if token is rejected :raises exc.ServiceError: if unable to authenticate token """ try: auth_ref = self._request_strategy.verify_token( user_token, allow_expired=allow_expired) except ksa_exceptions.NotFound as e: self._LOG.info('Authorization failed for token') self._LOG.info('Identity response: %s', e.response.text) raise ksm_exceptions.InvalidToken(_('Token authorization failed')) except ksa_exceptions.Unauthorized as e: self._LOG.info('Identity server rejected authorization') self._LOG.warning('Identity response: %s', e.response.text) if retry: self._LOG.info('Retrying validation') return self.verify_token(user_token, False) msg = _('Identity server rejected authorization necessary to ' 'fetch token data') raise ksm_exceptions.ServiceError(msg) except ksa_exceptions.HttpError as e: self._LOG.error( 'Bad response code while validating token: %s %s', e.http_status, e.message) if hasattr(e.response, 'text'): self._LOG.warning('Identity response: %s', e.response.text) msg = _('Failed to fetch token data from identity server') raise ksm_exceptions.ServiceError(msg) else: return auth_ref
def _do_fetch_token(self, token, **kwargs): """Helper method to fetch a token and convert it into an AccessInfo.""" # NOTE(edmondsw): strip the token to remove any whitespace that may # have been passed along in the header per bug 1689468 token = token.strip() data = self.fetch_token(token, **kwargs) try: return data, access.create(body=data, auth_token=token) except Exception: self.log.warning('Invalid token contents.', exc_info=True) raise ksm_exceptions.InvalidToken(_('Token authorization failed'))
def decrypt_data(key, data): """Decrypt the data with the given secret key.""" iv = data[:16] cipher = AES.new(key, AES.MODE_CBC, iv) try: result = cipher.decrypt(data[16:]) except Exception: raise DecryptError(_('Encrypted data appears to be corrupted.')) # Strip the last n padding bytes where n is the last value in # the plaintext return result[:-1 * six.byte2int([result[-1]])]
def verify(): try: signing_cert_path = self._signing_directory.calc_path( self._SIGNING_CERT_FILE_NAME) signing_ca_path = self._signing_directory.calc_path( self._SIGNING_CA_FILE_NAME) return cms.cms_verify(data, signing_cert_path, signing_ca_path, inform=inform).decode('utf-8') except (exceptions.CMSError, cms.subprocess.CalledProcessError) as err: self._LOG.warning(_LW('Verify error: %s'), err) raise exc.InvalidToken(_('Token authorization failed'))
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 verify(): try: signing_cert_path = self._signing_directory.calc_path( self._SIGNING_CERT_FILE_NAME) signing_ca_path = self._signing_directory.calc_path( self._SIGNING_CA_FILE_NAME) return cms.cms_verify(data, signing_cert_path, signing_ca_path, inform=inform).decode('utf-8') except (exceptions.CMSError, cms.subprocess.CalledProcessError) as err: self.log.warning(_LW('Verify error: %s'), err) raise exc.InvalidToken(_('Token authorization failed'))
def _verify_signing_dir(self): if os.path.isdir(self._directory_name): if not os.access(self._directory_name, os.W_OK): raise exc.ConfigurationError( _('unable to access signing_dir %s') % self._directory_name) uid = os.getuid() if os.stat(self._directory_name).st_uid != uid: self._log.warning(_LW('signing_dir is not owned by %s'), uid) current_mode = stat.S_IMODE(os.stat(self._directory_name).st_mode) if current_mode != stat.S_IRWXU: self._log.warning( _LW('signing_dir mode is %(mode)s instead of %(need)s'), {'mode': oct(current_mode), 'need': oct(stat.S_IRWXU)}) else: os.makedirs(self._directory_name, stat.S_IRWXU)
def _get_user_token_from_header(self, env): """Get token id from request. :param env: wsgi request environment :returns: token id :raises exc.InvalidToken: if no token is provided in request """ token = self._get_header(env, 'X-Auth-Token', self._get_header(env, 'X-Storage-Token')) if token: return token else: if not self._delay_auth_decision: self._LOG.debug('Headers: %s', env) raise exc.InvalidToken(_('Unable to find token in headers'))
def decrypt_data(key, data): """Decrypt the data with the given secret key.""" iv = data[:16] cipher = ciphers.Cipher(algorithms.AES(key), modes.CBC(iv), backend=crypto_backends.default_backend()) try: decryptor = cipher.decryptor() result = decryptor.update(data[16:]) + decryptor.finalize() except Exception: raise DecryptError(_('Encrypted data appears to be corrupted.')) # Strip the last n padding bytes where n is the last value in # the plaintext unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder() return unpadder.update(result) + unpadder.finalize()
def _get_user_token_from_request(self, request): """Get token id from request. :param env: wsgi request environment :returns: token id :raises exc.InvalidToken: if no token is provided in request """ token = request.user_token if token: return token else: if not self._delay_auth_decision: self.log.debug('Headers: %s', dict(request.headers)) raise exc.InvalidToken(_('Unable to find token in headers'))
def decrypt_data(key, data): """Decrypt the data with the given secret key.""" iv = data[:16] cipher = ciphers.Cipher( algorithms.AES(key), modes.CBC(iv), backend=crypto_backends.default_backend()) try: decryptor = cipher.decryptor() result = decryptor.update(data[16:]) + decryptor.finalize() except Exception: raise DecryptError(_('Encrypted data appears to be corrupted.')) # Strip the last n padding bytes where n is the last value in # the plaintext unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder() return unpadder.update(result) + unpadder.finalize()
def _conf_values_type_convert(group_name, all_options, conf): """Convert conf values into correct type.""" if not conf: return {} opts = {} opt_types = {} for group, options in all_options: # only accept paste overrides for the primary group if group != group_name: continue for o in options: type_dest = (getattr(o, 'type', str), o.dest) opt_types[o.dest] = type_dest # Also add the deprecated name with the same type and dest. for d_o in o.deprecated_opts: opt_types[d_o.name] = type_dest break for k, v in conf.items(): dest = k try: # 'here' and '__file__' come from paste.deploy # 'configkey' is added by panko and gnocchi if v is not None and k not in ['here', '__file__', 'configkey']: type_, dest = opt_types[k] v = type_(v) except KeyError: # nosec _LOG.warning('The option "%s" is not known to keystonemiddleware', k) except ValueError as e: raise exceptions.ConfigurationError( _('Unable to convert the value of option "%(key)s" into ' 'correct type: %(ex)s') % { 'key': k, 'ex': e }) opts[dest] = v return opts