Details
| ID | AWS - GuardDuty |
|---|---|
| Provider | Amazon |
| Category | IT Services |
| From Version | 5.0.0 |
| Docker Image | demisto/boto3py3:1.0.0.10221838 |
| Supported Modules | Agentix XSIAM |
README
Amazon Web Services Guard Duty Service (gd)
Use this integration to detect and manage threats to your AWS system. We recommend that you use roles that have the following
built-in AWS policies:
- AmazonGuardDutyFullAccess
- AmazonGuardDutyReadOnlyAccess
For detailed instructions about setting up authentication, see: AWS Integrations - Authentication.
Prerequisites
It is important that you familiarize yourself with and complete all steps detailed in
the Amazon AWS Integrations Configuration Guide
Some changes have been made that might affect your existing content.
If you are upgrading from a previous of this integration, see Breaking Changes.
Configure AWS - GuardDuty in Cortex
| Parameter | Description | Required |
|---|---|---|
| AWS Default Region | The AWS Region for this instance of the integration. For example, us-west-2 | True |
| Role Arn | The Amazon Resource Name (ARN) role used for EC2 instance authentication. If this is used, an access key and secret key are not required. | False |
| Fetch incidents | False | |
| Incident type | Incident type | False |
| Role Session Name | A descriptive name for the assumed role session. For example, xsiam-IAM.integration-Role_SESSION | False |
| Role Session Duration | The maximum length of each session in seconds. Default: 900 seconds. The Cortex XSOAR integration will have the permissions assigned only when the session is initiated and for the defined duration. | False |
| Access Key | The access key ID used for authentication, that was configured during IAM user configuration. If this is used, Role ARN is not required. | False |
| Secret Key | The secret key used for authentication, that was configured during IAM user configuration. If this is used, Role ARN is not required. | False |
| Timeout | The time in seconds until a timeout exception is reached. You can specify just the read timeout (for example 60) or also the connect timeout followed after a comma (for example 60,10). If a connect timeout is not specified, a default of 10 second will be used. | False |
| Retries | The maximum number of retry attempts when connection or throttling errors are encountered. Set to 0 to disable retries. The default value is 5 and the limit is 10. Note: Increasing the number of retries will increase the execution time. | False |
| How many incidents to fetch each time | Default 10 |
False |
| First fetch timestamp | First fetch query <number> <time unit>, e.g., 7 days. Default 3 days |
False |
| Guard Duty Severity level | The severity level or higher of findings to be fetched: Low, Medium, or High. For example, if you set the severity level to Medium, only findings with severity level Medium or High will be fetched. | False |
| Archive findings After Fetch | You can set whether findings that are fetched will be moved to the GuardDuty archive. | False |
| Incidents Fetch Interval | Time interval for fetching incidents. | False |
| Trust any certificate (not secure) | False | |
| Use system proxy settings | False |
Fetched Incidents Data
- The integration fetches newly created Guard DutyFindings.
Each integration instance can fetch findings from a single AWS Region. - Each region can have a maximum of 1,000 member accounts that are linked to a guard duty master account. For more information see
the Amazon GuardDuty documentation. - You can set the severity level of the findings to be fetched. “Low”, “Medium”, “High”. For example, if you set the severity
level to “Medium”, the integration will only fetch findings with severity level of Medium and higher.
Commands
You can execute these commands from the CLI, as part of an automation, or in a playbook. After you successfully
execute a command, a DBot message appears in the War Room with the command details.
aws-gd-create-detector
Create an AWS Guard Duty Detector on the integration instance specified aws account.
AWS IAM Policy Permission
Effect: Allow
Action: guardduty:CreateDetector
Base Command
aws-gd-create-detector
Input
| Argument Name | Description | Required |
|---|---|---|
| enabled | A boolean value that specifies whether the detector is to be enabled. Possible values are: True, False. Default is True. | Required |
| enableS3Logs | The status of S3 data event logs as a data source. Possible values are: True, False. | Optional |
| enableKubernetesLogs | The status of Kubernetes audit logs as a data source. Possible values are: True, False. | Optional |
| ebsVolumesMalwareProtection | Describes the configuration for scanning EBS volumes as a data source. Possible values are: True, False. | Optional |
| findingFrequency | Specifies how frequently updated findings are exported. Possible values are: Fifteen Minutes, One Hour, Six Hours. | Optional |
| region | The AWS Region, if not specified the default region will be used. | Optional |
| roleArn | The Amazon Resource Name (ARN) of the role to assume. | Optional |
| roleSessionName | An identifier for the assumed role session. | Optional |
| roleSessionDuration | The duration, in seconds, of the role session. The value can range from 900 seconds (15 minutes) up to the maximum session duration setting for the role. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| AWS.GuardDuty.Detectors.DetectorId | string | The unique ID of the created detector. |
Command Example
!aws-gd-create-detector enabled=True region=eu-west-2
aws-gd-delete-detector
Deletes a Amazon GuardDuty detector specified by the detector ID.
AWS IAM Policy Permission
Effect: Allow
Action: guardduty:DeleteDetector
Base Command
aws-gd-delete-detector
Input
| Argument Name | Description | Required |
|---|---|---|
| detectorId | The unique ID that specifies the detector that you want to delete. | Required |
| region | The AWS Region, if not specified the default region will be used. | Optional |
| roleArn | The Amazon Resource Name (ARN) of the role to assume. | Optional |
| roleSessionName | An identifier for the assumed role session. | Optional |
| roleSessionDuration | The duration, in seconds, of the role session. The value can range from 900 seconds (15 minutes) up to the maximum session duration setting for the role. | Optional |
Context Output
There is no context output for this command.
Command Example
!aws-gd-delete-detector detectorId=38b1235ed3fe245279cd0c8e235db0715ac5561eb
aws-gd-get-detector
Retrieves an Amazon GuardDuty detector specified by the detectorId.
AWS IAM Policy Permission
Effect: Allow
Action: guardduty:GetDetector
Base Command
aws-gd-get-detector
Input
| Argument Name | Description | Required |
|---|---|---|
| detectorId | The unique ID of the detector that you want to retrieve. | Required |
| region | The AWS Region, if not specified the default region will be used. | Optional |
| roleArn | The Amazon Resource Name (ARN) of the role to assume. | Optional |
| roleSessionName | An identifier for the assumed role session. | Optional |
| roleSessionDuration | The duration, in seconds, of the role session. The value can range from 900 seconds (15 minutes) up to the maximum session duration setting for the role. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| AWS.GuardDuty.Detectors.DetectorId | string | The unique ID of the created detector. |
| AWS.GuardDuty.Detectors.CreatedAt | string | The first time a resource was created. |
| AWS.GuardDuty.Detectors.ServiceRole | string | Customer serviceRole name or ARN for accessing customer resources. |
| AWS.GuardDuty.Detectors.Status | string | The status of detector. |
| AWS.GuardDuty.Detectors.UpdatedAt | string | The time a resource was last updated. |
| AWS.GuardDuty.Detectors.CloudTrailStatus | string | Describes whether CloudTrail is enabled as a data source for the detector. |
| AWS.GuardDuty.Detectors.DNSLogsStatus | string | Denotes whether DNS logs are enabled as a data source. |
| AWS.GuardDuty.Detectors.FlowLogsStatus | string | Denotes whether VPC flow logs are enabled as a data source. |
| AWS.GuardDuty.Detectors.S3LogsStatus | string | Describes whether S3 data event logs are automatically enabled for new members of the organization. |
| AWS.GuardDuty.Detectors.KubernetesAuditLogsStatus | string | Describes whether Kubernetes audit logs are enabled as a data source. |
| AWS.GuardDuty.Detectors.MalwareProtectionStatus | string | Describes whether scanning EBS volumes is enabled as a data source. |
| AWS.GuardDuty.Detectors.MalwareProtectionReason | string | Specifies the reason why scanning EBS volumes (Malware Protection) was not enabled as a data source. |
| AWS.GuardDuty.Detectors.Tags | string | The tags of the detector resource. |
Command Example
!aws-gd-get-detector detectorId=38b1ed3fe279fdascd0c8edb071dsf5ac5561eb region=eu-west-2
aws-gd-update-detector
Updates an Amazon GuardDuty detector specified by the detectorId.
AWS IAM Policy Permission
Effect: Allow
Action: guardduty:UpdateDetector
Base Command
aws-gd-update-detector
Input
| Argument Name | Description | Required |
|---|---|---|
| detectorId | The unique ID of the detector that you want to update. | Required |
| enable | Updated boolean value for the detector that specifies whether the detector is enabled. Possible values are: True, False. Default is True. | Required |
| enableS3Logs | The status of S3 data event logs as a data source. Possible values are: True, False. | Optional |
| enableKubernetesLogs | The status of Kubernetes audit logs as a data source. Possible values are: True, False. | Optional |
| ebsVolumesMalwareProtection | Describes the configuration for scanning EBS volumes as data source. Possible values are: True, False. | Optional |
| findingFrequency | A value that specifies how frequently updated findings are exported. Possible values are: Fifteen Minutes, One Hour, Six Hours. | Optional |
| region | The AWS Region, if not specified the default region will be used. | Optional |
| roleArn | The Amazon Resource Name (ARN) of the role to assume. | Optional |
| roleSessionName | An identifier for the assumed role session. | Optional |
| roleSessionDuration | The duration, in seconds, of the role session. The value can range from 900 seconds (15 minutes) up to the maximum session duration setting for the role. | Optional |
Context Output
There is no context output for this command.
Command Example
aws-gd-update-detector detectorId=38b1ed3fe279fdascd0c8edb071dsf5ac5561eb enable=True
aws-gd-create-ip-set
A list of trusted IP addresses on allow list for secure communication with AWS infrastructure and applications.
AWS IAM Policy Permission
Effect: Allow
Action: guardduty:CreateIPSet
Base Command
aws-gd-create-ip-set
Input
| Argument Name | Description | Required |
|---|---|---|
| activate | A boolean value that indicates whether GuardDuty is to start using the uploaded IPSet. Possible values are: True, False. Default is True. | Optional |
| detectorId | The unique ID of the detector that you want to update. | Required |
| format | The format of the file that contains the IPSet. Possible values are: TXT, STIX, OTX_CSV, ALIEN_VAULT, PROOF_POINT, FIRE_EYE. | Required |
| location | The URI of the file that contains the IPSet. For example (https://s3.us-west-2.amazonaws.com/my-bucket/my-object-key). | Optional |
| name | The user friendly name to identify the IPSet. This name is displayed in all findings that are triggered by activity that involves IP addresses included in this IPSet. | Optional |
| region | The AWS Region, if not specified the default region will be used. | Optional |
| roleArn | The Amazon Resource Name (ARN) of the role to assume. | Optional |
| roleSessionName | An identifier for the assumed role session. | Optional |
| roleSessionDuration | The duration, in seconds, of the role session. The value can range from 900 seconds (15 minutes) up to the maximum session duration setting for the role. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| AWS.GuardDuty.Detectors.IPSet.IpSetId | unknown | The unique identifier for an IP Set. |
Command Example
!aws-gd-create-ip-set format=TXT location=https://s3.eu-central-1.amazonaws.com/test/ipset.txt activate=True detectorId=38b1ed3fe279czvasdd0c8edb0715azdsfc5561eb name=test region=eu-west-2
aws-gd-delete-ip-set
Deletes the IPSet specified by the IPSet ID.
AWS IAM Policy Permission
Effect: Allow
Action: guardduty:DeleteIPSet
Base Command
aws-gd-delete-ip-set
Input
| Argument Name | Description | Required |
|---|---|---|
| detectorId | The detectorID that specifies the GuardDuty service whose IPSet you want to delete. | Required |
| ipSetId | The unique ID that specifies the IPSet that you want to delete. | Required |
| region | The AWS Region, if not specified the default region will be used. | Optional |
| roleArn | The Amazon Resource Name (ARN) of the role to assume. | Optional |
| roleSessionName | An identifier for the assumed role session. | Optional |
| roleSessionDuration | The duration, in seconds, of the role session. The value can range from 900 seconds (15 minutes) up to the maximum session duration setting for the role. | Optional |
Context Output
There is no context output for this command.
Command Example
!aws-gd-delete-ip-set detectorId=38b1ed3fe279cd0c8edb0715ac5561eb ipSetId=7eb1f440be5931f168280b574a26d44d region=eu-west-2
aws-gd-list-detectors
Lists detectorIds of all the existing Amazon GuardDuty detector resources.
AWS IAM Policy Permission
Effect: Allow
Action: guardduty:ListDetectors
Base Command
aws-gd-list-detectors
Input
| Argument Name | Description | Required |
|---|---|---|
| limit | Number of total results to query. Default is 50. |
Optional |
| page | Specific page to query. | Optional |
| page_size | Number of total results in each page. Default is 50. |
Optional |
| region | The AWS Region, if not specified the default region will be used. | Optional |
| roleArn | The Amazon Resource Name (ARN) of the role to assume. | Optional |
| roleSessionName | An identifier for the assumed role session. | Optional |
| roleSessionDuration | The duration, in seconds, of the role session. The value can range from 900 seconds (15 minutes) up to the maximum session duration setting for the role. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| AWS.GuardDuty.Detectors.DetectorId | string | The unique identifier for a detector. |
Command Example
!aws-gd-list-detectors region=eu-west-2
aws-gd-update-ip-set
Updates the IPSet specified by the IPSet ID.
AWS IAM Policy Permission
Effect: Allow
Action: guardduty:UpdateIPSet
Base Command
aws-gd-update-ip-set
Input
| Argument Name | Description | Required |
|---|---|---|
| activate | The updated boolean value that specifies whether the IPSet is active or not. Possible values are: True, False. | Optional |
| detectorId | The detectorID that specifies the GuardDuty service whose IPSet you want to update. | Required |
| ipSetId | The unique ID that specifies the IPSet that you want to update. | Required |
| location | The updated URI of the file that contains the IPSet. For example (https://s3.us-west-2.amazonaws.com/my-bucket/my-object-key). | Optional |
| name | The user friendly name to identify the IPSet. | Optional |
| region | The AWS Region, if not specified the default region will be used. | Optional |
| roleArn | The Amazon Resource Name (ARN) of the role to assume. | Optional |
| roleSessionName | An identifier for the assumed role session. | Optional |
| roleSessionDuration | The duration, in seconds, of the role session. The value can range from 900 seconds (15 minutes) up to the maximum session duration setting for the role. | Optional |
Context Output
There is no context output for this command.
Command Example
!aws-gd-update-ip-set detectorId=38b1ed3fe279cd0c8edb0715ac5561eb ipSetId=7eb1f440be5931f168280b574a26d44d activate=False region=eu-west-2
aws-gd-get-ip-set
Retrieves the IPSet specified by the IPSet ID.
AWS IAM Policy Permission
Effect: Allow
Action: guardduty:GetIPSet
Base Command
aws-gd-get-ip-set
Input
| Argument Name | Description | Required |
|---|---|---|
| detectorId | The detectorID that specifies the GuardDuty service whose IPSet you want to retrieve. | Required |
| ipSetId | The unique ID that specifies the IPSet that you want to describe. | Required |
| region | The AWS Region, if not specified the default region will be used. | Optional |
| roleArn | The Amazon Resource Name (ARN) of the role to assume. | Optional |
| roleSessionName | An identifier for the assumed role session. | Optional |
| roleSessionDuration | The duration, in seconds, of the role session. The value can range from 900 seconds (15 minutes) up to the maximum session duration setting for the role. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| AWS.GuardDuty.Detectors.IPSet.IpSetId | string | The unique ID for the IPSet. |
| AWS.GuardDuty.Detectors.IPSet.Format | string | The format of the file that contains the IPSet. |
| AWS.GuardDuty.Detectors.IPSet.Location | string | The URI of the file that contains the IPSet. |
| AWS.GuardDuty.Detectors.IPSet.Name | string | he user friendly name to identify the IPSet. |
| AWS.GuardDuty.Detectors.IPSet.Status | string | The status of ipSet file uploaded. |
Command Example
!aws-gd-get-ip-set detectorId=38b1ed3fesdf279cd0c8edbdsf071sdgfac5561eb ipSetId=7eb1sdff440be5931f1682adf80b574a26d44d region=eu-west-2
aws-gd-list-ip-sets
Lists the IPSets of the GuardDuty service specified by the detector ID.
AWS IAM Policy Permission
Effect: Allow
Action: guardduty:ListIPSet
Base Command
aws-gd-list-ip-sets
Input
| Argument Name | Description | Required |
|---|---|---|
| detectorId | The unique ID of the detector that you want to retrieve. | Required |
| region | The AWS Region, if not specified the default region will be used. | Optional |
| roleArn | The Amazon Resource Name (ARN) of the role to assume. | Optional |
| roleSessionName | An identifier for the assumed role session. | Optional |
| roleSessionDuration | The duration, in seconds, of the role session. The value can range from 900 seconds (15 minutes) up to the maximum session duration setting for the role. | Optional |
| limit | Number of total results to query. Default is 50. |
Optional |
| page | Specific page to query. | Optional |
| page_size | Number of total results in each page. Default is 50. |
Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| AWS.GuardDuty.Detectors.IPSet.IpSetId | unknown | The unique identifier for an IP Set |
Command Example
!aws-gd-list-ip-sets detectorId=38b1ed3fesdf279cd0c8edbdsf071sdgfac5561eb region=eu-west-2
aws-gd-create-threatintel-set
Create a new ThreatIntelSet. ThreatIntelSets consist of known malicious IP addresses. GuardDuty generates findings based on
ThreatIntelSets.
AWS IAM Policy Permission
Effect: Allow
Action: guardduty:CreateThreatIntelSet
Base Command
aws-gd-create-threatintel-set
Input
| Argument Name | Description | Required |
|---|---|---|
| activate | A boolean value that indicates whether GuardDuty is to start using the uploaded ThreatIntelSet. Possible values are: True, False. Default is True. | Required |
| detectorId | The unique ID of the detector that you want to update. | Required |
| format | The format of the file that contains the ThreatIntelSet. Possible values are: TXT, STIX, OTX_CSV, ALIEN_VAULT, PROOF_POINT, FIRE_EYE. | Required |
| location | The URI of the file that contains the ThreatIntelSet. For example (https://s3.us-west-2.amazonaws.com/my-bucket/my-object-key). | Required |
| name | A user-friendly ThreatIntelSet name that is displayed in all finding generated by activity that involves IP addresses included in this ThreatIntelSet. | Required |
| region | The AWS Region, if not specified the default region will be used. | Optional |
| roleArn | The Amazon Resource Name (ARN) of the role to assume. | Optional |
| roleSessionName | An identifier for the assumed role session. | Optional |
| roleSessionDuration | The duration, in seconds, of the role session. The value can range from 900 seconds (15 minutes) up to the maximum session duration setting for the role. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| AWS.GuardDuty.Detectors.ThreatIntelSet.ThreatIntelSetId | string | The unique identifier for an threat intel set. |
Command Example
!aws-gd-create-threatintel-set format=TXT location=https://s3.eu-central-1.amazonaws.com/test/threatintel.txt activate=True detectorId=38b1ed3fe279czvasdd0c8edb0715azdsfc5561eb name=test region=eu-west-2
aws-gd-delete-threatintel-set
Deletes ThreatIntelSet specified by the ThreatIntelSet ID.
AWS IAM Policy Permission
Effect: Allow
Action: guardduty:DeleteThreatIntelSet
Base Command
aws-gd-delete-threatintel-set
Input
| Argument Name | Description | Required |
|---|---|---|
| detectorId | The detectorID that specifies the GuardDuty service whose ThreatIntelSet you want to delete. | Required |
| threatIntelSetId | The unique ID that specifies the ThreatIntelSet that you want to delete. | Required |
| region | The AWS Region, if not specified the default region will be used. | Optional |
| roleArn | The Amazon Resource Name (ARN) of the role to assume. | Optional |
| roleSessionName | An identifier for the assumed role session. | Optional |
| roleSessionDuration | The duration, in seconds, of the role session. The value can range from 900 seconds (15 minutes) up to the maximum session duration setting for the role. | Optional |
Context Output
There is no context output for this command.
Command Example
!aws-gd-delete-threatintel-set detectorId=38b1ed3fe279cd0c8edb0715ac5561eb threatIntelSetId=7eb1f440be5931f168280b574a26d44d region=eu-west-2
aws-gd-get-threatintel-set
Retrieves the ThreatIntelSet that is specified by the ThreatIntelSet ID.
AWS IAM Policy Permission
Effect: Allow
Action: guardduty:GetThreatIntelSet
Base Command
aws-gd-get-threatintel-set
Input
| Argument Name | Description | Required |
|---|---|---|
| detectorId | The detectorID that specifies the GuardDuty service whose ThreatIntelSet you want to describe. | Required |
| threatIntelSetId | The unique ID that specifies the ThreatIntelSet that you want to describe. | Required |
| region | The AWS Region, if not specified the default region will be used. | Optional |
| roleArn | The Amazon Resource Name (ARN) of the role to assume. | Optional |
| roleSessionName | An identifier for the assumed role session. | Optional |
| roleSessionDuration | The duration, in seconds, of the role session. The value can range from 900 seconds (15 minutes) up to the maximum session duration setting for the role. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| AWS.GuardDuty.Detectors.ThreatIntelSet.ThreatIntelSetId | string | The unique ID that specifies the ThreatIntelSet. |
| AWS.GuardDuty.Detectors.ThreatIntelSet.Format | string | The format of the threatIntelSet. |
| AWS.GuardDuty.Detectors.ThreatIntelSet.Location | string | The URI of the file that contains the ThreatIntelSet. |
| AWS.GuardDuty.Detectors.ThreatIntelSet.Name | string | A user-friendly ThreatIntelSet name. |
| AWS.GuardDuty.Detectors.ThreatIntelSet.Status | string | The status of threatIntelSet file uploaded. |
Command Example
!aws-gd-get-threatintel-set detectorId=38b1ed3fe279cd0c8edb0715ac5561eb threatIntelSetId=7eb1f440be5931f168280b574a26d44d region=eu-west-2
aws-gd-list-threatintel-sets
Lists the ThreatIntelSets of the GuardDuty service specified by the detector ID.
AWS IAM Policy Permission
Effect: Allow
Action: guardduty:ListThreatIntelSet
Base Command
aws-gd-list-threatintel-sets
Input
| Argument Name | Description | Required |
|---|---|---|
| detectorId | The detectorID that specifies the GuardDuty service whose ThreatIntelSets you want to list. | Required |
| region | The AWS Region, if not specified the default region will be used. | Optional |
| roleArn | The Amazon Resource Name (ARN) of the role to assume. | Optional |
| roleSessionName | An identifier for the assumed role session. | Optional |
| roleSessionDuration | The duration, in seconds, of the role session. The value can range from 900 seconds (15 minutes) up to the maximum session duration setting for the role. | Optional |
| limit | Number of total results to query. Default is 50. |
Optional |
| page | Specific page to query. | Optional |
| page_size | Number of total results in each page. Default is 50. |
Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| AWS.GuardDuty.Detectors.ThreatIntelSet.ThreatIntelSetId | string | The unique identifier for an threat intel set |
Command Example
!aws-gd-list-threatintel-sets detectorId=38b1ed3fe279cd0c8edb0715ac5561eb region=eu-west-2
aws-gd-update-threatintel-set
Updates the ThreatIntelSet specified by ThreatIntelSet ID.
AWS IAM Policy Permission
Effect: Allow
Action: guardduty:UpdateThreatIntelSet
Base Command
aws-gd-update-threatintel-set
Input
| Argument Name | Description | Required |
|---|---|---|
| detectorId | The detectorID that specifies the GuardDuty service whose ThreatIntelSet you want to update. | Required |
| threatIntelSetId | The unique ID that specifies the ThreatIntelSet that you want to update. | Optional |
| activate | The updated boolean value that specifies whether the ThreatIntelSet is active or not. Possible values are: True, False. | Optional |
| location | The updated URI of the file that contains the ThreatIntelSet. For example (https://s3.us-west-2.amazonaws.com/my-bucket/my-object-key). | Optional |
| name | The user-friendly ThreatIntelSet name. | Optional |
| region | The AWS Region, if not specified the default region will be used. | Optional |
| roleArn | The Amazon Resource Name (ARN) of the role to assume. | Optional |
| roleSessionName | An identifier for the assumed role session. | Optional |
| roleSessionDuration | The duration, in seconds, of the role session. The value can range from 900 seconds (15 minutes) up to the maximum session duration setting for the role. | Optional |
Context Output
There is no context output for this command.
Command Example
!aws-gd-update-threatintel-set detectorId=38b1ed3fe279cd0c8edb0715ac5561eb threatIntelSetId=7eb1f440be5931f168280b574a26d44d activate=False region=eu-west-2
aws-gd-list-findings
Lists Amazon GuardDuty findings for the specified detector ID.
AWS IAM Policy Permission
Effect: Allow
Action: guardduty:ListFindings
Base Command
aws-gd-list-findings
Input
| Argument Name | Description | Required |
|---|---|---|
| detectorId | The ID of the detector that specifies the GuardDuty service whose findings you want to list. | Required |
| region | The AWS Region, if not specified the default region will be used. | Optional |
| roleArn | The Amazon Resource Name (ARN) of the role to assume. | Optional |
| roleSessionName | An identifier for the assumed role session. | Optional |
| roleSessionDuration | The duration, in seconds, of the role session. The value can range from 900 seconds (15 minutes) up to the maximum session duration setting for the role. | Optional |
| limit | Number of total results to query. Default is 50. |
Optional |
| page | Specific page to query. | Optional |
| page_size | Number of total results in each page. Default is 50. |
Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| AWS.GuardDuty.Findings.FindingId | string | The unique identifier for the Finding |
Command Example
!aws-gd-list-findings detectorId=38b1ed3fe279cd0c8edb0715ac5561eb region=eu-west-2
aws-gd-get-findings
Describes Amazon GuardDuty findings specified by finding IDs.
AWS IAM Policy Permission
Effect: Allow
Action: guardduty:GetFindings
Base Command
aws-gd-get-findings
Input
| Argument Name | Description | Required |
|---|---|---|
| detectorId | The ID of the detector that specifies the GuardDuty service whose findings you want to retrieve. | Required |
| findingIds | IDs of the findings that you want to retrieve. | Required |
| region | The AWS Region, if not specified the default region will be used. | Optional |
| roleArn | The Amazon Resource Name (ARN) of the role to assume. | Optional |
| roleSessionName | An identifier for the assumed role session. | Optional |
| roleSessionDuration | The duration, in seconds, of the role session. The value can range from 900 seconds (15 minutes) up to the maximum session duration setting for the role. | Optional |
| returnRawResponse | Select ‘true’ to save all fields from the response to the context. Otherwise, complex fields will be stored in JSON format. Default value is False. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| AWS.GuardDuty.Findings.AccountId | string | The ID of the account in which the finding was generated. |
| AWS.GuardDuty.Findings.CreatedAt | string | The time and date when the finding was created. |
| AWS.GuardDuty.Findings.Description | string | The description of the finding. |
| AWS.GuardDuty.Findings.Region | string | The region where the finding was generated. |
| AWS.GuardDuty.Findings.Id | string | The ID of the finding. |
| AWS.GuardDuty.Findings.Title | string | The title of the finding. |
| AWS.GuardDuty.Findings.Severity | string | The severity of the finding. |
| AWS.GuardDuty.Findings.Type | string | The type of finding. |
| AWS.GuardDuty.Findings.UpdatedAt | string | The time and date when the finding was last updated. |
| AWS.GuardDuty.Findings.Arn | string | The ARN of the finding. |
| AWS.GuardDuty.Findings.Confidence | string | The confidence score for the finding. |
| AWS.GuardDuty.Findings.Partition | string | The partition associated with the finding. |
| AWS.GuardDuty.Findings.ResourceType | string | The type of Amazon Web Services resource. |
| AWS.GuardDuty.Findings.SchemaVersion | string | The version of the schema used for the finding. |
| AWS.GuardDuty.Findings.Service | string | Contains additional information about the generated finding. |
| AWS.GuardDuty.Findings.Resource.AccessKeyDetails | string | The IAM access key details (IAM user information) of a user that engaged in the activity that prompted GuardDuty to generate a finding. |
| AWS.GuardDuty.Findings.Resource.InstanceDetails | string | The information about the EC2 instance associated with the activity that prompted GuardDuty to generate a finding. |
| AWS.GuardDuty.Findings.Resource.EksClusterDetails | string | Details about the EKS cluster involved in a Kubernetes finding. |
| AWS.GuardDuty.Findings.Resource.KubernetesDetails | string | Details about the Kubernetes user and workload involved in a Kubernetes finding. |
| AWS.GuardDuty.Findings.Resource.EbsVolumeDetails | string | Contains a list of scanned and skipped EBS volumes with details. |
| AWS.GuardDuty.Findings.Resource.EcsClusterDetails | string | Contains information about the details of the ECS Cluster. |
| AWS.GuardDuty.Findings.Resource.ContainerDetails | string | Details of a container. |
| AWS.GuardDuty.Findings.Resource.S3BucketDetails | string | Contains information on the S3 bucket. |
Command Example
!aws-gd-get-findings detectorIds=4f1fc7cd7dsg26sdf4328d8dc813 findingIds=96b1ac608sdf00e5183c3dds115c36aac328b,0ab180f5801sdg954418f3806c2a45282c9
aws-gd-create-sample-findings
Generates example findings of types specified by the list of finding types. If ‘NULL’ is specified for findingTypes, the API
generates example findings of all supported finding types.
AWS IAM Policy Permission
Effect: Allow
Action: guardduty:CreateSampleFindings
Base Command
aws-gd-create-sample-findings
Input
| Argument Name | Description | Required |
|---|---|---|
| detectorId | The ID of the detector to create sample findings for. | Required |
| findingTypes | Types of sample findings that you want to generate. Separated by comma. | Optional |
| region | The AWS Region, if not specified the default region will be used. | Optional |
| roleArn | The Amazon Resource Name (ARN) of the role to assume. | Optional |
| roleSessionName | An identifier for the assumed role session. | Optional |
| roleSessionDuration | The duration, in seconds, of the role session. The value can range from 900 seconds (15 minutes) up to the maximum session duration setting for the role. | Optional |
Context Output
There is no context output for this command.
Command Example
!aws-gd-create-sample-findings detectorId=4f1fc7cd7dsg2adf6sdf4328d8dc813 findingTypes=NULL region=eu-central-1
aws-gd-archive-findings
Archives Amazon GuardDuty findings specified by the list of finding IDs.
AWS IAM Policy Permission
Effect: Allow
Action: guardduty:ArchiveFindings
Base Command
aws-gd-archive-findings
Input
| Argument Name | Description | Required |
|---|---|---|
| detectorId | The ID of the detector that specifies the GuardDuty service whose findings you want to archive. | Required |
| findingIds | IDs of the findings that you want to archive. Separated by comma. | Optional |
| region | The AWS Region, if not specified the default region will be used. | Optional |
| roleArn | The Amazon Resource Name (ARN) of the role to assume. | Optional |
| roleSessionName | An identifier for the assumed role session. | Optional |
| roleSessionDuration | The duration, in seconds, of the role session. The value can range from 900 seconds (15 minutes) up to the maximum session duration setting for the role. | Optional |
Context Output
There is no context output for this command.
Command Example
!aws-gd-archive-findings detectorIds=4f1fc7cd7dsg26sdf4328d8dc813 findingIds=96b1ac608sdf00e5183c3dds115c36aac328b,0ab180f5801sdg954418f3806c2a45282c9
aws-gd-unarchive-findings
Unarchives Amazon GuardDuty findings specified by the list of finding IDs.
AWS IAM Policy Permission
Effect: Allow
Action: guardduty:UnarchiveFindings
Base Command
aws-gd-unarchive-findings
Input
| Argument Name | Description | Required |
|---|---|---|
| detectorId | The ID of the detector that specifies the GuardDuty service whose findings you want to unarchive. | Required |
| findingIds | IDs of the findings that you want to unarchive. | Optional |
Context Output
There is no context output for this command.
Command Example
!aws-gd-unarchive-findings detectorIds=4f1fc7cd7dsg26sdf4328d8dc813 findingIds=96b1ac608sdf00e5183c3dds115c36aac328b,0ab180f5801sdg954418f3806c2a45282c9
aws-gd-update-findings-feedback
Marks specified Amazon GuardDuty findings as useful or not useful.
AWS IAM Policy Permission
Effect: Allow
Action: guardduty:UpdateFindingsFeedback
Base Command
aws-gd-update-findings-feedback
Input
| Argument Name | Description | Required |
|---|---|---|
| detectorId | The ID of the detector that specifies the GuardDuty service whose findings you want to mark as useful or not useful. | Required |
| findingIds | IDs of the findings that you want to mark as useful or not useful. | Optional |
| comments | Additional feedback about the GuardDuty findings. | Optional |
| feedback | Specify whether the finding was useful or not. Possible values are: USEFUL, NOT_USEFUL. | Optional |
| region | The AWS Region, if not specified the default region will be used. | Optional |
| roleArn | The Amazon Resource Name (ARN) of the role to assume. | Optional |
| roleSessionName | An identifier for the assumed role session. | Optional |
| roleSessionDuration | The duration, in seconds, of the role session. The value can range from 900 seconds (15 minutes) up to the maximum session duration setting for the role. | Optional |
Context Output
There is no context output for this command.
Command Example
!aws-gd-update-findings-feedback detectorIds=4f1fc7cd7dsg26sdf4328d8dc813 findingIds=96b1ac608sdf00e5183c3dds115c36aac328b comments=Good Job feedback=USEFUL
aws-gd-list-members
Describes Amazon GuardDuty members for the specified detector ID.
AWS IAM Policy Permission
Effect: Allow
Action: guardduty:ListMembers
Base Command
aws-gd-list-members
Input
| Argument Name | Description | Required |
|---|---|---|
| detectorId | The ID of the detector that specifies the GuardDuty service whose members you want to retrieve. | Required |
| region | The AWS Region, if not specified the default region will be used. | Optional |
| roleArn | The Amazon Resource Name (ARN) of the role to assume. | Optional |
| roleSessionName | An identifier for the assumed role session. | Optional |
| roleSessionDuration | The duration, in seconds, of the role session. The value can range from 900 seconds (15 minutes) up to the maximum session duration setting for the role. | Optional |
| limit | Number of total results to query. Default is 50. |
Optional |
| page | Specific page to query. | Optional |
| page_size | Number of total results in each page. Default is 50. |
Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| AWS.GuardDuty.Members.AccountId | string | The unique account ID of the member. |
| AWS.GuardDuty.Members.DetectorId | string | The unique detector ID of the member. |
| AWS.GuardDuty.Members.MasterId | string | The unique detector ID of the master. |
| AWS.GuardDuty.Members.Email | string | The email of the member. |
| AWS.GuardDuty.Members.RelationshipStatus | string | The relationship status of member. |
| AWS.GuardDuty.Members.InvitedAt | string | The first time a member was invited. |
| AWS.GuardDuty.Members.UpdatedAt | string | The time a member was last updated. |
Command Example
!aws-gd-list-members detectorIds=4f1fc7cd7dsg26sdf4328d8dc813
aws-gd-get-members
Describes Amazon GuardDuty members for the specified detector ID & account ID.
AWS IAM Policy Permission
Effect: Allow
Action: guardduty:GetMembers
Base Command
aws-gd-get-members
Input
| Argument Name | Description | Required |
|---|---|---|
| detectorId | The ID of the detector that specifies the GuardDuty service whose members you want to retrieve. | Required |
| accountIds | The ID of the account that specifies the GuardDuty service whose details you want to retrieve. | Required |
| region | The AWS Region, if not specified the default region will be used. | Optional |
| roleArn | The Amazon Resource Name (ARN) of the role to assume. | Optional |
| roleSessionName | An identifier for the assumed role session. | Optional |
| roleSessionDuration | The duration, in seconds, of the role session. The value can range from 900 seconds (15 minutes) up to the maximum session duration setting for the role. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| AWS.GuardDuty.Members.AccountId | string | The unique account ID of the member. |
| AWS.GuardDuty.Members.DetectorId | string | The unique detector ID of the member. |
| AWS.GuardDuty.Members.MasterId | string | The unique detector ID of the master. |
| AWS.GuardDuty.Members.Email | string | The email of the member. |
| AWS.GuardDuty.Members.RelationshipStatus | string | The relationship status of member. |
| AWS.GuardDuty.Members.InvitedAt | string | The first time a member was invited. |
| AWS.GuardDuty.Members.UpdatedAt | string | The time a member was last updated. |
Command Example
!aws-gd-get-members detectorIds=4f1fc7cd7dsg26sdf4328d8dc813 accountIds=1f3fc2cd1dag26sdf4338d8aa813
Breaking changes from the previous version of this integration - AWS-GuardDuty
The following sections list the changes in this version.
Commands
Fetch incidents command - Findings that are fetched are no longer moved automatically to the GuardDuty archive.
Parameters
The following parameters were added in this version:
- How many incidents to fetch each time
- First fetch timestamp
- Archive findings After Fetch
Configuration parameters
defaultRegion— AWS Default Region (required)roleArn— Role ArnisFetch— Fetch incidentsincidentType— Incident typeroleSessionName— Role Session NamesessionDuration— Role Session Durationcredentials— Access Keyaccess_key— Access Keysecret_key— Secret Keytimeout— Timeoutretries— Retriesendpoint_url— PrivateLink service URL.sts_endpoint_url— STS PrivateLink URL.sts_regional_endpoint— AWS STS Regional Endpointsfetch_limit— How many incidents to fetch each timefirst_fetch_time— First fetch timestamp (<number> <time unit>, e.g., 12 hours, 7 days, 3 months, 1 year)gs_severity— Guard Duty Severity levelis_archive— Archive findings After FetchincidentFetchInterval— Incidents Fetch Intervalinsecure— Trust any certificate (not secure)proxy— Use system proxy settings
Commands (23)
-
aws-gd-archive-findingsArchives Amazon GuardDuty findings specified by the list of finding IDs.
-
aws-gd-create-detectorCreate an AWS Guard Duty Detector on the integration instance specified aws account.
-
aws-gd-create-ip-setA list of trusted IP addresses on allow list for secure communication with AWS infrastructure and applications.
-
aws-gd-create-sample-findingsGenerates example findings of types specified by the list of finding types. If 'NULL' is specified for findingTypes, the API generates example findings of all supported finding types.
-
aws-gd-create-threatintel-setCreate a new ThreatIntelSet. ThreatIntelSets consist of known malicious IP addresses. GuardDuty generates findings based on ThreatIntelSets.
-
aws-gd-delete-detectorDeletes a Amazon GuardDuty detector specified by the detector ID.
-
aws-gd-delete-ip-setDeletes the IPSet specified by the IPSet ID.
-
aws-gd-delete-threatintel-setDeletes ThreatIntelSet specified by the ThreatIntelSet ID.
-
aws-gd-get-detectorRetrieves an Amazon GuardDuty detector specified by the detectorId.
-
aws-gd-get-findingsDescribes Amazon GuardDuty findings specified by finding IDs.
-
aws-gd-get-ip-setRetrieves the IPSet specified by the IPSet ID.
-
aws-gd-get-membersDescribes Amazon GuardDuty members for the specified detector ID & account ID.
-
aws-gd-get-threatintel-setRetrieves the ThreatIntelSet that is specified by the ThreatIntelSet ID.
-
aws-gd-list-detectorsLists detectorIds of all the existing Amazon GuardDuty detector resources.
-
aws-gd-list-findingsLists Amazon GuardDuty findings for the specified detector ID.
-
aws-gd-list-ip-setsLists the IPSets of the GuardDuty service specified by the detector ID.
-
aws-gd-list-membersDescribes Amazon GuardDuty members for the specified detector ID.
-
aws-gd-list-threatintel-setsLists the ThreatIntelSets of the GuardDuty service specified by the detector ID.
-
aws-gd-unarchive-findingsUnarchives Amazon GuardDuty findings specified by the list of finding IDs.
-
aws-gd-update-detectorUpdates an Amazon GuardDuty detector specified by the detectorId.
-
aws-gd-update-findings-feedbackMarks specified Amazon GuardDuty findings as useful or not useful.
-
aws-gd-update-ip-setUpdates the IPSet specified by the IPSet ID.
-
aws-gd-update-threatintel-setUpdates the ThreatIntelSet specified by ThreatIntelSet ID.
import json from contextlib import nullcontext as does_not_raise import demistomock as demisto # noqa: F401 import pytest from AWSGuardDuty import ( archive_findings, connection_test, create_detector, create_ip_set, create_sample_findings, create_threat_intel_set, delete_detector, delete_ip_set, delete_threat_intel_set, fetch_incidents, get_detector, get_findings, get_ip_set, get_members, get_threat_intel_set, list_detectors, list_findings, list_ip_sets, list_members, list_threat_intel_sets, parse_incident_from_finding, unarchive_findings, update_detector, update_findings_feedback, update_ip_set, update_threat_intel_set, ) from test_data.api_responses_for_test import ( DETECTOR_RESPONSE, FINDING, GET_MEMBERS_RESPONSE, IP_SET_RESPONSE, LIST_MEMBERS_RESPONSE, RESPONSE_METADATA, THREAT_INTEL_SET_RESPONSE, ) class MockedBoto3Client: """Mocked AWSClient session for easier expectation settings.""" def list_detectors(self, **kwargs): pass def list_findings(self, **kwargs): pass def get_findings(self, **kwargs): pass def archive_findings(self, **kwargs): pass def create_sample_findings(self, **kwargs): pass def unarchive_findings(self, **kwargs): pass def update_findings_feedback(self, **kwargs): pass def list_members(self, **kwargs): pass def get_members(self, **kwargs): pass def create_detector(self, **kwargs): pass def update_detector(self, **kwargs): pass def delete_detector(self, **kwargs): pass def get_detector(self, **kwargs): pass def create_ip_set(self, **kwargs): pass def delete_ip_set(self, **kwargs): pass def update_ip_set(self, **kwargs): pass def get_ip_set(self, **kwargs): pass def list_ip_sets(self, **kwargs): pass def create_threat_intel_set(self, **kwargs): pass def delete_threat_intel_set(self, **kwargs): pass def get_threat_intel_set(self, **kwargs): pass def list_threat_intel_sets(self, **kwargs): pass def update_threat_intel_set(self, **kwargs): pass def get_paginator(self, **kwargs): pass def test_get_members(mocker): """ Given - get-members command When - running get-members, that returns empty map Then - Ensure that empty map is not returned to the context """ client = MockedBoto3Client() get_members_mock = mocker.patch.object(MockedBoto3Client, "get_members", side_effect=[GET_MEMBERS_RESPONSE]) command_results = get_members(client, {}) assert command_results.outputs == [{"AccountId": 1, "DetectorId": 1, "MasterId": 1}] assert get_members_mock.is_called_once() def test_parse_incident_from_finding(): """ Given: - Amazon GuardDuty finding with datetime object nested in it When: - Parsing finding to incident Then: - Ensure finding is parsed as expected """ title = "title" desc = "desc" incident = parse_incident_from_finding(FINDING) assert incident["name"] == title assert incident["details"] == desc assert incident["severity"] == 0 assert "2015-01-01" in incident["rawJSON"] @pytest.mark.parametrize( "response, raises", [ pytest.param({"DetectorIds": ["detector_id1"]}, does_not_raise(), id="Success"), pytest.param({}, pytest.raises(Exception), id="Failure"), ], ) def test_test_module(mocker, response, raises): """ Given: AWSClient session list_detectors valid responses When: Running test-module command Then: assert no exception is being raised. assert api calls are called exactly once. """ mocked_client = MockedBoto3Client() list_detectors_mock = mocker.patch.object(MockedBoto3Client, "list_detectors", side_effect=[response]) with raises: connection_test(mocked_client) assert list_detectors_mock.is_called_once() def test_list_members(mocker): """ Given: AWSClient session list_members valid response When: Running list_members command Then: assert no exception is being raised. assert api calls are called exactly once. """ mocked_client = MockedBoto3Client() get_paginator_mock = mocker.patch.object(MockedBoto3Client, "get_paginator", side_effect=[MockedPaginator()]) paginate_mock = mocker.patch.object(MockedPaginator, "paginate", side_effect=[[LIST_MEMBERS_RESPONSE]]) command_results = list_members(mocked_client, {"detectorId": "some_id"}) get_paginator_mock.assert_called_with("list_members") paginate_mock.assert_called_with(DetectorId="some_id", PaginationConfig={"MaxItems": 50, "PageSize": 50}) assert command_results.outputs == [{"Member": LIST_MEMBERS_RESPONSE.get("Members")[0]}] @pytest.mark.parametrize( "response, raises", [ pytest.param({}, does_not_raise(), id="Success"), pytest.param(RESPONSE_METADATA, does_not_raise(), id="Success with Metadata"), pytest.param({"response": "bad"}, pytest.raises(Exception), id="Failure"), ], ) def test_update_findings_feedback(mocker, response, raises): """ Given: AWSClient session update_findings_feedback various response When: Running update_findings_feedback command Then: assert exceptions are being raised according to api response assert api calls are called exactly once. """ mocked_client = MockedBoto3Client() update_findings_feedback_mock = mocker.patch.object(MockedBoto3Client, "update_findings_feedback", side_effect=[response]) with raises: update_findings_feedback( mocked_client, { "detectorId": "some_id", "findingIds": "finding_id1, finding_id2", "comments": "some_comment1, some_comment2", "feedback": "USEFUL", }, ) update_findings_feedback_mock.assert_called_with( DetectorId="some_id", FindingIds=["finding_id1", "finding_id2"], Comments="some_comment1, some_comment2", Feedback="USEFUL", ) @pytest.mark.parametrize( "response, raises", [ pytest.param({}, does_not_raise(), id="Success"), pytest.param(RESPONSE_METADATA, does_not_raise(), id="Success with Metadata"), pytest.param({"response": "bad"}, pytest.raises(Exception), id="Failure"), ], ) def test_archive_findings(mocker, response, raises): """ Given: AWSClient session archive_findings various response When: Running archive_findings command Then: assert exceptions are being raised according to api response assert api calls are called exactly once. """ mocked_client = MockedBoto3Client() archive_findings_mock = mocker.patch.object(MockedBoto3Client, "archive_findings", side_effect=[response]) with raises: archive_findings(mocked_client, {"detectorId": "some_id", "findingIds": "finding_id1, finding_id2"}) archive_findings_mock.assert_called_with(DetectorId="some_id", FindingIds=["finding_id1", "finding_id2"]) @pytest.mark.parametrize( "response, raises", [ pytest.param({}, does_not_raise(), id="Success"), pytest.param(RESPONSE_METADATA, does_not_raise(), id="Success with Metadata"), pytest.param({"response": "bad"}, pytest.raises(Exception), id="Failure"), ], ) def test_unarchive_findings(mocker, response, raises): """ Given: AWSClient session unarchive_findings various response When: Running unarchive_findings command Then: assert exceptions are being raised according to api response assert api calls are called exactly once. """ mocked_client = MockedBoto3Client() unarchive_findings_mock = mocker.patch.object(MockedBoto3Client, "unarchive_findings", side_effect=[response]) with raises: unarchive_findings(mocked_client, {"detectorId": "some_id", "findingIds": "finding_id1, finding_id2"}) unarchive_findings_mock.assert_called_with(DetectorId="some_id", FindingIds=["finding_id1", "finding_id2"]) @pytest.mark.parametrize( "response, raises", [ pytest.param({}, does_not_raise(), id="Success"), pytest.param(RESPONSE_METADATA, does_not_raise(), id="Success with Metadata"), pytest.param({"response": "bad"}, pytest.raises(Exception), id="Failure"), ], ) def test_create_sample_findings(mocker, response, raises): """ Given: AWSClient session create_sample_findings various response When: Running create_sample_findings command Then: assert exceptions are being raised according to api response assert api calls are called exactly once. """ mocked_client = MockedBoto3Client() create_sample_findings_mock = mocker.patch.object(MockedBoto3Client, "create_sample_findings", side_effect=[response]) with raises: create_sample_findings(mocked_client, {"detectorId": "some_id", "findingTypes": "finding_type1, finding_type2"}) create_sample_findings_mock.assert_called_with(DetectorId="some_id", FindingTypes=["finding_type1", "finding_type2"]) EXPECTED_FINDING_RESULT = { "AccountId": "string", "Arn": "string", "CreatedAt": "string", "Description": "desc", "Id": "string", "Region": "string", "Title": "title", "Type": "string", } def test_get_findings(mocker): """ Given: AWSClient session get_findings valid response When: Running get_findings command Then: assert api calls are called exactly once and as expected. """ from test_data.get_findings_expected_outputs import EXPECTED_FINDING_OUTPUTS mocked_client = MockedBoto3Client() get_findings_mock = mocker.patch.object( MockedBoto3Client, "get_findings", side_effect=[{"Findings": [FINDING, update_finding_id(FINDING.copy(), "finding2", "2022-09-07T13:48:00.814Z")]}], ) command_results = get_findings(mocked_client, {"detectorId": "some_id", "findingIds": "finding_id1, finding_id2"}) get_findings_mock.assert_called_with(DetectorId="some_id", FindingIds=["finding_id1", "finding_id2"]) assert command_results.get("EntryContext") == EXPECTED_FINDING_OUTPUTS class MockedPaginator: def paginate(self, **kwargs): pass def test_list_findings(mocker): """ Given: AWSClient session list_findings valid response When: Running list_findings command Then: assert api calls are called exactly once and as expected. """ mocked_client = MockedBoto3Client() get_paginator_mock = mocker.patch.object(MockedBoto3Client, "get_paginator", side_effect=[MockedPaginator()]) paginate_mock = mocker.patch.object( MockedPaginator, "paginate", side_effect=[[{"FindingIds": ["finding1", "finding2"]}, {"FindingIds": ["finding3", "finding4"]}]], ) command_results = list_findings(mocked_client, {"detectorId": "some_id"}) get_paginator_mock.assert_called_with("list_findings") paginate_mock.assert_called_with(DetectorId="some_id", PaginationConfig={"MaxItems": 50, "PageSize": 50}) assert command_results.outputs == [ {"FindingId": "finding1"}, {"FindingId": "finding2"}, {"FindingId": "finding3"}, {"FindingId": "finding4"}, ] @pytest.mark.parametrize( "response, raises", [ pytest.param({}, does_not_raise(), id="Success"), pytest.param(RESPONSE_METADATA, does_not_raise(), id="Success with Metadata"), pytest.param({"response": "bad"}, pytest.raises(Exception), id="Failure"), ], ) def test_update_threat_intel_set(mocker, response, raises): """ Given: AWSClient session update_threat_intel_set various responses When: Running update_threat_intel_set command Then: assert exceptions are being raised according to api response assert api calls are called exactly once and as expected. """ mocked_client = MockedBoto3Client() update_threat_intel_set_mock = mocker.patch.object(MockedBoto3Client, "update_threat_intel_set", side_effect=[response]) with raises: update_threat_intel_set( mocked_client, { "detectorId": "some_id", "threatIntelSetId": "ThreatIntelSetId1", "activate": "True", "location": "here", "name": "some_name", }, ) update_threat_intel_set_mock.assert_called_with( DetectorId="some_id", ThreatIntelSetId="ThreatIntelSetId1", Activate=True, Location="here", Name="some_name" ) EXPECTED_THREAT_INTEL_RESULT = { "DetectorId": "some_id", "Format": "TXT", "Location": "string", "Name": "string", "Status": "INACTIVE", "ThreatIntelSetId": "threat_id1", } def test_get_threat_intel_set(mocker): """ Given: AWSClient session get_threat_intel_set valid response When: Running get_threat_intel_set command Then: assert api calls are called exactly once and as expected. """ mocked_client = MockedBoto3Client() get_threat_intel_set_mock = mocker.patch.object( MockedBoto3Client, "get_threat_intel_set", side_effect=[THREAT_INTEL_SET_RESPONSE] ) command_results = get_threat_intel_set(mocked_client, {"detectorId": "some_id", "threatIntelSetId": "threat_id1"}) get_threat_intel_set_mock.assert_called_with(DetectorId="some_id", ThreatIntelSetId="threat_id1") assert command_results.outputs == EXPECTED_THREAT_INTEL_RESULT def test_list_threat_intel_sets(mocker): """ Given: AWSClient session list_threat_intel_set valid response When: Running list_threat_intel_set command Then: assert api calls are called exactly once and as expected. """ mocked_client = MockedBoto3Client() get_paginator_mock = mocker.patch.object(MockedBoto3Client, "get_paginator", side_effect=[MockedPaginator()]) paginate_mock = mocker.patch.object( MockedPaginator, "paginate", side_effect=[[{"ThreatIntelSetIds": ["threat1", "threat2"]}]] ) command_results = list_threat_intel_sets(mocked_client, {"detectorId": "some_id"}) get_paginator_mock.assert_called_with("list_threat_intel_sets") paginate_mock.assert_called_with(DetectorId="some_id", PaginationConfig={"MaxItems": 50, "PageSize": 50}) assert command_results.outputs == [ {"DetectorId": "some_id"}, {"ThreatIntelSetId": "threat1"}, {"ThreatIntelSetId": "threat2"}, ] @pytest.mark.parametrize( "response, raises", [ pytest.param({}, does_not_raise(), id="Success"), pytest.param(RESPONSE_METADATA, does_not_raise(), id="Success with Metadata"), pytest.param({"response": "bad"}, pytest.raises(Exception), id="Failure"), ], ) def test_delete_threat_intel_set(mocker, response, raises): """ Given: AWSClient session list_threat_intel_set various response When: Running list_threat_intel_set command Then: assert exceptions are being raised according to api response assert api calls are called exactly once and as expected. """ mocked_client = MockedBoto3Client() delete_threat_intel_set_mock = mocker.patch.object(MockedBoto3Client, "delete_threat_intel_set", side_effect=[response]) with raises: delete_threat_intel_set(mocked_client, {"detectorId": "some_id", "threatIntelSetId": "ThreatIntelSetId1"}) delete_threat_intel_set_mock.assert_called_with(DetectorId="some_id", ThreatIntelSetId="ThreatIntelSetId1") def test_create_threat_intel_set(mocker): """ Given: AWSClient session create_threat_intel_set valid response When: Running create_threat_intel_set command Then: assert api calls are called exactly once and as expected. """ mocked_client = MockedBoto3Client() create_threat_intel_set_mock = mocker.patch.object( MockedBoto3Client, "create_threat_intel_set", side_effect=[{"ThreatIntelSetId": "threat1"}] ) command_results = create_threat_intel_set( mocked_client, {"detectorId": "some_id", "activate": "True", "format": "some_format", "location": "some_location", "name": "some_name"}, ) create_threat_intel_set_mock.assert_called_with( DetectorId="some_id", Activate=True, Format="some_format", Location="some_location", Name="some_name" ) assert command_results.outputs == {"DetectorId": "some_id", "ThreatIntelSetId": "threat1"} EXPECTED_IP_SET_RESULT = { "DetectorId": "some_id", "Format": "TXT", "IpSetId": "ipset1", "Location": "string", "Name": "string", "Status": "INACTIVE", } def test_get_ip_set(mocker): """ Given: AWSClient session get_ip_set valid response When: Running get_ip_set command Then: assert api calls are called exactly once and as expected. """ mocked_client = MockedBoto3Client() get_ip_set_mock = mocker.patch.object(MockedBoto3Client, "get_ip_set", side_effect=[IP_SET_RESPONSE]) command_results = get_ip_set(mocked_client, {"detectorId": "some_id", "ipSetId": "ipset1"}) get_ip_set_mock.assert_called_with(DetectorId="some_id", IpSetId="ipset1") assert command_results.outputs == EXPECTED_IP_SET_RESULT def test_list_ip_sets(mocker): """ Given: AWSClient session list_ip_sets valid response When: Running list_ip_sets command Then: assert api calls are called exactly once and as expected. """ mocked_client = MockedBoto3Client() get_paginator_mock = mocker.patch.object(MockedBoto3Client, "get_paginator", side_effect=[MockedPaginator()]) paginate_mock = mocker.patch.object(MockedPaginator, "paginate", side_effect=[[{"IpSetIds": ["ipset1", "ipset2"]}]]) command_results = list_ip_sets(mocked_client, {"detectorId": "some_id"}) get_paginator_mock.assert_called_with("list_ip_sets") paginate_mock.assert_called_with(DetectorId="some_id", PaginationConfig={"MaxItems": 50, "PageSize": 50}) assert command_results.outputs == [{"DetectorId": "some_id"}, {"IpSetId": "ipset1"}, {"IpSetId": "ipset2"}] def test_create_ip_set(mocker): """ Given: AWSClient session create_ip_set valid response When: Running create_ip_set command Then: assert api calls are called exactly once and as expected. """ mocked_client = MockedBoto3Client() create_ip_set_mock = mocker.patch.object(MockedBoto3Client, "create_ip_set", side_effect=[{"IpSetId": "ipset1"}]) command_results = create_ip_set( mocked_client, {"detectorId": "some_id", "activate": "True", "format": "some_format", "location": "some_location", "name": "some_name"}, ) create_ip_set_mock.assert_called_with( DetectorId="some_id", Activate=True, Format="some_format", Location="some_location", Name="some_name" ) assert command_results.outputs == {"DetectorId": "some_id", "IpSetId": "ipset1"} @pytest.mark.parametrize( "response, raises", [ pytest.param({}, does_not_raise(), id="Success"), pytest.param(RESPONSE_METADATA, does_not_raise(), id="Success with Metadata"), pytest.param({"response": "bad"}, pytest.raises(Exception), id="Failure"), ], ) def test_update_ip_set(mocker, response, raises): """ Given: AWSClient session update_ip_set various response When: Running update_ip_set command Then: assert exceptions are being raised according to api response assert api calls are called exactly once and as expected. """ mocked_client = MockedBoto3Client() update_ip_set_mock = mocker.patch.object(MockedBoto3Client, "update_ip_set", side_effect=[response]) with raises: update_ip_set( mocked_client, {"detectorId": "some_id", "ipSetId": "ipSetId1", "activate": "True", "location": "here", "name": "some_name"}, ) update_ip_set_mock.assert_called_with( DetectorId="some_id", IpSetId="ipSetId1", Activate=True, Location="here", Name="some_name" ) @pytest.mark.parametrize( "response, raises", [ pytest.param({}, does_not_raise(), id="Success"), pytest.param(RESPONSE_METADATA, does_not_raise(), id="Success with Metadata"), pytest.param({"response": "bad"}, pytest.raises(Exception), id="Failure"), ], ) def test_delete_ip_set(mocker, response, raises): """ Given: AWSClient session delete_ip_set various response When: Running delete_ip_set command Then: assert exceptions are being raised according to api response assert api calls are called exactly once and as expected. """ mocked_client = MockedBoto3Client() delete_ip_set_mock = mocker.patch.object(MockedBoto3Client, "delete_ip_set", side_effect=[response]) with raises: delete_ip_set(mocked_client, {"detectorId": "some_id", "ipSetId": "IpSetId1"}) delete_ip_set_mock.assert_called_with(DetectorId="some_id", IpSetId="IpSetId1") @pytest.mark.parametrize( "args, response_iterator, expected_pagination_config, expected_results", [ ({"limit": "1"}, [{"DetectorIds": ["detector1"]}], {"MaxItems": 1, "PageSize": 50}, [{"DetectorId": "detector1"}]), ( {"page_size": "2", "page": "2"}, [{"DetectorIds": ["detector1", "detector2"]}, {"DetectorIds": ["detector3", "detector4"]}], {"MaxItems": 4, "PageSize": 2}, [{"DetectorId": "detector3"}, {"DetectorId": "detector4"}], ), ], ) def test_list_detectors(mocker, args, response_iterator, expected_pagination_config, expected_results): """ Given: AWSClient session list_detectors valid response When: Running list_detectors command with: 1. limit = 1 (Automatic Pagination) 2. page_size = 2, page = 2 (Manual Pagination) Then: assert api calls are called exactly once and as expected. """ mocked_client = MockedBoto3Client() get_paginator_mock = mocker.patch.object(MockedBoto3Client, "get_paginator", side_effect=[MockedPaginator()]) paginate_mock = mocker.patch.object(MockedPaginator, "paginate", side_effect=[response_iterator]) command_results = list_detectors(mocked_client, args) get_paginator_mock.assert_called_with("list_detectors") paginate_mock.assert_called_with(PaginationConfig=expected_pagination_config) assert command_results.outputs == expected_results @pytest.mark.parametrize( "response, raises", [ pytest.param({}, does_not_raise(), id="Success"), pytest.param(RESPONSE_METADATA, does_not_raise(), id="Success with Metadata"), pytest.param({"response": "bad"}, pytest.raises(Exception), id="Failure"), ], ) def test_update_detector(mocker, response, raises): """ Given: AWSClient session update_detector various response When: Running update_detector command Then: assert exceptions are being raised according to api response assert api calls are called exactly once and as expected. """ mocked_client = MockedBoto3Client() update_detector_mock = mocker.patch.object(MockedBoto3Client, "update_detector", side_effect=[response]) with raises: update_detector( mocked_client, { "enable": "True", "detectorId": "some_id", "findingFrequency": "One Hour", "enableKubernetesLogs": "True", "ebsVolumesMalwareProtection": "True", "enableS3Logs": "True", }, ) assert update_detector_mock.call_args_list[0][1] == { "Enable": True, "DetectorId": "some_id", "FindingPublishingFrequency": "ONE_HOUR", "DataSources": { "S3Logs": {"Enable": True}, "Kubernetes": {"AuditLogs": {"Enable": True}}, "MalwareProtection": {"ScanEc2InstanceWithFindings": {"EbsVolumes": True}}, }, } @pytest.mark.parametrize( "response, raises", [ pytest.param({}, does_not_raise(), id="Success"), pytest.param(RESPONSE_METADATA, does_not_raise(), id="Success with Metadata"), pytest.param({"response": "bad"}, pytest.raises(Exception), id="Failure"), ], ) def test_delete_detector(mocker, response, raises): """ Given: AWSClient session delete_detector various response When: Running delete_detector command Then: assert exceptions are being raised according to api response assert api calls are called exactly once and as expected. """ mocked_client = MockedBoto3Client() delete_detector_mock = mocker.patch.object(MockedBoto3Client, "delete_detector", side_effect=[response]) with raises: delete_detector(mocked_client, {"detectorId": "some_id", "ipSetId": "IpSetId1"}) delete_detector_mock.assert_called_with(DetectorId="some_id") EXPECTED_DETECTOR_RESPONSE = { "CloudTrailStatus": "ENABLED", "CreatedAt": "string", "DNSLogsStatus": "ENABLED", "DetectorId": "some_id", "FlowLogsStatus": "ENABLED", "KubernetesAuditLogsStatus": "ENABLED", "MalwareProtectionReason": None, "MalwareProtectionStatus": "ENABLED", "S3LogsStatus": "ENABLED", "ServiceRole": "string", "Status": "ENABLED", "Tags": {"string": "string"}, "UpdatedAt": "string", } def test_get_detector(mocker): """ Given: AWSClient session get_detector valid response When: Running get_detector command Then: assert api calls are called exactly once and as expected. """ mocked_client = MockedBoto3Client() get_detector_mock = mocker.patch.object(MockedBoto3Client, "get_detector", side_effect=[DETECTOR_RESPONSE]) command_results = get_detector(mocked_client, {"detectorId": "some_id"}) get_detector_mock.assert_called_with(DetectorId="some_id") assert command_results.outputs == EXPECTED_DETECTOR_RESPONSE def test_create_detector(mocker): """ Given: AWSClient session create_detector valid response When: Running create_detector command Then: assert api calls are called exactly once and as expected. """ mocked_client = MockedBoto3Client() create_detector_mock = mocker.patch.object(MockedBoto3Client, "create_detector", side_effect=[{"DetectorId": "some_id"}]) command_results = create_detector( mocked_client, { "enabled": "True", "findingFrequency": "One Hour", "enableKubernetesLogs": "True", "ebsVolumesMalwareProtection": "True", "enableS3Logs": "True", }, ) assert create_detector_mock.call_args_list[0][1] == { "Enable": True, "FindingPublishingFrequency": "ONE_HOUR", "DataSources": { "S3Logs": {"Enable": True}, "Kubernetes": {"AuditLogs": {"Enable": True}}, "MalwareProtection": {"ScanEc2InstanceWithFindings": {"EbsVolumes": True}}, }, } assert command_results.outputs == {"DetectorId": "some_id"} def update_finding_id(finding, new_id, updated_at=None): """Update finding with new id and updatedAt fields.""" finding["Id"] = new_id if updated_at: finding["UpdatedAt"] = updated_at return finding """ FETCH CONSTANTS """ FINDING_1 = update_finding_id(FINDING.copy(), "finding_id1") FINDING_2 = update_finding_id(FINDING.copy(), "finding_id2") INCIDENT_1 = { "name": "title", "details": "desc", "occurred": "2022-11-08T14:24:52.908Z", "severity": 0, "rawJSON": json.dumps(FINDING_1, default=str), } INCIDENT_2 = { "name": "title", "details": "desc", "occurred": "2022-11-08T14:24:52.908Z", "severity": 0, "rawJSON": json.dumps(FINDING_2, default=str), } INCIDENTS_NEXT_RUN = { "latest_created_time": "2022-11-08T14:24:52.908000Z", "latest_updated_time": "2022-11-08T14:24:52.908000Z", "last_incidents_ids": ["finding_id1", "finding_id2"], "last_next_token": "", } @pytest.mark.parametrize( "gd_severity, " "last_run, fetch_limit, first_fetch_time," "expected_incidents, expected_next_run, " "expected_criterion_conditions," "mock_list_finding_res, mock_get_finding_res, is_archive", [ # case - 1: First run (no Last Run) should get all incident from 'First fetch timestamp' # field to current time. # is_archive = True, should archive the findings and to get only unarchived findings. ( ["Medium"], {}, 2, "2022-11-08T14:24:52.908Z", [INCIDENT_1, INCIDENT_2], INCIDENTS_NEXT_RUN, {"severity": {"Gte": 4}, "service.archived": {"Eq": ["false"]}}, {"FindingIds": ["finding_id1", "finding_id2"], "NextToken": ""}, [FINDING_1, FINDING_2], True, ), # case - 2: Second run should get all incidents from last run time to current time # without duplicates ( [], { "last_incidents_ids": ["finding_id1"], "last_next_token": "", "latest_created_time": "2022-11-08T14:24:52.908000Z", "latest_updated_time": "2022-11-08T14:24:52.908000Z", }, 2, "3 days", [INCIDENT_2], INCIDENTS_NEXT_RUN, {"id": {"Neq": ["finding_id1"]}, "severity": {"Gte": 1}, "updatedAt": {"Gte": 1667917492908}}, {"FindingIds": ["finding_id2"], "NextToken": ""}, [FINDING_2], False, ), # case - 3: A run without new finding since last run, should not change the Last Run ( [], INCIDENTS_NEXT_RUN, 2, "3 years", [], INCIDENTS_NEXT_RUN, {"severity": {"Gte": 1}, "updatedAt": {"Gte": 1667917492908}, "id": {"Neq": ["finding_id1", "finding_id2"]}}, {"FindingIds": [], "NextToken": ""}, [], False, ), # case - 4: A run without incidents (all incidents has earlier time then the last run) # should get 0 incidents and should not change the Last Run # [incidents created time is 08.11 but latest created time is 16.11] ( [], {"latest_created_time": "2022-11-16T14:24:52.908000Z", "latest_updated_time": "2022-11-06T14:24:52.908000Z"}, 2, "3 days", [], { "last_incidents_ids": [], "last_next_token": "", "latest_created_time": "2022-11-16T14:24:52.908000Z", "latest_updated_time": "2022-11-08T14:24:52.908000Z", }, {"severity": {"Gte": 1}, "updatedAt": {"Gte": 1667744692908}}, {"FindingIds": ["finding_id1", "finding_id2"], "NextToken": ""}, [FINDING_1, FINDING_2], False, ), # case - 5: A run given last_next_token and latest_updated_time, # validate the latest_updated_time is not used ( [], { "last_incidents_ids": [], "last_next_token": "test", "latest_created_time": "2022-11-08T14:24:52.908000Z", "latest_updated_time": "2022-11-11T14:24:52.908000Z", }, 2, "3 days", [INCIDENT_1, INCIDENT_2], { "last_incidents_ids": ["finding_id1", "finding_id2"], "last_next_token": "", "latest_created_time": "2022-11-08T14:24:52.908000Z", "latest_updated_time": "2022-11-11T14:24:52.908000Z", }, {"severity": {"Gte": 1}}, {"FindingIds": ["finding_id1", "finding_id2"], "NextToken": ""}, [FINDING_1, FINDING_2], False, ), # case - 6: A run given last_next_token and latest_updated_time is None, # validate the latest_updated_time is not used, # and the next run's latest_updated_time is the same as latest_created_time ( [], { "last_incidents_ids": [], "last_next_token": "test", "latest_created_time": "2022-11-08T14:24:52.908000Z", "latest_updated_time": None, }, 2, "3 days", [INCIDENT_1, INCIDENT_2], { "last_incidents_ids": ["finding_id1", "finding_id2"], "last_next_token": "", "latest_created_time": "2022-11-08T14:24:52.908000Z", "latest_updated_time": "2022-11-08T14:24:52.908000Z", }, {"severity": {"Gte": 1}}, {"FindingIds": ["finding_id1", "finding_id2"], "NextToken": ""}, [FINDING_1, FINDING_2], False, ), ], ids=["case - 1", "case - 2", "case - 3", "case - 4", "case - 5", "last_updated_time is None"], ) def test_fetch_incidents( mocker, gd_severity, last_run, fetch_limit, first_fetch_time, expected_incidents, expected_next_run, expected_criterion_conditions, mock_list_finding_res, mock_get_finding_res, is_archive, ): """ Given: AWSClient session list_detectors, list_finding_ids, get_finding_ids valid responses. When: Running fetch-incidents. Then: assert incidents are returned as expected. assert api calls are called as expected. """ mocked_client = MockedBoto3Client() list_detectors_mock = mocker.patch.object( MockedBoto3Client, "list_detectors", side_effect=[{"DetectorIds": ["detector_id1"]}] ) list_findings_mock = mocker.patch.object(MockedBoto3Client, "list_findings", return_value=mock_list_finding_res) get_findings_mock = mocker.patch.object(MockedBoto3Client, "get_findings", return_value={"Findings": mock_get_finding_res}) archive_findings_mock = mocker.patch.object(MockedBoto3Client, "archive_findings", side_effect=[{}]) next_run, incidents = fetch_incidents( client=mocked_client, aws_gd_severity=gd_severity, last_run=last_run, fetch_limit=fetch_limit, first_fetch_time=first_fetch_time, is_archive=is_archive, ) assert list_detectors_mock.is_called_once assert list_findings_mock.call_count == 1 assert get_findings_mock.call_count == 1 assert list_findings_mock.call_args[1]["FindingCriteria"]["Criterion"] == expected_criterion_conditions if is_archive: assert archive_findings_mock.call_count == 1 assert archive_findings_mock.call_args[1]["FindingIds"] == mock_list_finding_res["FindingIds"] assert next_run == expected_next_run assert incidents == expected_incidents @pytest.mark.parametrize( "args, expected_results", [ ({}, (50, 50, None)), # no pagination arguments ({"limit": "3"}, (3, 50, None)), # given limit argument ({"page_size": "5", "page": "2"}, (10, 5, 2)), ], ) # given page_size and page arguments def test_get_pagination_args(args, expected_results): """ Given: - pagination arguments. When: - Running a list command. Then: - Make sure that the correct amount of results to display is returned. expected_results = (limit, page_size, page) == get_pagination_args(args) """ from AWSGuardDuty import get_pagination_args assert expected_results == get_pagination_args(args)