diff --git a/README.md b/README.md index 0f20f72..05a57fc 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ # Slack Publisher: Splunk -Connector Version: 2.6.1 +Connector Version: 2.6.2 Product Vendor: Slack Technologies Product Name: Slack Product Version Supported (regex): ".\*" diff --git a/release_notes/2.6.2.md b/release_notes/2.6.2.md new file mode 100644 index 0000000..6484a9e --- /dev/null +++ b/release_notes/2.6.2.md @@ -0,0 +1 @@ +* Add log rotation for bot log files [PAPP-30433] \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 02b231b..33dff53 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,4 @@ beautifulsoup4==4.10.0 -Django==3.2.16 idna==3.3 requests==2.27.1 sh==1.14.2 diff --git a/slack.json b/slack.json index 09b2e87..3fb42f1 100644 --- a/slack.json +++ b/slack.json @@ -15,8 +15,8 @@ "type": "information", "license": "Copyright (c) 2016-2023 Splunk Inc.", "main_module": "slack_connector.py", - "app_version": "2.6.1", - "utctime_updated": "2023-04-21T23:58:08.000000Z", + "app_version": "2.6.2", + "utctime_updated": "2023-05-11T00:32:21.000000Z", "product_vendor": "Slack Technologies", "product_name": "Slack", "product_version_regex": ".*", @@ -4280,21 +4280,13 @@ ], "pip_dependencies": { "wheel": [ - { - "module": "Django", - "input_file": "wheels/py3/Django-3.2.16-py3-none-any.whl" - }, - { - "module": "asgiref", - "input_file": "wheels/py3/asgiref-3.4.1-py3-none-any.whl" - }, { "module": "beautifulsoup4", "input_file": "wheels/py3/beautifulsoup4-4.10.0-py3-none-any.whl" }, { "module": "certifi", - "input_file": "wheels/py3/certifi-2022.12.7-py3-none-any.whl" + "input_file": "wheels/py3/certifi-2023.5.7-py3-none-any.whl" }, { "module": "charset_normalizer", @@ -4304,10 +4296,6 @@ "module": "idna", "input_file": "wheels/py3/idna-3.3-py3-none-any.whl" }, - { - "module": "pytz", - "input_file": "wheels/shared/pytz-2022.7.1-py2.py3-none-any.whl" - }, { "module": "requests", "input_file": "wheels/shared/requests-2.27.1-py2.py3-none-any.whl" @@ -4330,23 +4318,15 @@ }, { "module": "slack_sdk", - "input_file": "wheels/shared/slack_sdk-3.20.0-py2.py3-none-any.whl" + "input_file": "wheels/shared/slack_sdk-3.21.3-py2.py3-none-any.whl" }, { "module": "soupsieve", "input_file": "wheels/py3/soupsieve-2.3.2.post1-py3-none-any.whl" }, - { - "module": "sqlparse", - "input_file": "wheels/py3/sqlparse-0.4.3-py3-none-any.whl" - }, - { - "module": "typing_extensions", - "input_file": "wheels/py3/typing_extensions-4.1.1-py3-none-any.whl" - }, { "module": "urllib3", - "input_file": "wheels/shared/urllib3-1.26.14-py2.py3-none-any.whl" + "input_file": "wheels/shared/urllib3-1.26.15-py2.py3-none-any.whl" }, { "module": "websocket_client", @@ -4356,21 +4336,13 @@ }, "pip39_dependencies": { "wheel": [ - { - "module": "Django", - "input_file": "wheels/py3/Django-3.2.16-py3-none-any.whl" - }, - { - "module": "asgiref", - "input_file": "wheels/py3/asgiref-3.6.0-py3-none-any.whl" - }, { "module": "beautifulsoup4", "input_file": "wheels/py3/beautifulsoup4-4.10.0-py3-none-any.whl" }, { "module": "certifi", - "input_file": "wheels/py3/certifi-2022.12.7-py3-none-any.whl" + "input_file": "wheels/py3/certifi-2023.5.7-py3-none-any.whl" }, { "module": "charset_normalizer", @@ -4380,10 +4352,6 @@ "module": "idna", "input_file": "wheels/py3/idna-3.3-py3-none-any.whl" }, - { - "module": "pytz", - "input_file": "wheels/shared/pytz-2022.7.1-py2.py3-none-any.whl" - }, { "module": "requests", "input_file": "wheels/shared/requests-2.27.1-py2.py3-none-any.whl" @@ -4406,19 +4374,15 @@ }, { "module": "slack_sdk", - "input_file": "wheels/shared/slack_sdk-3.20.0-py2.py3-none-any.whl" + "input_file": "wheels/shared/slack_sdk-3.21.3-py2.py3-none-any.whl" }, { "module": "soupsieve", - "input_file": "wheels/py3/soupsieve-2.4-py3-none-any.whl" - }, - { - "module": "sqlparse", - "input_file": "wheels/py3/sqlparse-0.4.3-py3-none-any.whl" + "input_file": "wheels/py3/soupsieve-2.4.1-py3-none-any.whl" }, { "module": "urllib3", - "input_file": "wheels/shared/urllib3-1.26.14-py2.py3-none-any.whl" + "input_file": "wheels/shared/urllib3-1.26.15-py2.py3-none-any.whl" }, { "module": "websocket_client", diff --git a/slack_bot.py b/slack_bot.py index 57aea42..79fb24f 100644 --- a/slack_bot.py +++ b/slack_bot.py @@ -12,16 +12,17 @@ # 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. +import logging +import logging.handlers import os import re import shlex import sys +import tempfile from argparse import ArgumentParser -from datetime import datetime from pathlib import Path import encryption_helper -import pytz import requests import simplejson as json import six @@ -131,19 +132,6 @@ """ -def tmp_log(msg): - log_dir = "/tmp" - log_path = Path(log_dir) / "slack.log" - log_path.touch() - - tz_Denver = pytz.timezone('America/Denver') - now = datetime.now(tz_Denver) - current_time = now.strftime("%Y-%m-%d %H:%M:%S") - - with log_path.open('a') as bubbly: - bubbly.write(current_time + ": " + msg + "\n") - - def _load_app_state(asset_id): """ This function is used to load the current state file. @@ -1116,7 +1104,7 @@ def interactive_message_handler(ack, body, respond): answer_filename = '{0}.json'.format(qid) answer_path = "{0}/{1}".format(state_dir, answer_filename) - tmp_log('**going to put answer file here: {}'.format(answer_path)) + logging.debug('**going to put answer file here: {}'.format(answer_path)) final_payload = process_payload(body, answer_path) @@ -1136,17 +1124,17 @@ def mention_handler(body, say): is mentioned in the cat. It receives a json body which contains the data of the event. The command and channel name are parsed from the body and passed to command handler to further process the command. """ - tmp_log('**app_mention handler hit') + logging.info('**app_mention handler hit') if body: - # tmp_log('**body from app mention: {}'.format(body)) + # logging.debug('**body from app mention: {}'.format(body)) user = body.get("event", {}).get("user") - tmp_log('**user that spawned bot command is {}'.format(user)) + logging.info('**user that spawned bot command is {}'.format(user)) if not self._check_user_authorization(user): say('`User {} is not authorized to use this bot`'.format(user)) return out_text = body.get("event", {}).get("text") - tmp_log('**body exists, app_mention text: {}'.format(out_text)) + logging.debug('**body exists, app_mention text: {}'.format(out_text)) if out_text and out_text.startswith(self.cmd_start): if out_text.strip() == self.cmd_start: @@ -1178,54 +1166,54 @@ def mention_handler(body, say): handler.start() def _check_user_authorization(self, user): - tmp_log('**Checking authorization for user "{}"'.format(user)) + logging.info('**Checking authorization for user "{}"'.format(user)) permitted_users = self.permitted_users if not permitted_users: - tmp_log('**No permitted users specified. falling back to allow all') + logging.info('**No permitted users specified. falling back to allow all') return True else: user_list = permitted_users.split(",") - tmp_log('**Permitted_users: {}'.format(user_list)) + logging.debug('**Permitted_users: {}'.format(user_list)) if user in user_list: - tmp_log('**User "{}" is permitted to use bot'.format(user)) + logging.info('**User "{}" is permitted to use bot'.format(user)) return True else: - tmp_log('**User "{}" is not permitted to use bot'.format(user)) + logging.info('**User "{}" is not permitted to use bot'.format(user)) return False def _check_command_authorization(self, cmd_type): if cmd_type == "act": if self.permit_act: - tmp_log('**Command: "{}" is permitted'.format(cmd_type)) + logging.info('**Command: "{}" is permitted'.format(cmd_type)) return True else: - tmp_log('**Command:"{}" is not permitted'.format(cmd_type)) + logging.info('**Command:"{}" is not permitted'.format(cmd_type)) return False if cmd_type == "run_playbook": if self.permit_playbook: - tmp_log('**Command: "{}" is permitted'.format(cmd_type)) + logging.info('**Command: "{}" is permitted'.format(cmd_type)) return True else: - tmp_log('**Command: "{}" is not permitted'.format(cmd_type)) + logging.info('**Command: "{}" is not permitted'.format(cmd_type)) return False if cmd_type == "get_container": if self.permit_container: - tmp_log('**Command:" {}" is permitted'.format(cmd_type)) + logging.info('**Command:" {}" is permitted'.format(cmd_type)) return True else: - tmp_log('**Command: "{}" is not permitted'.format(cmd_type)) + logging.info('**Command: "{}" is not permitted'.format(cmd_type)) return False if cmd_type == "list": if self.permit_list: - tmp_log('**Command: "{}" is permitted'.format(cmd_type)) + logging.info('**Command: "{}" is permitted'.format(cmd_type)) return True else: - tmp_log('**Command: "{}" is not permitted'.format(cmd_type)) + logging.info('**Command: "{}" is not permitted'.format(cmd_type)) return False else: return False @@ -1250,7 +1238,7 @@ def _handle_command(self, command, channel): return if cmd_type == "act": - tmp_log("**permit_bot_act: {}".format(self.permit_act)) + logging.info("**permit_bot_act: {}".format(self.permit_act)) status, result = self._parse_action(args[1:]) if (status): msg = self._action_run_request(result, channel) @@ -1258,7 +1246,7 @@ def _handle_command(self, command, channel): msg = result elif cmd_type == "run_playbook": - tmp_log("**permit_bot_playbook: {}".format(self.permit_playbook)) + logging.info("**permit_bot_playbook: {}".format(self.permit_playbook)) status, result = self._parse_playbook(args[1:]) if (status): msg = self._playbook_request(result, channel) @@ -1266,11 +1254,11 @@ def _handle_command(self, command, channel): msg = result elif cmd_type == "get_container": - tmp_log("**permit_bot_container: {}".format(self.permit_container)) + logging.info("**permit_bot_container: {}".format(self.permit_container)) status, msg = self._parse_container(args[1:]) elif cmd_type == "list": - tmp_log("**permit_bot_list: {}".format(self.permit_list)) + logging.info("**permit_bot_list: {}".format(self.permit_list)) status, msg = self._parse_list(args[1:]) else: @@ -1279,9 +1267,25 @@ def _handle_command(self, command, channel): self._post_message(msg, channel) +def set_up_logging(): + """ Set up logging for the bot. """ + log_file = Path(tempfile.gettempdir()) / 'slack.log' + max_bytes = 5 * 1024 * 1024 # 5MB + log_formatter = logging.Formatter('[%(process)d][%(asctime)s][%(levelname)s] %(message)s') + + log_handler = logging.handlers.RotatingFileHandler(log_file, maxBytes=max_bytes, backupCount=4) + log_handler.setFormatter(log_formatter) + + logger = logging.getLogger() + logger.addHandler(log_handler) + logger.setLevel(logging.DEBUG) + return logger + + if __name__ == '__main__': # noqa: C901 + set_up_logging() - tmp_log('**Spawning slack_bot.py...') + logging.info('**Spawning slack_bot.py...') if (not os.path.exists('./bot_config.py')): if (len(sys.argv) != 3): print("Please create a bot_config.py file, and place it in this directory") diff --git a/wheels/py3/Django-3.2.16-py3-none-any.whl b/wheels/py3/Django-3.2.16-py3-none-any.whl deleted file mode 100644 index 73298a7..0000000 Binary files a/wheels/py3/Django-3.2.16-py3-none-any.whl and /dev/null differ diff --git a/wheels/py3/asgiref-3.4.1-py3-none-any.whl b/wheels/py3/asgiref-3.4.1-py3-none-any.whl deleted file mode 100644 index 238f1dc..0000000 Binary files a/wheels/py3/asgiref-3.4.1-py3-none-any.whl and /dev/null differ diff --git a/wheels/py3/asgiref-3.6.0-py3-none-any.whl b/wheels/py3/asgiref-3.6.0-py3-none-any.whl deleted file mode 100644 index 338be69..0000000 Binary files a/wheels/py3/asgiref-3.6.0-py3-none-any.whl and /dev/null differ diff --git a/wheels/py3/certifi-2022.12.7-py3-none-any.whl b/wheels/py3/certifi-2023.5.7-py3-none-any.whl similarity index 89% rename from wheels/py3/certifi-2022.12.7-py3-none-any.whl rename to wheels/py3/certifi-2023.5.7-py3-none-any.whl index a083056..c983e79 100644 Binary files a/wheels/py3/certifi-2022.12.7-py3-none-any.whl and b/wheels/py3/certifi-2023.5.7-py3-none-any.whl differ diff --git a/wheels/py3/soupsieve-2.4-py3-none-any.whl b/wheels/py3/soupsieve-2.4-py3-none-any.whl deleted file mode 100644 index c16c128..0000000 Binary files a/wheels/py3/soupsieve-2.4-py3-none-any.whl and /dev/null differ diff --git a/wheels/py3/soupsieve-2.4.1-py3-none-any.whl b/wheels/py3/soupsieve-2.4.1-py3-none-any.whl new file mode 100644 index 0000000..26a486c Binary files /dev/null and b/wheels/py3/soupsieve-2.4.1-py3-none-any.whl differ diff --git a/wheels/py3/sqlparse-0.4.3-py3-none-any.whl b/wheels/py3/sqlparse-0.4.3-py3-none-any.whl deleted file mode 100644 index abf6615..0000000 Binary files a/wheels/py3/sqlparse-0.4.3-py3-none-any.whl and /dev/null differ diff --git a/wheels/py3/typing_extensions-4.1.1-py3-none-any.whl b/wheels/py3/typing_extensions-4.1.1-py3-none-any.whl deleted file mode 100644 index 73c3dce..0000000 Binary files a/wheels/py3/typing_extensions-4.1.1-py3-none-any.whl and /dev/null differ diff --git a/wheels/shared/pytz-2022.7.1-py2.py3-none-any.whl b/wheels/shared/pytz-2022.7.1-py2.py3-none-any.whl deleted file mode 100644 index ed7c492..0000000 Binary files a/wheels/shared/pytz-2022.7.1-py2.py3-none-any.whl and /dev/null differ diff --git a/wheels/shared/slack_sdk-3.20.0-py2.py3-none-any.whl b/wheels/shared/slack_sdk-3.21.3-py2.py3-none-any.whl similarity index 68% rename from wheels/shared/slack_sdk-3.20.0-py2.py3-none-any.whl rename to wheels/shared/slack_sdk-3.21.3-py2.py3-none-any.whl index a366d25..ce0e62f 100644 Binary files a/wheels/shared/slack_sdk-3.20.0-py2.py3-none-any.whl and b/wheels/shared/slack_sdk-3.21.3-py2.py3-none-any.whl differ diff --git a/wheels/shared/urllib3-1.26.14-py2.py3-none-any.whl b/wheels/shared/urllib3-1.26.15-py2.py3-none-any.whl similarity index 65% rename from wheels/shared/urllib3-1.26.14-py2.py3-none-any.whl rename to wheels/shared/urllib3-1.26.15-py2.py3-none-any.whl index 2e969c0..ad723d5 100644 Binary files a/wheels/shared/urllib3-1.26.14-py2.py3-none-any.whl and b/wheels/shared/urllib3-1.26.15-py2.py3-none-any.whl differ