Beispiel #1
0
    def process_request(self, request):
        """Process request.

        If this method returns a value then that value will be used as the
        response. The next application down the stack will not be executed and
        process_response will not be called.

        Otherwise, the next application down the stack will be executed and
        process_response will be called with the generated response.

        By default this method does not return a value.

        :param request: Incoming request
        :type request: _request.AuthTokenRequest

        """
        request.remove_auth_headers()

        user_auth_ref = None
        serv_auth_ref = None

        if request.user_token:
            self.log.debug('Authenticating user token')
            try:
                data, user_auth_ref = self._do_fetch_token(request.user_token)
                self._validate_token(user_auth_ref)
                self._confirm_token_bind(user_auth_ref, request)
            except exc.InvalidToken:
                self.log.info(_LI('Invalid user token'))
                request.user_token_valid = False
            else:
                request.user_token_valid = True
                request.environ['keystone.token_info'] = data

        if request.service_token:
            self.log.debug('Authenticating service token')
            try:
                _, serv_auth_ref = self._do_fetch_token(request.service_token)
                self._validate_token(serv_auth_ref)
                self._confirm_token_bind(serv_auth_ref, request)
            except exc.InvalidToken:
                self.log.info(_LI('Invalid service token'))
                request.service_token_valid = False
            else:
                request.service_token_valid = True

        p = _user_plugin.UserAuthPlugin(user_auth_ref, serv_auth_ref)
        request.environ['keystone.token_auth'] = p
    def process_request(self, request):
        """Process request.

        If this method returns a value then that value will be used as the
        response. The next application down the stack will not be executed and
        process_response will not be called.

        Otherwise, the next application down the stack will be executed and
        process_response will be called with the generated response.

        By default this method does not return a value.

        :param request: Incoming request
        :type request: _request.AuthTokenRequest

        """
        user_auth_ref = None
        serv_auth_ref = None
        allow_expired = False

        if request.service_token:
            self.log.debug('Authenticating service token')
            try:
                _, serv_auth_ref = self._do_fetch_token(request.service_token)
                self._validate_token(serv_auth_ref)
                self._confirm_token_bind(serv_auth_ref, request)
            except ksm_exceptions.InvalidToken:
                self.log.info('Invalid service token')
                request.service_token_valid = False
            else:
                # FIXME(jamielennox): The new behaviour for service tokens is
                # that they have to pass the policy check to be allowed.
                # Previously any token was accepted here. For now we will
                # continue to mark service tokens as valid if they are valid
                # but we will only allow service role tokens to do
                # allow_expired. In future we should reject any token that
                # isn't a service token here.
                role_names = set(serv_auth_ref.role_names)
                check = self._service_token_roles.intersection(role_names)
                role_check_passed = bool(check)

                # if service_token_role_required then the service token is only
                # valid if the roles check out. Otherwise at this point it is
                # true because keystone has already validated it.
                if self._service_token_roles_required:
                    request.service_token_valid = role_check_passed
                else:
                    if not self._service_token_warning_emitted:
                        self.log.warning('A valid token was submitted as '
                                         'a service token, but it was not '
                                         'a valid service token. This is '
                                         'incorrect but backwards '
                                         'compatible behaviour. This will '
                                         'be removed in future releases.')
                        # prevent log spam on every single request
                        self._service_token_warning_emitted = True

                    request.service_token_valid = True

                # allow_expired always requires passing the role check.
                allow_expired = role_check_passed

        if request.user_token:
            self.log.debug('Authenticating user token')
            try:
                data, user_auth_ref = self._do_fetch_token(
                    request.user_token,
                    allow_expired=allow_expired)
                self._validate_token(user_auth_ref,
                                     allow_expired=allow_expired)
                if not request.service_token:
                    self._confirm_token_bind(user_auth_ref, request)
            except ksm_exceptions.InvalidToken:
                self.log.info('Invalid user token')
                request.user_token_valid = False
            else:
                request.user_token_valid = True
                request.token_info = data

        request.token_auth = _user_plugin.UserAuthPlugin(user_auth_ref,
                                                         serv_auth_ref)
    def __call__(self, env, start_response):
        """Handle incoming request.

        Authenticate send downstream on success. Reject request if
        we can't authenticate.

        """
        def _fmt_msg(env):
            msg = ('user: user_id %s, project_id %s, roles %s '
                   'service: user_id %s, project_id %s, roles %s' % (
                       env.get('HTTP_X_USER_ID'), env.get('HTTP_X_PROJECT_ID'),
                       env.get('HTTP_X_ROLES'),
                       env.get('HTTP_X_SERVICE_USER_ID'),
                       env.get('HTTP_X_SERVICE_PROJECT_ID'),
                       env.get('HTTP_X_SERVICE_ROLES')))
            return msg

        self._token_cache.initialize(env)
        self._remove_auth_headers(env)

        try:
            user_auth_ref = None
            serv_auth_ref = None

            try:
                self._LOG.debug('Authenticating user token')
                user_token = self._get_user_token_from_header(env)
                user_token_info = self._validate_token(user_token, env)
                user_auth_ref = access.AccessInfo.factory(
                    body=user_token_info,
                    auth_token=user_token)
                env['keystone.token_info'] = user_token_info
                user_headers = self._build_user_headers(user_auth_ref,
                                                        user_token_info)
                self._add_headers(env, user_headers)
            except exc.InvalidToken:
                if self._delay_auth_decision:
                    self._LOG.info(
                        _LI('Invalid user token - deferring reject '
                            'downstream'))
                    self._add_headers(env, {'X-Identity-Status': 'Invalid'})
                else:
                    self._LOG.info(
                        _LI('Invalid user token - rejecting request'))
                    return self._reject_request(env, start_response)

            try:
                self._LOG.debug('Authenticating service token')
                serv_token = self._get_service_token_from_header(env)
                if serv_token is not None:
                    serv_token_info = self._validate_token(
                        serv_token, env)
                    serv_auth_ref = access.AccessInfo.factory(
                        body=serv_token_info,
                        auth_token=serv_token)
                    serv_headers = self._build_service_headers(serv_token_info)
                    self._add_headers(env, serv_headers)
            except exc.InvalidToken:
                if self._delay_auth_decision:
                    self._LOG.info(
                        _LI('Invalid service token - deferring reject '
                            'downstream'))
                    self._add_headers(env,
                                      {'X-Service-Identity-Status': 'Invalid'})
                else:
                    self._LOG.info(
                        _LI('Invalid service token - rejecting request'))
                    return self._reject_request(env, start_response)

            env['keystone.token_auth'] = _user_plugin.UserAuthPlugin(
                user_auth_ref, serv_auth_ref)

        except exc.ServiceError as e:
            self._LOG.critical(_LC('Unable to obtain admin token: %s'), e)
            return self._do_503_error(env, start_response)

        self._LOG.debug("Received request from %s", _fmt_msg(env))

        return self._call_app(env, start_response)