Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Doing serverless with Terraform? Check out [serverless.tf framework](https://ser
- AWS CloudWatch Alarms
- AWS CloudWatch LogMetrics Alarms
- AWS GuardDuty Findings
- AWS GuardDuty Malware Protection Object Scan Results

## Usage

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"Records": [{
"EventSource": "aws:sns",
"EventVersion": "1.0",
"EventSubscriptionArn": "arn:aws:sns:us-gov-east-1::ExampleTopic",
"Sns": {
"Type": "Notification",
"MessageId": "95df01b4-ee98-5cb9-9903-4c221d41eb5e",
"TopicArn": "arn:aws:sns:us-gov-east-1:123456789012:ExampleTopic",
"Subject": "GuardDuty Malware Protection Object Scan Result",
"Message": "{\"version\":\"0\",\"id\":\"72c7d362-737a-6dce-fc78-9e27a0171419\",\"detail-type\":\"GuardDuty Malware Protection Object Scan Result\",\"source\":\"aws.guardduty\",\"account\":\"111122223333\",\"time\":\"2024-02-28T01:01:01Z\",\"region\":\"us-east-1\",\"resources\":[\"arn:aws:guardduty:us-east-1:111122223333:malware-protection-plan/b4c7f464ab3a4EXAMPLE\"],\"detail\":{\"schemaVersion\":\"1.0\",\"scanStatus\":\"COMPLETED\",\"resourceType\":\"S3_OBJECT\",\"s3ObjectDetails\":{\"bucketName\":\"amzn-s3-demo-bucket\",\"objectKey\":\"APKAEIBAERJR2EXAMPLE\",\"eTag\":\"ASIAI44QH8DHBEXAMPLE\",\"versionId\":\"d41d8cd98f00b204e9800998eEXAMPLE\",\"s3Throttled\":false},\"scanResultDetails\":{\"scanResultStatus\":\"THREATS_FOUND\",\"threats\":[{\"name\":\"EICAR-Test-File (not a virus)\"}]}}}",
"Timestamp": "1970-01-01T00:00:00.000Z",
"SignatureVersion": "1",
"Signature": "EXAMPLE",
"SigningCertUrl": "EXAMPLE",
"UnsubscribeUrl": "EXAMPLE",
"MessageAttributes": {}
}
}]
}
69 changes: 69 additions & 0 deletions functions/notify_slack.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,20 @@ def get_service_url(region: str, service: str) -> str:
raise


def get_s3_object_url(region: str, bucket: str, key: str) -> str:
"""Get the appropriate S3 object URL for the region

:param region: name of the AWS region
:param bucket: name of the S3 bucket
:param key: key of the relevant S3 object
:returns: AWS console url formatted for the region and bucket + key provided
"""
if region.startswith("us-gov-"):
return f"https://console.amazonaws-us-gov.com/s3/object/{bucket}?region={region}&prefix={key}"
else:
return f"https://console.aws.amazon.com/s3/object/{bucket}?region={region}&prefix={key}"


class CloudWatchAlarmState(Enum):
"""Maps CloudWatch notification state to Slack message format color"""

Expand Down Expand Up @@ -342,6 +356,59 @@ def format_guardduty_finding(message: Dict[str, Any], region: str) -> Dict[str,
}


def format_guardduty_malware_protection_object_scan_result(message: Dict[str, Any], region: str) -> Dict[str, Any]:
"""
Format GuardDuty Malware Protection Object Scan Result into Slack message format

:params message: SNS message body containing GuardDuty Malware Protection Object Scan Result
:params region: AWS region where the event originated from
:returns: formatted Slack message payload
"""

detail = message["detail"]
scanResultDetails = detail.get("scanResultDetails")
scanResultStatus = scanResultDetails.get("scanResultStatus")

s3ObjectDetails = detail.get("s3ObjectDetails")
s3_url = get_s3_object_url(region=region, bucket=s3ObjectDetails["bucketName"], key=s3ObjectDetails["objectKey"])

severity = "High"

if scanResultStatus == "NO_THREATS_FOUND":
severity = "Low"
elif scanResultStatus == "THREATS_FOUND":
severity = "High"
elif scanResultStatus == "UNSUPPORTED":
severity = "Medium"
elif scanResultStatus == "ACCESS_DENIED":
severity = "Medium"
elif scanResultStatus == "FAILED":
severity = "Medium"

return {
"color": GuardDutyFindingSeverity[severity].value,
"fallback": f"GuardDuty Malware Scan Result: {scanResultStatus}",
"fields": [
{
"title": "S3 Bucket",
"value": f"`{detail['s3ObjectDetails']['bucketName']}`",
"short": False,
},
{
"title": "S3 Object",
"value": f"`{detail['s3ObjectDetails']['objectKey']}`",
"short": False,
},
{
"title": "Link to S3 object",
"value": f"{s3_url}",
"short": False,
},
],
"text": f"AWS GuardDuty Malware Scan Result - {scanResultStatus}",
}


class AwsHealthCategory(Enum):
"""Maps AWS Health eventTypeCategory to Slack message format color

Expand Down Expand Up @@ -520,6 +587,8 @@ def parse_notification(message: Dict[str, Any], subject: Optional[str], region:
return format_cloudwatch_alarm(message=message, region=region)
if isinstance(message, Dict) and message.get("detail-type") == "GuardDuty Finding":
return format_guardduty_finding(message=message, region=message["region"])
if isinstance(message, Dict) and message.get("detail-type") == "GuardDuty Malware Protection Object Scan Result":
return format_guardduty_malware_protection_object_scan_result(message=message, region=message["region"])
if isinstance(message, Dict) and message.get("detail-type") == "Security Hub Findings - Imported":
return format_aws_security_hub(message=message, region=message["region"])
if isinstance(message, Dict) and message.get("detail-type") == "AWS Health Event":
Expand Down
32 changes: 32 additions & 0 deletions functions/snapshots/snap_notify_slack_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,38 @@
}
]

snapshots['test_sns_get_slack_message_payload_snapshots message_guardduty_malware_protection_object_scan_result.json'] = [
{
'attachments': [
{
'color': 'danger',
'fallback': 'GuardDuty Malware Scan Result: THREATS_FOUND',
'fields': [
{
'short': False,
'title': 'S3 Bucket',
'value': '`amzn-s3-demo-bucket`'
},
{
'short': False,
'title': 'S3 Object',
'value': '`APKAEIBAERJR2EXAMPLE`'
},
{
'short': False,
'title': 'Link to S3 object',
'value': 'https://console.aws.amazon.com/s3/object/amzn-s3-demo-bucket?region=us-east-1&prefix=APKAEIBAERJR2EXAMPLE'
}
],
'text': 'AWS GuardDuty Malware Scan Result - THREATS_FOUND'
}
],
'channel': 'slack_testing_sandbox',
'icon_emoji': ':aws:',
'username': 'notify_slack_test'
}
]

snapshots['test_sns_get_slack_message_payload_snapshots message_text_message.json'] = [
{
'attachments': [
Expand Down