13be91013885a57f91127fecc9433bef5f0bafbc
[pti/o2.git] / o2common / authmw / authmiddleware.py
1 # Copyright (C) 2022 Wind River Systems, Inc.
2 #
3 #  Licensed under the Apache License, Version 2.0 (the "License");
4 #  you may not use this file except in compliance with the License.
5 #  You may obtain 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,
11 #  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 #  See the License for the specific language governing permissions and
13 #  limitations under the License.
14
15 from werkzeug.wrappers import Request, Response
16 from o2common.helper import o2logging
17 from o2common.authmw.authprov import auth_definer
18
19 logger = o2logging.get_logger(__name__)
20
21
22 class AuthRequiredExp(Exception):
23     def __init__(self, value):
24         self.value = value
25
26     def dictize(self):
27         return {
28             'WWW-Authenticate': '{}'.format(self.value)}
29
30
31 class AuthFailureExp(Exception):
32     def __init__(self, value):
33         self.value = value
34
35     def dictize(self):
36         return {
37             'WWW-Authenticate': '{}'.format(self.value)}
38
39
40 def _response_wrapper(environ, start_response, header):
41     res = Response(headers=header,
42                    mimetype='text/plain', status=401)
43     return res(environ, start_response)
44
45
46 def _internal_err_response_wrapper(environ, start_response):
47     res = Response(mimetype='text/plain', status=500)
48     return res(environ, start_response)
49
50
51 class authmiddleware():
52
53     '''
54     Auth WSGI middleware
55     '''
56
57     def __init__(self, app):
58         self.app = app
59
60     def __call__(self, environ, start_response):
61         logger.info(__name__ + 'authentication middleware')
62         req = Request(environ, populate_request=True, shallow=True)
63         try:
64             auth_header = req.headers['Authorization']
65
66             if auth_header:
67                 auth_token = auth_header.split(" ")[1]
68
69                 ad = auth_definer('oauth')
70                 # invoke underlying auth mdw to make k8s/keystone api
71                 ret = ad.authenticate(auth_token)
72                 if ret is True:
73                     logger.info(
74                         "auth success with oauth token: " + auth_token)
75                     try:
76                         return self.app(environ, start_response)
77                     except Exception as ex:
78                         logger.error(
79                             'Internal exception happend \
80                             ed {}'.format(str(ex)), exc_info=True)
81                         return \
82                             _internal_err_response_wrapper(environ,
83                                                            start_response)
84                 else:
85                     raise AuthFailureExp(
86                         'Bearer realm="Authentication Failed"')
87             else:
88                 raise AuthRequiredExp('Bearer realm="Authentication Required"')
89         except AuthRequiredExp as ex:
90             return _response_wrapper(environ, start_response, ex.dictize())
91         except AuthFailureExp as ex:
92             return _response_wrapper(environ, start_response, ex.dictize())
93         except Exception as ex:
94             logger.error('Internal exception happended {}'.format(
95                 str(ex)), exc_info=True)
96             return _internal_err_response_wrapper(environ, start_response)