AWS GuardDuty¶
Table of Contents¶
Release Notes¶
Version |
Date |
Notes |
---|---|---|
1.0.0 |
03/2021 |
Initial Release |
1.1.0 |
04/2024 |
Add Playbooks |
AWS GuardDuty App 1.1.0 Changes¶
In v1.1.0, the existing rules and workflows have been replaced with playbooks. This change is made to support the ongoing, newer capabilities of playbooks. Each playbook has the same functionality as the previous, corresponding rule/workflow.
If upgrading from a previous release, you’ll noticed that the previous release’s rules/workflows remain in place. Both sets of rules and playbooks are active. For manual actions, playbooks will have the same name as it’s corresponding rule, but with “(PB)” added at the end. For automatic actions, the playbooks will be disabled by default.
You can continue to use the rules/workflows. But migrating to playbooks will provide greater functionality along with future app enhancements and bug fixes.
Overview¶
Amazon AWS GuardDuty Integration for Resilient.
Amazon AWS GuardDuty is a continuous security monitoring service that identifies unexpected and potentially unauthorized and malicious activity within an AWS environment. GuardDuty informs the user of the status of their AWS environment by producing security findings that can be viewed in the GuardDuty console. A finding is a potential security issue discovered by GuardDuty.
The Amazon AWS GuardDuty Integration for Resilient allows you to process and respond to GuardDuty findings within the IBM Resilient Platform.
Key Features¶
The GuardDuty Integration provides the following functionality:
A poller which gathers current findings from GuardDuty and escalates to the Resilient platform as incidents.
A function to archive a GuardDuty finding when the corresponding Resilient incident is closed.
A function to refresh a Resilient incident with the latest information from the corresponding GuardDuty finding.
Close Resilient incidents if the corresponding GuardDuty findings are archived.
Archive GuardDuty findings if the corresponding Resilient incidents are closed.
Trigger a refresh for a Resilient incident if the corresponding GuardDuty finding gets updated.
A refresh of Resilient incidents can be executed manually.
Requirements¶
This app supports the IBM Security QRadar SOAR Platform and the IBM Security QRadar SOAR for IBM Cloud Pak for Security.
SOAR platform¶
The SOAR platform supports two app deployment mechanisms, Edge Gateway (also known as App Host) and integration server.
If deploying to a SOAR platform with an App Host, the requirements are:
SOAR platform >=
51.0.0.0.9339
.The app is in a container-based format (available from the AppExchange as a
zip
file).
If deploying to a SOAR platform with an integration server, the requirements are:
SOAR platform >=
51.0.0.0.9339
.The app is in the older integration format (available from the AppExchange as a
zip
file which contains atar.gz
file).Integration server is running
resilient_circuits>=51.0.1.1.824
.If using an API key account, make sure the account provides the following minimum permissions:
Name
Permissions
Org Data
Read
Function
Read
incident
create
all_incidents
Read
The following SOAR platform guides provide additional information:
Edge Gateway Deployment Guide or App Host Deployment Guide: provides installation, configuration, and troubleshooting information, including proxy server settings.
Integration Server Guide: provides installation, configuration, and troubleshooting information, including proxy server settings.
System Administrator Guide: provides the procedure to install, configure and deploy apps.
The above guides are available on the IBM Documentation website at ibm.biz/soar-docs. On this web page, select your SOAR platform version. On the follow-on page, you can find the Edge Gateway Deployment Guide, App Host Deployment Guide, or Integration Server Guide by expanding Apps in the Table of Contents pane. The System Administrator Guide is available by expanding System Administrator.
Cloud Pak for Security¶
If you are deploying to IBM Cloud Pak for Security, the requirements are:
IBM Cloud Pak for Security >=
1.10.15
.Cloud Pak is configured with an Edge Gateway.
The app is in a container-based format (available from the AppExchange as a
zip
file).
The following Cloud Pak guides provide additional information:
Edge Gateway Deployment Guide or App Host Deployment Guide: provides installation, configuration, and troubleshooting information, including proxy server settings. From the Table of Contents, select Case Management and Orchestration & Automation > Orchestration and Automation Apps.
System Administrator Guide: provides information to install, configure, and deploy apps. From the IBM Cloud Pak for Security IBM Documentation table of contents, select Case Management and Orchestration & Automation > System administrator.
These guides are available on the IBM Documentation website at ibm.biz/cp4s-docs. From this web page, select your IBM Cloud Pak for Security version. From the version-specific IBM Documentation page, select Case Management and Orchestration & Automation.
Proxy Server¶
The app does support a proxy server.
Python Environment¶
Python 3.6 and Python 3.9 are supported. Additional package dependencies may exist for each of these packages:
boto3>=1.16.19
resilient_circuits>=45.0.0
Installation¶
Install¶
To install or uninstall an App or Integration on the SOAR platform, see the documentation at ibm.biz/soar-docs.
To install or uninstall an App on IBM Cloud Pak for Security, see the documentation at ibm.biz/cp4s-docs and follow the instructions above to navigate to Orchestration and Automation.
App Configuration¶
The following table provides the settings you need to configure the app. These settings are made in the app.config file. See the documentation discussed in the Requirements section for the procedure.
Config |
Required |
Example |
Description |
---|---|---|---|
aws_gd_access_key_id |
Yes |
|
AWS access key id of user with programmatic (API) access to AWS GuardDuty services for an AWS account. Note: User must have sufficent permissions to be able to manage GuardDuty resources for the AWS account. |
aws_gd_secret_access_key |
Yes |
|
AWS secret access key used for programmatic (API) access to AWS services. |
aws_gd_master_region |
Yes |
|
Default or master region for the integration. |
aws_gd_regions |
Yes |
|
Filter by GuardDuty region names. Can be a string or regular expression. |
aws_gd_regions_interval |
Yes |
|
Interval to refresh regions information (in minutes). |
aws_gd_polling_interval |
Yes |
|
Interval to poll GuardDuty for findings (in minutes). |
aws_gd_severity_threshold |
No |
|
Severity threshold (int) to use in criterion to filter findings . |
aws_gd_lookback_interval |
No |
|
How long, (in minutes) to check back for previous findings at startup. Filter to process only more recent findings. |
aws_gd_close_incident_template |
No |
`` |
User defined JSON template file to use for closing Resilient incidents. |
http_proxy |
No |
|
Optional setting for an http proxy if required. |
https_proxy |
No |
|
Optional setting for an https proxy if required. |
Poller - AWS GuardDuty: Escalate Findings¶
The GuardDuty integration poller starts querying GuardDuty for findings as soon as the app begins running.
The poller provide the following functionality.
For any new findings discovered, creates a matching incident in the Resilient platform.
Enhances the incidents by adding artifacts, data tables and a note with data from the findings. The note includes the JSON content of the finding.
Can be configured to filter the findings, which are escalated to the Resilient incidents.
Closes Resilient incidents if the corresponding GuardDuty findings are archived.
Archives GuardDuty findings if the corresponding Resilient incidents are closed.
Triggers a refresh of GuardDuty information for a Resilient incident if the corresponding GuardDuty finding is updated.
The following screenshot shows examples of Resilient incidents created by the poller from GuardDuty findings:
The following screenshot shows an example of a Resilient incident Details tab created by the poller:
The following screenshot shows an example of GuardDuty finding custom properties in the Details tab of a Resilient incident created by the poller:
The following screenshot shows examples of artifacts added to a Resilient incident created by the poller:
The following screenshot shows an example of a note added to a Resilient incident created by the poller:
Note: See the data tables section for examples of data tables added by the poller.
Function - AWS GuardDuty: Archive finding¶
Resilient Function to archive an AWS GuardDuty finding when the corresponding incident is closed.
Inputs:
Name |
Type |
Required |
Example |
Tooltip |
---|---|---|---|---|
|
|
No |
|
AWS GuardDuty detector ID. |
|
|
No |
|
AWS GuardDuty finding ID. |
|
|
No |
|
AWS GuardDuty region. |
Outputs:
NOTE: This example might be in JSON format, but
results
is a Python Dictionary on the SOAR platform.
results = {
"content": {
"status": "ok"
},
"inputs": {
"aws_gd_detector_id": "48bbf98612290af2215c7a02b7ccbc82",
"aws_gd_finding_id": "xxxxyyyyzzzz",
"aws_gd_region": "us-east-1"
},
"metrics": {
"execution_time_ms": 2058,
"host": "IBM-dummy-MacBookPro.local",
"package": "fn-aws-guardduty",
"package_version": "1.1.0",
"timestamp": "2024-04-11 14:09:19",
"version": "1.0"
},
"raw": "{\"status\": \"ok\"}",
"reason": null,
"success": true,
"version": "1.0"
}
Example Function Input Script:
inputs.aws_gd_region = incident.properties.aws_guardduty_region
inputs.aws_gd_detector_id = incident.properties.aws_guardduty_detector_id
inputs.aws_gd_finding_id = incident.properties.aws_guardduty_finding_id
Example Function Post Process Script:
## wf_aws_guardduty_refresh_finding ##
# Example result:
"""
Good
====
Result: {'version': '1.0', 'success': True, 'reason': None,
'content': {'status': 'ok'},
'raw': '{"status": "ok"}',
'inputs': {'aws_gd_finding_id': 'c2bb95a17b879bffc96c58f8a1689785', 'aws_gd_region': 'us-east-2',
'aws_gd_detector_id': '32b7017d2019dfe922abc4e07c3fdded'
},
'metrics': {'version': '1.0', 'package': 'fn-aws-guardduty', 'package_version': '1.0.0',
'host': 'myhost.ibm.com', 'execution_time_ms': 1310, 'timestamp': '2021-01-28 11:31:30'
}
}
Error:
Result: {'version': '1.0', 'success': True, 'reason': None,
'content': {'status': 'error',
'msg': 'An error occurred (BadRequestException) when calling the ArchiveFindings operation:
The request is rejected because the input detectorId is not owned by the current account.'},
'raw': '<content_as_string>',
'inputs': {'aws_gd_finding_id': 'c2bb95a17b879bffc96c58f8a1689784', 'aws_gd_region': 'us-east-2',
'aws_gd_detector_id': '32b7017d2019dfe922abc4e07c3fdfff'
},
'metrics': {'version': '1.0', 'package': 'fn-aws-guardduty', 'package_version': '1.0.0',
'host': 'myhost.ibm.com', 'execution_time_ms': 1446, 'timestamp': '2021-01-28 11:34:53'
}
}
"""
# Globals
FN_NAME = "func_aws_guardduty_archive_finding"
WF_NAME = "Example: AWS GuardDuty: Archive Finding"
# Resilient artifact names to api names.
# Processing
# Processing
CONTENT = playbook.functions.results.output
INPUTS = playbook.functions.results.inputs
QUERY_EXECUTION_DATE = playbook.functions.results.output["metrics"]["timestamp"]
# Processing
def main():
note_text = ''
if CONTENT:
if CONTENT["status"] == "ok":
note_text = "AWS IAM Integration: Workflow <b>{0}</b>: The finding with id <b>{1}</b> and detector id " \
"<b>{2}</b> in region <b>{3}</b> was successfully archived for Resilient function <b>{4}</b>"\
.format(WF_NAME, INPUTS["aws_gd_finding_id"], INPUTS["aws_gd_detector_id"], INPUTS["aws_gd_region"], FN_NAME)
# Update archived property.
incident.properties.aws_guardduty_archived = "True"
elif CONTENT["status"] == "error":
note_text = "AWS IAM Integration: Workflow <b>{0}</b>: The finding with id <b>{1}</b> and detector id " \
"<b>{2}</b> in region <b>{3}</b> failed archive with error <b>{4}</b> for Resilient function <b>{5}</b>"\
.format(WF_NAME, INPUTS["aws_gd_finding_id"], INPUTS["aws_gd_detector_id"], INPUTS["aws_gd_region"],
CONTENT["msg"], FN_NAME)
else:
note_text = "AWS IAM Integration: Workflow <b>{0}</b>: The finding with id <b>{1}</b> and detector id " \
"<b>{2}</b> in region <b>{3}</b> got unexpected status <b>{4}</b> for Resilient function <b>{5}</b>" \
.format(WF_NAME, INPUTS["aws_gd_finding_id"], INPUTS["aws_gd_detector_id"], CONTENT["status"], INPUTS["aws_gd_region"],
FN_NAME)
else:
note_text += "AWS IAM Integration: Workflow <b>{0}</b>: There was no result returned for Resilient function <b>{0}</b>"\
.format(WF_NAME, FN_NAME)
incident.addNote(helper.createRichText(note_text))
if __name__ == "__main__":
main()
Function - AWS GuardDuty: Refresh Finding¶
Resilient Function to refresh AWS GuardDuty finding details in an incident.
Inputs:
Name |
Type |
Required |
Example |
Tooltip |
---|---|---|---|---|
|
|
No |
|
AWS GuardDuty detector ID. |
|
|
No |
|
AWS GuardDuty finding ID. |
|
|
No |
|
AWS GuardDuty region. |
|
|
No |
|
Resilient incident ID. |
Outputs:
NOTE: This example might be in JSON format, but
results
is a Python Dictionary on the SOAR platform.
results = {
"content": {
"data_tables": {
"gd_access_key_details": [
{
"cells": {
"access_key_id": {
"value": "xxxxyyyy"
},
"principal_id": {
"value": "xxxxyyyy"
},
"query_execution_date": {
"value": "2024-04-11 14:08:54"
},
"user_name": {
"value": "dummy"
},
"user_type": {
"value": "IAMUser"
}
}
}
],
"gd_action_details": [
{
"cells": {
"action_api": {
"value": "ListFindings"
},
"action_type": {
"value": "AWS_API_CALL"
},
"actor_caller_type": {
"value": "Remote IP"
},
"asn": {
"value": "17390"
},
"asn_org": {
"value": "CIO-ORGANIZATION"
},
"city_name": {
"value": "Singapore"
},
"country_name": {
"value": "Singapore"
},
"event_first_seen": {
"value": "2024-04-11T05:26:01.000Z"
},
"event_last_seen": {
"value": "2024-04-11T05:32:48.000Z"
},
"isp": {
"value": "IBM Corporation"
},
"org": {
"value": "IBM Corporation"
},
"query_execution_date": {
"value": "2024-04-11 14:08:54"
},
"remote_ip": {
"value": "129.41.56.2"
},
"service_name": {
"value": "guardduty.amazonaws.com"
}
}
}
],
"gd_finding_overview": [
{
"cells": {
"account_id": {
"value": "xxxxyyyyzzzz"
},
"count": {
"value": "1"
},
"created_at": {
"value": "2024-04-11T05:47:16.625Z"
},
"query_execution_date": {
"value": "2024-04-11 14:08:54"
},
"region": {
"value": "us-east-1"
},
"severity": {
"value": "2"
},
"updated_at": {
"value": "2024-04-11T05:47:16.625Z"
}
}
}
],
"gd_instance_details": [],
"gd_resource_affected": [
{
"cells": {
"query_execution_date": {
"value": "2024-04-11 14:08:54"
},
"resource_role": {
"value": "TARGET"
},
"resource_type": {
"value": "AccessKey"
}
}
}
],
"gd_s3_bucket_details": []
},
"finding": {
"AccountId": "xxxxyyyyzzzz",
"Arn": "arn:aws:guardduty:us-east-1:xxxxyyyyzzzz:detector/48bbf98612290af2215c7a02b7ccbc82/finding/xxxxyyyyzzzz",
"CreatedAt": "2024-04-11T05:47:16.625Z",
"Description": "APIs commonly used in Discovery tactics were invoked by user IAMUser : dummy under unusual circumstances. Such activity is not typically seen from this user.",
"Id": "xxxxyyyyzzzz",
"Partition": "aws",
"Region": "us-east-1",
"Resource": {
"AccessKeyDetails": {
"AccessKeyId": "xxxxyyyy",
"PrincipalId": "xxxxyyyy",
"UserName": "dummy",
"UserType": "IAMUser"
},
"ResourceType": "AccessKey"
},
"SchemaVersion": "2.0",
"Service": {
"Action": {
"ActionType": "AWS_API_CALL",
"AwsApiCallAction": {
"AffectedResources": {},
"Api": "ListFindings",
"CallerType": "Remote IP",
"RemoteIpDetails": {
"City": {
"CityName": "Singapore"
},
"Country": {
"CountryName": "Singapore"
},
"GeoLocation": {
"Lat": 1.2868,
"Lon": 103.8503
},
"IpAddressV4": "129.41.56.2",
"Organization": {
"Asn": "17390",
"AsnOrg": "CIO-ORGANIZATION",
"Isp": "IBM Corporation",
"Org": "IBM Corporation"
}
},
"ServiceName": "guardduty.amazonaws.com"
}
},
"AdditionalInfo": {
"Type": "default",
"Value": "{\"userAgent\":{\"fullUserAgent\":\"Boto3/1.34.82 md/Botocore#1.34.82 ua/2.0 os/macos#23.4.0 md/arch#x86_64 lang/python#3.9.16 md/pyimpl#CPython cfg/retry-mode#legacy Botocore/1.34.82\",\"userAgentCategory\":\"Botocore\"},\"anomalies\":{\"anomalousAPIs\":\"guardduty.amazonaws.com:[ListFindings:success , ListDetectors:success , GetFindings:success , ArchiveFindings:success] , ec2.amazonaws.com:[DescribeRegions:success]\"},\"profiledBehavior\":{\"rareProfiledAPIsAccountProfiling\":\"\",\"infrequentProfiledAPIsAccountProfiling\":\"\",\"frequentProfiledAPIsAccountProfiling\":\"ListFindings , DescribeVolumes , GetResources , BatchGetResourceConfig , ListHostedZones , SelectResourceConfig , DescribeConfigurationRecorderStatus , ListResourceRecordSets , DescribeTrails , DescribeRegions , GetBucketLocation , DescribeDBInstances , GetAccountPublicAccessBlock , GetBucketLifecycle , GenerateCredentialReport , DescribeMetricFilters , DescribeInstances , DescribeDBClusters , GetTrailStatus , ListBuckets\",\"rareProfiledAPIsUserIdentityProfiling\":\"ListFindings , TerminateInstances , EnableAlarmActions , CreateImage , ListMembers , GetBucketPolicy , DeleteAlarms , ModifyVolume , DescribeRegions , StartInstances , CreateSnapshot , GetFindings\",\"infrequentProfiledAPIsUserIdentityProfiling\":\"DescribeInstances , AllocateAddress , ListDetectors , PutBucketPolicy , RebootInstances , CreateTags\",\"frequentProfiledAPIsUserIdentityProfiling\":\"CreateBucket , ListBuckets\",\"rareProfiledUserTypesAccountProfiling\":\"\",\"infrequentProfiledUserTypesAccountProfiling\":\"\",\"frequentProfiledUserTypesAccountProfiling\":\"IAM_USER , ASSUMED_ROLE , ROOT\",\"rareProfiledUserNamesAccountProfiling\":\"aws:ec2-instance\",\"infrequentProfiledUserNamesAccountProfiling\":\"\",\"frequentProfiledUserNamesAccountProfiling\":\"dummy , AWSServiceRoleForSecurityHub , AWSServiceRoleForTrustedAdvisor , CloudabilityRole , AWSServiceRoleForAccessAnalyzer , AWSServiceRoleForConfig , gtrotman , mscherfling , Root , aws-controltower-ForwardSnsNotificationRole , AWSServiceRoleForAmazonGuardDuty\",\"rareProfiledASNsAccountProfiling\":\"asnNumber: 12271 asnOrg: TWC-12271-NYC asnNumber: 23908 asnOrg: IIAC asnNumber: 6167 asnOrg: CELLCO-PART asnNumber: 701 asnOrg: UUNET asnNumber: 209 asnOrg: CENTURYLINK-US-LEGACY-QWEST\",\"infrequentProfiledASNsAccountProfiling\":\"asnNumber: 4766 asnOrg: Korea Telecom\",\"frequentProfiledASNsAccountProfiling\":\"asnNumber: 17390 asnOrg: CIO-ORGANIZATION asnNumber: 16509 asnOrg: AMAZON-02 asnNumber: 36351 asnOrg: SOFTLAYER asnNumber: 2386 asnOrg: INS-AS asnNumber: 3462 asnOrg: Data Communication Business Group asnNumber: 15502 asnOrg: Vodafone Ireland Limited asnNumber: 14618 asnOrg: AMAZON-AES asnNumber: 7018 asnOrg: ATT-INTERNET4\",\"rareProfiledASNsUserIdentityProfiling\":\"\",\"infrequentProfiledASNsUserIdentityProfiling\":\"\",\"frequentProfiledASNsUserIdentityProfiling\":\"asnNumber: 2386 asnOrg: INS-AS\",\"rareProfiledUserAgentsAccountProfiling\":\"aws-sdk-go\",\"infrequentProfiledUserAgentsAccountProfiling\":\"aws-internal/account-settings\",\"frequentProfiledUserAgentsAccountProfiling\":\"AWS Service , aws-sdk-java , Botocore , AWS Internal , browser , aws-internal/3 , OTHER\",\"rareProfiledUserAgentsUserIdentityProfiling\":\"\",\"infrequentProfiledUserAgentsUserIdentityProfiling\":\"\",\"frequentProfiledUserAgentsUserIdentityProfiling\":\"Botocore\"},\"unusualBehavior\":{\"unusualAPIsAccountProfiling\":\"ArchiveFindings\",\"unusualUserTypesAccountProfiling\":\"\",\"unusualUserNamesAccountProfiling\":\"\",\"unusualASNsAccountProfiling\":\"\",\"unusualUserAgentsAccountProfiling\":\"\",\"unusualAPIsUserIdentityProfiling\":\"ArchiveFindings\",\"unusualASNsUserIdentityProfiling\":\"asnNumber: 17390 asnOrg: CIO-ORGANIZATION\",\"unusualUserAgentsUserIdentityProfiling\":\"\",\"isUnusualUserIdentity\":\"false\"}}"
},
"Archived": false,
"Count": 1,
"DetectorId": "48bbf98612290af2215c7a02b7ccbc82",
"EventFirstSeen": "2024-04-11T05:26:01.000Z",
"EventLastSeen": "2024-04-11T05:32:48.000Z",
"ResourceRole": "TARGET",
"ServiceName": "guardduty"
},
"Severity": 2,
"Title": "The user IAMUser : dummy is anomalously invoking APIs commonly used in Discovery tactics.",
"Type": "Discovery:IAMUser/AnomalousBehavior",
"UpdatedAt": "2024-04-11T05:47:16.625Z"
},
"payload": {
"artifacts": [],
"comments": [],
"description": {
"content": "APIs commonly used in Discovery tactics were invoked by user IAMUser : dummy under unusual circumstances. Such activity is not typically seen from this user.",
"format": "text"
},
"discovered_date": "2024-04-11T05:47:16.625Z",
"name": "AWS GuardDuty: The user IAMUser : dummy is anomalously invoking APIs commonly used in Discovery tactics.",
"properties": {
"aws_guardduty_archived": "False",
"aws_guardduty_count": "1",
"aws_guardduty_detector_id": "48bbf98612290af2215c7a02b7ccbc82",
"aws_guardduty_finding_arn": "arn:aws:guardduty:us-east-1:xxxxyyyyzzzz:detector/48bbf98612290af2215c7a02b7ccbc82/finding/xxxxyyyyzzzz",
"aws_guardduty_finding_id": "xxxxyyyyzzzz",
"aws_guardduty_finding_type": "Discovery:IAMUser/AnomalousBehavior",
"aws_guardduty_finding_updated_at": "2024-04-11T05:47:16.625Z",
"aws_guardduty_region": "us-east-1",
"aws_guardduty_resource_type": "AccessKey",
"aws_guardduty_severity": "2"
},
"severity_code": "Low"
},
"region": "us-east-1",
"timestamp": "2024-04-11 14:08:54"
},
"inputs": {
"aws_gd_detector_id": "48bbf98612290af2215c7a02b7ccbc82",
"aws_gd_finding_id": "xxxxyyyyzzzz",
"aws_gd_region": "us-east-1",
"incident_id": 2114
},
"metrics": {
"execution_time_ms": 1530,
"host": "IBM-dummy-MacBookPro.local",
"package": "fn-aws-guardduty",
"package_version": "1.1.0",
"timestamp": "2024-04-11 14:08:54",
"version": "1.0"
},
"raw": "{\"timestamp\": \"2024-04-11 14:08:54\", \"finding\": {\"AccountId\": \"xxxxyyyyzzzz\", \"Arn\": \"arn:aws:guardduty:us-east-1:xxxxyyyyzzzz:detector/48bbf98612290af2215c7a02b7ccbc82/finding/xxxxyyyyzzzz\", \"CreatedAt\": \"2024-04-11T05:47:16.625Z\", \"Description\": \"APIs commonly used in Discovery tactics were invoked by user IAMUser : dummy under unusual circumstances. Such activity is not typically seen from this user.\", \"Id\": \"xxxxyyyyzzzz\", \"Partition\": \"aws\", \"Region\": \"us-east-1\", \"Resource\": {\"AccessKeyDetails\": {\"AccessKeyId\": \"xxxxyyyy\", \"PrincipalId\": \"xxxxyyyy\", \"UserName\": \"dummy\", \"UserType\": \"IAMUser\"}, \"ResourceType\": \"AccessKey\"}, \"SchemaVersion\": \"2.0\", \"Service\": {\"Action\": {\"ActionType\": \"AWS_API_CALL\", \"AwsApiCallAction\": {\"Api\": \"ListFindings\", \"CallerType\": \"Remote IP\", \"RemoteIpDetails\": {\"City\": {\"CityName\": \"Singapore\"}, \"Country\": {\"CountryName\": \"Singapore\"}, \"GeoLocation\": {\"Lat\": 1.2868, \"Lon\": 103.8503}, \"IpAddressV4\": \"129.41.56.2\", \"Organization\": {\"Asn\": \"17390\", \"AsnOrg\": \"CIO-ORGANIZATION\", \"Isp\": \"IBM Corporation\", \"Org\": \"IBM Corporation\"}}, \"ServiceName\": \"guardduty.amazonaws.com\", \"AffectedResources\": {}}}, \"Archived\": false, \"Count\": 1, \"DetectorId\": \"48bbf98612290af2215c7a02b7ccbc82\", \"EventFirstSeen\": \"2024-04-11T05:26:01.000Z\", \"EventLastSeen\": \"2024-04-11T05:32:48.000Z\", \"ResourceRole\": \"TARGET\", \"ServiceName\": \"guardduty\", \"AdditionalInfo\": {\"Value\": \"{\\\"userAgent\\\":{\\\"fullUserAgent\\\":\\\"Boto3/1.34.82 md/Botocore#1.34.82 ua/2.0 os/macos#23.4.0 md/arch#x86_64 lang/python#3.9.16 md/pyimpl#CPython cfg/retry-mode#legacy Botocore/1.34.82\\\",\\\"userAgentCategory\\\":\\\"Botocore\\\"},\\\"anomalies\\\":{\\\"anomalousAPIs\\\":\\\"guardduty.amazonaws.com:[ListFindings:success , ListDetectors:success , GetFindings:success , ArchiveFindings:success] , ec2.amazonaws.com:[DescribeRegions:success]\\\"},\\\"profiledBehavior\\\":{\\\"rareProfiledAPIsAccountProfiling\\\":\\\"\\\",\\\"infrequentProfiledAPIsAccountProfiling\\\":\\\"\\\",\\\"frequentProfiledAPIsAccountProfiling\\\":\\\"ListFindings , DescribeVolumes , GetResources , BatchGetResourceConfig , ListHostedZones , SelectResourceConfig , DescribeConfigurationRecorderStatus , ListResourceRecordSets , DescribeTrails , DescribeRegions , GetBucketLocation , DescribeDBInstances , GetAccountPublicAccessBlock , GetBucketLifecycle , GenerateCredentialReport , DescribeMetricFilters , DescribeInstances , DescribeDBClusters , GetTrailStatus , ListBuckets\\\",\\\"rareProfiledAPIsUserIdentityProfiling\\\":\\\"ListFindings , TerminateInstances , EnableAlarmActions , CreateImage , ListMembers , GetBucketPolicy , DeleteAlarms , ModifyVolume , DescribeRegions , StartInstances , CreateSnapshot , GetFindings\\\",\\\"infrequentProfiledAPIsUserIdentityProfiling\\\":\\\"DescribeInstances , AllocateAddress , ListDetectors , PutBucketPolicy , RebootInstances , CreateTags\\\",\\\"frequentProfiledAPIsUserIdentityProfiling\\\":\\\"CreateBucket , ListBuckets\\\",\\\"rareProfiledUserTypesAccountProfiling\\\":\\\"\\\",\\\"infrequentProfiledUserTypesAccountProfiling\\\":\\\"\\\",\\\"frequentProfiledUserTypesAccountProfiling\\\":\\\"IAM_USER , ASSUMED_ROLE , ROOT\\\",\\\"rareProfiledUserNamesAccountProfiling\\\":\\\"aws:ec2-instance\\\",\\\"infrequentProfiledUserNamesAccountProfiling\\\":\\\"\\\",\\\"frequentProfiledUserNamesAccountProfiling\\\":\\\"dummy , AWSServiceRoleForSecurityHub , AWSServiceRoleForTrustedAdvisor , CloudabilityRole , AWSServiceRoleForAccessAnalyzer , AWSServiceRoleForConfig , gtrotman , mscherfling , Root , aws-controltower-ForwardSnsNotificationRole , AWSServiceRoleForAmazonGuardDuty\\\",\\\"rareProfiledASNsAccountProfiling\\\":\\\"asnNumber: 12271 asnOrg: TWC-12271-NYC asnNumber: 23908 asnOrg: IIAC asnNumber: 6167 asnOrg: CELLCO-PART asnNumber: 701 asnOrg: UUNET asnNumber: 209 asnOrg: CENTURYLINK-US-LEGACY-QWEST\\\",\\\"infrequentProfiledASNsAccountProfiling\\\":\\\"asnNumber: 4766 asnOrg: Korea Telecom\\\",\\\"frequentProfiledASNsAccountProfiling\\\":\\\"asnNumber: 17390 asnOrg: CIO-ORGANIZATION asnNumber: 16509 asnOrg: AMAZON-02 asnNumber: 36351 asnOrg: SOFTLAYER asnNumber: 2386 asnOrg: INS-AS asnNumber: 3462 asnOrg: Data Communication Business Group asnNumber: 15502 asnOrg: Vodafone Ireland Limited asnNumber: 14618 asnOrg: AMAZON-AES asnNumber: 7018 asnOrg: ATT-INTERNET4\\\",\\\"rareProfiledASNsUserIdentityProfiling\\\":\\\"\\\",\\\"infrequentProfiledASNsUserIdentityProfiling\\\":\\\"\\\",\\\"frequentProfiledASNsUserIdentityProfiling\\\":\\\"asnNumber: 2386 asnOrg: INS-AS\\\",\\\"rareProfiledUserAgentsAccountProfiling\\\":\\\"aws-sdk-go\\\",\\\"infrequentProfiledUserAgentsAccountProfiling\\\":\\\"aws-internal/account-settings\\\",\\\"frequentProfiledUserAgentsAccountProfiling\\\":\\\"AWS Service , aws-sdk-java , Botocore , AWS Internal , browser , aws-internal/3 , OTHER\\\",\\\"rareProfiledUserAgentsUserIdentityProfiling\\\":\\\"\\\",\\\"infrequentProfiledUserAgentsUserIdentityProfiling\\\":\\\"\\\",\\\"frequentProfiledUserAgentsUserIdentityProfiling\\\":\\\"Botocore\\\"},\\\"unusualBehavior\\\":{\\\"unusualAPIsAccountProfiling\\\":\\\"ArchiveFindings\\\",\\\"unusualUserTypesAccountProfiling\\\":\\\"\\\",\\\"unusualUserNamesAccountProfiling\\\":\\\"\\\",\\\"unusualASNsAccountProfiling\\\":\\\"\\\",\\\"unusualUserAgentsAccountProfiling\\\":\\\"\\\",\\\"unusualAPIsUserIdentityProfiling\\\":\\\"ArchiveFindings\\\",\\\"unusualASNsUserIdentityProfiling\\\":\\\"asnNumber: 17390 asnOrg: CIO-ORGANIZATION\\\",\\\"unusualUserAgentsUserIdentityProfiling\\\":\\\"\\\",\\\"isUnusualUserIdentity\\\":\\\"false\\\"}}\", \"Type\": \"default\"}}, \"Severity\": 2, \"Title\": \"The user IAMUser : dummy is anomalously invoking APIs commonly used in Discovery tactics.\", \"Type\": \"Discovery:IAMUser/AnomalousBehavior\", \"UpdatedAt\": \"2024-04-11T05:47:16.625Z\"}, \"region\": \"us-east-1\", \"payload\": {\"name\": \"AWS GuardDuty: The user IAMUser : dummy is anomalously invoking APIs commonly used in Discovery tactics.\", \"description\": {\"format\": \"text\", \"content\": \"APIs commonly used in Discovery tactics were invoked by user IAMUser : dummy under unusual circumstances. Such activity is not typically seen from this user.\"}, \"discovered_date\": \"2024-04-11T05:47:16.625Z\", \"severity_code\": \"Low\", \"properties\": {\"aws_guardduty_finding_id\": \"xxxxyyyyzzzz\", \"aws_guardduty_finding_arn\": \"arn:aws:guardduty:us-east-1:xxxxyyyyzzzz:detector/48bbf98612290af2215c7a02b7ccbc82/finding/xxxxyyyyzzzz\", \"aws_guardduty_finding_type\": \"Discovery:IAMUser/AnomalousBehavior\", \"aws_guardduty_finding_updated_at\": \"2024-04-11T05:47:16.625Z\", \"aws_guardduty_region\": \"us-east-1\", \"aws_guardduty_severity\": \"2\", \"aws_guardduty_resource_type\": \"AccessKey\", \"aws_guardduty_detector_id\": \"48bbf98612290af2215c7a02b7ccbc82\", \"aws_guardduty_count\": \"1\", \"aws_guardduty_archived\": \"False\"}, \"artifacts\": [], \"comments\": []}, \"data_tables\": {\"gd_finding_overview\": [{\"cells\": {\"severity\": {\"value\": \"2\"}, \"query_execution_date\": {\"value\": \"2024-04-11 14:08:54\"}, \"region\": {\"value\": \"us-east-1\"}, \"count\": {\"value\": \"1\"}, \"account_id\": {\"value\": \"xxxxyyyyzzzz\"}, \"created_at\": {\"value\": \"2024-04-11T05:47:16.625Z\"}, \"updated_at\": {\"value\": \"2024-04-11T05:47:16.625Z\"}}}], \"gd_action_details\": [{\"cells\": {\"action_type\": {\"value\": \"AWS_API_CALL\"}, \"query_execution_date\": {\"value\": \"2024-04-11 14:08:54\"}, \"action_api\": {\"value\": \"ListFindings\"}, \"event_first_seen\": {\"value\": \"2024-04-11T05:26:01.000Z\"}, \"event_last_seen\": {\"value\": \"2024-04-11T05:32:48.000Z\"}, \"actor_caller_type\": {\"value\": \"Remote IP\"}, \"city_name\": {\"value\": \"Singapore\"}, \"country_name\": {\"value\": \"Singapore\"}, \"asn\": {\"value\": \"17390\"}, \"asn_org\": {\"value\": \"CIO-ORGANIZATION\"}, \"isp\": {\"value\": \"IBM Corporation\"}, \"org\": {\"value\": \"IBM Corporation\"}, \"service_name\": {\"value\": \"guardduty.amazonaws.com\"}, \"remote_ip\": {\"value\": \"129.41.56.2\"}}}], \"gd_resource_affected\": [{\"cells\": {\"resource_type\": {\"value\": \"AccessKey\"}, \"query_execution_date\": {\"value\": \"2024-04-11 14:08:54\"}, \"resource_role\": {\"value\": \"TARGET\"}}}], \"gd_s3_bucket_details\": [], \"gd_instance_details\": [], \"gd_access_key_details\": [{\"cells\": {\"access_key_id\": {\"value\": \"xxxxyyyy\"}, \"query_execution_date\": {\"value\": \"2024-04-11 14:08:54\"}, \"principal_id\": {\"value\": \"xxxxyyyy\"}, \"user_type\": {\"value\": \"IAMUser\"}, \"user_name\": {\"value\": \"dummy\"}}}]}}",
"reason": null,
"success": true,
"version": "1.0"
}
Example Function Input Script:
inputs.aws_gd_region = incident.properties.aws_guardduty_region
inputs.aws_gd_detector_id = incident.properties.aws_guardduty_detector_id
inputs.aws_gd_finding_id = incident.properties.aws_guardduty_finding_id
inputs.incident_id = incident.id
Example Function Post Process Script:
## wf_aws_guardduty_refresh_finding ##
# Example result:
"""
Result: { 'version': '1.0',
'success': True,
'reason': None,
'content': {'payload': {'name': 'AWS GuardDuty: API GeneratedFindingAPIName was invoked from an IP address on a custom threat list.',
'description': {'format': 'text', 'content': 'An API was used to access a bucket from an IP address on a custom threat list.'},
'discovered_date': '2020-11-25T13:46:37.960Z',
'severity_code': 'Low',
'properties': {'aws_guardduty_finding_id': '60baffd3f9042e38640f2300d5c5a631',
'aws_guardduty_finding_arn': 'arn:aws:guardduty:us-west-2:xxxxyyyyzzzz:detector/f2baedb0ac74f8f42fc929e15f56da6a/finding/60baffd3f9042e38640f2300d5c5a631',
'aws_guardduty_finding_type': 'UnauthorizedAccess:S3/MaliciousIPCaller.Custom',
'aws_guardduty_finding_updated_at': '2020-11-26T15:18:12.620Z', 'aws_guardduty_region': 'us-west-2',
'aws_guardduty_resource_type': 'S3Bucket', 'aws_guardduty_count': 4,
'aws_guardduty_detector_id': 'f2baedb0ac74f8f42fc929e15f56da6a'},
'artifacts': [],
'comments': [{'text': {'format': 'text', 'content': "AWS GuardDuty finding Payload:\n<FINDING_PAYLOAD_AS_STRING>"}}]
},
"data_tables": {"gd_action_details": [{"cells": {"action_type": {"value": "AWS_API_CALL"},
"action_api": {"value": "GeneratedFindingAPIName"},
"event_first_seen": {"value": "2020-11-25T13:46:37.960Z"},
"event_last_seen": {"value": "2020-11-26T15:18:12.620Z"},
"actor_caller_type": {"value": "Remote IP"}, "city_name": {"value": "GeneratedFindingCityName"}, "country_name": {"value": "GeneratedFindingCountryName"}, "asn": {"value": "-1"}, "asn_org": {"value": "GeneratedFindingASNOrg"}, "isp": {"value": "GeneratedFindingISP"}, "org": {"value": "GeneratedFindingORG"}, "action_service_name": {"value": "GeneratedFindingAPIServiceName"}, "remote_ip": {"value": "198.51.100.0"}}}],
"gd_resource_affected": [{"cells": {"resource_type": {"value": "S3Bucket"}, "instance_id": {"value": "i-99999999"}, "instance_type": {"value": "m3.xlarge"}, "instance_state": {"value": "running"}, "resource_role": {"value": "TARGET"}, "instance_private_ip": {"value": "10.0.0.1"}, "instance_private_dns": {"value": "GeneratedFindingPrivateName"}, "instance_public_ip": {"value": "198.51.100.0"}, "instance_public_dns": {"value": "GeneratedFindingPublicDNSName"}, "s3bucket_name": {"value": "bucketName"}, "s3bucket_owner": {"value": "CanonicalId of Owner"}}}]
}}',
'inputs': {'incident_id': 2168, 'aws_gd_finding_id': '60baffd3f9042e38640f2300d5c5a631',
'aws_gd_region': 'us-west-2', 'aws_gd_detector_id': 'f2baedb0ac74f8f42fc929e15f56da6a'},
'metrics': {'version': '1.0', 'package': 'fn-aws-guardduty', 'package_version': '1.0.0',
'host': 'Johnp-MacBook-Pro-2.galway.ie.ibm.com', 'execution_time_ms': 10739,
'timestamp': '2021-01-18 16:51:10'}
}
"""
# Globals
# List of fields in datatable for wf_aws_guardduty_refresh_finding script
DATA_TABLES = ["gd_action_details", "gd_resource_affected"]
FN_NAME = "func_aws_guardduty_refresh_finding"
WF_NAME = "Example: AWS GuardDuty: Refresh Finding"
# Resilient artifact names to api names.
ARTIFACT_API_TO_TYPE = {
"aws_iam_access_key_id": "AWS IAM Access Key ID",
"aws_iam_user_name": "AWS IAM User Name",
"aws_s3_bucket_name": "AWS S3 Bucket Name",
"IP Address": "IP Address",
"DNS Name": "DNS Name",
"Port": "Port"
}
CONTENT = playbook.functions.results.output
QUERY_EXECUTION_DATE = playbook.functions.results.output["metrics"]["timestamp"]
if CONTENT:
FINDING = CONTENT.finding
PAYLOAD = CONTENT.payload
ARTIFACTS = CONTENT.artifacts
DATA_TABLES = CONTENT.data_tables
# Processing
def main():
note_text = ''
if CONTENT:
note_text = "AWS GuardDuty Integration: Workflow <b>{0}</b>: Finding data returned for Resilient function " \
"<b>{2}</b>".format(WF_NAME, len(CONTENT), FN_NAME)
update_fields()
update_datatables()
if ARTIFACTS:
add_artifacts()
else:
note_text = "AWS GuardDuty Integration: Workflow <b>{0}</b>: No finding data returned for Resilient function " \
"<b>{2}</b>".format(WF_NAME, len(CONTENT), FN_NAME)
incident.addNote(helper.createRichText(note_text))
def update_fields():
incident.severity_code = PAYLOAD["severity_code"]
incident.properties.aws_guardduty_finding_updated_at = PAYLOAD["properties"]["aws_guardduty_finding_updated_at"]
incident.properties.aws_guardduty_count = str(PAYLOAD["properties"]["aws_guardduty_count"])
incident.properties.aws_guardduty_archived = str(PAYLOAD["properties"]["aws_guardduty_archived"])
incident.properties.aws_guardduty_severity = str(PAYLOAD["properties"]["aws_guardduty_severity"])
def update_datatables():
for data_table in DATA_TABLES:
for row in DATA_TABLES[data_table]:
newrow = incident.addRow(data_table)
newrow.query_execution_date = QUERY_EXECUTION_DATE
data_table_fields = row["cells"]
for f, v_info in data_table_fields.items():
newrow[f] = v_info.value
def add_artifacts():
for artifact in ARTIFACTS:
artifact_type = ARTIFACT_API_TO_TYPE[artifact["type"]["name"]]
artifact_value = artifact["value"]
description = artifact["description"]["content"]
incident.addArtifact(artifact_type, artifact_value, description)
if __name__ == "__main__":
main()
Playbooks¶
Playbook Name |
Description |
Activation Type |
Object |
Status |
Condition |
---|---|---|---|---|---|
Example: AWS GuardDuty: Archive Finding (PB) |
A SOAR playbook to archive an AWS GuardDuty finding when the corresponding incident is closed. |
Automatic |
incident |
|
|
Example: AWS GuardDuty: Refresh Finding Details (PB) |
A SOAR playbook to refresh or update AWS GuardDuty finding details in an incident. |
Manual |
incident |
|
|
Example: AWS GuardDuty: Update Finding Details (PB) |
None |
Automatic |
incident |
|
|
Custom Layouts¶
Import the Data Tables and Custom Fields like the screenshot below:
Data Table - GuardDuty Action/Actor Details¶
API Name:¶
gd_action_details
Columns:¶
Column Name |
API Access Name |
Type |
Tooltip |
---|---|---|---|
Action api |
|
|
- |
Action type |
|
|
- |
Actor caller type |
|
|
- |
Asn |
|
|
- |
City name |
|
|
- |
Connection direction |
|
|
- |
Country |
|
|
- |
DNS domain name |
|
|
- |
DNS request blocked |
|
|
- |
Event first Seen |
|
|
- |
Event Last Seen |
|
|
- |
Finding asn org |
|
|
- |
Finding isp |
|
|
- |
Finding org |
|
|
- |
Local IP address |
|
|
- |
Local port |
|
|
- |
Protocol |
|
|
- |
Query Execution date |
|
|
- |
Remote IP address |
|
|
- |
Remote port |
|
|
- |
Service name |
|
|
- |
Data Table - GuardDuty Finding Overview¶
API Name:¶
gd_finding_overview
Columns:¶
Column Name |
API Access Name |
Type |
Tooltip |
---|---|---|---|
Account ID |
|
|
- |
Count |
|
|
- |
Created at |
|
|
- |
Query Execution date |
|
|
- |
Region |
|
|
- |
Resource ID |
|
|
- |
Severity |
|
|
- |
Updated at |
|
|
- |
Data Table - GuardDuty Resource - Access Key Details¶
API Name:¶
gd_access_key_details
Columns:¶
Column Name |
API Access Name |
Type |
Tooltip |
---|---|---|---|
Access key ID |
|
|
- |
Principal ID |
|
|
- |
Query Execution date |
|
|
- |
User name |
|
|
- |
User type |
|
|
- |
Data Table - GuardDuty Resource - Instance Details¶
API Name:¶
gd_instance_details
Columns:¶
Column Name |
API Access Name |
Type |
Tooltip |
---|---|---|---|
ID |
|
|
- |
Private dns name |
|
|
- |
Private ip address |
|
|
- |
Public dns name |
|
|
- |
Public ip address |
|
|
- |
Query execution date |
|
|
- |
State |
|
|
- |
Type |
|
|
- |
Data Table - GuardDuty Resource - S3 Bucket Details¶
API Name:¶
gd_s3_bucket_details
Columns:¶
Column Name |
API Access Name |
Type |
Tooltip |
---|---|---|---|
Bucket Arn |
|
|
- |
Bucket name |
|
|
- |
Bucket owner |
|
|
- |
Bucket Type |
|
|
- |
Effective Permission |
|
|
- |
Encryption type |
|
|
- |
Kms master key ARN |
|
|
- |
Query execution date |
|
|
- |
Data Table - GuardDuty Resource Affected¶
API Name:¶
gd_resource_affected
Columns:¶
Column Name |
API Access Name |
Type |
Tooltip |
---|---|---|---|
Instance ID |
|
|
- |
Instance type |
|
|
- |
Query execution date |
|
|
- |
Resource role |
|
|
- |
Resource type |
|
|
- |
Custom Fields¶
Label |
API Access Name |
Type |
Prefix |
Placeholder |
Tooltip |
---|---|---|---|---|---|
AWS GuardDuty Archived |
|
|
|
- |
A true or false value that indicates whether this is GuardDuty finding has been archived. |
AWS GuardDuty Count |
|
|
|
- |
The number of times GuardDuty has aggregated an activity matching this pattern to this finding ID. |
AWS GuardDuty Detector Id |
|
|
|
- |
The detector ID where the GuardDuty finding was detected. |
AWS GuardDuty Finding Arn |
|
|
|
- |
Arn of the GuardDuty finding. |
AWS GuardDuty Finding Id |
|
|
|
- |
A unique Finding ID for this GuardDuty finding type and set of parameters. New occurrences of activity matching this pattern will be aggregated to the same ID. |
AWS GuardDuty Finding Type |
|
|
|
- |
The type of activity that triggered the GuardDuty finding. |
AWS GuardDuty Resource Updated At |
|
|
|
- |
The last time this finding was updated with new activity matching the pattern that prompted GuardDuty to generate this finding. |
AWS GuardDuty Region |
|
|
|
- |
The AWS Region in which the GuardDuty finding was generated. |
AWS GuardDuty Resource Type |
|
|
|
- |
The type of the affected resource of the GuardDuty finding. This value is either AccessKey, S3 bucket or Instance. |
AWS GuardDuty Severity |
|
|
|
- |
The severity of the affected resource of the GuardDuty finding. |
AWS GuardDuty Trigger Refresh |
|
|
|
False |
Used by integration to trigger an refresh of GuardDuty incidents. |
Custom Artifact Types¶
Display Name |
API Access Name |
Description |
---|---|---|
AWS IAM Access Key ID |
|
Amazon Web Services (AWS) IAM access key id. |
AWS IAM User Name |
|
Amazon Web Services (AWS) IAM user name. |
AWS S3 Bucket Name |
|
Amazon Web Services (AWS) S3 bucket name. |
Troubleshooting & Support¶
Refer to the documentation listed in the Requirements section for troubleshooting information.
For Support¶
This is an IBM supported app. Please search ibm.com/mysupport for assistance.