def check_auth(): """ Returns True/False if the username/password of Basic Auth match/not match Will also check role-based access controls if AAF integration configured :return boolean value """ try: if pecan.request.headers['Authorization'] and verify_user( pecan.request.headers['Authorization']): LOG.debug("Authorized username and password") plan = True else: plan = False auth_str = pecan.request.headers['Authorization'] user_pw = auth_str.split(' ')[1] decode_user_pw = base64.b64decode(user_pw) list_id_pw = decode_user_pw.split(':') LOG.error("Incorrect username={} / password={}".format( list_id_pw[0], list_id_pw[1])) except: error( '/errors/basic_auth_error', _('Unauthorized: The request does not ' 'provide any HTTP authentication (basic authentication)')) plan = False if not plan: error('/errors/authentication_error', _('Invalid credentials: username or password is incorrect')) return plan
def check_basic_auth(): ''' :return: boolean ''' try: if pecan.request.headers['Authorization'] and verify_user( pecan.request.headers['Authorization']): LOG.debug("Authorized username and password") plan = True else: plan = False auth_str = pecan.request.headers['Authorization'] user_pw = auth_str.split(' ')[1] decode_user_pw = base64.b64decode(user_pw) list_id_pw = decode_user_pw.split(':') LOG.error("Incorrect username={} / password={}".format( list_id_pw[0], list_id_pw[1])) except: error( '/errors/basic_auth_error', _('Unauthorized: The request does not provide any HTTP authentication (basic authetnication)' )) if not plan: error('/errors/authentication_error', _('Invalid credentials: username or password is incorrect')) return plan
def index_post(self): """Create a Plan""" # Look for duplicate keys in the YAML/JSON, first in the # entire request, and then again if the template parameter # value is itself an embedded JSON/YAML string. where = "API Request" try: parsed = yaml.load(pecan.request.text, validator.UniqueKeyLoader) if 'template' in parsed: where = "Template" template = parsed['template'] if isinstance(template, six.string_types): yaml.load(template, validator.UniqueKeyLoader) except ConstructorError as exc: # Only bail on the duplicate key problem (problem and problem_mark # attributes are available in ConstructorError): if exc.problem is \ validator.UniqueKeyLoader.DUPLICATE_KEY_PROBLEM_MARK: # ConstructorError messages have a two line snippet. # Grab it, get rid of the second line, and strip any # remaining whitespace so we can fashion a one line msg. snippet = exc.problem_mark.get_snippet() snippet = snippet.split('\n')[0].strip() msg = _('{} has a duplicate key on line {}: {}') error('/errors/invalid', msg.format(where, exc.problem_mark.line + 1, snippet)) except Exception as exc: # Let all others pass through for now. pass args = pecan.request.json # Print request id from SNIOR at the beginning of API component if args and args['name']: LOG.info('Plan name: {}'.format(args['name'])) auth_flag = CONF.conductor_api.basic_auth_secure or CONF.aaf_api.is_aaf_enabled # Create the plan only when the basic authentication is disabled or pass the authenticaiton check if not auth_flag or \ (auth_flag and check_auth()): plan = self.plan_create(args) if not plan: error('/errors/server_error', _('Unable to create Plan.')) else: pecan.response.status = 201 return plan
def __init__(self, uuid4): """Initializer.""" self.uuid = uuid4 self.plan = self.plans_get(plan_id=self.uuid) if not self.plan: error('/errors/not_found', _('Plan {} not found').format(self.uuid)) pecan.request.context['plan_id'] = self.uuid
def __init__(self, uuid4): """Initializer.""" self.uuid = uuid4 self.triage = self.triage_get(id=self.uuid) if not self.triage: error('/errors/not_found', _('DAta {} not found').format(self.uuid)) pecan.request.context['id'] = self.uuid
def index_post(self): args = pecan.request.json if check_basic_auth(): response = self.load(args) if not response: error('/errors/server_error', _('Unable to insert')) else: pecan.response.status = 201 return response
def index_post(self): args = pecan.request.json if check_basic_auth(): response = self.test_rule(args) if not response: error('/errors/server_error', _('Unable to release orders')) else: pecan.response.status = 201 return response
def unauthorized(self, **kw): """401""" # This error is terse and opaque on purpose. # Don't give any clues to help AuthN along. pecan.response.status = 401 pecan.response.content_type = 'text/plain' LOG.error('unauthorized') traceback.print_stack() LOG.error(self.__class__) LOG.error(kw) pecan.response.body = _('Authentication required') LOG.error(pecan.response.body) return pecan.response
def index(self): """Catchall for unallowed methods""" message = _('The {} method is not allowed.').format( pecan.request.method) kwargs = {'allow': self.allow()} error('/errors/not_allowed', message, **kwargs)
# Copyright (c) 2015-2017 AT&T Intellectual Property # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # ------------------------------------------------------------------------- # from oslo_config import cfg from conductor.i18n import _ INV_PROVIDER_EXT_MANAGER_OPTS = [ cfg.ListOpt('extensions', default=['aai'], help=_('Extensions list to use')), ] def register_extension_manager_opts(cfg=cfg.CONF): cfg.register_opts(INV_PROVIDER_EXT_MANAGER_OPTS, 'inventory_provider')
def __call__(self, environ, start_response): # Request for this state, modified by replace_start_response() # and used when an error is being reported. state = {} latest_version = version.version_info.version_string() latest_version_semantic = latest_version.split('.') minor_version = latest_version_semantic[1] patch_version = latest_version_semantic[2] req_minor_version = environ.get('HTTP_X_MINORVERSION') req_patch_version = environ.get('HTTP_X_PATCHVERSION') version_auth_flag = CONF.version_auth.version_auth_flag conf_version_auth_token = CONF.version_auth.version_auth_token version_auth_token = environ.get('HTTP_VERSION_AUTH_TOKEN') if req_minor_version is not None: if int(req_minor_version) <= int(minor_version): minor_version = req_minor_version else: raise Exception(( 'Expecting minor version less than or equal to %s' % minor_version )) if req_patch_version is not None: if int(req_patch_version) <= int(patch_version): patch_version = req_patch_version else: raise Exception(( 'Not expecting a patch version but the entered patch version is not acceptable if it is not less than or equal to %s' % patch_version )) def replacement_start_response(status, headers, exc_info=None): """Overrides the default response to make errors parsable.""" try: status_code = int(status.split(' ')[0]) state['status_code'] = status_code except (ValueError, TypeError): # pragma: nocover raise Exception(( 'ErrorDocumentMiddleware received an invalid ' 'status %s' % status )) else: if (state['status_code'] // 100) not in (2, 3): # Remove some headers so we can replace them later # when we have the full error message and can # compute the length. headers = [(h, v) for (h, v) in headers if h not in ('Content-Length', 'Content-Type') ] # Save the headers in case we need to modify them. state['headers'] = headers if not version_auth_flag or \ (version_auth_flag and version_auth_token == conf_version_auth_token): state['headers'].append(('X-MinorVersion', minor_version)) state['headers'].append(('X-PatchVersion', patch_version)) state['headers'].append(('X-LatestVersion', latest_version)) return start_response(status, headers, exc_info) app_iter = self.app(environ, replacement_start_response) if (state['status_code'] // 100) not in (2, 3): req = webob.Request(environ) error = environ.get('translatable_error') user_locale = self.best_match_language(req.accept_language) if (req.accept.best_match(['application/json', 'application/xml']) == 'application/xml'): content_type = 'application/xml' try: # simple check xml is valid fault = etree.fromstring(b'\n'.join(app_iter)) # Add the translated error to the xml data if error is not None: for fault_string in fault.findall('faultstring'): fault_string.text = i18n.translate(error, user_locale) error_message = etree.tostring(fault) body = b''.join((b'<error_message>', error_message, b'</error_message>')) except etree.XMLSyntaxError as err: LOG.error(_('Error parsing HTTP response: %s'), err) error_message = state['status_code'] body = '<error_message>%s</error_message>' % error_message if six.PY3: body = body.encode('utf-8') else: content_type = 'application/json' app_data = b'\n'.join(app_iter) if six.PY3: app_data = app_data.decode('utf-8') try: fault = list(json.loads(app_data)) if error is not None and 'faultstring' in fault: fault['faultstring'] = i18n.translate(error, user_locale) except ValueError as err: fault = app_data body = json.dumps({'error_message': fault}) if six.PY3: body = body.encode('utf-8') state['headers'].append(('Content-Length', str(len(body)))) state['headers'].append(('Content-Type', content_type)) if not version_auth_flag or \ (version_auth_flag and version_auth_token == conf_version_auth_token): state['headers'].append(('X-minorVersion', minor_version)) state['headers'].append(('X-patchVersion', patch_version)) state['headers'].append(('X-latestVersion', latest_version)) body = [body] else: body = app_iter return body
def index(self): """Catchall for unallowed methods""" message = _('The %s method is not allowed.') % pecan.request.method kwargs = {} error('/errors/not_allowed', message, **kwargs)