"Fossies" - the Fresh Open Source Software Archive

Member "masakari-9.0.0/masakari/api/auth.py" (13 May 2020, 6042 Bytes) of package /linux/misc/openstack/masakari-9.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 "auth.py" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 8.0.0_vs_9.0.0.

    1 # Copyright (c) 2016 NTT DATA
    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 Common Auth Middleware.
   16 
   17 """
   18 
   19 from oslo_log import log as logging
   20 from oslo_middleware import request_id
   21 from oslo_serialization import jsonutils
   22 import webob.dec
   23 import webob.exc
   24 
   25 import masakari.conf
   26 from masakari import context
   27 from masakari.i18n import _
   28 from masakari import wsgi
   29 
   30 
   31 CONF = masakari.conf.CONF
   32 LOG = logging.getLogger(__name__)
   33 
   34 
   35 def _load_pipeline(loader, pipeline):
   36     filters = [loader.get_filter(n) for n in pipeline[:-1]]
   37     app = loader.get_app(pipeline[-1])
   38     filters.reverse()
   39     for filter in filters:
   40         app = filter(app)
   41     return app
   42 
   43 
   44 def pipeline_factory_v1(loader, global_conf, **local_conf):
   45     """A paste pipeline replica that keys off of auth_strategy."""
   46 
   47     return _load_pipeline(loader, local_conf[CONF.auth_strategy].split())
   48 
   49 
   50 class InjectContext(wsgi.Middleware):
   51     """Add a 'masakari.context' to WSGI environ."""
   52 
   53     def __init__(self, context, *args, **kwargs):
   54         self.context = context
   55         super(InjectContext, self).__init__(*args, **kwargs)
   56 
   57     @webob.dec.wsgify(RequestClass=wsgi.Request)
   58     def __call__(self, req):
   59         req.environ['masakari.context'] = self.context
   60         return self.application
   61 
   62 
   63 class MasakariKeystoneContext(wsgi.Middleware):
   64     """Make a request context from keystone headers."""
   65 
   66     @webob.dec.wsgify(RequestClass=wsgi.Request)
   67     def __call__(self, req):
   68         user_id = req.headers.get('X_USER')
   69         user_id = req.headers.get('X_USER_ID', user_id)
   70         if user_id is None:
   71             LOG.debug("Neither X_USER_ID nor X_USER found in request")
   72             return webob.exc.HTTPUnauthorized()
   73 
   74         roles = self._get_roles(req)
   75 
   76         if 'X_TENANT_ID' in req.headers:
   77             # This is the new header since Keystone went to ID/Name
   78             project_id = req.headers['X_TENANT_ID']
   79         else:
   80             # This is for legacy compatibility
   81             project_id = req.headers['X_TENANT']
   82         project_name = req.headers.get('X_TENANT_NAME')
   83         user_name = req.headers.get('X_USER_NAME')
   84 
   85         req_id = req.environ.get(request_id.ENV_REQUEST_ID)
   86 
   87         # Get the auth token
   88         auth_token = req.headers.get('X_AUTH_TOKEN',
   89                                      req.headers.get('X_STORAGE_TOKEN'))
   90 
   91         # Build a context, including the auth_token...
   92         remote_address = req.remote_addr
   93         if CONF.use_forwarded_for:
   94             remote_address = req.headers.get('X-Forwarded-For', remote_address)
   95 
   96         service_catalog = None
   97         if req.headers.get('X_SERVICE_CATALOG') is not None:
   98             try:
   99                 catalog_header = req.headers.get('X_SERVICE_CATALOG')
  100                 service_catalog = jsonutils.loads(catalog_header)
  101             except ValueError:
  102                 raise webob.exc.HTTPInternalServerError(
  103                     _('Invalid service catalog json.'))
  104 
  105         # NOTE: This is a full auth plugin set by auth_token
  106         # middleware in newer versions.
  107         user_auth_plugin = req.environ.get('keystone.token_auth')
  108 
  109         ctx = context.RequestContext(user_id,
  110                                      project_id,
  111                                      user_name=user_name,
  112                                      project_name=project_name,
  113                                      roles=roles,
  114                                      auth_token=auth_token,
  115                                      remote_address=remote_address,
  116                                      service_catalog=service_catalog,
  117                                      request_id=req_id,
  118                                      user_auth_plugin=user_auth_plugin)
  119 
  120         req.environ['masakari.context'] = ctx
  121         return self.application
  122 
  123     def _get_roles(self, req):
  124         """Get the list of roles."""
  125 
  126         roles = req.headers.get('X_ROLES', '')
  127         return [r.strip() for r in roles.split(',')]
  128 
  129 
  130 class NoAuthMiddleware(wsgi.Middleware):
  131     """Return a fake token if one isn't specified.
  132 
  133     noauth2 provides admin privs if 'admin' is provided as the user id.
  134 
  135     """
  136 
  137     @webob.dec.wsgify(RequestClass=wsgi.Request)
  138     def __call__(self, req):
  139         user_id = req.headers.get('X_USER', 'admin')
  140         user_id = req.headers.get('X_USER_ID', user_id)
  141 
  142         project_name = req.headers.get('X_TENANT_NAME')
  143         user_name = req.headers.get('X_USER_NAME')
  144 
  145         req_id = req.environ.get(request_id.ENV_REQUEST_ID)
  146 
  147         remote_address = req.remote_addr
  148         if CONF.use_forwarded_for:
  149             remote_address = req.headers.get('X-Forwarded-For', remote_address)
  150 
  151         service_catalog = None
  152         if req.headers.get('X_SERVICE_CATALOG') is not None:
  153             try:
  154                 catalog_header = req.headers.get('X_SERVICE_CATALOG')
  155                 service_catalog = jsonutils.loads(catalog_header)
  156             except ValueError:
  157                 raise webob.exc.HTTPInternalServerError(
  158                     _('Invalid service catalog json.'))
  159 
  160         ctx = context.RequestContext(user_id,
  161                                      user_name=user_name,
  162                                      project_name=project_name,
  163                                      remote_address=remote_address,
  164                                      service_catalog=service_catalog,
  165                                      request_id=req_id,
  166                                      is_admin=True)
  167 
  168         req.environ['masakari.context'] = ctx
  169         return self.application