Esempio n. 1
0
    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
Esempio n. 2
0
    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
Esempio n. 3
0
    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
Esempio n. 4
0
    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
Esempio n. 5
0
    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
Esempio n. 6
0
    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)
Esempio n. 8
0
    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)
Esempio n. 9
0
    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
Esempio n. 10
0
    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]
Esempio n. 11
0
    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()
Esempio n. 12
0
    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()
Esempio n. 13
0
 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
Esempio n. 14
0
 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
Esempio n. 15
0
    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()
Esempio n. 16
0
    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'))
Esempio n. 17
0
    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'))
Esempio n. 18
0
 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))
Esempio n. 19
0
 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))