"Fossies" - the Fresh Open Source Software Archive

Member "keystone-17.0.0/keystone/auth/plugins/token.py" (13 May 2020, 5084 Bytes) of package /linux/misc/openstack/keystone-17.0.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. For more information about "token.py" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 16.0.1_vs_17.0.0.

    1 # Copyright 2013 OpenStack Foundation
    2 #
    3 # Licensed under the Apache License, Version 2.0 (the "License"); you may
    4 # not use this file except in compliance with the License. You may obtain
    5 # a copy of the License at
    6 #
    7 #      http://www.apache.org/licenses/LICENSE-2.0
    8 #
    9 # Unless required by applicable law or agreed to in writing, software
   10 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
   11 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
   12 # License for the specific language governing permissions and limitations
   13 # under the License.
   14 
   15 import flask
   16 from oslo_log import log
   17 
   18 from keystone.auth.plugins import base
   19 from keystone.auth.plugins import mapped
   20 from keystone.common import provider_api
   21 import keystone.conf
   22 from keystone import exception
   23 from keystone.i18n import _
   24 
   25 
   26 LOG = log.getLogger(__name__)
   27 
   28 CONF = keystone.conf.CONF
   29 PROVIDERS = provider_api.ProviderAPIs
   30 
   31 
   32 class Token(base.AuthMethodHandler):
   33 
   34     def _get_token_ref(self, auth_payload):
   35         token_id = auth_payload['id']
   36         return PROVIDERS.token_provider_api.validate_token(token_id)
   37 
   38     def authenticate(self, auth_payload):
   39         if 'id' not in auth_payload:
   40             raise exception.ValidationError(attribute='id',
   41                                             target='token')
   42         token = self._get_token_ref(auth_payload)
   43         if token.is_federated and PROVIDERS.federation_api:
   44             response_data = mapped.handle_scoped_token(
   45                 token, PROVIDERS.federation_api,
   46                 PROVIDERS.identity_api
   47             )
   48         else:
   49             response_data = token_authenticate(token)
   50 
   51         # NOTE(notmorgan): The Token auth method is *very* special and sets the
   52         # previous values to the method_names. This is because it can be used
   53         # for re-scoping and we want to maintain the values. Most
   54         # AuthMethodHandlers do no such thing and this is not required.
   55         response_data.setdefault('method_names', []).extend(token.methods)
   56 
   57         return base.AuthHandlerResponse(status=True, response_body=None,
   58                                         response_data=response_data)
   59 
   60 
   61 def token_authenticate(token):
   62     response_data = {}
   63     try:
   64 
   65         # Do not allow tokens used for delegation to
   66         # create another token, or perform any changes of
   67         # state in Keystone. To do so is to invite elevation of
   68         # privilege attacks
   69 
   70         json_body = flask.request.get_json(silent=True, force=True) or {}
   71         project_scoped = 'project' in json_body['auth'].get(
   72             'scope', {}
   73         )
   74         domain_scoped = 'domain' in json_body['auth'].get(
   75             'scope', {}
   76         )
   77 
   78         if token.oauth_scoped:
   79             raise exception.ForbiddenAction(
   80                 action=_(
   81                     'Using OAuth-scoped token to create another token. '
   82                     'Create a new OAuth-scoped token instead'))
   83         elif token.trust_scoped:
   84             raise exception.ForbiddenAction(
   85                 action=_(
   86                     'Using trust-scoped token to create another token. '
   87                     'Create a new trust-scoped token instead'))
   88         elif token.system_scoped and (project_scoped or domain_scoped):
   89             raise exception.ForbiddenAction(
   90                 action=_(
   91                     'Using a system-scoped token to create a project-scoped '
   92                     'or domain-scoped token is not allowed.'
   93                 )
   94             )
   95 
   96         if not CONF.token.allow_rescope_scoped_token:
   97             # Do not allow conversion from scoped tokens.
   98             if token.project_scoped or token.domain_scoped:
   99                 raise exception.ForbiddenAction(
  100                     action=_('rescope a scoped token'))
  101 
  102         # New tokens maintain the audit_id of the original token in the
  103         # chain (if possible) as the second element in the audit data
  104         # structure. Look for the last element in the audit data structure
  105         # which will be either the audit_id of the token (in the case of
  106         # a token that has not been rescoped) or the audit_chain id (in
  107         # the case of a token that has been rescoped).
  108         try:
  109             token_audit_id = token.parent_audit_id or token.audit_id
  110         except IndexError:
  111             # NOTE(morganfainberg): In the case this is a token that was
  112             # issued prior to audit id existing, the chain is not tracked.
  113             token_audit_id = None
  114 
  115         # To prevent users from never having to re-authenticate, the original
  116         # token expiration time is maintained in the new token. Not doing this
  117         # would make it possible for a user to continuously bump token
  118         # expiration through token rescoping without proving their identity.
  119         response_data.setdefault('expires_at', token.expires_at)
  120         response_data['audit_id'] = token_audit_id
  121         response_data.setdefault('user_id', token.user_id)
  122 
  123         return response_data
  124 
  125     except AssertionError as e:
  126         LOG.error(e)
  127         raise exception.Unauthorized(e)