From e9dace33dca9254e05a86e79a865ab68e33e29d6 Mon Sep 17 00:00:00 2001 From: Arik Alon Date: Thu, 5 May 2022 10:38:52 +0300 Subject: [PATCH] Safe logging --- src/robusta/integrations/receiver.py | 33 +++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/src/robusta/integrations/receiver.py b/src/robusta/integrations/receiver.py index d5f4e3f35..158b7cde6 100644 --- a/src/robusta/integrations/receiver.py +++ b/src/robusta/integrations/receiver.py @@ -98,14 +98,16 @@ def __sync_response(cls, status_code: int, request_id: str, data) -> Dict: def __exec_external_request( self, action_request: ExternalActionRequest, validate_timestamp: bool ): + logging.info(f"Callback `{action_request.body.action_name}` {to_safe_str(action_request.body.action_params)}") sync_response = action_request.request_id != "" # if request_id is set, we need to write back the response if not self.__validate_request(action_request, validate_timestamp): - logging.error(f"Failed to validate action request {action_request}") + req_json = action_request.json(exclude={"body"}) + body_json = action_request.body.json(exclude={"action_params"}) # action params already printed above + logging.error(f"Failed to validate action request {req_json} {body_json}") if sync_response: self.ws.send(data=json.dumps(self.__sync_response(401, action_request.request_id, ""))) return - logging.info(f"got callback `{action_request.body.action_name}` {to_safe_str(action_request.body.action_params)}") response = self.event_handler.run_external_action( action_request.body.action_name, action_request.body.action_params, @@ -120,7 +122,6 @@ def __exec_external_request( def on_message(self, ws, message): # TODO: use typed pydantic classes here? - logging.debug(f"received incoming message {message}") incoming_event = json.loads(message) actions = incoming_event.get("actions", None) if actions: # this is slack callback format @@ -128,13 +129,15 @@ def on_message(self, ws, message): # which container the actual action details we need to run. # This wrapper format is part of the slack API, and cannot be changed by us. for action in actions: + raw_action = action.get("value", None) try: self.__exec_external_request( - ExternalActionRequest.parse_raw(action["value"]), False + ExternalActionRequest.parse_raw(raw_action), False ) except Exception: logging.error( - f"Failed to run incoming event {incoming_event}", exc_info=True + f"Failed to run incoming event {ActionRequestReceiver._stringify_incoming_event(raw_action)}", + exc_info=True ) else: # assume it's ActionRequest format try: @@ -143,9 +146,27 @@ def on_message(self, ws, message): ) except Exception: logging.error( - f"Failed to run incoming event {incoming_event}", exc_info=True + f"Failed to run incoming event {ActionRequestReceiver._stringify_incoming_event(incoming_event)}", + exc_info=True ) + @staticmethod + def _stringify_incoming_event(incoming_event) -> str: + """Stringify incoming request masking action params in case it contains secrets""" + if isinstance(incoming_event, str): # slack format, stringified json + try: + event_dict = json.loads(incoming_event) + except Exception: + logging.error("Failed to parse raw incoming event", exc_info=True) + return "parse error" + elif isinstance(incoming_event, dict): + event_dict = incoming_event + else: + return f"Unknown incoming_event type {type(incoming_event)}" + body = event_dict.pop("body", {}) + action_params = body.pop("action_params", {}) + return f"{event_dict} {body} {to_safe_str(action_params)}" + def on_error(self, ws, error): logging.info(f"Relay websocket error: {error}")