def _validate_offline(self, token, token_hashes): try: if cms.is_pkiz(token): verified = self._verify_pkiz_token(token, token_hashes) elif cms.is_asn1_token(token): verified = self._verify_signed_token(token, token_hashes) else: # Can't do offline validation for this type of token. return except exceptions.CertificateConfigError: self.log.warning( _LW('Fetch certificate config failed, ' 'fallback to online validation.')) except exc.RevocationListError: self.log.warning( _LW('Fetch revocation list failed, ' 'fallback to online validation.')) else: data = jsonutils.loads(verified) audit_ids = None if 'access' in data: # It's a v2 token. audit_ids = data['access']['token'].get('audit_ids') else: # It's a v3 token audit_ids = data['token'].get('audit_ids') if audit_ids: self._revocations.check_by_audit_id(audit_ids) return data
def _validate_offline(self, token, token_hashes): if cms.is_pkiz(token): token_data = _uncompress_pkiz(token) inform = cms.PKIZ_CMS_FORM elif cms.is_asn1_token(token): token_data = cms.token_to_cms(token) inform = cms.PKI_ASN1_FORM else: # Can't do offline validation for this type of token. return try: self._revocations.check(token_hashes) verified = self._cms_verify(token_data, inform) except ksc_exceptions.CertificateConfigError: self.log.warning(_LW('Fetch certificate config failed, ' 'fallback to online validation.')) except ksm_exceptions.RevocationListError: self.log.warning(_LW('Fetch revocation list failed, ' 'fallback to online validation.')) else: data = jsonutils.loads(verified) audit_ids = None if 'access' in data: # It's a v2 token. audit_ids = data['access']['token'].get('audit_ids') else: # It's a v3 token audit_ids = data['token'].get('audit_ids') if audit_ids: self._revocations.check_by_audit_id(audit_ids) return data
def __call__(self, req): if 'X-Auth-Token' not in req.headers: user_id = req.headers.get('X-Auth-User', 'admin') project_id = req.headers.get('X-Auth-Project-Id', 'admin') os_url = os.path.join(req.url, project_id) res = webob.Response() res.headers['X-Auth-Token'] = '%s:%s' % (user_id, project_id) res.headers['X-Server-Management-Url'] = os_url res.content_type = 'text/plain' res.status = '204' return res req_id = req.environ.get(request_id.ENV_REQUEST_ID) token = req.headers['X-Auth-Token'] if cms.is_pkiz(token): user_id = '' project_id = '' else: user_id, _sep, project_id = token.partition(':') project_id = project_id or user_id remote_address = getattr(req, 'remote_address', '127.0.0.1') if CONF.use_forwarded_for: remote_address = req.headers.get('X-Forwarded-For', remote_address) start_session(req, req_id, user_id, 'noauth', 'SUCCESS') return self.application
def _validate_offline(self, token, token_hashes): if cms.is_pkiz(token): token_data = _uncompress_pkiz(token) inform = cms.PKIZ_CMS_FORM elif cms.is_asn1_token(token): token_data = cms.token_to_cms(token) inform = cms.PKI_ASN1_FORM else: # Can't do offline validation for this type of token. return try: self._revocations.check(token_hashes) verified = self._cms_verify(token_data, inform) except ksc_exceptions.CertificateConfigError: self.log.warning('Fetch certificate config failed, ' 'fallback to online validation.') except ksm_exceptions.RevocationListError: self.log.warning('Fetch revocation list failed, ' 'fallback to online validation.') else: data = jsonutils.loads(verified) audit_ids = None if 'access' in data: # It's a v2 token. audit_ids = data['access']['token'].get('audit_ids') else: # It's a v3 token audit_ids = data['token'].get('audit_ids') if audit_ids: self._revocations.check_by_audit_id(audit_ids) return data
def _validate_offline(self, token, token_hashes): if cms.is_pkiz(token): token_data = _uncompress_pkiz(token) inform = cms.PKIZ_CMS_FORM elif cms.is_asn1_token(token): token_data = cms.token_to_cms(token) inform = cms.PKI_ASN1_FORM else: # Can't do offline validation for this type of token. return try: verified = self._cms_verify(token_data, inform) except ksc_exceptions.CertificateConfigError: self.log.warning('Fetch certificate config failed, ' 'fallback to online validation.') else: self.log.warning('auth_token middleware received a PKI/Z token. ' 'This form of token is deprecated and has been ' 'removed from keystone server and will be ' 'removed from auth_token middleware in the Rocky ' 'release. Please contact your administrator ' 'about upgrading keystone and the token format.') data = jsonutils.loads(verified) return data
def get(self, user_token): """Check if the token is cached already. Returns a tuple. The first element is a list of token IDs, where the first one is the preferred hash. The second element is the token data from the cache if the token was cached, otherwise ``None``. :raises exc.InvalidToken: if the token is invalid """ if cms.is_asn1_token(user_token) or cms.is_pkiz(user_token): # user_token is a PKI token that's not hashed. token_hashes = list(cms.cms_hash_token(user_token, mode=algo) for algo in self._hash_algorithms) for token_hash in token_hashes: cached = self._cache_get(token_hash) if cached: return (token_hashes, cached) # The token wasn't found using any hash algorithm. return (token_hashes, None) # user_token is either a UUID token or a hashed PKI token. token_id = user_token cached = self._cache_get(token_id) return ([token_id], cached)
def get(self, user_token): """Check if the token is cached already. Returns a tuple. The first element is a list of token IDs, where the first one is the preferred hash. The second element is the token data from the cache if the token was cached, otherwise ``None``. :raises exc.InvalidToken: if the token is invalid """ if cms.is_asn1_token(user_token) or cms.is_pkiz(user_token): # user_token is a PKI token that's not hashed. token_hashes = list( cms.cms_hash_token(user_token, mode=algo) for algo in self._hash_algorithms) for token_hash in token_hashes: cached = self._cache_get(token_hash) if cached: return (token_hashes, cached) # The token wasn't found using any hash algorithm. return (token_hashes, None) # user_token is either a UUID token or a hashed PKI token. token_id = user_token cached = self._cache_get(token_id) return ([token_id], cached)
def _validate_offline(self, token, token_hashes): try: if cms.is_pkiz(token): verified = self._verify_pkiz_token(token, token_hashes) elif cms.is_asn1_token(token): verified = self._verify_signed_token(token, token_hashes) else: # Can't do offline validation for this type of token. return except ksc_exceptions.CertificateConfigError: self.log.warning(_LW('Fetch certificate config failed, ' 'fallback to online validation.')) except ksm_exceptions.RevocationListError: self.log.warning(_LW('Fetch revocation list failed, ' 'fallback to online validation.')) else: data = jsonutils.loads(verified) audit_ids = None if 'access' in data: # It's a v2 token. audit_ids = data['access']['token'].get('audit_ids') else: # It's a v3 token audit_ids = data['token'].get('audit_ids') if audit_ids: self._revocations.check_by_audit_id(audit_ids) return data
def _token_hashes(self, token): """Generate a list of hashes that the current token may be cached as. The first element of this list is the preferred algorithm and is what new cache values should be saved as. :param str token: The token being presented by a user. :returns: list of str token hashes. """ if cms.is_asn1_token(token) or cms.is_pkiz(token): return list(cms.cms_hash_token(token, mode=algo) for algo in self._hash_algorithms) else: return [token]
def __init__(self, auth_ref, unscoped_token=None): # User-related attributes user = {} user['id'] = auth_ref.user_id user['name'] = auth_ref.username self.user = user self.user_domain_id = auth_ref.user_domain_id self.user_domain_name = auth_ref.user_domain_name # Token-related attributes self.id = auth_ref.auth_token self.unscoped_token = unscoped_token if (_TOKEN_HASH_ENABLED and (keystone_cms.is_asn1_token(self.id) or keystone_cms.is_pkiz(self.id))): algorithm = getattr(settings, 'OPENSTACK_TOKEN_HASH_ALGORITHM', 'md5') hasher = hashlib.new(algorithm) hasher.update(self.id) self.id = hasher.hexdigest() # If the scoped_token is long, then unscoped_token must be too. hasher = hashlib.new(algorithm) hasher.update(self.unscoped_token) self.unscoped_token = hasher.hexdigest() self.expires = auth_ref.expires # Project-related attributes project = {} project['id'] = auth_ref.project_id project['name'] = auth_ref.project_name self.project = project self.tenant = self.project # Domain-related attributes domain = {} domain['id'] = auth_ref.domain_id domain['name'] = auth_ref.domain_name self.domain = domain # Federation-related attributes self.is_federated = auth_ref.is_federated if auth_ref.version == 'v2.0': self.roles = auth_ref['user'].get('roles', []) else: self.roles = auth_ref.get('roles', []) self.serviceCatalog = auth_ref.service_catalog.get_data()
def _validate_offline(self, token, token_hashes): try: if cms.is_pkiz(token): verified = self._verify_pkiz_token(token, token_hashes) elif cms.is_asn1_token(token): verified = self._verify_signed_token(token, token_hashes) else: # Can't do offline validation for this type of token. return except exceptions.CertificateConfigError: self.log.warning(_LW("Fetch certificate config failed, " "fallback to online validation.")) except exc.RevocationListError: self.log.warning(_LW("Fetch revocation list failed, " "fallback to online validation.")) else: data = jsonutils.loads(verified) return data
def _validate_offline(self, token, token_hashes): try: if cms.is_pkiz(token): verified = self._verify_pkiz_token(token, token_hashes) elif cms.is_asn1_token(token): verified = self._verify_signed_token(token, token_hashes) else: # Can't do offline validation for this type of token. return except exceptions.CertificateConfigError: self.log.warning( _LW('Fetch certificate config failed, ' 'fallback to online validation.')) except exc.RevocationListError: self.log.warning( _LW('Fetch revocation list failed, ' 'fallback to online validation.')) else: data = jsonutils.loads(verified) return data
def _validate_token(self, token, env, retry=True): """Authenticate user token :param token: token id :param env: wsgi environment :param retry: Ignored, as it is not longer relevant :returns: uncrypted body of the token if the token is valid :raises exc.InvalidToken: if token is rejected """ token_id = None try: token_ids, cached = self._token_cache.get(token) token_id = token_ids[0] if cached: # Token was retrieved from the cache. In this case, there's no # need to check that the token is expired because the cache # fetch fails for an expired token. Also, there's no need to # put the token in the cache because it's already in the cache. 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_ids) self._confirm_token_bind(data, env) else: verified = None # Token wasn't cached. In this case, the token needs to be # checked that it's not expired, and also put in the cache. try: if cms.is_pkiz(token): verified = self._verify_pkiz_token(token, token_ids) elif cms.is_asn1_token(token): verified = self._verify_signed_token(token, token_ids) except exceptions.CertificateConfigError: self._LOG.warn(_LW('Fetch certificate config failed, ' 'fallback to online validation.')) except exc.RevocationListError: self._LOG.warn(_LW('Fetch revocation list failed, ' 'fallback to online validation.')) if verified is not None: data = jsonutils.loads(verified) audit_ids = None if 'access' in data: # It's a v2 token. audit_ids = data['access']['token'].get('audit_ids') else: # It's a v3 token audit_ids = data['token'].get('audit_ids') if audit_ids: self._revocations.check_by_audit_id(audit_ids) expires = _get_token_expiration(data) _confirm_token_not_expired(expires) else: data = self._identity_server.verify_token(token, retry) # No need to confirm token expiration here since # verify_token fails for expired tokens. expires = _get_token_expiration(data) self._confirm_token_bind(data, env) self._token_cache.store(token_id, data, expires) return data except (exceptions.ConnectionRefused, exceptions.RequestTimeout, exc.RevocationListError, exc.ServiceError) as e: self._LOG.critical(_LC('Unable to validate token: %s'), e) raise ServiceError() except exc.InvalidToken: self._LOG.debug('Token validation failure.', exc_info=True) if token_id: self._token_cache.store_invalid(token_id) self._LOG.warning(_LW('Authorization failed for token')) raise except Exception: self._LOG.critical(_LC('Unable to validate token'), exc_info=True) raise exc._InternalServiceError()
def _validate_token(self, token, env): """Authenticate user token :param token: token id :param env: wsgi environment :returns: uncrypted body of the token if the token is valid :raises exc.InvalidToken: if token is rejected """ token_id = None try: token_ids, cached = self._token_cache.get(token) token_id = token_ids[0] if cached: # Token was retrieved from the cache. In this case, there's no # need to check that the token is expired because the cache # fetch fails for an expired token. Also, there's no need to # put the token in the cache because it's already in the cache. 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_ids) self._confirm_token_bind(data, env) else: verified = None # Token wasn't cached. In this case, the token needs to be # checked that it's not expired, and also put in the cache. try: if cms.is_pkiz(token): verified = self._verify_pkiz_token(token, token_ids) elif cms.is_asn1_token(token): verified = self._verify_signed_token(token, token_ids) except exceptions.CertificateConfigError: self._LOG.warn(_LW('Fetch certificate config failed, ' 'fallback to online validation.')) except exc.RevocationListError: self._LOG.warn(_LW('Fetch revocation list failed, ' 'fallback to online validation.')) if verified is not None: data = jsonutils.loads(verified) expires = _get_token_expiration(data) _confirm_token_not_expired(expires) else: data = self._identity_server.verify_token(token) # No need to confirm token expiration here since # verify_token fails for expired tokens. expires = _get_token_expiration(data) self._confirm_token_bind(data, env) self._token_cache.store(token_id, data, expires) return data except (exceptions.ConnectionRefused, exceptions.RequestTimeout): self._LOG.debug('Token validation failure.', exc_info=True) self._LOG.warn(_LW('Authorization failed for token')) raise exc.InvalidToken(_('Token authorization failed')) except exc.ServiceError: raise except Exception: self._LOG.debug('Token validation failure.', exc_info=True) if token_id: self._token_cache.store_invalid(token_id) self._LOG.warn(_LW('Authorization failed for token')) raise exc.InvalidToken(_('Token authorization failed'))
def _validate_token(self, token, env): """Authenticate user token :param token: token id :param env: wsgi environment :returns: uncrypted body of the token if the token is valid :raises exc.InvalidToken: if token is rejected """ 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: verified = None try: if cms.is_pkiz(token): verified = self._verify_pkiz_token(token, token_hashes) elif cms.is_asn1_token(token): verified = self._verify_signed_token(token, token_hashes) except exceptions.CertificateConfigError: self._LOG.warning(_LW('Fetch certificate config failed, ' 'fallback to online validation.')) except exc.RevocationListError: self._LOG.warning(_LW('Fetch revocation list failed, ' 'fallback to online validation.')) if verified is not None: data = jsonutils.loads(verified) else: data = self._identity_server.verify_token(token) auth_ref = access.AccessInfo.factory(body=data, auth_token=token) # 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')) if _token_is_v2(data) and not auth_ref.project_id: msg = _('Unable to determine service tenancy.') raise exc.InvalidToken(msg) self._confirm_token_bind(data, env) if not cached: self._token_cache.store(token_hashes[0], data) return auth_ref, 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: raise 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'))
def _is_pki_token(self, token): """Determines if this is a pki-based token (pki or pkiz)""" if token is None: return False return (keystone_cms.is_ans1_token(token) or keystone_cms.is_pkiz(token))
def _is_pki_token(self, token): """Determines if this is a pki-based token (pki or pkiz)""" return (keystone_cms.is_ans1_token(token) or keystone_cms.is_pkiz(token))