Skip to content

Commit

Permalink
Merge pull request #10 from usegalaxy-au/slack-alerts
Browse files Browse the repository at this point in the history
Slack alerts option
  • Loading branch information
neoformit authored Nov 3, 2024
2 parents f038a33 + 837738f commit aa04558
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 1 deletion.
11 changes: 11 additions & 0 deletions defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,17 @@ walle_envs_user_deletion:
walle_verbose: false
walle_kill: false

walle_slack_alerts: false
walle_slack_api_token: null # Make a "Slack app" to get a token
walle_slack_channel_id: null # Copy from your Slack channel settings
walle_envs_slack:
- key: SLACK_API_TOKEN
value: "{{ walle_slack_api_token }}"
- key: SLACK_CHANNEL_ID
value: "{{ walle_slack_channel_id }}"
- key: WALLE_HOSTNAME
value: "{{ inventory_hostname }}"

# Cron
walle_cron_day: "*"
walle_cron_hour: "*/1"
Expand Down
62 changes: 61 additions & 1 deletion files/walle.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import sys
import time
import zlib
from typing import Dict, List, Union
from typing import Dict, List

import galaxy_jwd
import requests
Expand All @@ -33,6 +33,7 @@
If you think your account was deleted due to an error, please contact
"""
ONLY_ONE_INSTANCE = "The other must be an instance of the Severity class"
SLACK_URL = "https://slack.com/api/chat.postMessage"

UserId = str
UserMail = str
Expand Down Expand Up @@ -208,6 +209,16 @@ def make_parser() -> argparse.ArgumentParser:
action="store_true",
help="Show table header.",
)
my_parser.add_argument(
"--slack-alerts",
action="store_true",
help=(
"Report matches to a Slack channel defined with env variables"
" [SLACK_API_TOKEN, SLACK_CHANNEL_ID], where the Slack token"
" authenticates a Slack App with permission to post in your"
" Workspace."
),
)
my_parser.add_argument(
"--delete-user",
metavar="MIN_SEVERITY",
Expand Down Expand Up @@ -394,6 +405,27 @@ def report_matching_malware(self):
self.job.files[self.fileindex],
)

def post_slack_alert(self):
msg = f"""
:rotating_light: WALLE: *Malware detected* :rotating_light:
- *Hostname*: {os.getenv('WALLE_HOSTNAME')}
- *Severity*: {self.malware.severity.name}
- *User*: {self.job.user_id} ({self.job.user_name})
- *User email*: {self.job.user_mail}
- *Tool*: {self.job.tool_id}
- *Galaxy job ID*: {self.job.galaxy_id}
- *Runner job ID*: {self.job.runner_id}
- *Runner name*: {self.job.runner_name}
- *Object store ID*: {self.job.object_store_id}
- *Malware class*: {self.malware.malware_class}
- *Malware name*: {self.malware.program}
- *Malware version*: {self.malware.version}
- *File*: {self.job.files[self.fileindex]}
- *Job working dir*: {self.job.jwd}
"""
post_slack_msg(msg)


def file_accessed_in_range(
file_stat: os.stat_result, since: float, now=time.time()
Expand Down Expand Up @@ -783,6 +815,32 @@ def get_database_with_password() -> RunningJobDatabase:
)


def post_slack_msg(message):
"""Post a message to Slack."""
key = os.getenv("SLACK_API_TOKEN")
channel_id = os.getenv("SLACK_CHANNEL_ID")

if not all([key, channel_id]):
logger.warning(
"Slack notifications cannot be sent. Make sure your"
" playbook defines required vars:"
" [walle_slack_api_token, walle_slack_channel_id]."
)
return

logger.info(f"Posting incident report to Slack channel {channel_id}...")
requests.post(
SLACK_URL,
json={
"text": message,
"channel": channel_id,
},
headers={
"Authorization": f"Bearer {key}",
},
)


def main():
args = make_parser().parse_args()
logger.setLevel(logging.DEBUG if args.verbose else logging.INFO)
Expand Down Expand Up @@ -823,6 +881,8 @@ def main():
reported_users.update(case.report_according_to_verbosity())
if args.delete_user:
delete_users.update(case.mark_user_for_deletion(args.delete_user))
if args.slack_alerts:
case.post_slack_alert()
if matching_malware and args.kill:
kill_job(job)
# Deletes users at the end, to report all malicious jobs of a user
Expand Down
9 changes: 9 additions & 0 deletions tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,14 @@
owner: "{{ walle_user_name }}"
group: "{{ walle_user_group }}"

- name: Add env variables for slack notifications (WallE)
ansible.builtin.lineinfile:
path: "{{ walle_bashrc }}"
regexp: "^export {{ item.key }}="
line: 'export {{ item.key }}="{{ item.value }}"'
with_items: "{{ walle_envs_slack }}"
when: walle_slack_alerts

- name: Create logfile (WallE)
ansible.builtin.file:
state: touch
Expand Down Expand Up @@ -99,6 +107,7 @@
{% if walle_filesize_max %} --max-size {{ walle_filesize_max }} {% endif %}
{% if walle_since_hours %} --since {{ walle_since_hours }} {% endif %}
{% if walle_verbose %} --verbose {% endif %}
{% if walle_slack_alerts %} --slack-alerts {% endif %}
{% if walle_delete_users %} --delete-user {{ walle_delete_threshold }}
{% endif %}
{% if walle_kill %} --kill {% endif %}
Expand Down

0 comments on commit aa04558

Please sign in to comment.