def common_error_handler(exception): """ Generally, each route handler should be decorated with @dss_handler, which manages exceptions. The two cases that fail are: 1. handlers that are not decorated. 2. handlers that return a code that is not in the swagger spec. In both cases, the exception would be punted here, and we return this very generic error that also happens to bypass all validation. """ problem = { 'status': requests.codes.server_error, 'code': "unhandled_exception", 'title': str(exception), 'stacktrace': traceback.format_exc(), } if isinstance(exception, (OAuthProblem, OAuthResponseProblem, OAuthScopeProblem, Forbidden)): problem['status'] = exception.code problem['code'] = exception.__class__.__name__ problem['title'] = exception.description return FlaskApi.get_response( ConnexionResponse( status_code=problem['status'], mimetype="application/problem+json", content_type="application/problem+json", body=problem, ))
def wrapper(*args, **kwargs): try: return func(*args, **kwargs) except werkzeug.exceptions.HTTPException as ex: status = ex.code code = ex.name title = str(ex) stacktrace = traceback.format_exc() headers = None except DRSException as ex: status = ex.status code = ex.code title = ex.message stacktrace = traceback.format_exc() headers = None except Exception as ex: status = requests.codes.server_error code = "unhandled_exception" title = str(ex) stacktrace = traceback.format_exc() headers = None logger.error(stacktrace) return ConnexionResponse(status_code=status, mimetype="application/problem+json", content_type="application/problem+json", headers=headers, body={ 'status': status, 'code': code, 'title': title, 'stacktrace': stacktrace, })
def authorize(): query_params = request.args.copy() if request.args else {} openid_provider = Config.get_openid_provider() query_params["openid_provider"] = openid_provider query_params['response_type'] = "code" client_id = query_params.get("client_id") client_id = client_id if client_id != 'None' else None if client_id: query_params['audience'] = Config.get_audience() auth_params = query_params else: state = base64.b64encode(json.dumps(query_params).encode()).decode() # TODO: set random state oauth2_config = Config.get_oauth2_config() auth_params = dict( client_id=oauth2_config[openid_provider]["client_id"], response_type="code", scope="openid email profile", redirect_uri=oauth2_config[openid_provider]["redirect_uri"], state=state, audience=Config.get_audience(), prompt=query_params.get('prompt') if query_params.get('prompt') == 'none' else 'login') dest = furl(get_openid_config(openid_provider)["authorization_endpoint"], query_params=auth_params) return ConnexionResponse(status_code=requests.codes.found, headers=dict(Location=dest.url))
def _framework_to_connexion_response(cls, response, mimetype): """ Cast framework response class to ConnexionResponse used for schema validation """ return ConnexionResponse(status_code=response.status, mimetype=mimetype, content_type=response.content_type, headers=response.headers, body=response.body)
async def get_configuration_node(request, node_id, pretty=False, wait_for_complete=False, section=None, field=None, raw: bool = False): """Get a specified node's configuration (ossec.conf) Parameters ---------- node_id : str Cluster node name pretty : bool Show results in human-readable format. It only works when `raw` is False (JSON format). Default `True` wait_for_complete : bool, optional Disable response timeout or not. Default `False` section : str Indicates the wazuh configuration section field : str Indicates a section child, e.g, fields for rule section are include, decoder_dir, etc. raw : bool, optional Whether to return the file content in raw or JSON format. Default `True` Returns ------- web.json_response or ConnexionResponse Depending on the `raw` parameter, it will return an object or other: raw=True -> ConnexionResponse (application/xml) raw=False (default) -> web.json_response (application/json) If any exception was raised, it will return a web.json_response with details. """ f_kwargs = { 'node_id': node_id, 'section': section, 'field': field, 'raw': raw } nodes = raise_if_exc(await get_system_nodes()) dapi = DistributedAPI( f=manager.read_ossec_conf, f_kwargs=remove_nones_to_dict(f_kwargs), request_type='distributed_master', is_async=False, wait_for_complete=wait_for_complete, logger=logger, rbac_permissions=request['token_info']['rbac_policies'], nodes=nodes) data = raise_if_exc(await dapi.distribute_function()) if isinstance(data, AffectedItemsWazuhResult): response = web.json_response(data=data, status=200, dumps=prettify if pretty else dumps) else: response = ConnexionResponse(body=data["message"], mimetype='application/xml', content_type='application/xml') return response
async def get_download_file(request, pretty: bool = False, wait_for_complete: bool = False, filename: str = None): """Download an specified decoder file. :param pretty: Show results in human-readable format :param wait_for_complete: Disable timeout response :param filename: Filename to download. :return: Raw XML file """ f_kwargs = {'filename': filename} dapi = DistributedAPI( f=rule_framework.get_file, f_kwargs=remove_nones_to_dict(f_kwargs), request_type='local_any', is_async=False, wait_for_complete=wait_for_complete, logger=logger, rbac_permissions=request['token_info']['rbac_policies']) data = raise_if_exc(await dapi.distribute_function()) response = ConnexionResponse(body=data["message"], mimetype='application/xml') return response
def image_id_image_get(id_): # noqa: E501 """Fetch the image file belonging to the image object identified by the ID in the path. # noqa: E501 :param id_: ID number of the image to fetch. :type id_: int :rtype: bytearray """ engine = QueryEngine() i = engine.query_image(id_) if not i: return Error('404', f'Image {id_} not found'), 404 try: fname = os.path.join(IMG_DIR, i.file) with open(fname, 'rb') as f: data = f.read() except FileNotFoundError: return Error('404', f'Image file not found'), 404 except PermissionError: return Error('404', f'Permission denied'), 403 response = ConnexionResponse(status_code=200, mimetype=i.mime, content_type=f'{i.mime}; charset=binary', body=data, headers={}) return response
async def get_group_file_xml(request, group_id, file_name, pretty=False, wait_for_complete=False): """Get the files placed under the group directory in xml format. :param pretty: Show results in human-readable format :param wait_for_complete: Disable timeout response :param group_id: Group ID. :param file_name: Filename :return: File data in XML """ f_kwargs = { 'group_list': [group_id], 'filename': file_name, 'type_conf': request.query.get('type', None), 'return_format': 'xml' } dapi = DistributedAPI( f=agent.get_file_conf, f_kwargs=remove_nones_to_dict(f_kwargs), request_type='local_master', is_async=False, wait_for_complete=wait_for_complete, logger=logger, rbac_permissions=request['token_info']['rbac_policies']) data = raise_if_exc(await dapi.distribute_function()) response = ConnexionResponse(body=data["data"], mimetype='application/xml') return response
def test_get_response_from_connexion_response(api): response = yield from api.get_response(ConnexionResponse(status_code=201, mimetype='text/plain', body='foo', headers={'X-header': 'value'})) assert isinstance(response, web.Response) assert response.status == 201 assert response.body == b'foo' assert response.content_type == 'text/plain' assert dict(response.headers) == {'Content-Type': 'text/plain; charset=utf-8', 'X-header': 'value'}
def post(body): """Provide detailed information about a specific place.""" result = collect_place_details( body['place_id'], body['name'], body['address'], ) return ConnexionResponse(body=dataclasses.asdict(result))
async def aiohttp_users_post(user): if "name" not in user: return ConnexionResponse(body={"error": "name is undefined"}, status_code=400, content_type='application/json') user['id'] = len(USERS) + 1 USERS.append(user) return aiohttp.web.json_response(data=USERS[-1], status=201)
def get_connexion_response(cls, response): return ConnexionResponse( status_code=response.status_code, mimetype=response.mimetype, content_type=response.content_type, headers=response.headers, body=response.get_data(), )
def rfc7807error_response(title, status, detail=None): body = {'title': title, 'status': status} if detail: body['detail'] = detail return ConnexionResponse(status_code=status, mimetype=RFC7807_MIMETYPE, content_type=RFC7807_MIMETYPE, body=body)
def readiness(): """Readiness probe that checks if connection to DB is established.""" try: # TODO: Check if there is a better way to check database connection can be established. assert db.session.query(literal_column("1")).all() return "ready", 200, {"Content-Type": "text/plain"} except: # Bad gateway since database can't be reached. return ConnexionResponse(status_code=502)
def problem(status, title, detail=None, type=None, instance=None, headers=None, ext=None): """ Returns a `Problem Details <https://tools.ietf.org/html/draft-ietf-appsawg-http-problem-00>`_ error response. :param status: The HTTP status code generated by the origin server for this occurrence of the problem. :type status: int :param title: A short, human-readable summary of the problem type. It SHOULD NOT change from occurrence to occurrence of the problem, except for purposes of localisation. :type title: str :param detail: An human readable explanation specific to this occurrence of the problem. :type detail: str :param type: An absolute URI that identifies the problem type. When dereferenced, it SHOULD provide human-readable documentation for the problem type (e.g., using HTML). When this member is not present its value is assumed to be "about:blank". :type: type: str :param instance: An absolute URI that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced. :type instance: str :param headers: HTTP headers to include in the response :type headers: dict | None :param ext: Extension members to include in the body :type ext: dict | None :return: error response :rtype: ConnexionResponse """ if not type: type = 'about:blank' problem_response = ApiStatus(code=status, msg=title, data=[]) if detail: problem_response.data.append( ProtobufAny(type_url='detail', value=detail)) if instance: problem_response.data.append( ProtobufAny(type_url='instance', value=instance)) if ext: problem_response.data.append(ProtobufAny(type_url='ext', value=ext)) mimetype = content_type = 'application/problem+json' # return 200 http status code # http://wiki.envisioncn.com/pages/viewpage.action?pageId=13057195 return ConnexionResponse(200, mimetype, content_type, body=problem_response, headers=headers)
def logout(): oauth2_config = Config.get_oauth2_config() openid_provider = Config.get_openid_provider() query_params = getattr(Config.app.current_request, 'query_params') client_id = oauth2_config[openid_provider][ "client_id"] if not query_params else query_params.get('client_id') url = furl(f"https://{openid_provider}/v2/logout", query_params=dict(client_id=client_id)).url return ConnexionResponse(status_code=requests.codes.ok, headers=dict(Location=url))
def _framework_to_connexion_response(cls, response, mimetype): """ Cast framework response class to ConnexionResponse used for schema validation """ body = None if hasattr(response, "body"): # StreamResponse and FileResponse don't have body body = response.body return ConnexionResponse(status_code=response.status, mimetype=mimetype, content_type=response.content_type, headers=response.headers, body=body)
def get_connexion_response(cls, response, mimetype=None): response.body = cls._cast_body(response.body, mimetype) if isinstance(response, ConnexionResponse): return response return ConnexionResponse(status_code=response.status, mimetype=response.content_type, content_type=response.content_type, headers=response.headers, body=response.body)
def search(location): """Return a list of all places nearby our coordinates.""" # Define data. places_api_key = os.environ['RYR_COLLECTOR_GOOGLE_PLACES_API_KEY'] # Prepare client. gmap = GoogleCollector() gmap.authenticate(api_key=places_api_key) # Retrieve nearby places. places_nearby = gmap.search_places_nearby(location) return ConnexionResponse(body=places_nearby)
def get_connexion_response(cls, response, mimetype=None): if isinstance(response, ConnexionResponse): return response if not isinstance(response, flask.current_app.response_class): response = cls.get_response(response, mimetype) return ConnexionResponse( status_code=response.status_code, mimetype=response.mimetype, content_type=response.content_type, headers=response.headers, body=response.get_data(), )
def health_check(*args, **kwargs): health_checks = dict() health_checks.update(**Config.get_directory().health_checks(), **get_openip_health_status(), **authorize.health_checks()) if all([check == 'ok' for check in health_checks.values()]): body = dict(health_status='ok', services=health_checks) status = 200 headers = {"Content-Type": "application/json"} else: body = dict(health_status='unhealthy', services=health_checks) status = 500 headers = {"Content-Type": "application/json+problem"} return ConnexionResponse(status_code=status, headers=headers, body=body)
def serve_openid_config(): """ Part of OIDC """ auth_host = request.headers['host'] if auth_host != os.environ["API_DOMAIN_NAME"]: raise FusilladeHTTPException( status=400, title="Bad Request", detail= f"host: {auth_host}, is not supported. host must be {os.environ['API_DOMAIN_NAME']}." ) openid_config = get_openid_config(Config.get_openid_provider()).copy() openid_config.update(**proxied_endpoints) return ConnexionResponse(body=openid_config, status_code=requests.codes.ok)
async def get_file(request, pretty: bool = False, wait_for_complete: bool = False, filename: str = None, raw: bool = False): """"Get content of one CDB list file, in raw or dict format. Parameters ---------- pretty : bool Show results in human-readable format. wait_for_complete : bool Disable timeout response. filename : str Name of filename to get data from. raw : bool, optional Respond in raw format. Returns ------- web.json_response, ConnexionResponse Depending on the `raw` parameter, it will return an object or other: raw=True -> ConnexionResponse (text/plain) raw=False (default) -> web.json_response (application/json) If any exception was raised, it will return a web.json_response with details. """ f_kwargs = {'filename': filename, 'raw': raw} dapi = DistributedAPI( f=cdb_list.get_list_file, f_kwargs=remove_nones_to_dict(f_kwargs), request_type='local_master', is_async=False, wait_for_complete=wait_for_complete, logger=logger, rbac_permissions=request['token_info']['rbac_policies']) data = raise_if_exc(await dapi.distribute_function()) if isinstance(data, AffectedItemsWazuhResult): response = web.json_response(data=data, status=200, dumps=prettify if pretty else dumps) else: response = ConnexionResponse(body=data["message"], mimetype='text/plain', content_type='text/plain') return response
async def get_file(request, pretty: bool = False, wait_for_complete: bool = False, filename: str = None, raw: bool = False): """Get rule file content. Parameters ---------- pretty : bool, optional Show results in human-readable format. It only works when `raw` is False (JSON format). Default `True` wait_for_complete : bool, optional Disable response timeout or not. Default `False` filename : str Filename to download. raw : bool, optional Whether to return the file content in raw or JSON format. Default `False` Returns ------- web.json_response or ConnexionResponse Depending on the `raw` parameter, it will return an object or other: raw=True -> ConnexionResponse (application/xml) raw=False (default) -> web.json_response (application/json) If any exception was raised, it will return a web.json_response with details. """ f_kwargs = {'filename': filename, 'raw': raw} dapi = DistributedAPI( f=rule_framework.get_rule_file, f_kwargs=remove_nones_to_dict(f_kwargs), request_type='local_master', is_async=False, wait_for_complete=wait_for_complete, logger=logger, rbac_permissions=request['token_info']['rbac_policies']) data = raise_if_exc(await dapi.distribute_function()) if isinstance(data, AffectedItemsWazuhResult): response = web.json_response(data=data, status=200, dumps=prettify if pretty else dumps) else: response = ConnexionResponse(body=data["message"], mimetype='application/xml', content_type='application/xml') return response
def dss_notification(body): bundle_uuid = body['match']['bundle_uuid'] bundle_version = body['match']['bundle_version'] subscription_id = body['subscription_id'] event_type = body['event_type'] payload = { 'bundle_uuid': bundle_uuid, 'bundle_version': bundle_version, 'event_type': event_type, } queue_url = matrix_infra_config.notification_q_url sqs_handler.add_message_to_queue(queue_url, payload) return ConnexionResponse( status_code=requests.codes.ok, body=f"Received notification from subscription {subscription_id}: " f"{event_type} {bundle_uuid}.{bundle_version}")
def wrapper(*args, **kwargs): method, path = request.method, request.path if os.environ.get('DSS_READ_ONLY_MODE') is None or "GET" == method or ("POST" == method and "search" in path): try: return func(*args, **kwargs) except werkzeug.exceptions.HTTPException as ex: status = ex.code code = ex.name title = str(ex) stacktrace = traceback.format_exc() except DSSException as ex: status = ex.status code = ex.code title = ex.message stacktrace = traceback.format_exc() except Exception as ex: status = requests.codes.server_error code = "unhandled_exception" title = str(ex) stacktrace = traceback.format_exc() headers = None logger.error(json.dumps(dict(status=status, code=code, title=title, stacktrace=stacktrace), indent=4)) else: status = requests.codes.unavailable code = "read_only" title = "The DSS is currently read-only" stacktrace = "" headers = {'Retry-After': '600'} if include_retry_after_header(return_code=status, method=method, uri=path): headers = {'Retry-After': '10'} return ConnexionResponse( status_code=status, mimetype="application/problem+json", content_type="application/problem+json", headers=headers, body={ 'status': status, 'code': code, 'title': title, 'stacktrace': stacktrace, })
def click_get(query, doc_id): # noqa: E501 """Click-through redirector for capturing implicit feedback :param query: Original query content :type query: str :param url: URL of selected result :type url: str :rtype: None """ url = mainEngine.get_metadata_for_doc_id(doc_id).get("url") #FIXME: Validate that URL is something from the index metadata! response = ConnexionResponse(status_code=302, headers={'Location': url}) #,"X-Debug": r[0]["url"]}) return response
def wrapper(request): try: return origwrapper(request) except DSSBindingException as ex: status = ex.status code = ex.code title = ex.message stacktrace = traceback.format_exc() return FlaskApi.get_response( ConnexionResponse( status_code=status, mimetype="application/problem+json", content_type="application/problem+json", body={ 'status': status, 'code': code, 'title': title, 'stacktrace': stacktrace, }, ))
async def get_date(): return ConnexionResponse(body={'value': datetime.date(2000, 1, 2)})
async def get_uuid(): return ConnexionResponse( body={'value': uuid.UUID(hex='e7ff66d0-3ec2-4c4e-bed0-6e4723c24c51')})