Skip to content

Commit

Permalink
feat: Improved AWS backup notification readability (#222)
Browse files Browse the repository at this point in the history
Co-authored-by: Anton Babenko <anton@antonbabenko.com>
Co-authored-by: Bryant Biggs <bryantbiggs@gmail.com>
  • Loading branch information
3 people committed Apr 24, 2024
1 parent 6c17291 commit 27d1c46
Show file tree
Hide file tree
Showing 3 changed files with 633 additions and 261 deletions.
109 changes: 109 additions & 0 deletions functions/messages/backup.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
{
"Records": [
{
"EventSource": "aws:sns",
"EventVersion": "1.0",
"EventSubscriptionArn": "arn:aws:sns:...-a3802aa1ed45",
"Sns": {
"Type": "Notification",
"MessageId": "12345678-abcd-123a-def0-abcd1a234567",
"TopicArn": "arn:aws:sns:us-west-1:123456789012:backup-2sqs-sns-topic",
"Subject": "Notification from AWS Backup",
"Message": "An AWS Backup job was completed successfully. Recovery point ARN: arn:aws:ec2:us-west-1:123456789012:volume/vol-012f345df6789012d. Resource ARN : arn:aws:ec2:us-west-1:123456789012:volume/vol-012f345df6789012e. BackupJob ID : 1b2345b2-f22c-4dab-5eb6-bbc7890ed123",
"Timestamp": "2019-08-02T18:46:02.788Z",
"MessageAttributes": {
"EventType": {
"Type": "String",
"Value": "BACKUP_JOB"
},
"State": {
"Type": "String",
"Value": "COMPLETED"
},
"AccountId": {
"Type": "String",
"Value": "123456789012"
},
"Id": {
"Type": "String",
"Value": "1b2345b2-f22c-4dab-5eb6-bbc7890ed123"
},
"StartTime": {
"Type": "String",
"Value": "2019-09-02T13:48:52.226Z"
}
}
}
},
{
"EventSource": "aws:sns",
"EventVersion": "1.0",
"EventSubscriptionArn": "arn:aws:sns:...-a3802aa1ed45",
"Sns": {
"Type": "Notification",
"MessageId": "12345678-abcd-123a-def0-abcd1a234567",
"TopicArn": "arn:aws:sns:us-west-1:123456789012:backup-2sqs-sns-topic",
"Subject": "Notification from AWS Backup",
"Message": "An AWS Backup job failed. Resource ARN : arn:aws:ec2:us-west-1:123456789012:volume/vol-012f345df6789012e. BackupJob ID : 1b2345b2-f22c-4dab-5eb6-bbc7890ed123",
"Timestamp": "2019-08-02T18:46:02.788Z",
"MessageAttributes": {
"EventType": {
"Type": "String",
"Value": "BACKUP_JOB"
},
"State": {
"Type": "String",
"Value": "FAILED"
},
"AccountId": {
"Type": "String",
"Value": "123456789012"
},
"Id": {
"Type": "String",
"Value": "1b2345b2-f22c-4dab-5eb6-bbc7890ed123"
},
"StartTime": {
"Type": "String",
"Value": "2019-09-02T13:48:52.226Z"
}
}
}
},
{
"EventSource": "aws:sns",
"EventVersion": "1.0",
"EventSubscriptionArn": "arn:aws:sns:...-a3802aa1ed45",
"Sns": {
"Type": "Notification",
"MessageId": "12345678-abcd-123a-def0-abcd1a234567",
"TopicArn": "arn:aws:sns:us-west-1:123456789012:backup-2sqs-sns-topic",
"Subject": "Notification from AWS Backup",
"Message": "An AWS Backup job failed to complete in time. Resource ARN : arn:aws:ec2:us-west-1:123456789012:volume/vol-012f345df6789012e. BackupJob ID : 1b2345b2-f22c-4dab-5eb6-bbc7890ed123",
"Timestamp": "2019-08-02T18:46:02.788Z",
"MessageAttributes": {
"EventType": {
"Type": "String",
"Value": "BACKUP_JOB"
},
"State": {
"Type": "String",
"Value": "EXPIRED"
},
"AccountId": {
"Type": "String",
"Value": "123456789012"
},
"Id": {
"Type": "String",
"Value": "1b2345b2-f22c-4dab-5eb6-bbc7890ed123"
},
"StartTime": {
"Type": "String",
"Value": "2019-09-02T13:48:52.226Z"
}
}
}
}
]
}
65 changes: 65 additions & 0 deletions functions/notify_slack.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import json
import logging
import os
import re
import urllib.parse
import urllib.request
from enum import Enum
Expand Down Expand Up @@ -266,6 +267,66 @@ def format_aws_health(message: Dict[str, Any], region: str) -> Dict[str, Any]:
}


def aws_backup_field_parser(message: str) -> Dict[str, str]:
"""
Parser for AWS Backup event message. It extracts the fields from the message and returns a dictionary.
:params message: message containing AWS Backup event
:returns: dictionary containing the fields extracted from the message
"""
# Order is somewhat important, working in reverse order of the message payload
# to reduce right most matched values
field_names = {
"BackupJob ID": r"(BackupJob ID : ).*",
"Resource ARN": r"(Resource ARN : ).*[.]",
"Recovery point ARN": r"(Recovery point ARN: ).*[.]",
}
fields = {}

for fname, freg in field_names.items():
match = re.search(freg, message)
if match:
value = match.group(0).split(" ")[-1]
fields[fname] = value.removesuffix(".")

# Remove the matched field from the message
message = message.replace(match.group(0), "")

return fields


def format_aws_backup(message: str) -> Dict[str, Any]:
"""
Format AWS Backup event into Slack message format
:params message: SNS message body containing AWS Backup event
:returns: formatted Slack message payload
"""

fields: list[Dict[str, Any]] = []
attachments = {}

title = message.split(".")[0]

if "failed" in title:
title = f"⚠️ {title}"

if "completed" in title:
title = f"✅ {title}"

fields.append({"title": title})

backup_fields = aws_backup_field_parser(message)

for k, v in backup_fields.items():
fields.append({"value": k, "short": False})
fields.append({"value": f"`{v}`", "short": False})

attachments["fields"] = fields # type: ignore

return attachments


def format_default(
message: Union[str, Dict], subject: Optional[str] = None
) -> Dict[str, Any]:
Expand Down Expand Up @@ -344,6 +405,10 @@ def get_slack_message_payload(
notification = format_aws_health(message=message, region=message["region"])
attachment = notification

elif subject == "Notification from AWS Backup":
notification = format_aws_backup(message=str(message))
attachment = notification

elif "attachments" in message or "text" in message:
payload = {**payload, **message}

Expand Down

0 comments on commit 27d1c46

Please sign in to comment.