InfobloxBloxOneThreatDefense
Infoblox Threat Defense with DDI integration leverages DNS as the first line of defense to detect and block cyber threats, while also using threat intelligence to manage SOC Insight incident response and enrich indicators.
Data Enrichment & Threat Intelligence · Infoblox Threat Defense with DDI
Details
| ID | InfobloxBloxOneThreatDefense |
|---|---|
| Provider | Infoblox |
| Category | Data Enrichment & Threat Intelligence |
| From Version | 6.5.0 |
| Docker Image | demisto/python3:3.12.13.10116658 |
| Supported Modules | Agentix XSIAM |
README
Infoblox Threat Defense with DDI integration leverages DNS as the first line of defense to detect and block cyber threats, while also using threat intelligence to manage insight incident response and enrich indicators.
This integration was integrated and tested with version 1.0.0 of Infoblox Threat Defense with DDI.
Configure Infoblox Threat Defense with DDI in Cortex
| Parameter | Description | Required |
|---|---|---|
| Service API Key | True | |
| Source Reliability | Reliability of the source providing the intelligence data. | False |
| Create relationships | Create relationships between indicators as part of Enrichment. | False |
| Fetch incidents | False | |
| Incident type | False | |
| Ingestion Type | Select the ingestion type to fetch as XSOAR incident. Default is SOC Insight. | False |
| SOC Insight Status | Retrieve the SOC Insights as specified status. | False |
| SOC Insight Threat Type | Retrieve the SOC Insights as specified threat type. | False |
| SOC Insight Priority Level | Retrieve the SOC Insights as specified priority level. | False |
| DNS Security Event Feed Name | Retrieve the DNS Security Events as specified feed name or custom list name. | False |
| DNS Security Event Network | Retrieve the DNS Security Events as specified network name. | False |
| DNS Security Event Policy Action | Retrieve the DNS Security Events as specified policy action. | False |
| DNS Security Event Policy Name | Retrieve the DNS Security Events as specified policy name. | False |
| DNS Security Event Queried Name | Retrieve the DNS Security Events as specified queried name. | False |
| DNS Security Event Threat Class | Retrieve the DNS Security Events as specified threat class. | False |
| DNS Security Event Threat Family | Retrieve the DNS Security Events as specified threat family. | False |
| DNS Security Event Threat Indicator | Retrieve the DNS Security Events as specified threat indicator. | False |
| DNS Security Event Threat Level | Retrieve the DNS Security Events as specified threat level. | False |
| Max Fetch | The maximum number of SOC Insights or DNS Security Events to fetch each time. If the value is greater than 200, it will be considered as 200. The maximum is 200. | False |
| First fetch timestamp | The date or relative timestamp from which to begin fetching incidents. Note: This parameter is only applicable for DNS Security Events. Supported formats: 2 minutes, 2 hours, 2 days, 2 weeks, 2 months, 2 years, yyyy-mm-dd, yyyy-mm-ddTHH:MM:SSZ. For example: 01 May 2025, 01 May 2025 04:45:33, 2025-05-17T14:05:44Z. |
False |
| Incidents Fetch Interval | False | |
| Trust any certificate (not secure) | False | |
| Use system proxy settings | False |
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.
bloxone-td-dossier-lookup-get
The Dossier Lookup API returns detailed information on the specified indicator from the requested sources.
Base Command
bloxone-td-dossier-lookup-get
Input
| Argument Name | Description | Required |
|---|---|---|
| indicator_type | The type of indcator to search by. Possible values are: host, ip, url, hash, email. | Required |
| value | The indicator to search on. | Required |
| sources | The sources to query. Multiple sources can be specified. If no source is specified, the call will search on all available sources. (You can see the list of the available sources by running bloxone-td-dossier-source-list). | Optional |
| interval_in_seconds | The interval in seconds between each poll. Default is 10. | Optional |
| timeout | The timeout in seconds until polling ends. Default is 600. | Optional |
| job_id | used for polling. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| BloxOneTD.DossierLookup.source | String | The Dossier source. |
| BloxOneTD.DossierLookup.target | String | The targeted indicator. |
| BloxOneTD.DossierLookup.task_id | String | The Dossier task ID. |
| BloxOneTD.DossierLookup.type | String | The indicator type. |
Command example
!bloxone-td-dossier-lookup-get indicator_type="ip" value="11.22.33.44" sources="activity,threatfox,ccb"
Context Example
{
"BloxOneTD": {
"DossierLookup": [
{
"params": {
"source": "ccb",
"target": "11.22.33.44",
"type": "ip"
},
"status": "success",
"task_id": "97bdeca2-b66d-47b1-b1ef-9e4833654df2",
"time": 6401,
"v": "3.0.0"
},
{
"data": {
"impacted_devices": [],
"requests_by_day": []
},
"params": {
"source": "activity",
"target": "11.22.33.44",
"type": "ip"
},
"status": "success",
"task_id": "4074cb34-2bec-485d-8d6d-9e9cc88d5229",
"time": 1708,
"v": "3.0.0"
},
{
"data": {
"matches": []
},
"params": {
"source": "threatfox",
"target": "11.22.33.44",
"type": "ip"
},
"status": "success",
"task_id": "73892ea3-1e22-433f-bc74-f59133b914d0",
"time": 8,
"v": "3.0.0"
}
]
}
}
Human Readable Output
Lookalike Domain List
Task Id Type Target Source d418b8d6-831c-4f6f-a31a-6d48995d2267 ip 11.22.33.44 threatfox 91945be3-0cef-4d03-afd7-e4f25864553d ip 11.22.33.44 ccb 7145a1ca-40a9-43df-b0a3-c4281e5abd7e ip 11.22.33.44 activity
bloxone-td-dossier-source-list
Get available Dossier sources.
Base Command
bloxone-td-dossier-source-list
Input
There are no input arguments for this command.
Context Output
| Path | Type | Description |
|---|---|---|
| BloxOneTD.DossierSource | String | Available Dossier sources. |
Command example
#### Context Example
```json
{
"BloxOneTD": {
"DossierSource": [
"ccb",
"activity",
"geo",
"threatfox"
]
}
}
Human Readable Output
Results
DossierSource activity ccb geo threatfox
bloxone-td-lookalike-domain-list
Get lookalike domain lists.
Notice: Submitting indicators using this command might make the indicator data publicly available. See the vendor’s documentation for more details.
Base Command
bloxone-td-lookalike-domain-list
Input
| Argument Name | Description | Required |
|---|---|---|
| filter | The free query filter argument. | Optional |
| target_domain | Filter by target domain. | Optional |
| detected_at | Filter by values that are greater than or equal to the given value. You can use ISO format (e.g. ‘2023-02-14T00:11:22Z’) or use a relative time (e.g. “3 days”). | Optional |
| limit | Maximum number of results to return from the query. Default is 50. | Optional |
| offset | Return results starting at this offset. Should be an integer. Default is 0. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| BloxOneTD.LookalikeDomain.detected_at | Date | The date of the lookalike detection. |
| BloxOneTD.LookalikeDomain.lookalike_domain | String | The lookalike domain. |
| BloxOneTD.LookalikeDomain.lookalike_host | String | The lookalike host. |
| BloxOneTD.LookalikeDomain.reason | String | The reason for the detection. |
| BloxOneTD.LookalikeDomain.target_domain | String | The domain that was targeted by the lookalike domain. |
Command example
!bloxone-td-lookalike-domain-list detected_at="1y"
Context Example
{
"BloxOneTD": {
"LookalikeDomain": [
{
"detected_at": "2023-01-27T18:43:01Z",
"lookalike_domain": "test.a.com",
"lookalike_host": "test.a.com",
"reason": "Domain is a lookalike to test.com. The creation date is 2023-01-22.",
"target_domain": "test.com"
},
{
"detected_at": "2023-01-28T18:36:27Z",
"lookalike_domain": "test.b.com",
"lookalike_host": "test.b.com",
"reason": "Domain is a lookalike to test.com and has suspicious registration, behavior, or associations with known threats. The creation date is 2022-11-30.",
"suspicious": true,
"target_domain": "test.com"
},
{
"detected_at": "2023-01-28T18:37:03Z",
"lookalike_domain": "test.c.com",
"lookalike_host": "test.c.com",
"reason": "Domain is a lookalike to test.com. The creation date is 2022-09-18.",
"target_domain": "test.com"
}
]
}
}
Human Readable Output
Results
Detected At Lookalike Domain Lookalike Host Reason Target Domain 2023-01-27T18:43:01Z test.a.com test.a.com Domain is a lookalike to test.com. The creation date is 2023-01-22. test.com 2023-01-28T18:36:27Z test.b.com test.b.com Domain is a lookalike to test.com and has suspicious registration, behavior, or associations with known threats. The creation date is 2022-11-30. test.com 2023-01-28T18:37:03Z test.c.com test.c.com Domain is a lookalike to test.com. The creation date is 2022-09-18. test.com
infobloxcloud-block-ip
The given IP addresses will be added to the provided block list.
Base Command
infobloxcloud-block-ip
Input
| Argument Name | Description | Required |
|---|---|---|
| ip | Specify the IP addresses to block. Supports comma-separated values. | Required |
| custom_list_name | Specify the name of the custom list to add the given IP addresses to. Default is Default Block. | Optional |
| custom_list_type | Specify the type of the custom list to add the given IP addresses to. Possible values are: default_block, custom_list, threat_insight, dga, dnsm, zero_day_dns, threat_insight_nde. Default is default_block. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| InfobloxCloud.CustomList.id | String | The ID of the custom list. |
| InfobloxCloud.CustomList.name | String | The name of the custom list. |
| InfobloxCloud.CustomList.type | String | The type of the custom list. |
| InfobloxCloud.CustomList.items | String | The items in the custom list. |
| InfobloxCloud.CustomList.items_described | Array | The items described in the custom list. |
| InfobloxCloud.CustomList.item_count | Number | The number of items in the custom list. |
| InfobloxCloud.CustomList.confidence_level | String | The confidence level of the custom list. |
| InfobloxCloud.CustomList.created_time | String | The time the custom list was created. |
| InfobloxCloud.CustomList.last_updated_time | String | The time the custom list was last updated. |
| InfobloxCloud.CustomList.description | String | The description of the custom list. |
| InfobloxCloud.CustomList.policies | String | The policies of the custom list. |
| InfobloxCloud.CustomList.tags | String | The tags of the custom list. |
| InfobloxCloud.CustomList.type | String | The type of the custom list. |
| InfobloxCloud.CustomList.threat_level | String | The threat level of the custom list. |
Command example
!infobloxcloud-block-ip ip=0.0.0.0
Context Example
{
"InfobloxCloud": {
"CustomList": {
"confidence_level": "HIGH",
"created_time": "2024-04-01T18:24:37Z",
"description": "Auto-generated",
"id": 456789,
"item_count": 2,
"items": [
"0.0.0.0/32",
"0.0.0.1/32"
],
"items_described": [
{
"description": "",
"item": "0.0.0.0/32",
"status": "ACTIVE",
"status_details": ""
},
{
"description": "",
"item": "0.0.0.1/32",
"status": "ACTIVE",
"status_details": ""
}
],
"name": "Test Block",
"policies": [
"Test Policy"
],
"tags": {
"test_key": "test_value"
},
"threat_level": "MEDIUM",
"type": "test_block",
"updated_time": "2025-07-29T08:47:54Z"
}
}
}
Human Readable Output
‘0.0.0.0’ indicators added to the ‘Test Block’ list
ID Name Type Description Items Confidence Level Threat Level Tags Created Time Updated Time 792594 Test Block test_block Auto-generated 0.0.0.0/32,
0.0.0.1/32HIGH MEDIUM test_key: test_value 2024-04-01T18:24:37Z 2025-07-29T08:47:54Z
infobloxcloud-unblock-ip
The given IP addresses will be added to the provided allow list.
Base Command
infobloxcloud-unblock-ip
Input
| Argument Name | Description | Required |
|---|---|---|
| ip | Specify the IP addresses to unblock. Supports comma-separated values. | Required |
| custom_list_name | Specify the name of the custom list to add the given IP addresses to. Default is Default Allow. | Optional |
| custom_list_type | Specify the type of the custom list to add the given IP addresses to. Possible values are: default_allow, custom_list, threat_insight, threat_insight_nde. Default is default_allow. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| InfobloxCloud.CustomList.id | String | The ID of the custom list. |
| InfobloxCloud.CustomList.name | String | The name of the custom list. |
| InfobloxCloud.CustomList.type | String | The type of the custom list. |
| InfobloxCloud.CustomList.items | String | The items in the custom list. |
| InfobloxCloud.CustomList.items_described | Array | The items described in the custom list. |
| InfobloxCloud.CustomList.item_count | Number | The number of items in the custom list. |
| InfobloxCloud.CustomList.confidence_level | String | The confidence level of the custom list. |
| InfobloxCloud.CustomList.created_time | String | The time the custom list was created. |
| InfobloxCloud.CustomList.last_updated_time | String | The time the custom list was last updated. |
| InfobloxCloud.CustomList.description | String | The description of the custom list. |
| InfobloxCloud.CustomList.policies | String | The policies of the custom list. |
| InfobloxCloud.CustomList.tags | String | The tags of the custom list. |
| InfobloxCloud.CustomList.type | String | The type of the custom list. |
| InfobloxCloud.CustomList.threat_level | String | The threat level of the custom list. |
Command example
!infobloxcloud-unblock-ip ip=0.0.0.0
Context Example
{
"InfobloxCloud": {
"CustomList": {
"confidence_level": "HIGH",
"created_time": "2024-04-01T18:24:37Z",
"description": "Auto-generated",
"id": 123456,
"item_count": 2,
"items": [
"0.0.0.0/32",
"0.0.0.1/32"
],
"items_described": [
{
"description": "",
"item": "0.0.0.0/32",
"status": "ACTIVE",
"status_details": ""
},
{
"description": "",
"item": "0.0.0.1/32",
"status": "ACTIVE",
"status_details": ""
}
],
"name": "Test Allow",
"policies": [
"Test Policy"
],
"tags": {
"test_key": "test_value"
},
"threat_level": "MEDIUM",
"type": "test_allow",
"updated_time": "2025-07-29T08:48:02Z"
}
}
}
Human Readable Output
‘0.0.0.0’ indicators added to the ‘Test Allow’ list
ID Name Type Description Items Confidence Level Threat Level Tags Created Time Updated Time 123456 Test Allow test_allow Auto-generated 0.0.0.0/32,
0.0.0.1/32HIGH MEDIUM test_key: test_value 2024-04-01T18:24:37Z 2025-07-29T08:48:02Z
infobloxcloud-block-domain
The given domains will be added to the provided block list.
Base Command
infobloxcloud-block-domain
Input
| Argument Name | Description | Required |
|---|---|---|
| domain | Specify the Domains to block. Supports comma-separated values. | Required |
| custom_list_name | Specify the name of the custom list to add the given domains to. Default is Default Block. | Optional |
| custom_list_type | Specify the type of the custom list to add the given domains to. Possible values are: default_block, custom_list, threat_insight, dga, dnsm, zero_day_dns, threat_insight_nde. Default is default_block. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| InfobloxCloud.CustomList.id | String | The ID of the custom list. |
| InfobloxCloud.CustomList.name | String | The name of the custom list. |
| InfobloxCloud.CustomList.type | String | The type of the custom list. |
| InfobloxCloud.CustomList.items | String | The items in the custom list. |
| InfobloxCloud.CustomList.items_described | Array | The items described in the custom list. |
| InfobloxCloud.CustomList.item_count | Number | The number of items in the custom list. |
| InfobloxCloud.CustomList.confidence_level | String | The confidence level of the custom list. |
| InfobloxCloud.CustomList.created_time | String | The time the custom list was created. |
| InfobloxCloud.CustomList.last_updated_time | String | The time the custom list was last updated. |
| InfobloxCloud.CustomList.description | String | The description of the custom list. |
| InfobloxCloud.CustomList.policies | String | The policies of the custom list. |
| InfobloxCloud.CustomList.tags | String | The tags of the custom list. |
| InfobloxCloud.CustomList.type | String | The type of the custom list. |
| InfobloxCloud.CustomList.threat_level | String | The threat level of the custom list. |
Command example
!infobloxcloud-block-domain domain="test.com"
Context Example
{
"InfobloxCloud": {
"CustomList": {
"confidence_level": "HIGH",
"created_time": "2024-04-01T18:24:37Z",
"description": "Auto-generated",
"id": 456789,
"item_count": 2,
"items": [
"test.com",
"test.org"
],
"items_described": [
{
"description": "",
"item": "test.com",
"status": "ACTIVE",
"status_details": ""
},
{
"description": "",
"item": "test.org",
"status": "ACTIVE",
"status_details": ""
}
],
"name": "Test Block",
"policies": [
"Test Policy"
],
"tags": null,
"threat_level": "MEDIUM",
"type": "test_block",
"updated_time": "2025-07-29T10:27:49Z"
}
}
}
Human Readable Output
‘test.com’ indicator added to the ‘Test Block’ list
ID Name Type Description Items Confidence Level Threat Level Created Time Updated Time 456789 Test Block test_block Auto-generated test.com,
test.orgHIGH MEDIUM 2024-04-01T18:24:37Z 2025-07-29T10:27:49Z
infobloxcloud-unblock-domain
The given domains will be added to the provided allow list.
Base Command
infobloxcloud-unblock-domain
Input
| Argument Name | Description | Required |
|---|---|---|
| domain | Specify the Domains to unblock. Supports comma-separated values. | Required |
| custom_list_name | Specify the name of the custom list to add the given domains to. Default is Default Allow. | Optional |
| custom_list_type | Specify the type of the custom list to add the given domains to. Possible values are: default_allow, custom_list, threat_insight, threat_insight_nde. Default is default_allow. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| InfobloxCloud.CustomList.id | String | The ID of the custom list. |
| InfobloxCloud.CustomList.name | String | The name of the custom list. |
| InfobloxCloud.CustomList.type | String | The type of the custom list. |
| InfobloxCloud.CustomList.items | String | The items in the custom list. |
| InfobloxCloud.CustomList.items_described | Array | The items described in the custom list. |
| InfobloxCloud.CustomList.item_count | Number | The number of items in the custom list. |
| InfobloxCloud.CustomList.confidence_level | String | The confidence level of the custom list. |
| InfobloxCloud.CustomList.created_time | String | The time the custom list was created. |
| InfobloxCloud.CustomList.last_updated_time | String | The time the custom list was last updated. |
| InfobloxCloud.CustomList.description | String | The description of the custom list. |
| InfobloxCloud.CustomList.policies | String | The policies of the custom list. |
| InfobloxCloud.CustomList.tags | String | The tags of the custom list. |
| InfobloxCloud.CustomList.type | String | The type of the custom list. |
| InfobloxCloud.CustomList.threat_level | String | The threat level of the custom list. |
Command example
!infobloxcloud-unblock-domain domain="test.com"
Context Example
{
"InfobloxCloud": {
"CustomList": {
"confidence_level": "HIGH",
"created_time": "2024-04-01T18:24:37Z",
"description": "Auto-generated",
"id": 123456,
"item_count": 2,
"items": [
"test.com",
"test.org"
],
"items_described": [
{
"description": "",
"item": "test.com",
"status": "ACTIVE",
"status_details": ""
},
{
"description": "",
"item": "test.org",
"status": "ACTIVE",
"status_details": ""
}
],
"name": "Test Allow",
"policies": [
"Test Policy"
],
"tags": {
"test_key": "test_value"
},
"threat_level": "MEDIUM",
"type": "test_allow",
"updated_time": "2025-07-29T10:27:56Z"
}
}
}
Human Readable Output
‘test.com’ indicator added to the ‘Test Allow’ list
ID Name Type Description Items Confidence Level Threat Level Tags Created Time Updated Time 123456 Test Allow test_allow Auto-generated test.com,
test.orgHIGH MEDIUM test_key: test_value 2024-04-01T18:24:37Z 2025-07-29T10:27:56Z
infobloxcloud-customlist-indicator-remove
The given indicators will be removed from the provided custom list.
Base Command
infobloxcloud-customlist-indicator-remove
Input
| Argument Name | Description | Required |
|---|---|---|
| indicators | Specify the indicators to remove from the custom list. Format accepted is: “0.0.0.0, example.com”. | Required |
| custom_list_name | Specify the name of the custom list to remove the given indicators from. | Required |
| custom_list_type | Specify the type of the custom list to remove the given indicators from. Possible values are: default_allow, default_block, custom_list, threat_insight, dga, dnsm, zero_day_dns, threat_insight_nde. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| InfobloxCloud.CustomList.id | String | The ID of the custom list. |
| InfobloxCloud.CustomList.name | String | The name of the custom list. |
| InfobloxCloud.CustomList.type | String | The type of the custom list. |
| InfobloxCloud.CustomList.items | String | The items in the custom list. |
| InfobloxCloud.CustomList.items_described | Array | The items described in the custom list. |
| InfobloxCloud.CustomList.item_count | Number | The number of items in the custom list. |
| InfobloxCloud.CustomList.confidence_level | String | The confidence level of the custom list. |
| InfobloxCloud.CustomList.created_time | String | The time the custom list was created. |
| InfobloxCloud.CustomList.last_updated_time | String | The time the custom list was last updated. |
| InfobloxCloud.CustomList.description | String | The description of the custom list. |
| InfobloxCloud.CustomList.policies | String | The policies of the custom list. |
| InfobloxCloud.CustomList.tags | String | The tags of the custom list. |
| InfobloxCloud.CustomList.type | String | The type of the custom list. |
| InfobloxCloud.CustomList.threat_level | String | The threat level of the custom list. |
Command example
!infobloxcloud-customlist-indicator-remove indicators="0.0.0.0" custom_list_name="Test Allow" custom_list_type="test_allow"
Context Example
{
"InfobloxCloud": {
"CustomList": {
"confidence_level": "HIGH",
"created_time": "2024-04-01T18:24:37Z",
"description": "Auto-generated",
"id": 123456,
"item_count": 1,
"items": [
"example.com"
],
"items_described": [
{
"description": "",
"item": "example.com",
"status": "ACTIVE",
"status_details": ""
}
],
"name": "Test Allow",
"policies": [
"Test Policy",
],
"tags": {
"test_key": "test_value"
},
"threat_level": "MEDIUM",
"type": "test_allow",
"updated_time": "2025-07-31T11:07:41Z"
}
}
}
Human Readable Output
‘0.0.0.0’ indicators removed from the ‘Test Allow’ list
ID Name Type Description Items Confidence Level Threat Level Tags Created Time Updated Time 123456 Test Allow test_allow Auto-generated example.com HIGH MEDIUM test_key: test_value 2024-04-01T18:24:37Z 2025-07-31T11:07:41Z
ip
Gets the comprehensive IP reputation and threat intelligence from Infoblox Threat Defense, including threat indicators, IPAM address information, and standard IP reputation data.
Base Command
ip
Input
| Argument Name | Description | Required |
|---|---|---|
| ip | IP(s) for which to retrieve reputation and threat intelligence. Supports comma-separated values. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| InfobloxCloud.IP.ip | String | The requested IP address. |
| IP.Address | String | IP address. |
| IP.Relationships.EntityA | String | The source of the relationship. |
| IP.Relationships.EntityB | String | The destination of the relationship. |
| IP.Relationships.Relationship | String | The name of the relationship. |
| IP.Relationships.EntityAType | String | The type of the source of the relationship. |
| IP.Relationships.EntityBType | String | The type of the destination of the relationship. |
| IP.ASN | String | The autonomous system name for the IP address, for example: “AS8948”. |
| IP.Hostname | String | The hostname that is mapped to this IP address. |
| IP.Geo.Location | String | The geolocation where the IP address is located, in the format: latitude:longitude. |
| IP.Geo.Country | String | The country in which the IP address is located. |
| IP.Geo.Description | String | Additional information about the location. |
| IP.DetectionEngines | Number | The total number of engines that checked the indicator. |
| IP.PositiveDetections | Number | The number of engines that positively detected the indicator as malicious. |
| IP.Malicious.Vendor | String | The vendor reporting the IP address as malicious. |
| IP.Malicious.Description | String | A description explaining why the IP address was reported as malicious. |
| IP.Tags | Unknown | (List) Tags of the IP address. |
| IP.FeedRelatedIndicators.value | String | Indicators that are associated with the IP address. |
| IP.FeedRelatedIndicators.type | String | The type of the indicators that are associated with the IP address. |
| IP.FeedRelatedIndicators.description | String | The description of the indicators that are associated with the IP address. |
| IP.MalwareFamily | String | The malware family associated with the IP address. |
| IP.Organization.Name | String | The organization of the IP address. |
| IP.Organization.Type | String | The organization type of the IP address. |
| IP.ASOwner | String | The autonomous system owner of the IP address. |
| IP.Region | String | The region in which the IP address is located. |
| IP.Port | String | Ports that are associated with the IP address. |
| IP.Internal | Boolean | Whether the IP address is internal or external. |
| IP.UpdatedDate | Date | The date that the IP address was last updated. |
| IP.Registrar.Abuse.Name | String | The name of the contact for reporting abuse. |
| IP.Registrar.Abuse.Address | String | The address of the contact for reporting abuse. |
| IP.Registrar.Abuse.Country | String | The country of the contact for reporting abuse. |
| IP.Registrar.Abuse.Network | String | The network of the contact for reporting abuse. |
| IP.Registrar.Abuse.Phone | String | The phone number of the contact for reporting abuse. |
| IP.Registrar.Abuse.Email | String | The email address of the contact for reporting abuse. |
| IP.Campaign | String | The campaign associated with the IP address. |
| IP.TrafficLightProtocol | String | The Traffic Light Protocol (TLP) color that is suitable for the IP address. |
| IP.CommunityNotes.note | String | Notes on the IP address that were given by the community. |
| IP.CommunityNotes.timestamp | Date | The time in which the note was published. |
| IP.Publications.source | String | The source in which the article was published. |
| IP.Publications.title | String | The name of the article. |
| IP.Publications.link | String | A link to the original article. |
| IP.Publications.timestamp | Date | The time in which the article was published. |
| IP.ThreatTypes.threatcategory | String | The threat category associated to this indicator by the source vendor. For example, Phishing, Control, TOR, etc. |
| IP.ThreatTypes.threatcategoryconfidence | String | The confidence level provided by the vendor for the threat type category For example, a confidence of 90 for the threat type category ‘malware’ means that the vendor rates that this is 90% confidence of being a malware. |
| DBotScore.Indicator | String | The indicator that was tested. |
| DBotScore.Type | String | The indicator type. |
| DBotScore.Vendor | String | The vendor used to calculate the score. |
| DBotScore.Score | Number | The actual score. |
| DBotScore.Reliability | String | Reliability of the source providing the intelligence data. |
| InfobloxCloud.IP.Threat.id | String | The unique identifier for the threat indicator. |
| InfobloxCloud.IP.Threat.type | String | The type of threat indicator. |
| InfobloxCloud.IP.Threat.ip | String | The IP address identified as a threat indicator. |
| InfobloxCloud.IP.Threat.profile | String | The threat profile or classification source. |
| InfobloxCloud.IP.Threat.property | String | The specific property or category of the threat. |
| InfobloxCloud.IP.Threat.class | String | The classification of the threat. |
| InfobloxCloud.IP.Threat.threat_level | Number | The numeric threat level score. |
| InfobloxCloud.IP.Threat.threat_label | String | The textual threat level label. |
| InfobloxCloud.IP.Threat.expiration | Date | The timestamp when the threat indicator will expire. |
| InfobloxCloud.IP.Threat.detected | Date | The timestamp when the threat activity was first detected. |
| InfobloxCloud.IP.Threat.received | Date | The timestamp when the threat indicator was received by the system. |
| InfobloxCloud.IP.Threat.imported | Date | The timestamp when the threat indicator was imported into the system. |
| InfobloxCloud.IP.Threat.up | String | The boolean status flag indicating whether the threat indicator is currently active. |
| InfobloxCloud.IP.Threat.batch_id | String | The batch ID of the threat indicator. |
| InfobloxCloud.IP.Threat.confidence | Number | The numeric confidence score representing the reliability of the threat indicator. |
| InfobloxCloud.IP.Threat.extended.notes | String | The additional notes or information about the threat indicator. |
| InfobloxCloud.IP.Threat.threat_score | Number | The numeric score representing the calculated threat severity. |
| InfobloxCloud.IP.Threat.threat_score_rating | String | The textual rating of the threat score. |
| InfobloxCloud.IP.Threat.threat_score_vector | String | The vector string representing threat scoring details. |
| InfobloxCloud.IP.Threat.risk_score | Number | The numeric risk score assigned to the threat indicator. |
| InfobloxCloud.IP.Threat.risk_score_rating | String | The textual rating of the risk score. |
| InfobloxCloud.IP.Threat.risk_score_vector | String | The vector string representing risk scoring details. |
| InfobloxCloud.IP.Threat.confidence_score | Number | The numeric confidence score for the threat assessment. |
| InfobloxCloud.IP.Threat.confidence_score_rating | String | The textual rating of the confidence score. |
| InfobloxCloud.IP.Threat.confidence_score_vector | String | The vector string representing confidence scoring details. |
| InfobloxCloud.IP.Threat.extended.cyberint_guid | String | The unique identifier for the threat indicator. |
| InfobloxCloud.IP.Threat.extended.attack_chain | String | The attack chain associated with the threat indicator. |
| InfobloxCloud.IP.Threat.extended.extended | String | The additional information or metadata associated with the threat indicator. |
| InfobloxCloud.IP.Threat.extended.protocol | String | The protocol associated with the threat indicator. |
| InfobloxCloud.IP.Threat.extended.references | String | The references associated with the threat indicator. |
| InfobloxCloud.IP.Threat.extended.threat_actor | String | The threat actor associated with the threat indicator. |
| InfobloxCloud.IP.Threat.extended.threat_actor_vector | String | The vector string representing threat actor details. |
| InfobloxCloud.IP.Threat.extended.risk_score | String | The numeric risk score assigned to the threat indicator. |
| InfobloxCloud.IP.Threat.extended.threat_score | String | The numeric threat score assigned to the threat indicator. |
| InfobloxCloud.IP.Threat.extended.sample_sha256 | String | The SHA-256 hash of the sample associated with the threat. |
| InfobloxCloud.IP.Threat.extended.original_profile | String | The original profile or classification source of the threat. |
| InfobloxCloud.IP.Address.address | String | The IP address assigned to the resource. |
| InfobloxCloud.IP.Address.comment | String | A user-provided comment or annotation for the address record. |
| InfobloxCloud.IP.Address.compartment_id | String | The compartment ID of the IP address. |
| InfobloxCloud.IP.Address.created_at | Date | The timestamp when the IP address was created. |
| InfobloxCloud.IP.Address.dhcp_info | Unknown | The DHCP information associated with the IP address. |
| InfobloxCloud.IP.Address.disable_dhcp | Boolean | A boolean flag indicating whether DHCP is disabled for the IP address. |
| InfobloxCloud.IP.Address.discovery_attrs | Unknown | The discovery attributes associated with the IP address. |
| InfobloxCloud.IP.Address.discovery_metadata | Unknown | The discovery metadata associated with the IP address. |
| InfobloxCloud.IP.Address.external_keys | Unknown | External keys associated with the IP address. |
| InfobloxCloud.IP.Address.host | Unknown | The host name of the IP address. |
| InfobloxCloud.IP.Address.hwaddr | String | The hardware address of the IP address. |
| InfobloxCloud.IP.Address.id | String | The unique identifier of the IP address. |
| InfobloxCloud.IP.Address.interface | String | The interface of the IP address. |
| InfobloxCloud.IP.Address.names | Unknown | The names associated with the IP address. |
| InfobloxCloud.IP.Address.parent | String | The parent of the IP address. |
| InfobloxCloud.IP.Address.protocol | String | The protocol of the IP address. |
| InfobloxCloud.IP.Address.range | String | The range of the IP address. |
| InfobloxCloud.IP.Address.space | String | The space of the IP address. |
| InfobloxCloud.IP.Address.state | String | The state of the IP address. |
| InfobloxCloud.IP.Address.tags | Unknown | The tags associated with the IP address. |
| InfobloxCloud.IP.Address.updated_at | Date | The timestamp when the IP address was last updated. |
| InfobloxCloud.IP.Address.usage | String | The usage of the IP address. |
| InfobloxCloud.IP.Address.names.name | String | The name of the IP address. |
| InfobloxCloud.IP.Address.names.type | Unknown | The type of the IP address. |
Command example
!ip ip="0.0.0.1"
Context Example
{
"DBotScore": {
"Indicator": "0.0.0.1",
"Reliability": "A - Completely reliable",
"Score": 3,
"Type": "ip",
"Vendor": "InfobloxThreatDefensewithDDI"
},
"IP": {
"Address": "0.0.0.1",
"Description": "Malware Download associated with the APT group",
"ThreatTypes": [
{
"threatcategory": "IP",
"threatcategoryconfidence": "100"
}
],
"Hostname": "name",
"DetectionEngines": 1,
"Tags": [
"cyberint_guid: simple_cyberint_guid",
"notes: Malware Download associated with the APT group",
"Protocol: ip4",
"State: used",
"temp: true"
],
"MalwareFamily": "APT",
"Malicious": {
"Vendor": "InfobloxThreatDefensewithDDI",
"Description": "Malware Download associated with the APT group"
}
},
"InfobloxCloud": {
"IP": {
"ip": "0.0.0.1",
"Threat": {
"id": "00000000-0000-0000-0000-000000000000",
"type": "IP",
"ip": "0.0.0.1",
"profile": "IID",
"property": "APT_Malware",
"class": "APT",
"threat_level": 100,
"expiration": "2042-11-01T09:29:18.721Z",
"detected": "2025-07-29T09:29:18.721Z",
"received": "2025-07-29T09:31:39.329Z",
"imported": "2025-07-29T09:31:39.329Z",
"up": "true",
"confidence": 100,
"batch_id": "00000000-0000-0000-0000-000000000000",
"threat_score": 10,
"threat_score_rating": "Critical",
"threat_score_vector": "simple_threat_vector",
"risk_score": 9.9,
"risk_score_rating": "Critical",
"risk_score_vector": "simple_risk_vector",
"confidence_score": 0.1,
"confidence_score_rating": "Unconfirmed",
"confidence_score_vector": "simple_confidence_vector",
"extended": {
"cyberint_guid": "simple_cyberint_guid",
"notes": "Malware Download associated with the APT group"
}
},
"Address": {
"address": "0.0.0.1",
"comment": "comment",
"compartment_id": "00000000-0000-0000-0000-000000000000",
"created_at": "2025-06-27T13:07:21.476126Z",
"disable_dhcp": false,
"external_keys": {
"e3": "3e3"
},
"host": "ipam/host/00000000-0000-0000-0000-000000000000",
"hwaddr": "00:00:00:00:00:00",
"id": "ipam/address/00000000-0000-0000-0000-000000000000",
"interface": "interface",
"names": [
{
"name": "name",
"type": "user"
}
],
"parent": "ipam/subnet/00000000-0000-0000-0000-000000000000",
"protocol": "ip4",
"range": "ipam/range/00000000-0000-0000-0000-000000000000",
"space": "ipam/ip_space/00000000-0000-0000-0000-000000000000",
"state": "used",
"tags": {
"temp": "true"
},
"updated_at": "2025-06-27T13:07:21.429056Z",
"usage": [
"IPAM RESERVED"
]
}
}
}
}
Human Readable Output
Information for the given Bad IP: 0.0.0.1
Threat Intelligence Summary
Batch Id Class Confidence Confidence Score Confidence Score Rating Confidence Score Vector Detected Expiration Extended Id Imported IP Profile Property Received Risk Score Risk Score Rating Risk Score Vector Threat Level Threat Score Threat Score Rating Threat Score Vector Type Up 00000000-0000-0000-0000-000000000000 APT 100 0.1 Unconfirmed simple_confidence_vector 2025-07-29T09:29:18.721Z 2042-11-01T09:29:18.721Z cyberint_guid: simple_cyberint_guid
notes: Malware Download associated with the APT group00000000-0000-0000-0000-000000000000 2025-07-29T09:31:39.329Z 0.0.0.1 IID APT_Malware 2025-07-29T09:31:39.329Z 9.9 Critical simple_risk_vector 100 10 Critical simple_threat_vector IP true Address Information
Address Comment Compartment Id Created At Disable Dhcp External Keys Host Hwaddr Id Interface Names Parent Protocol Range Space State Tags Updated At Usage 0.0.0.1 comment 00000000-0000-0000-0000-000000000000 2025-06-27T13:07:21.476126Z False e3: 3e3 ipam/host/00000000-0000-0000-0000-000000000000 00:00:00:00:00:00 ipam/address/00000000-0000-0000-0000-000000000000 interface - name: name
type: useripam/subnet/00000000-0000-0000-0000-000000000000 ip4 ipam/range/00000000-0000-0000-0000-000000000000 ipam/ip_space/00000000-0000-0000-0000-000000000000 used temp: true 2025-06-27T13:07:21.429056Z values: IPAM RESERVED
domain
Gets the comprehensive domain/host reputation and threat intelligence from Infoblox Threat Defense, including threat indicators, IPAM address information and standard domain reputation data.
Base Command
domain
Input
| Argument Name | Description | Required |
|---|---|---|
| domain | Domain(s) or Hosts(s) for which to retrieve reputation and threat intelligence. Supports comma-separated values. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| InfobloxCloud.Domain.domain | String | The requested domain. |
| Domain.Name | String | The domain name, for example: “google.com”. |
| Domain.Relationships.EntityA | string | The source of the relationship. |
| Domain.Relationships.EntityB | string | The destination of the relationship. |
| Domain.Relationships.Relationship | string | The name of the relationship. |
| Domain.Relationships.EntityAType | string | The type of the source of the relationship. |
| Domain.Relationships.EntityBType | string | The type of the destination of the relationship. |
| Domain.DNS | String | A list of IP objects resolved by DNS. |
| Domain.DetectionEngines | Number | The total number of engines that checked the indicator. |
| Domain.PositiveDetections | Number | The number of engines that positively detected the indicator as malicious. |
| Domain.CreationDate | Date | The date that the domain was created. |
| Domain.UpdatedDate | String | The date that the domain was last updated. |
| Domain.ExpirationDate | Date | The expiration date of the domain. |
| Domain.DomainStatus | Datte | The status of the domain. |
| Domain.NameServers | Unknown | (List<String>) Name servers of the domain. |
| Domain.Organization | String | The organization of the domain. |
| Domain.Subdomains | Unknown | (List<String>) Subdomains of the domain. |
| Domain.Admin.Country | String | The country of the domain administrator. |
| Domain.Admin.Email | String | The email address of the domain administrator. |
| Domain.Admin.Name | String | The name of the domain administrator. |
| Domain.Admin.Phone | String | The phone number of the domain administrator. |
| Domain.Registrant.Country | String | The country of the registrant. |
| Domain.Registrant.Email | String | The email address of the registrant. |
| Domain.Registrant.Name | String | The name of the registrant. |
| Domain.Registrant.Phone | String | The phone number for receiving abuse reports. |
| Domain.Tags | Unknown | (List) Tags of the domain. |
| Domain.FeedRelatedIndicators.value | String | Indicators that are associated with the domain. |
| Domain.FeedRelatedIndicators.type | String | The type of the indicators that are associated with the domain. |
| Domain.FeedRelatedIndicators.description | String | The description of the indicators that are associated with the domain. |
| Domain.MalwareFamily | String | The malware family associated with the domain. |
| Domain.WHOIS.DomainStatus | String | The status of the domain. |
| Domain.WHOIS.NameServers | String | (List<String>) Name servers of the domain. |
| Domain.WHOIS.CreationDate | Date | The date that the domain was created. |
| Domain.WHOIS.UpdatedDate | Date | The date that the domain was last updated. |
| Domain.WHOIS.ExpirationDate | Date | The expiration date of the domain. |
| Domain.WHOIS.Registrant.Name | String | The name of the registrant. |
| Domain.WHOIS.Registrant.Email | String | The email address of the registrant. |
| Domain.WHOIS.Registrant.Phone | String | The phone number of the registrant. |
| Domain.WHOIS.Registrar.Name | String | The name of the registrar. |
| Domain.WHOIS.Registrar.AbuseEmail | String | The email address of the contact for reporting abuse. |
| Domain.WHOIS.Registrar.AbusePhone | String | The phone number of contact for reporting abuse. |
| Domain.WHOIS.Admin.Name | String | The name of the domain administrator. |
| Domain.WHOIS.Admin.Email | String | The email address of the domain administrator. |
| Domain.WHOIS.Admin.Phone | String | The phone number of the domain administrator. |
| Domain.WHOIS/History | String | List of Whois objects. |
| Domain.Malicious.Vendor | String | The vendor reporting the domain as malicious. |
| Domain.Malicious.Description | String | A description explaining why the domain was reported as malicious. |
| Domain.DomainIDNName | String | The internationalized domain name (IDN) of the domain. |
| Domain.Port | String | Ports that are associated with the domain. |
| Domain.Internal | Bool | Whether or not the domain is internal or external. |
| Domain.Category | String | The category associated with the indicator. |
| Domain.Campaign | String | The campaign associated with the domain. |
| Domain.TrafficLightProtocol | String | The Traffic Light Protocol (TLP) color that is suitable for the domain. |
| Domain.ThreatTypes.threatcategory | String | The threat category associated to this indicator by the source vendor. For example, Phishing, Control, TOR, etc. |
| Domain.ThreatTypes.threatcategoryconfidence | String | Threat Category Confidence is the confidence level provided by the vendor for the threat type category For example a confidence of 90 for threat type category ‘malware’ means that the vendor rates that this is 90% confidence of being a malware. |
| Domain.Geo.Location | String | The geolocation where the domain address is located, in the format: latitude:longitude. |
| Domain.Geo.Country | String | The country in which the domain address is located. |
| Domain.Geo.Description | String | Additional information about the location. |
| Domain.Tech.Country | String | The country of the domain technical contact. |
| Domain.Tech.Name | String | The name of the domain technical contact. |
| Domain.Tech.Organization | String | The organization of the domain technical contact. |
| Domain.Tech.Email | String | The email address of the domain technical contact. |
| Domain.CommunityNotes.note | String | Notes on the domain that were given by the community. |
| Domain.CommunityNotes.timestamp | Date | The time in which the note was published. |
| Domain.Publications.source | String | The source in which the article was published. |
| Domain.Publications.title | String | The name of the article. |
| Domain.Publications.link | String | A link to the original article. |
| Domain.Publications.timestamp | Date | The time in which the article was published. |
| Domain.Billing | String | The billing address of the domain. |
| DBotScore.Indicator | String | The indicator that was tested. |
| DBotScore.Type | String | The indicator type. |
| DBotScore.Vendor | String | The vendor used to calculate the score. |
| DBotScore.Score | Number | The actual score. |
| DBotScore.Reliability | String | Reliability of the source providing the intelligence data. |
| InfobloxCloud.Domain.Threat.id | String | The unique identifier for the threat indicator. |
| InfobloxCloud.Domain.Threat.type | String | The type of threat indicator. |
| InfobloxCloud.Domain.Threat.domain | String | The domain identified as a threat indicator. |
| InfobloxCloud.Domain.Threat.profile | String | The threat profile or classification source. |
| InfobloxCloud.Domain.Threat.property | String | The specific property or category of the threat. |
| InfobloxCloud.Domain.Threat.class | String | The classification of the threat. |
| InfobloxCloud.Domain.Threat.threat_level | Number | The numeric threat level score. |
| InfobloxCloud.Domain.Threat.threat_label | String | The textual threat level label. |
| InfobloxCloud.Domain.Threat.expiration | Date | The timestamp when the threat indicator will expire. |
| InfobloxCloud.Domain.Threat.detected | Date | The timestamp when the threat activity was first detected. |
| InfobloxCloud.Domain.Threat.received | Date | The timestamp when the threat indicator was received by the system. |
| InfobloxCloud.Domain.Threat.imported | Date | The timestamp when the threat indicator was imported into the system. |
| InfobloxCloud.Domain.Threat.up | String | The boolean status flag indicating whether the threat indicator is currently active. |
| InfobloxCloud.Domain.Threat.batch_id | String | The batch ID of the threat indicator. |
| InfobloxCloud.Domain.Threat.confidence | Number | The numeric confidence score representing the reliability of the threat indicator. |
| InfobloxCloud.Domain.Threat.extended.notes | String | The additional notes or information about the threat indicator. |
| InfobloxCloud.Domain.Threat.threat_score | Number | The numeric score representing the calculated threat severity. |
| InfobloxCloud.Domain.Threat.threat_score_rating | String | The textual rating of the threat score. |
| InfobloxCloud.Domain.Threat.threat_score_vector | String | The vector string representing threat scoring details. |
| InfobloxCloud.Domain.Threat.risk_score | Number | The numeric risk score assigned to the threat indicator. |
| InfobloxCloud.Domain.Threat.risk_score_rating | String | The textual rating of the risk score. |
| InfobloxCloud.Domain.Threat.risk_score_vector | String | The vector string representing risk scoring details. |
| InfobloxCloud.Domain.Threat.confidence_score | Number | The numeric confidence score for the threat assessment. |
| InfobloxCloud.Domain.Threat.confidence_score_rating | String | The textual rating of the confidence score. |
| InfobloxCloud.Domain.Threat.confidence_score_vector | String | The vector string representing confidence scoring details. |
| InfobloxCloud.Domain.Threat.extended.cyberint_guid | String | The unique identifier for the threat indicator. |
| InfobloxCloud.Domain.Threat.extended.attack_chain | String | The attack chain associated with the threat indicator. |
| InfobloxCloud.Domain.Threat.extended.extended | String | The additional information or metadata associated with the threat indicator. |
| InfobloxCloud.Domain.Threat.extended.protocol | String | The protocol associated with the threat indicator. |
| InfobloxCloud.Domain.Threat.extended.references | String | The references associated with the threat indicator. |
| InfobloxCloud.Domain.Threat.extended.threat_actor | String | The threat actor associated with the threat indicator. |
| InfobloxCloud.Domain.Threat.extended.threat_actor_vector | String | The vector string representing threat actor details. |
| InfobloxCloud.Domain.Threat.extended.risk_score | String | The numeric risk score assigned to the threat indicator. |
| InfobloxCloud.Domain.Threat.extended.threat_score | String | The numeric threat score assigned to the threat indicator. |
| InfobloxCloud.Domain.Threat.extended.sample_sha256 | String | The SHA-256 hash of the sample associated with the threat. |
| InfobloxCloud.Domain.Threat.extended.original_profile | String | The original profile or classification source of the threat. |
| InfobloxCloud.Domain.Threat.dga | String | The domain name generated by a DGA (Domain Generation Algorithm). |
| InfobloxCloud.Domain.Threat.host | String | The host name of the domain. |
| InfobloxCloud.Domain.Threat.tld | String | The top-level domain (TLD) of the threat. |
| InfobloxCloud.Domain.Address.addresses.address | String | The address of the IP address. |
| InfobloxCloud.Domain.Address.addresses.ref | String | The reference of the IP address. |
| InfobloxCloud.Domain.Address.addresses.space | String | The space of the IP address. |
| InfobloxCloud.Domain.Address.auto_generate_records | Boolean | A boolean flag indicating whether auto generate records is enabled for the IP address. |
| InfobloxCloud.Domain.Address.comment | String | The description for the IPAM host. |
| InfobloxCloud.Domain.Address.created_at | Date | Time when the object has been created. |
| InfobloxCloud.Domain.Address.host_names | Unknown | The name records to be generated for the host. |
| InfobloxCloud.Domain.Address.id | String | The resource identifier. |
| InfobloxCloud.Domain.Address.name | String | The name of the IPAM host. |
| InfobloxCloud.Domain.Address.host_names.alias | Boolean | A boolean flag indicating whether the name record is an alias. |
| InfobloxCloud.Domain.Address.host_names.name | String | The name of the host. |
| InfobloxCloud.Domain.Address.host_names.primary_name | Boolean | A boolean flag indicating whether the name record is the primary name. |
| InfobloxCloud.Domain.Address.host_names.zone | String | The zone of the host. |
| InfobloxCloud.Domain.Address.tags | Unknown | The tags associated with the IP address. |
| InfobloxCloud.Domain.Address.addresses | Unknown | The IP address assigned to the resource. |
Command example
!domain domain=test.com
Context Example
{
"DBotScore": {
"Indicator": "test.com",
"Reliability": "A - Completely reliable",
"Score": 3,
"Type": "domain",
"Vendor": "InfobloxBloxOneThreatDefense"
},
"Domain": {
"Description": "cyber actors, possibly associated with the APT group Agent Serpens, created a fake website mimicking a modeling agency to collect detailed visitor.",
"DetectionEngines": 1,
"Malicious": {
"Description": "cyber actors, possibly associated with the APT group Agent Serpens, created a fake website mimicking a modeling agency to collect detailed visitor.",
"Vendor": "InfobloxThreatDefensewithDDI"
},
"MalwareFamily": "Phishing",
"Name": "test.com",
"Relationships": [
{
"EntityA": "test.com",
"EntityAType": "Domain",
"EntityB": "0.0.0.1",
"EntityBType": "IP",
"Relationship": "resolves-to"
}
],
"Tags": [
"cyberint_guid: simple_cyberint_guid",
"notes: cyber actors, possibly associated with the APT group Agent Serpens, created a fake website mimicking a modeling agency to collect detailed visitor."
],
"ThreatTypes": [
{
"threatcategory": "HOST",
"threatcategoryconfidence": "100"
}
]
},
"InfobloxCloud": {
"Domain": {
"Address": {
"addresses": [
{
"address": "0.0.0.1",
"ref": "ipam/address/00000000-0000-0000-0000-000000000000",
"space": "ipam/ip_space/00000000-0000-0000-0000-000000000000"
}
],
"auto_generate_records": true,
"comment": "comment",
"created_at": "2025-07-22T05:26:46.834693Z",
"host_names": [
{
"alias": false,
"name": "test.com",
"primary_name": true,
"zone": "dns/auth_zone/8ce66502-8d4b-439e-8690-0c59d3122b9f"
}
],
"id": "ipam/host/00000000-0000-0000-0000-000000000000",
"name": "test.com",
"updated_at": "2025-07-22T05:26:57.219235Z"
},
"domain": "test.com",
"Threat": {
"batch_id": "00000000-0000-0000-0000-000000000001",
"class": "Phishing",
"confidence": 100,
"detected": "2025-05-08T16:39:38.959Z",
"dga": "false",
"domain": "test.com",
"expiration": "2025-09-05T16:39:38.959Z",
"extended": {
"cyberint_guid": "simple_cyberint_guid",
"notes": "cyber actors, possibly associated with the APT group Agent Serpens, created a fake website mimicking a modeling agency to collect detailed visitor."
},
"host": "test.com",
"id": "00000000-0000-0000-0000-000000000001",
"imported": "2025-05-08T16:41:37.894Z",
"profile": "IID",
"property": "Phishing_Lookalike",
"received": "2025-05-08T16:41:37.894Z",
"threat_level": 100,
"tld": "com",
"type": "HOST",
"up": "true"
}
}
}
}
Human Readable Output
Information for the given Bad Domain: test.com
Threat Intelligence Summary
Batch Id Class Confidence Detected Dga Domain Expiration Extended Host Id Imported Profile Property Received Threat Level Tld Type Up 00000000-0000-0000-0000-000000000001 Phishing 100 2025-05-08T16:39:38.959Z false test.com 2025-09-05T16:39:38.959Z cyberint_guid: simple_cyberint_guid
notes: cyber actors, possibly associated with the APT group Agent Serpens, created a fake website mimicking a modeling agency to collect detailed visitor.test.com 00000000-0000-0000-0000-000000000001 2025-05-08T16:41:37.894Z IID Phishing_Lookalike 2025-05-08T16:41:37.894Z 100 com HOST true Address Information
Addresses Auto Generate Records Comment Created At Host Names Id Name Updated At - address: 0.0.0.1
ref: ipam/address/00000000-0000-0000-0000-000000000000
space: ipam/ip_space/00000000-0000-0000-0000-000000000000True comment 2025-07-22T05:26:46.834693Z - alias: False
name: test.com
primary_name: True
zone: dns/auth_zone/8ce66502-8d4b-439e-8690-0c59d3122b9fipam/host/00000000-0000-0000-0000-000000000000 test.com 2025-07-22T05:26:57.219235Z
url
Gets the comprehensive URL reputation and threat intelligence from Infoblox Threat Defense, including threat indicators, and standard URL reputation data.
Base Command
url
Input
| Argument Name | Description | Required |
|---|---|---|
| url | URL(s) for which to retrieve reputation and threat intelligence. Supports comma-separated values. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| InfobloxCloud.URL.url | String | The requested URL. |
| URL.Data | String | The URL. |
| URL.Relationships.EntityA | string | The source of the relationship. |
| URL.Relationships.EntityB | string | The destination of the relationship. |
| URL.Relationships.Relationship | string | The name of the relationship. |
| URL.Relationships.EntityAType | string | The type of the source of the relationship. |
| URL.Relationships.EntityBType | string | The type of the destination of the relationship. |
| URL.DetectionEngines | String | The total number of engines that checked the indicator. |
| URL.PositiveDetections | String | The number of engines that positively detected the indicator as malicious. |
| URL.Category | String | The category associated with the indicator. |
| URL.Malicious.Vendor | String | The vendor reporting the URL as malicious. |
| URL.Malicious.Description | String | A description of the malicious URL. |
| URL.Tags | Unknown | (List) Tags of the URL. |
| URL.FeedRelatedIndicators.value | String | Indicators that are associated with the URL. |
| URL.FeedRelatedIndicators.type | String | The type of the indicators that are associated with the URL. |
| URL.FeedRelatedIndicators.description | String | The description of the indicators that are associated with the URL. |
| URL.MalwareFamily | String | The malware family associated with the URL. |
| URL.Port | String | Ports that are associated with the URL. |
| URL.Internal | Bool | Whether or not the URL is internal or external. |
| URL.Campaign | String | The campaign associated with the URL. |
| URL.TrafficLightProtocol | String | The Traffic Light Protocol (TLP) color that is suitable for the URL. |
| URL.ThreatTypes.threatcategory | String | The threat category associated to this indicator by the source vendor. For example, Phishing, Control, TOR, etc. |
| URL.ThreatTypes.threatcategoryconfidence | String | Threat Category Confidence is the confidence level provided by the vendor for the threat type category For example a confidence of 90 for threat type category ‘malware’ means that the vendor rates that this is 90% confidence of being a malware. |
| URL.ASN | String | The autonomous system name for the URL, for example: ‘AS8948’. |
| URL.ASOwner | String | The autonomous system owner of the URL. |
| URL.GeoCountry | String | The country in which the URL is located. |
| URL.Organization | String | The organization of the URL. |
| URL.CommunityNotes.note | String | Notes on the URL that were given by the community. |
| URL.CommunityNotes.timestamp | Date | The time in which the note was published. |
| URL.Publications.source | String | The source in which the article was published. |
| URL.Publications.title | String | The name of the article. |
| URL.Publications.link | String | A link to the original article. |
| URL.Publications.timestamp | Date | The time in which the article was published. |
| DBotScore.Indicator | String | The indicator that was tested. |
| DBotScore.Type | String | The indicator type. |
| DBotScore.Vendor | String | The vendor used to calculate the score. |
| DBotScore.Score | Number | The actual score. |
| DBotScore.Reliability | String | Reliability of the source providing the intelligence data. |
| InfobloxCloud.URL.Threat.id | String | The unique identifier for the threat indicator. |
| InfobloxCloud.URL.Threat.type | String | The type of threat indicator. |
| InfobloxCloud.URL.Threat.url | String | The URL identified as a threat indicator. |
| InfobloxCloud.URL.Threat.profile | String | The threat profile or classification source. |
| InfobloxCloud.URL.Threat.property | String | The specific property or category of the threat. |
| InfobloxCloud.URL.Threat.class | String | The classification of the threat. |
| InfobloxCloud.URL.Threat.threat_level | Number | The numeric threat level score. |
| InfobloxCloud.URL.Threat.threat_label | String | The textual threat level label. |
| InfobloxCloud.URL.Threat.expiration | Date | The timestamp when the threat indicator will expire. |
| InfobloxCloud.URL.Threat.detected | Date | The timestamp when the threat activity was first detected. |
| InfobloxCloud.URL.Threat.received | Date | The timestamp when the threat indicator was received by the system. |
| InfobloxCloud.URL.Threat.imported | Date | The timestamp when the threat indicator was imported into the system. |
| InfobloxCloud.URL.Threat.up | String | The boolean status flag indicating whether the threat indicator is currently active. |
| InfobloxCloud.URL.Threat.batch_id | String | The batch ID of the threat indicator. |
| InfobloxCloud.URL.Threat.confidence | Number | The numeric confidence score representing the reliability of the threat indicator. |
| InfobloxCloud.URL.Threat.extended.notes | String | The additional notes or information about the threat indicator. |
| InfobloxCloud.URL.Threat.threat_score | Number | The numeric score representing the calculated threat severity. |
| InfobloxCloud.URL.Threat.threat_score_rating | String | The textual rating of the threat score. |
| InfobloxCloud.URL.Threat.threat_score_vector | String | The vector string representing threat scoring details. |
| InfobloxCloud.URL.Threat.risk_score | Number | The numeric risk score assigned to the threat indicator. |
| InfobloxCloud.URL.Threat.risk_score_rating | String | The textual rating of the risk score. |
| InfobloxCloud.URL.Threat.risk_score_vector | String | The vector string representing risk scoring details. |
| InfobloxCloud.URL.Threat.confidence_score | Number | The numeric confidence score for the threat assessment. |
| InfobloxCloud.URL.Threat.confidence_score_rating | String | The textual rating of the confidence score. |
| InfobloxCloud.URL.Threat.confidence_score_vector | String | The vector string representing confidence scoring details. |
| InfobloxCloud.URL.Threat.extended.cyberint_guid | String | The unique identifier for the threat indicator. |
| InfobloxCloud.URL.Threat.extended.attack_chain | String | The attack chain associated with the threat indicator. |
| InfobloxCloud.URL.Threat.extended.extended | String | The additional information or metadata associated with the threat indicator. |
| InfobloxCloud.URL.Threat.extended.protocol | String | The protocol associated with the threat indicator. |
| InfobloxCloud.URL.Threat.extended.references | String | The references associated with the threat indicator. |
| InfobloxCloud.URL.Threat.extended.threat_actor | String | The threat actor associated with the threat indicator. |
| InfobloxCloud.URL.Threat.extended.threat_actor_vector | String | The vector string representing threat actor details. |
| InfobloxCloud.URL.Threat.extended.risk_score | String | The numeric risk score assigned to the threat indicator. |
| InfobloxCloud.URL.Threat.extended.threat_score | String | The numeric threat score assigned to the threat indicator. |
| InfobloxCloud.URL.Threat.extended.sample_sha256 | String | The SHA-256 hash of the sample associated with the threat. |
| InfobloxCloud.URL.Threat.extended.original_profile | String | The original profile or classification source of the threat. |
Command example
!url url=https://test.com
Context Example
{
"DBotScore": {
"Indicator": "https://test.com",
"Reliability": "A - Completely reliable",
"Score": 3,
"Type": "url",
"Vendor": "InfobloxBloxOneThreatDefense"
},
"InfobloxCloud": {
"URL": {
"Threat": {
"id": "00000000-0000-0000-0000-000000000001",
"type": "URL",
"host": "test.com",
"url": "https://test.com",
"domain": "test.com",
"tld": "com",
"profile": "IID",
"property": "Scam_Generic",
"class": "Scam",
"threat_level": 100,
"expiration": "2025-10-05T12:12:00.22Z",
"detected": "2025-06-07T12:12:00.22Z",
"received": "2025-06-07T12:16:32.337Z",
"imported": "2025-06-07T12:16:32.337Z",
"up": "true",
"confidence": 100,
"batch_id": "00000000-0000-0000-0000-000000000000",
"extended": {
"cyberint_guid": "simple_cyberint_guid",
"notes": "Scam advertised. Lures victims to put their money into fake investments.",
"protocol": "https",
"references": "https://test.com"
}
},
"url": "https://test.com"
}
},
"URL": {
"Data": "https://test.com",
"Description": "Scam advertised. Lures victims to put their money into fake investments.",
"DetectionEngines": 1,
"Malicious": {
"Description": "Scam advertised. Lures victims to put their money into fake investments.",
"Vendor": "InfobloxThreatDefensewithDDI"
},
"MalwareFamily": "Scam",
"Tags": [
"cyberint_guid: simple_cyberint_guid",
"notes: Scam advertised. Lures victims to put their money into fake investments.",
"protocol: https",
"references: https://test.com"
],
"ThreatTypes": [
{
"threatcategory": "URL",
"threatcategoryconfidence": "100"
}
]
}
}
Human Readable Output
Information for the given Bad URL: https://test.com
Threat Intelligence Summary
Batch Id Class Confidence Detected Domain Expiration Extended Host Id Imported Profile Property Received Threat Level Tld Type Up URL 00000000-0000-0000-0000-000000000000 Scam 100 2025-06-07T12:12:00.22Z test.com 2025-10-05T12:12:00.22Z cyberint_guid: simple_cyberint_guid
notes: Scam advertised. Lures victims to put their money into fake investments.
protocol: https
references: https://test.comtest.com 00000000-0000-0000-0000-000000000001 2025-06-07T12:16:32.337Z IID Scam_Generic 2025-06-07T12:16:32.337Z 100 com URL true https://test.com
infobloxcloud-mac-enrich
Enrich a MAC address with DHCP lease information.
Base Command
infobloxcloud-mac-enrich
Input
| Argument Name | Description | Required |
|---|---|---|
| mac | Specify the MAC Address to enrich. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| InfobloxCloud.DHCPLease.address | String | The IP address assigned in the DHCP lease. |
| InfobloxCloud.DHCPLease.client_id | String | The identifier of the DHCP client. |
| InfobloxCloud.DHCPLease.ends | String | The timestamp indicating when the DHCP lease ends. |
| InfobloxCloud.DHCPLease.fingerprint | String | The DHCP client fingerprint, indicating device type or OS. |
| InfobloxCloud.DHCPLease.fingerprint_processed | String | The processed fingerprint result, if available. |
| InfobloxCloud.DHCPLease.ha_group | Unknown | The high-availability group associated with the lease, if any. |
| InfobloxCloud.DHCPLease.hardware | String | The hardware (MAC) address of the DHCP client. |
| InfobloxCloud.DHCPLease.host | String | The reference or identifier for the host associated with this lease. |
| InfobloxCloud.DHCPLease.hostname | String | The hostname provided by the DHCP client. |
| InfobloxCloud.DHCPLease.iaid | Number | The Identity Association Identifier (IAID) for the DHCP lease. |
| InfobloxCloud.DHCPLease.last_updated | String | The timestamp when the lease was last updated. |
| InfobloxCloud.DHCPLease.options | String | The encoded DHCP options provided with the lease. |
| InfobloxCloud.DHCPLease.preferred_lifetime | String | The preferred lifetime of the lease. |
| InfobloxCloud.DHCPLease.protocol | String | The protocol used for the lease. |
| InfobloxCloud.DHCPLease.space | String | The identifier for the IP space to which this lease belongs. |
| InfobloxCloud.DHCPLease.starts | String | The timestamp indicating when the DHCP lease started. |
| InfobloxCloud.DHCPLease.state | String | The current state of the lease. |
| InfobloxCloud.DHCPLease.type | String | The type of DHCP lease. |
Command example
!infobloxcloud-mac-enrich mac="00:00:00:00:00:01"
Context Example
{
"InfobloxCloud": {
"DHCPLease": {
"address": "0.0.0.1",
"client_id": "01:00:00:00:00:00:01",
"ends": "2025-07-01T19:25:24Z",
"fingerprint": "VMware:Virtual Machine:Windows:",
"fingerprint_processed": "processed",
"hardware": "00:00:00:00:00:01",
"host": "dhcp/host/123456",
"hostname": "test-host01",
"iaid": 0,
"last_updated": "2025-07-01T18:25:24.792Z",
"options": "{\"Options\":[{\"Code\":\"57\",\"Value\":\"test\"},{\"Code\":\"61\",\"Value\":\"sample\"},{\"Code\":\"53\",\"Value\":\"world\"},{\"Code\":\"55\",\"Value\":\"bar\"}]}",
"preferred_lifetime": "2025-07-01T18:25:24Z",
"protocol": "",
"space": "ipam/ip_space/12345678-1234-1234-1234-123456789012",
"starts": "2025-07-01T18:25:24Z",
"state": "used",
"type": "DHCPv4"
}
}
}
Human Readable Output
DHCP Lease Information for MAC: 00:00:00:00:00:01
Address Client Id Ends Fingerprint Fingerprint Processed Hardware Host Hostname Iaid Last Updated Options Preferred Lifetime Space Starts State Type 0.0.0.1 01:00:00:00:00:00:01 2025-07-01T19:25:24Z VMware:Virtual Machine:Windows: processed 00:00:00:00:00:01 dhcp/host/123456 test-host01 0 2025-07-01T18:25:24.792Z - Code: 57
Value: test
- Code: 61
Value: sample
- Code: 53
Value: world
- Code: 55
Value: bar2025-07-01T18:25:24Z ipam/ip_space/12345678-1234-1234-1234-123456789012 2025-07-01T18:25:24Z used DHCPv4
infobloxcloud-soc-insight-list
List SOC Insights from Infoblox Cloud.
Base Command
infobloxcloud-soc-insight-list
Input
| Argument Name | Description | Required |
|---|---|---|
| status | Specify the status of SOC Insights to fetch. Possible values are: Active, Closed. | Optional |
| threat_type | Specify the threat type of SOC Insights to fetch. Possible values are: DGA, Undefined, Malicious, Open Resolver, Phishing, DNS Tunneling, MalwareDownload, Sinkhole, Zero Day DNS, Notional Data Exfiltration, MalwareC2DGA, MalwareC2, Restricted Country Communications, Suspicious, CompromisedHost, CompromisedDomain, Lookalike Threat, Sanctioned Feed Disabled, DNSTunnel. | Optional |
| priority | Specify the priority level of SOC Insights to fetch. Possible values are: INFO, MEDIUM, HIGH, CRITICAL. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| InfobloxCloud.SOCInsight.insightId | String | The ID of the SOC Insight. |
| InfobloxCloud.SOCInsight.priorityText | String | The priority level of the SOC Insight. |
| InfobloxCloud.SOCInsight.tClass | String | The threat class of the SOC Insight. |
| InfobloxCloud.SOCInsight.tFamily | String | The threat family of the SOC Insight. |
| InfobloxCloud.SOCInsight.startedAt | String | The start time of the SOC Insight. |
| InfobloxCloud.SOCInsight.status | String | The status of the SOC Insight. |
| InfobloxCloud.SOCInsight.persistentDate | String | Timestamp when the threat was first observed as persistent. |
| InfobloxCloud.SOCInsight.spreadingDate | String | Timestamp when the threat was first observed as spreading. |
| InfobloxCloud.SOCInsight.dateChanged | String | Timestamp when the SOC Insight was last updated. |
| InfobloxCloud.SOCInsight.changer | String | The user or process that last changed the SOC Insight status or data. |
| InfobloxCloud.SOCInsight.feedSource | String | The source feed or provider of the SOC Insight. |
| InfobloxCloud.SOCInsight.threatType | String | The threat type of the SOC Insight. |
| InfobloxCloud.SOCInsight.numEvents | String | The number of events associated with the SOC Insight. |
| InfobloxCloud.SOCInsight.eventsNotBlockedCount | String | The number of events not blocked by the SOC Insight. |
| InfobloxCloud.SOCInsight.mostRecentAt | String | The most recent time the SOC Insight was updated. |
Command example
#### Context Example
```json
{
"InfobloxCloud": {
"SOCInsight": [
{
"changer": "abc@xyz.com",
"dateChanged": "2025-05-21T00:54:49.407214Z",
"eventsBlockedCount": "3",
"feedSource": "Insight Detection Framework",
"insightId": "00000000-0000-0000-0000-000000000000",
"mostRecentAt": "2025-07-19T19:25:11.723397Z",
"numEvents": "3",
"persistentDate": "2025-04-14T07:00:00Z",
"priorityText": "HIGH",
"spreadingDate": "2025-05-10T19:00:00Z",
"startedAt": "2025-04-14T07:00:00Z",
"status": "Active",
"tClass": "Suspicious",
"tFamily": "EmergentDomain",
"threatType": "Suspicious"
},
{
"tClass": "TI-RESTRICTED",
"tFamily": "OFAC",
"insightId": "00000000-0000-0000-0000-000000000001",
"feedSource": "Insight Detection Framework",
"startedAt": "2025-04-12T18:00:00Z",
"threatType": "Sanctioned Feed Disabled",
"status": "Active",
"persistentDate": "2025-04-12T15:00:00Z",
"numEvents": "246",
"mostRecentAt": "2025-08-07T23:59:19Z",
"eventsNotBlockedCount": "246",
"changer": "abc@xyz.com",
"dateChanged": "2025-08-06T13:58:01.050800Z",
"priorityText": "INFO"
}
]
}
}
Human Readable Output
SOC Insights
ID Priority Class Threat Type Status Threat Family Feed Source Most Recent At 00000000-0000-0000-0000-000000000000 HIGH Suspicious Suspicious Active EmergentDomain Insight Detection Framework 2025-07-19T19:25:11.723397Z 00000000-0000-0000-0000-000000000001 INFO TI-RESTRICTED Sanctioned Feed Disabled Active OFAC Insight Detection Framework 2025-08-07T23:59:19Z
infobloxcloud-soc-insight-event-list
List events for a specific SOC Insight.
Base Command
infobloxcloud-soc-insight-event-list
Input
| Argument Name | Description | Required |
|---|---|---|
| soc_insight_id | Specify the SOC Insight ID to fetch events for. | Required |
| limit | Specify the maximum number of events to fetch. Default is 50. | Optional |
| start_time | Specify the start time for the events. Format: YYYY-MM-DDTHH:MM:SSZ, YYYY-MM-DD, N days, N hours. Example: 2025-04-25T00:00:00Z, 2025-04-25, 2 days, 5 hours, 01 Mar 2025, 01 Feb 2025 04:45:33, 15 Jun. |
Optional |
| end_time | Specify the end time for the events. Format: YYYY-MM-DDTHH:MM:SSZ, YYYY-MM-DD, N days, N hours. Example: 2025-04-25T00:00:00Z, 2025-04-25, 2 days, 5 hours, 01 Mar 2025, 01 Feb 2025 04:45:33, 15 Jun. |
Optional |
| threat_level | Specify the threat level of the events. Possible values are: High, Medium, Low, Info. | Optional |
| confidence_level | Specify the confidence level of the events. Possible values are: High, Medium, Low, Info. | Optional |
| query | Specify the query to search for events. | Optional |
| query_type | Specify the query type to search for events. Possible values are: A, AAAA, ANY, TXT, RRSIG, CNAME, MX, NS, PTR, SOA, SRV. | Optional |
| source | Specify the source of the events. | Optional |
| device_ip | Specify the device IP of the events. | Optional |
| indicator | Specify the indicator of the events. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| InfobloxCloud.Event.confidenceLevel | String | The confidence level of the threat detection. |
| InfobloxCloud.Event.deviceCountry | String | The country where the device is located. |
| InfobloxCloud.Event.deviceName | String | The name or identifier of the device. |
| InfobloxCloud.Event.deviceRegion | String | The region where the device is located. |
| InfobloxCloud.Event.dnsView | String | The DNS view used for the query. |
| InfobloxCloud.Event.feed | String | The feed that identified the threat. |
| InfobloxCloud.Event.source | String | The source of the threat detection. |
| InfobloxCloud.Event.action | String | The action taken on the detected threat. |
| InfobloxCloud.Event.policy | String | The policy applied to the detection. |
| InfobloxCloud.Event.deviceIp | String | The IP address of the device. |
| InfobloxCloud.Event.query | String | The DNS query that triggered the detection. |
| InfobloxCloud.Event.queryType | String | The type of DNS query. |
| InfobloxCloud.Event.response | String | The DNS response for the query. |
| InfobloxCloud.Event.class | String | The classification of the threat. |
| InfobloxCloud.Event.threatFamily | String | The family of the threat. |
| InfobloxCloud.Event.threatIndicator | String | The indicator of the threat. |
| InfobloxCloud.Event.detected | String | The timestamp when the event was detected. |
| InfobloxCloud.Event.property | String | The property of the event. |
| InfobloxCloud.Event.user | String | The user associated with the detection. |
| InfobloxCloud.Event.threatLevel | String | The severity level of the event. |
Command example
!infobloxcloud-soc-insight-event-list soc_insight_id="00000000-0000-0000-0000-000000000000"
Context Example
{
"InfobloxCloud": {
"Event": [
{
"action": "Allow - No Log",
"class": "TI-CONFIGURATIONISSUE",
"confidenceLevel": "High",
"detected": "2025-08-11 23:42:04 +0000 UTC",
"deviceIp": "0.0.0.0",
"deviceName": "0.0.0.0",
"policy": "DoH",
"property": "example.com",
"query": "example.com",
"queryType": "A",
"source": "unknown",
"threatFamily": "OPENRESOLVER",
"threatLevel": "Low",
"user": "unknown"
},
{
"action": "Block",
"class": "Suspicious",
"confidenceLevel": "High",
"detected": "2025-07-16 07:37:29 +0000 UTC",
"deviceIp": "0.0.0.1",
"deviceName": "0.0.0.1",
"policy": "Default Policy",
"property": "EmergentDomain",
"query": "example.org",
"queryType": "RRSIG",
"source": "Endpoint",
"threatFamily": "EmergentDomain",
"threatLevel": "High",
"user": "unknown"
}
]
}
}
Human Readable Output
Events for the given SOC Insight: 00000000-0000-0000-0000-000000000000
Confidence Level Threat Level Threat Family Action Class Detected High Low OPENRESOLVER Allow - No Log TI-CONFIGURATIONISSUE 2025-08-11 23:42:04 +0000 UTC High High EmergentDomain Block Suspicious 2025-07-16 07:37:29 +0000 UTC
infobloxcloud-soc-insight-indicator-list
List indicators for a specific SOC Insight.
Base Command
infobloxcloud-soc-insight-indicator-list
Input
| Argument Name | Description | Required |
|---|---|---|
| soc_insight_id | Specify the SOC Insight ID to fetch indicators for. | Required |
| limit | Specify the maximum number of indicators to fetch. Default is 50. | Optional |
| start_time | Specify the start time for the indicators. Format: YYYY-MM-DDTHH:MM:SSZ, YYYY-MM-DD, N days, N hours. Example: 2025-04-25T00:00:00Z, 2025-04-25, 2 days, 5 hours, 01 Mar 2025, 01 Feb 2025 04:45:33, 15 Jun. |
Optional |
| end_time | Specify the end time for the indicators. Format: YYYY-MM-DDTHH:MM:SSZ, YYYY-MM-DD, N days, N hours. Example: 2025-04-25T00:00:00Z, 2025-04-25, 2 days, 5 hours, 01 Mar 2025, 01 Feb 2025 04:45:33, 15 Jun. |
Optional |
| confidence | Specify the confidence of the indicators. Possible values are: 1, 2, 3. | Optional |
| indicator | Specify the indicator of the indicators. | Optional |
| action | Specify the action of the indicators. Possible values are: Blocked, Not Blocked. | Optional |
| actor | Specify the actor of the indicators. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| InfobloxCloud.Indicator.action | String | The action taken for the indicator. |
| InfobloxCloud.Indicator.confidence | String | The confidence level of the indicator. |
| InfobloxCloud.Indicator.count | Number | The number of occurrences of the indicator. |
| InfobloxCloud.Indicator.feedName | String | The feed name that identified the indicator. |
| InfobloxCloud.Indicator.threatLevelMax | String | The maximum threat level associated with the indicator. |
| InfobloxCloud.Indicator.indicator | String | The value of the indicator. |
| InfobloxCloud.Indicator.timeMax | Date | The latest time the indicator was observed. |
| InfobloxCloud.Indicator.timeMin | Date | The earliest time the indicator was observed. |
Command example
!infobloxcloud-soc-insight-indicator-list soc_insight_id="00000000-0000-0000-0000-000000000000"
Context Example
{
"InfobloxCloud": {
"Indicator": [
{
"action": "Not Blocked",
"confidence": "3",
"count": 189,
"indicator": "example.org",
"threatLevelMax": "1",
"timeMax": "2025-08-11T23:00:00.000",
"timeMin": "2025-07-13T15:00:00.000"
},
{
"action": "Blocked",
"confidence": "1",
"count": 5,
"indicator": "example.com",
"threatLevelMax": "3",
"timeMax": "2025-08-11T12:00:00.000",
"timeMin": "2025-07-14T10:00:00.000"
}
]
}
}
Human Readable Output
Indicators for the given SOC Insight: 00000000-0000-0000-0000-000000000000
Action Confidence Max Threat Level Indicator Count Max Time Min Time Not Blocked 3 1 example.org 189 2025-08-11T23:00:00.000 2025-07-13T15:00:00.000 Blocked 1 3 example.com 5 2025-08-11T12:00:00.000 2025-07-14T10:00:00.000
infobloxcloud-soc-insight-asset-list
List assets for a specific SOC Insight.
Base Command
infobloxcloud-soc-insight-asset-list
Input
| Argument Name | Description | Required |
|---|---|---|
| soc_insight_id | Specify the SOC Insight ID to fetch assets for. | Required |
| limit | Specify the maximum number of assets to fetch. Default is 50. | Optional |
| start_time | Specify the start time for the assets. Format: YYYY-MM-DDTHH:MM:SSZ, YYYY-MM-DD, N days, N hours. Example: 2025-04-25T00:00:00Z, 2025-04-25, 2 days, 5 hours, 01 Mar 2025, 01 Feb 2025 04:45:33, 15 Jun. |
Optional |
| end_time | Specify the end time for the assets. Format: YYYY-MM-DDTHH:MM:SSZ, YYYY-MM-DD, N days, N hours. Example: 2025-04-25T00:00:00Z, 2025-04-25, 2 days, 5 hours, 01 Mar 2025, 01 Feb 2025 04:45:33, 15 Jun. |
Optional |
| qip | Specify the IP address of the assets. | Optional |
| cmac | Specify the MAC address of the assets. | Optional |
| os_version | Specify the OS version of the assets. | Optional |
| user | Specify the user of the assets. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| InfobloxCloud.Asset.count | Number | The number of occurrences associated with the asset. |
| InfobloxCloud.Asset.qip | String | The IP address of the asset. |
| InfobloxCloud.Asset.location | String | The geographical location of the asset. |
| InfobloxCloud.Asset.threatLevelMax | String | The maximum threat level associated with the asset. |
| InfobloxCloud.Asset.threatIndicatorDistinctCount | String | The number of distinct threat indicators associated with the asset. |
| InfobloxCloud.Asset.timeMax | Date | The latest time the asset was observed. |
| InfobloxCloud.Asset.timeMin | Date | The earliest time the asset was observed. |
| InfobloxCloud.Asset.mostRecentAction | String | The most recent action taken for the asset. |
Command example
!infobloxcloud-soc-insight-asset-list soc_insight_id="00000000-0000-0000-0000-000000000000"
Context Example
{
"InfobloxCloud": {
"Asset": [
{
"count": 5,
"location": "Leidschendam,Netherlands",
"mostRecentAction": "Not Blocked",
"qip": "0.0.0.0",
"threatIndicatorDistinctCount": "1",
"threatLevelMax": "1",
"timeMax": "2025-08-11T12:00:00.000",
"timeMin": "2025-07-14T10:00:00.000"
},
{
"count": 1,
"location": "Minneapolis,United States",
"mostRecentAction": "Not Blocked",
"qip": "0.0.0.1",
"threatIndicatorDistinctCount": "1",
"threatLevelMax": "1",
"timeMax": "2025-08-07T12:00:00.000",
"timeMin": "2025-08-07T12:00:00.000"
}
]
}
}
Human Readable Output
Assets for the given SOC Insight: 00000000-0000-0000-0000-000000000000
Count QIP Max Threat Level Location Threat Indicator Distinct Count Time Max Time Min Most Recent Action 5 0.0.0.0 1 Leidschendam,Netherlands 1 2025-08-11T12:00:00.000 2025-07-14T10:00:00.000 Not Blocked 1 0.0.0.1 1 Minneapolis,United States 1 2025-08-07T12:00:00.000 2025-08-07T12:00:00.000 Not Blocked
infobloxcloud-soc-insight-comment-list
List comments for a specific SOC Insight.
Base Command
infobloxcloud-soc-insight-comment-list
Input
| Argument Name | Description | Required |
|---|---|---|
| soc_insight_id | Specify the SOC Insight ID to fetch comments for. | Required |
| start_time | Specify the start time for the comments. Format: YYYY-MM-DDTHH:MM:SSZ, YYYY-MM-DD, N days, N hours. Example: 2025-04-25T00:00:00Z, 2025-04-25, 2 days, 5 hours, 01 Mar 2025, 01 Feb 2025 04:45:33, 15 Jun. |
Optional |
| end_time | Specify the end time for the comments. Format: YYYY-MM-DDTHH:MM:SSZ, YYYY-MM-DD, N days, N hours. Example: 2025-04-25T00:00:00Z, 2025-04-25, 2 days, 5 hours, 01 Mar 2025, 01 Feb 2025 04:45:33, 15 Jun. |
Optional |
| limit | Specify the maximum number of comments to fetch. Default is 50. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| InfobloxCloud.Comment.commentsChanger | String | The user who created or changed the comment. |
| InfobloxCloud.Comment.dateChanged | Date | The timestamp when the comment was created or modified. |
| InfobloxCloud.Comment.status | String | The status associated with the comment. |
| InfobloxCloud.Comment.newComment | String | The comment text. |
Command example
!infobloxcloud-soc-insight-comment-list soc_insight_id="00000000-0000-0000-0000-000000000000"
Context Example
{
"InfobloxCloud": {
"Comment": [
{
"commentsChanger": "abc.zyx.com",
"dateChanged": "2025-08-02T08:39:43.675",
"newComment": "\nAsset IP: 0.0.0.0\nScan ID: None\nReference ID: None\nQualys Scan Report URL: https://example.com/fo/report/report_view.php?&id=None\n",
"status": "Active"
},
{
"commentsChanger": "abc.zyx.com",
"dateChanged": "2025-07-15T05:24:29.803",
"newComment": "\nAsset IP: 0.0.0.0\nScan ID: None\nReference ID: None\nQualys Scan Report URL: https://example.com/fo/report/report_view.php?&id=None\n",
"status": "Active"
}
]
}
}
Human Readable Output
Comments for the given SOC Insight: 00000000-0000-0000-0000-000000000000
Comment Changer Date Changed Status Comment abc.zyx.com 2025-08-02T08:39:43.675 Active
Asset IP: 0.0.0.0
Scan ID: None
Reference ID: None
Qualys Scan Report URL: https://example.com/fo/report/report_view.php?&id=Noneabc.zyx.com 2025-07-15T05:24:29.803 Active
Asset IP: 0.0.0.0
Scan ID: None
Reference ID: None
Qualys Scan Report URL: https://example.com/fo/report/report_view.php?&id=None
Configuration parameters
credentials— (required)integrationReliability— Source Reliabilitycreate_relationships— Create relationshipsisFetch— Fetch incidentsincidentType— Incident typeingestion_type— Ingestion Typesoc_insight_status— SOC Insight Statussoc_insight_threat_type— SOC Insight Threat Typesoc_insight_priority_level— SOC Insight Priority Leveldns_events_feed_name— DNS Security Event Feed Namedns_events_network— DNS Security Event Networkdns_events_policy_action— DNS Security Event Policy Actiondns_events_policy_name— DNS Security Event Policy Namedns_events_queried_name— DNS Security Event Queried Namedns_events_threat_class— DNS Security Event Threat Classdns_events_threat_family— DNS Security Event Threat Familydns_events_threat_indicator— DNS Security Event Threat Indicatordns_events_threat_level— DNS Security Event Threat Levelmax_fetch— Max Fetchfirst_fetch— First fetch timestampincidentFetchInterval— Incidents Fetch Intervalinsecure— Trust any certificate (not secure)proxy— Use system proxy settings
Commands (17)
-
bloxone-td-dossier-lookup-getThe Dossier Lookup API returns detailed information on the specified indicator from the requested sources.
-
bloxone-td-dossier-source-listGet available Dossier sources.
-
bloxone-td-lookalike-domain-listGet lookalike domain lists.
-
domainGets the comprehensive domain/host reputation and threat intelligence from Infoblox Threat Defense, including threat indicators, IPAM address information and standard domain reputation data.
-
infobloxcloud-block-domainThe given domains will be added to the provided block list.
-
infobloxcloud-block-ipThe given IP addresses will be added to the provided block list.
-
infobloxcloud-customlist-indicator-removeThe given indicators will be removed from the provided custom list.
-
infobloxcloud-mac-enrichEnrich a MAC address with DHCP lease information.
-
infobloxcloud-soc-insight-asset-listList assets for a specific SOC Insight.
-
infobloxcloud-soc-insight-comment-listList comments for a specific SOC Insight.
-
infobloxcloud-soc-insight-event-listList events for a specific SOC Insight.
-
infobloxcloud-soc-insight-indicator-listList indicators for a specific SOC Insight.
-
infobloxcloud-soc-insight-listList SOC Insights from Infoblox Cloud.
-
infobloxcloud-unblock-domainThe given domains will be added to the provided allow list.
-
infobloxcloud-unblock-ipThe given IP addresses will be added to the provided allow list.
-
ipGets the comprehensive IP reputation and threat intelligence from Infoblox Threat Defense, including threat indicators, IPAM address information, and standard IP reputation data.
-
urlGets the comprehensive URL reputation and threat intelligence from Infoblox Threat Defense, including threat indicators, and standard URL reputation data.
import json from pathlib import Path import pytest from copy import deepcopy from freezegun import freeze_time from unittest.mock import patch, call from InfobloxBloxOneThreatDefense import * TEST_PATH = Path(__file__).parent / "test_data" def load_json_file(file_description): file_path = TEST_PATH / f"{file_description}.json" with open(file_path) as f: return f.read() def util_load_json(file_name: str): """Load file in JSON format.""" file_path = TEST_PATH / file_name with open(file_path, encoding="utf-8") as f: return json.loads(f.read()) def util_load_text_data(file_name: str) -> str: """Load a text file.""" file_path = TEST_PATH / file_name with open(file_path, encoding="utf-8") as f: return f.read() @pytest.fixture def blox_client() -> BloxOneTDClient: return BloxOneTDClient("") @pytest.fixture def mock_results(mocker): return mocker.patch.object(demisto, "results") @pytest.fixture(autouse=True) def mock_demisto_version(mocker): return mocker.patch.object(demisto, "demistoVersion", return_value={"version": "6.5.0", "buildNumber": "12345"}) def patch_command_args_and_params(mocker, command, args): mocker.patch.object(demisto, "args", return_value=args) mocker.patch.object(demisto, "command", return_value=command) mocker.patch.object(demisto, "params", return_value={"credentials": {"password": ""}}) class TestE2E: def test_dossier_source_list_command(self, requests_mock, mocker, mock_results): patch_command_args_and_params(mocker, "bloxone-td-dossier-source-list", {}) request_call = requests_mock.get( f"{BASE_URL}/tide/api/services/intel/lookup/sources", text=load_json_file("bloxone-td-dossier-source-list"), ) res_list = ["dns", "geo", "ptr", "whois", "ssl_cert", "urlhaus"] main() assert mock_results.call_args[0][0]["EntryContext"]["BloxOneTD"]["DossierSource"] == res_list assert mock_results.call_args[0][0]["Contents"]["DossierSource"] == res_list assert request_call.called_once def test_lookalike_domain_list_command(self, requests_mock, mocker, mock_results): patch_command_args_and_params(mocker, "bloxone-td-lookalike-domain-list", {"target_domain": "test.com"}) request_call = requests_mock.get( f"{BASE_URL}/api/tdlad/v1/lookalike_domains", text=load_json_file("bloxone-td-lookalike-domain-list"), ) main() assert request_call.called_once assert request_call.request_history[0].qs["_filter"][0].startswith("target_domain") raw = mock_results.call_args[0][0]["Contents"] assert raw assert mock_results.call_args[0][0]["EntryContext"]["BloxOneTD.LookalikeDomain"] == raw def test_lookalike_domain_list_command_with_invalid_args(self, mocker, mock_results): patch_command_args_and_params( mocker, "bloxone-td-lookalike-domain-list", {"target_domain": "test.com", "filter": "test"}, ) with pytest.raises(SystemExit): main() assert mock_results.call_args[0][0]["Type"] == 4 assert "Exactly one of them, more than one is argument is not accepted" in mock_results.call_args[0][0]["Contents"] def test_dossier_lookup_get_command(self, requests_mock, mocker, mock_results): job_id = "c924d233-ddeb-8877-1234-fedd6a9bb070" create_job_request_mock = requests_mock.get( f"{BASE_URL}/tide/api/services/intel/lookup/indicator/ip", text=load_json_file("bloxone-td-dossier-lookup-get_create-job"), ) results_request_mock = requests_mock.get( f"{BASE_URL}/tide/api/services/intel/lookup/jobs/c924d233-ddeb-8877-1234-fedd6a9bb070/results", text=load_json_file("bloxone-td-dossier-lookup-get_results"), ) pending_request_mock_data = [ {"state": "created", "status": "pending"}, {"state": "created", "status": "pending"}, {"state": "completed", "status": "success"}, ] pending_request_mock = requests_mock.get( f"{BASE_URL}/tide/api/services/intel/lookup/jobs/c924d233-ddeb-8877-1234-fedd6a9bb070/pending", text=lambda _x, _y: json.dumps(pending_request_mock_data.pop(0)), ) patch_command_args_and_params( mocker, "bloxone-td-dossier-lookup-get", { "indicator_type": "ip", "value": "11.22.33.44", "sources": "urlhaus,atp,geo", }, ) # first time the command is running (creating the job + one poll) main() polling_args = mock_results.call_args[0][0]["PollingArgs"] assert mock_results.call_count == 1 assert isinstance(mock_results.call_args[0][0]["HumanReadable"], str) assert polling_args["job_id"] == job_id assert polling_args["timeout"] == 590 assert pending_request_mock.call_count == 1 patch_command_args_and_params(mocker, "bloxone-td-dossier-lookup-get", polling_args) # second time the command is running (second poll) main() polling_args = mock_results.call_args[0][0]["PollingArgs"] assert mock_results.call_count == 2 assert mock_results.call_args[0][0].get("HumanReadable") is None assert polling_args["job_id"] == job_id assert polling_args["timeout"] == 580 assert pending_request_mock.call_count == 2 # third time the command is running (third poll + get results) main() assert "PollingArgs" not in mock_results.call_args[0][0] assert mock_results.call_count == 3 assert mock_results.call_args[0][0]["HumanReadable"] assert pending_request_mock.call_count == 3 assert create_job_request_mock.called_once assert results_request_mock.called_once def test_command_test_module_401(self, requests_mock, mocker, mock_results): patch_command_args_and_params(mocker, "test-module", {}) requests_mock.get( f"{BASE_URL}/tide/api/services/intel/lookup/sources", status_code=401, text="{}", ) with pytest.raises(SystemExit): main() assert mock_results.call_args[0][0]["Type"] == 4 assert "an error occurred while executing command test-module" in mock_results.call_args[0][0]["Contents"] assert ( "Error in API call [401] - Encountered error while trying to get information from Infoblox Cloud: " "Invalid Service API Key configured." in mock_results.call_args[0][0]["Contents"] ) def test_command_test_module(self, requests_mock, mocker, mock_results): patch_command_args_and_params(mocker, "test-module", {}) request_call = requests_mock.get(f"{BASE_URL}/tide/api/services/intel/lookup/sources", text="{}") main() assert request_call.called_once assert mock_results.call_args[0][0] == "ok" def test_command_test_module_with_is_fetch(self, blox_client, requests_mock, mocker): """Test command_test_module function with isFetch parameter""" # Mock the dossier_source_list API call requests_mock.get(f"{BASE_URL}/tide/api/services/intel/lookup/sources", text="{}") # Test case 1: isFetch is False (default behavior) mock_params = mocker.patch.object(demisto, "params", return_value={"isFetch": False}) mock_fetch_incidents = mocker.patch("InfobloxBloxOneThreatDefense.fetch_incidents") result = command_test_module(blox_client) assert result == "ok" mock_fetch_incidents.assert_not_called() # Test case 2: isFetch is True (should call fetch_incidents with is_test=True) mock_params.return_value = {"isFetch": True, "max_fetch": "10", "soc_insight_status": "Active"} # Mock the insights API call for fetch_incidents requests_mock.get(f"{BASE_URL}/api/v1/insights", json={"insightList": []}) result = command_test_module(blox_client) assert result == "ok" mock_fetch_incidents.assert_called_once_with(blox_client, mock_params.return_value, is_test=True) def test_command_test_module_with_fetch_validation_error(self, blox_client, requests_mock, mocker): """Test command_test_module when fetch_incidents raises validation error""" # Mock the dossier_source_list API call requests_mock.get(f"{BASE_URL}/tide/api/services/intel/lookup/sources", text="{}") # Mock params with invalid max_fetch to trigger validation error mocker.patch.object( demisto, "params", return_value={ "isFetch": True, "max_fetch": "300", # Invalid - exceeds 200 }, ) # Mock the insights API call requests_mock.get(f"{BASE_URL}/api/v1/insights", json={"insightList": []}) with pytest.raises(ValueError, match="Invalid Max Fetch: 300"): command_test_module(blox_client) def test_not_implemented_command(self, mocker): patch_command_args_and_params(mocker, "not-implemented-command", {}) with pytest.raises(SystemExit): main() class TestBloxOneTDClient: def test_http_request_success(self, blox_client, requests_mock): """Test successful HTTP request with JSON response.""" # Mock response mock_response = {"status": "success", "data": [1, 2, 3]} requests_mock.get(f"{BASE_URL}/test/endpoint", json=mock_response, status_code=200) # Call the method response = blox_client.http_request("GET", "/test/endpoint", params={"key": "value"}) # Assertions assert response == mock_response assert requests_mock.last_request.method == "GET" assert requests_mock.last_request.path == "/test/endpoint" assert requests_mock.last_request.qs == {"key": ["value"]} def test_http_request_invalid_json(self, blox_client, requests_mock): """Test handling of non-JSON response.""" # Mock non-JSON response requests_mock.get(f"{BASE_URL}/test/endpoint", text="Not a JSON response", status_code=200) # Call the method and expect an exception with pytest.raises(DemistoException) as excinfo: blox_client.http_request("GET", "/test/endpoint") # Assert the error message is as expected assert "Failed to parse json object from response" in str(excinfo.value) @pytest.mark.parametrize( "status_code, expected_error_msg", [ (400, "Invalid argument value while trying to get information from Infoblox Cloud"), (401, "Invalid Service API Key configured"), (404, "No record found for given argument(s): Not Found"), (403, "Test connectivity failed. Please provide valid input parameters"), (521, "Test connectivity failed. Please provide valid input parameters"), ], ) def test_http_request_error_status_codes(self, blox_client, requests_mock, status_code, expected_error_msg): """Test error handling for different HTTP status codes.""" # Mock error response error_response = {"detail": "Detailed error message"} requests_mock.get(f"{BASE_URL}/test/endpoint", json=error_response, status_code=status_code) # Call the method and expect an exception with pytest.raises(DemistoException) as excinfo: blox_client.http_request("GET", "/test/endpoint") # Assert the error message contains the expected text assert expected_error_msg in str(excinfo.value) assert str(status_code) in str(excinfo.value) def test_http_request_with_json_data(self, blox_client, requests_mock): """Test HTTP request with JSON data in the body.""" # Mock response test_data = {"key": "value", "nested": {"a": 1}} requests_mock.post(f"{BASE_URL}/test/endpoint", json={"status": "success"}, status_code=200) # Call the method response = blox_client.http_request("POST", "/test/endpoint", json_data=test_data) # Assertions assert response == {"status": "success"} assert requests_mock.last_request.method == "POST" assert requests_mock.last_request.json() == test_data def test_http_request_timeout_and_retry(self, blox_client, requests_mock, mocker): """Test timeout and retry behavior.""" # Mock is_time_sensitive to control retry behavior is_time_sensitive_mock = mocker.patch( "InfobloxBloxOneThreatDefense.is_time_sensitive", side_effect=lambda: False, # Always return False for this test ) # Mock response requests_mock.get(f"{BASE_URL}/test/endpoint", json={"status": "success"}) # Call the method response = blox_client.http_request("GET", "/test/endpoint") # Assert the request was made assert requests_mock.last_request is not None assert response == {"status": "success"} is_time_sensitive_mock.assert_called() def test_dossier_source_list(self, blox_client, requests_mock): requests_mock.get( f"{BASE_URL}/tide/api/services/intel/lookup/sources", text=load_json_file("bloxone-td-dossier-source-list"), ) assert blox_client.dossier_source_list() == [ "dns", "geo", "ptr", "whois", "ssl_cert", "urlhaus", ] assert "rlabs" not in blox_client.dossier_source_list() def test_lookalike_domain_list_with_filter(self, blox_client, requests_mock): lookalike_request_mock = requests_mock.get( f"{BASE_URL}/api/tdlad/v1/lookalike_domains", text=load_json_file("bloxone-td-lookalike-domain-list"), ) blox_client.lookalike_domain_list(user_filter="test-filter") assert lookalike_request_mock.request_history[0].qs["_filter"][0] == "test-filter" def test_lookalike_domain_list_with_target_domain(self, blox_client, requests_mock): lookalike_request_mock = requests_mock.get( f"{BASE_URL}/api/tdlad/v1/lookalike_domains", text=load_json_file("bloxone-td-lookalike-domain-list"), ) blox_client.lookalike_domain_list(target_domain="target.domain") assert lookalike_request_mock.request_history[0].qs["_filter"][0] == 'target_domain=="target.domain"' def test_lookalike_domain_list_with_detected_at(self, blox_client, requests_mock): lookalike_request_mock = requests_mock.get( f"{BASE_URL}/api/tdlad/v1/lookalike_domains", text=load_json_file("bloxone-td-lookalike-domain-list"), ) blox_client.lookalike_domain_list(detected_at="2023-02-21T00:00:00Z") assert 'detected_at>="2023-02-21T00:00:00Z"'.lower() == lookalike_request_mock.request_history[0].qs["_filter"][0] def test_dossier_lookup_get_create(self, blox_client, requests_mock): lookup_get_create_request_mock = requests_mock.get( f"{BASE_URL}/tide/api/services/intel/lookup/indicator/ip", text=load_json_file("bloxone-td-dossier-lookup-get_create-job"), ) job_id = blox_client.dossier_lookup_get_create(indicator_type="ip", value="11.22.33.44") assert "11.22.33.44" in lookup_get_create_request_mock.request_history[0].qs["value"] assert job_id == "c924d233-ddeb-8877-1234-fedd6a9bb070" def test_dossier_lookup_get_is_done_check_when_not_done(self, blox_client, requests_mock): requests_mock.get( f"{BASE_URL}/tide/api/services/intel/lookup/jobs/c924d233-ddeb-8877-1234-fedd6a9bb070/pending", text=json.dumps({"state": "created", "status": "pending"}), ) is_done = blox_client.dossier_lookup_get_is_done("c924d233-ddeb-8877-1234-fedd6a9bb070") assert is_done is False def test_dossier_lookup_get_is_done_check_when_job_failed(self, blox_client, requests_mock): requests_mock.get( f"{BASE_URL}/tide/api/services/intel/lookup/jobs/c924d233-ddeb-8877-1234-fedd6a9bb070/pending", text=json.dumps({"state": "completed", "status": "error"}), ) with pytest.raises(DemistoException): blox_client.dossier_lookup_get_is_done("c924d233-ddeb-8877-1234-fedd6a9bb070") def test_dossier_lookup_get_is_done_check_when_done(self, blox_client, requests_mock): requests_mock.get( f"{BASE_URL}/tide/api/services/intel/lookup/jobs/c924d233-ddeb-8877-1234-fedd6a9bb070/pending", text=json.dumps({"state": "completed", "status": "success"}), ) is_done = blox_client.dossier_lookup_get_is_done("c924d233-ddeb-8877-1234-fedd6a9bb070") assert is_done is True def test_dossier_lookup_get_results(self, blox_client, requests_mock): dossier_lookup_get_results_request_mock = requests_mock.get( f"{BASE_URL}/tide/api/services/intel/lookup/jobs/c924d233-ddeb-8877-1234-fedd6a9bb070/results", text=load_json_file("bloxone-td-dossier-lookup-get_results"), ) blox_client.dossier_lookup_get_results("c924d233-ddeb-8877-1234-fedd6a9bb070") assert dossier_lookup_get_results_request_mock.called_once class TestUnitTests: def test_dossier_lookup_task_output(self): task_data = json.loads(load_json_file("bloxone-td-dossier-lookup-get_results"))["results"][0] expected_outputs = { "Source": "urlhaus", "Target": "11.22.33.44", "Task Id": "d4e24d99-1f98-4a1f-8434-cbf4c284c7d0", "Type": "ip", } assert dossier_lookup_task_output(task_data) == expected_outputs data_test_validate_and_format_lookalike_domain_list_args_with_multiple_filters = [ {}, {"filter": "filter", "target_domain": "target_domain"}, { "filter": "filter", "target_domain": "target_domain", "detected_at": "detected_at", }, ] @pytest.mark.parametrize( "args", data_test_validate_and_format_lookalike_domain_list_args_with_multiple_filters, ) def test_validate_and_format_lookalike_domain_list_args_with_multiple_filters(self, args): with pytest.raises(DemistoException): validate_and_format_lookalike_domain_list_args(args) data_test_validate_and_format_lookalike_domain_list_args_with_a_single_filter = [ {"filter": "filter"}, {"target_domain": "target_domain"}, ] @pytest.mark.parametrize( "args", data_test_validate_and_format_lookalike_domain_list_args_with_a_single_filter, ) def test_validate_and_format_lookalike_domain_list_args_with_a_single_filter(self, args): assert validate_and_format_lookalike_domain_list_args(args) == args data_test_validate_and_format_lookalike_domain_list_args_with_detected_at_filter = [ ("2023-02-20T00:00:00.000Z", "2023-02-20T00:00:00.000"), ("1 day", "2023-02-19T00:00:00.000"), ("1y", "2022-02-20T00:00:00.000"), ] @freeze_time("2023-02-20T00:00:00.000Z") @pytest.mark.parametrize( "detected_at, expected", data_test_validate_and_format_lookalike_domain_list_args_with_detected_at_filter, ) def test_validate_and_format_lookalike_domain_list_args_with_detected_at_filter(self, detected_at, expected): out_args = validate_and_format_lookalike_domain_list_args({"detected_at": detected_at}) assert out_args["detected_at"] == expected def test_validate_and_format_lookalike_domain_list_args_with_invalid_detected_at_filter( self, ): with pytest.raises(DemistoException): validate_and_format_lookalike_domain_list_args({"detected_at": "test"}) def test_dossier_lookup_get_command_results(self): data = json.loads(load_json_file("bloxone-td-dossier-lookup-get_results")) command_results = dossier_lookup_get_command_results(data) assert command_results.outputs == data["results"] assert command_results.raw_response == data assert command_results.readable_output.count("11.22.33.44") == 4 assert "\n|Task Id|Type|Target|Source|\n" in command_results.readable_output def test_dossier_lookup_get_schedule_polling_result_with_first_time_true(self): command_results = dossier_lookup_get_schedule_polling_result({"job_id": "1"}, first_time=True) assert command_results.readable_output def test_dossier_lookup_get_schedule_polling_result_without_first_time(self): command_results = dossier_lookup_get_schedule_polling_result({"job_id": "1"}) assert command_results.readable_output is None def test_dossier_lookup_get_schedule_polling_result_polling_args_default(self): command_results = dossier_lookup_get_schedule_polling_result({"job_id": "1"}) assert command_results.scheduled_command._args["timeout"] == 590 assert command_results.scheduled_command._command == "bloxone-td-dossier-lookup-get" def test_dossier_lookup_get_schedule_polling_result_polling_args(self): command_results = dossier_lookup_get_schedule_polling_result({"job_id": "1", "interval_in_seconds": 30, "timeout": 300}) assert command_results.scheduled_command._args["timeout"] == 270 assert int(command_results.scheduled_command._next_run) == 30 assert int(command_results.scheduled_command._timeout) == 300 assert command_results.scheduled_command._command == "bloxone-td-dossier-lookup-get" class TestIpCommand: @patch("InfobloxBloxOneThreatDefense.return_warning") def test_ip_command_success(self, mock_return_warning, blox_client, requests_mock, capfd): success_ip_address = "0.0.0.1" not_found_ip_address = "0001:0000:0000:0000:0000:0000:0000:0000" invalid_ip_address = "0.0.0.256" list_of_ip_addresses = ", ".join([success_ip_address, not_found_ip_address, invalid_ip_address]) address_response = util_load_json("enrichment_ip_address_response.json") threat_response = util_load_json("enrichment_ip_threat_response.json") output = util_load_json("ip_command_context.json") ip_hr = util_load_text_data("ip_command_success_hr.md") ip_indicator = util_load_json("ip_command_indicator.json") requests_mock.get( f"{BASE_URL}/tide/api/data/threats?ip={success_ip_address}&rlimit=1", json=threat_response, status_code=200 ) requests_mock.get( f"{BASE_URL}/api/ddi/v1/ipam/address?_filter=address=='{success_ip_address}'&_limit=1", json=address_response, status_code=200, ) requests_mock.get(f"{BASE_URL}/tide/api/data/threats?ip={not_found_ip_address}&rlimit=1", json={}, status_code=200) requests_mock.get( f"{BASE_URL}/api/ddi/v1/ipam/address?_filter=address=='{not_found_ip_address}'&_limit=1", json={}, status_code=200 ) capfd.disabled() command_output = ip_command(blox_client, args={"ip": list_of_ip_addresses}) # Ensure return_warning is called with the expected message mock_return_warning.assert_has_calls( [ call(f"The following IP Addresses were found invalid: {invalid_ip_address}", exit=False), call(MESSAGES["NO_INFO_FOUND"].format("threat and address", "IP", not_found_ip_address)), ] ) # Verify command outputs assert output == command_output[0].outputs assert command_output[0].raw_response == {"threat_data": threat_response, "address_data": address_response} assert ip_hr == command_output[0].readable_output assert command_output[0].outputs_key_field == "ip" assert OUTPUT_PREFIX["IP"] == command_output[0].outputs_prefix assert ip_indicator == command_output[0].indicator.to_context() @pytest.mark.parametrize("threat_level,expected_reputation", [(100, 3), (80, 3), (30, 2), (10, 1), (0, 0)]) def test_ip_command_all_threat(self, blox_client, requests_mock, threat_level, expected_reputation): success_ip_address = "0.0.0.1" address_response = util_load_json("enrichment_ip_address_response.json") threat_response = util_load_json("enrichment_ip_threat_response.json") ip_indicator = util_load_json("ip_command_indicator.json") if threat_level < 80: del ip_indicator[list(ip_indicator.keys())[0]]["Malicious"] ip_indicator[list(ip_indicator.keys())[1]]["Score"] = expected_reputation threat_response["threat"][0]["threat_level"] = threat_level requests_mock.get( f"{BASE_URL}/tide/api/data/threats?ip={success_ip_address}&rlimit=1", json=threat_response, status_code=200 ) requests_mock.get( f"{BASE_URL}/api/ddi/v1/ipam/address?_filter=address=='{success_ip_address}'&_limit=1", json=address_response, status_code=200, ) command_output = ip_command(blox_client, args={"ip": success_ip_address}) # Verify indicator score assert ip_indicator == command_output[0].indicator.to_context() def test_ip_command_empty_input(self, blox_client): """Test command behavior with empty input""" with pytest.raises(ValueError, match=MESSAGES["REQUIRED_ARGUMENT"].format("ip")): ip_command(blox_client, args={"ip": ",,,"}) @patch("InfobloxBloxOneThreatDefense.return_warning") def test_ip_command_invalid_input(self, mock_return_warning, blox_client): """Test command behavior with invalid input""" try: ip_command(blox_client, args={"ip": ",123,,"}) except Exception: pass mock_return_warning.assert_has_calls( [ call(MESSAGES["INVALID_IP_ADDRESS"].format("123"), exit=True), ] ) class TestUrlCommand: @patch("InfobloxBloxOneThreatDefense.return_warning") def test_url_command_success(self, mock_return_warning, blox_client, requests_mock, capfd): url = "https://test.com" not_found_url = "https://notfound.com" list_of_urls = ", ".join([url, not_found_url]) threat_response = util_load_json("enrichment_url_threat_response.json") output = util_load_json("url_command_context.json") url_hr = util_load_text_data("url_command_success_hr.md") url_indicator = util_load_json("url_command_indicator.json") requests_mock.get( f"{BASE_URL}/tide/api/data/threats?text_search={url}&type=url&rlimit=1", json=threat_response, status_code=200 ) requests_mock.get( f"{BASE_URL}/tide/api/data/threats?text_search={not_found_url}&type=url&rlimit=1", json={}, status_code=200 ) capfd.disabled() command_output = url_command(blox_client, args={"url": list_of_urls}) # Ensure return_warning is called with the expected message mock_return_warning.assert_has_calls( [ call(MESSAGES["NO_INFO_FOUND"].format("threat", "URL", not_found_url)), ] ) # Verify command outputs assert output == command_output[0].outputs assert command_output[0].raw_response == {"threat_data": threat_response} assert url_hr == command_output[0].readable_output assert command_output[0].outputs_key_field == "url" assert OUTPUT_PREFIX["URL"] == command_output[0].outputs_prefix assert url_indicator == command_output[0].indicator.to_context() @pytest.mark.parametrize("threat_level,expected_reputation", [(100, 3), (80, 3), (30, 2), (10, 1), (0, 0)]) def test_url_command_all_threat(self, blox_client, requests_mock, threat_level, expected_reputation): success_url_address = "https://test.com" threat_response = util_load_json("enrichment_url_threat_response.json") url_indicator = util_load_json("url_command_indicator.json") if threat_level < 80: del url_indicator[list(url_indicator.keys())[0]]["Malicious"] url_indicator[list(url_indicator.keys())[1]]["Score"] = expected_reputation threat_response["threat"][0]["threat_level"] = threat_level requests_mock.get( f"{BASE_URL}/tide/api/data/threats?text_search={success_url_address}&rlimit=1", json=threat_response, status_code=200 ) command_output = url_command(blox_client, args={"url": success_url_address}) # Verify indicator score assert url_indicator == command_output[0].indicator.to_context() def test_url_command_invalid_args(self, blox_client, capfd): capfd.disabled() with pytest.raises(ValueError) as error_msg: url_command(blox_client, args={"url": ",,,"}) assert str(error_msg.value) == MESSAGES["REQUIRED_ARGUMENT"].format("url") class TestFetchIncidents: """Test cases for the fetch_incidents function""" @pytest.fixture def mock_demisto_methods(self, mocker): """Mock demisto methods used by fetch_incidents""" mock_get_last_run = mocker.patch.object(demisto, "getLastRun") mock_set_last_run = mocker.patch.object(demisto, "setLastRun") mock_incidents = mocker.patch.object(demisto, "incidents") return {"getLastRun": mock_get_last_run, "setLastRun": mock_set_last_run, "incidents": mock_incidents} def test_fetch_incidents_first_run_no_last_run(self, blox_client, requests_mock, mock_demisto_methods): """Test fetch_incidents when no previous last_run exists (first run)""" # Mock API response requests_mock.get(f"{BASE_URL}/api/v1/insights", text=load_json_file("soc-insights-list")) # Mock no previous last run mock_demisto_methods["getLastRun"].return_value = None params = { "max_fetch": "10", "soc_insight_status": "Active", "soc_insight_priority_level": "HIGH", "soc_insight_threat_type": "Malware", } fetch_incidents(blox_client, params) # Verify API was called with correct parameters assert requests_mock.call_count == 1 request = requests_mock.request_history[0] assert request.qs["status"] == ["active"] assert request.qs["priority"] == ["high"] assert request.qs["threat_type"] == ["malware"] # Verify incidents were created mock_demisto_methods["incidents"].assert_called_once() incidents = mock_demisto_methods["incidents"].call_args[0][0] assert len(incidents) == 3 # Verify incident structure incident = incidents[0] assert "insightId" in incident["rawJSON"] assert incident["severity"] == 3 # HIGH priority maps to severity 3 # Verify last run was set mock_demisto_methods["setLastRun"].assert_called_once() last_run_call = mock_demisto_methods["setLastRun"].call_args[0][0] assert "soc_insight_ids" in last_run_call assert "insight-001" in last_run_call["soc_insight_ids"] assert "insight-002" in last_run_call["soc_insight_ids"] assert "insight-003" in last_run_call["soc_insight_ids"] def test_fetch_incidents_with_existing_last_run(self, blox_client, requests_mock, mock_demisto_methods): """Test fetch_incidents with existing last_run data""" # Mock API response requests_mock.get(f"{BASE_URL}/api/v1/insights", text=load_json_file("soc-insights-list")) # Mock existing last run with one insight already processed existing_last_run = {"soc_insight_ids": ["insight-001"]} mock_demisto_methods["getLastRun"].return_value = existing_last_run params = {"max_fetch": "10"} fetch_incidents(blox_client, params) # Verify only new incidents were created (insight-002 and insight-003) mock_demisto_methods["incidents"].assert_called_once() incidents = mock_demisto_methods["incidents"].call_args[0][0] assert len(incidents) == 2 # Verify the skipped insight is not in the incidents incident_data = [json.loads(inc["rawJSON"]) for inc in incidents] soc_insight_ids = [data["insightId"] for data in incident_data] assert "insight-001" not in soc_insight_ids assert "insight-002" in soc_insight_ids assert "insight-003" in soc_insight_ids def test_fetch_incidents_max_fetch_limit(self, blox_client, requests_mock, mock_demisto_methods): """Test fetch_incidents respects max_fetch limit""" # Mock API response requests_mock.get(f"{BASE_URL}/api/v1/insights", text=load_json_file("soc-insights-list")) mock_demisto_methods["getLastRun"].return_value = None params = {"max_fetch": "2"} # Limit to 2 incidents fetch_incidents(blox_client, params) # Verify only 2 incidents were created despite 3 available mock_demisto_methods["incidents"].assert_called_once() incidents = mock_demisto_methods["incidents"].call_args[0][0] assert len(incidents) == 2 # Verify last_run only contains the processed insights last_run_call = mock_demisto_methods["setLastRun"].call_args[0][0] assert len(last_run_call["soc_insight_ids"]) == 2 def test_fetch_incidents_with_max_fetch_less_than_1(self, blox_client, requests_mock): requests_mock.get(f"{BASE_URL}/api/v1/insights", json={"insightList": []}) with pytest.raises(ValueError, match="Invalid Max Fetch: -1"): fetch_incidents(blox_client, {"max_fetch": -1}) def test_fetch_incidents_empty_response(self, blox_client, requests_mock, mock_demisto_methods): """Test fetch_incidents when API returns empty insight list""" # Mock empty API response requests_mock.get(f"{BASE_URL}/api/v1/insights", json={"insightList": []}) mock_demisto_methods["getLastRun"].return_value = None params = {"max_fetch": "10"} fetch_incidents(blox_client, params) # Verify no incidents were created mock_demisto_methods["incidents"].assert_called_once() incidents = mock_demisto_methods["incidents"].call_args[0][0] assert len(incidents) == 0 # Verify empty last_run was set last_run_call = mock_demisto_methods["setLastRun"].call_args[0][0] assert "soc_insight_ids" not in last_run_call def test_fetch_incidents_empty_response_with_last_run(self, blox_client, requests_mock, mock_demisto_methods): """Test fetch_incidents when API returns empty insight list""" # Mock empty API response requests_mock.get(f"{BASE_URL}/api/v1/insights", json={"insightList": []}) mock_demisto_methods["getLastRun"].return_value = {"soc_insight_ids": ["insight-001"]} params = {"max_fetch": "10"} fetch_incidents(blox_client, params) # Verify no incidents were created mock_demisto_methods["incidents"].assert_called_once() incidents = mock_demisto_methods["incidents"].call_args[0][0] assert len(incidents) == 0 # Verify empty last_run was set last_run_call = mock_demisto_methods["setLastRun"].call_args[0][0] assert last_run_call["soc_insight_ids"] == ["insight-001"] def test_fetch_incidents_invalid_insights_skipped(self, blox_client, requests_mock, mock_demisto_methods): """Test fetch_incidents skips insights with missing required fields""" # Mock API response with invalid insights requests_mock.get(f"{BASE_URL}/api/v1/insights", text=load_json_file("soc-insights-list-invalid")) mock_demisto_methods["getLastRun"].return_value = None params = {"max_fetch": "10"} fetch_incidents(blox_client, params) # Verify only 1 incident was created (1 insight are invalid) mock_demisto_methods["incidents"].assert_called_once() incidents = mock_demisto_methods["incidents"].call_args[0][0] assert len(incidents) == 1 # Verify empty last_run was set last_run_call = mock_demisto_methods["setLastRun"].call_args[0][0] assert last_run_call["soc_insight_ids"] == ["insight-004"] @pytest.mark.parametrize( "priority_text,expected_severity", [ ("INFO", 1), ("MEDIUM", 2), ("HIGH", 3), ("CRITICAL", 4), ("UNKNOWN", 1), # Default severity for unmapped priority (None, 1), # Default severity for missing priority ], ) def test_fetch_incidents_severity_mapping( self, blox_client, requests_mock, mock_demisto_methods, priority_text, expected_severity ): """Test fetch_incidents correctly maps priority to severity""" # Create custom response with specific priority insight_data = { "insightList": [ { "insightId": "test-insight", "dateChanged": "2023-12-01T10:00:00Z", "priorityText": priority_text, "title": "Test Insight", "description": "Test description", } ] } requests_mock.get(f"{BASE_URL}/api/v1/insights", json=insight_data) mock_demisto_methods["getLastRun"].return_value = None params = {"max_fetch": "10"} fetch_incidents(blox_client, params) # Verify correct severity mapping mock_demisto_methods["incidents"].assert_called_once() incidents = mock_demisto_methods["incidents"].call_args[0][0] assert len(incidents) == 1 assert incidents[0]["severity"] == expected_severity def test_fetch_incidents_default_max_fetch(self, blox_client, requests_mock, mock_demisto_methods): """Test fetch_incidents uses default max_fetch of 50 when not specified""" requests_mock.get(f"{BASE_URL}/api/v1/insights", text=load_json_file("soc-insights-list")) mock_demisto_methods["getLastRun"].return_value = None # Don't specify max_fetch parameter params = {} fetch_incidents(blox_client, params) # Verify function completes successfully (default max_fetch is used internally) mock_demisto_methods["incidents"].assert_called_once() incidents = mock_demisto_methods["incidents"].call_args[0][0] assert len(incidents) == 3 # All 3 test insights should be processed def test_fetch_incidents_through_main_function(self, requests_mock, mocker): """Test of fetch_incidents through main() function""" # Mock demisto methods mock_incidents = mocker.patch.object(demisto, "incidents") # Mock API response requests_mock.get(f"{BASE_URL}/api/v1/insights", text=load_json_file("soc-insights-list")) # Mock demisto command and params patch_command_args_and_params(mocker, "fetch-incidents", {}) mocker.patch.object( demisto, "params", return_value={"credentials": {"password": "test-api-key"}, "max_fetch": "201", "soc_insight_status": "open"}, ) # Run main function main() # Verify fetch_incidents was executed successfully mock_incidents.assert_called_once() incidents = mock_incidents.call_args[0][0] assert len(incidents) == 3 @patch("InfobloxBloxOneThreatDefense.return_results") def test_test_module_through_main_function_for_insight_fetch(self, mock_return, requests_mock, mocker): """Test of test_module through main() function for insight fetch""" # Mock API response requests_mock.get(f"{BASE_URL}/api/v1/insights", text=load_json_file("soc-insights-list")) # Mock demisto command and params patch_command_args_and_params(mocker, "test-module", {}) mocker.patch.object( demisto, "params", return_value={ "credentials": {"password": "test-api-key"}, "isFetch": True, "max_fetch": "10", "soc_insight_status": "open", }, ) # Run main function main() # Verify fetch_incidents was executed successfully assert mock_return.call_args.args[0] == "ok" @pytest.mark.parametrize( "max_fetch,expected_error", [ ("0", ERRORS["INVALID_MAX_FETCH"].format("0")), ("201", ERRORS["INVALID_MAX_FETCH"].format("201")), ], ) def test_fetch_invalid_max_fetch(self, blox_client, max_fetch, expected_error): """Test command behavior with error input""" with pytest.raises(ValueError, match=expected_error): fetch_incidents(blox_client, params={"max_fetch": max_fetch}, is_test=True) class TestFetchDnsSecurityEvents: """Test cases for the fetch_dns_security_events function""" @pytest.fixture def dns_events_response(self): """Load DNS security events test data""" return util_load_json("dns-security-event-response-success.json") def test_fetch_dns_security_events_first_run_no_last_run(self, blox_client, requests_mock, dns_events_response): """Test fetch_dns_security_events when no previous last_run exists (first run)""" # Mock API response requests_mock.get(f"{BASE_URL}/api/dnsdata/v2/dns_event", json={"result": dns_events_response}) params = {"first_fetch": "24 hours", "dns_events_queried_name": "example.com", "dns_events_threat_level": "HIGH,MEDIUM"} last_run = {} max_fetch = 50 incidents, updated_last_run = fetch_dns_security_events(blox_client, params, last_run, max_fetch) # Verify API was called with correct parameters assert requests_mock.call_count == 1 request = requests_mock.request_history[0] assert "_limit" in request.qs assert request.qs["_limit"] == ["50"] assert "t0" in request.qs # Should have start time assert "t1" in request.qs # Should have end time assert request.qs["qname"] == ["example.com"] assert request.qs["threat_level"] == ["high,medium"] # Verify incident was created assert len(incidents) == 1 incident = incidents[0] assert "Infoblox DNS Security Event - Data Exfiltration" in incident["name"] assert incident["severity"] == 3 # HIGH severity maps to 3 assert "occurred" in incident assert "rawJSON" in incident # Verify last run was updated assert "dns_events_last_fetch" in updated_last_run assert "dns_events_ids" in updated_last_run assert len(updated_last_run["dns_events_ids"]) == 1 def test_fetch_dns_security_events_with_existing_last_run(self, blox_client, requests_mock, dns_events_response): """Test fetch_dns_security_events with existing last_run data""" # Mock API response with same event requests_mock.get(f"{BASE_URL}/api/dnsdata/v2/dns_event", json={"result": dns_events_response}) # Create composite key from the test data event event = dns_events_response[0] event_time = event.get("event_time") qname_truncated = event.get("qname", "")[:20] composite_key = "|".join([event_time, qname_truncated, event.get("device", ""), event.get("feed_name", "")]) # Mock existing last run with the event already processed existing_last_run = {"dns_events_last_fetch": "2025-09-17T07:45:30.000Z", "dns_events_ids": [composite_key]} params = {"first_fetch": "24 hours"} max_fetch = 50 incidents, updated_last_run = fetch_dns_security_events(blox_client, params, existing_last_run, max_fetch) # Verify no incidents were created (event was already processed) assert len(incidents) == 0 # Verify last run was updated assert updated_last_run["dns_events_last_fetch"] == event_time assert composite_key in updated_last_run["dns_events_ids"] def test_fetch_dns_security_events_max_fetch_limit(self, blox_client, requests_mock): """Test fetch_dns_security_events respects max_fetch limit""" # Create multiple events multiple_events = [] base_event = util_load_json("dns-security-event-response-success.json")[0] for i in range(5): event = base_event.copy() event["event_time"] = f"2025-09-18T07:45:3{i}.000Z" event["qname"] = f"test{i}.example.com" multiple_events.append(event) requests_mock.get(f"{BASE_URL}/api/dnsdata/v2/dns_event", json={"result": multiple_events}) params = {"first_fetch": "24 hours"} last_run = {} max_fetch = 5 # Limit to 5 events incidents, _ = fetch_dns_security_events(blox_client, params, last_run, max_fetch) # Verify API was called with correct limit request = requests_mock.request_history[0] assert request.qs["_limit"] == ["5"] # Note: The function doesn't actually limit incidents in processing, # it relies on API _limit parameter assert len(incidents) == 5 def test_fetch_dns_security_events_with_filters(self, blox_client, requests_mock, dns_events_response): """Test fetch_dns_security_events with various filter parameters""" requests_mock.get(f"{BASE_URL}/api/dnsdata/v2/dns_event", json={"result": dns_events_response}) params = { "first_fetch": "24 hours", "dns_events_queried_name": "example.com,test.com", "dns_events_policy_name": "Policy1,Policy2", "dns_events_threat_level": "HIGH,MEDIUM", "dns_events_threat_class": "Malware,Phishing", "dns_events_threat_family": "Family1,Family2", "dns_events_threat_indicator": "indicator1,indicator2", "dns_events_policy_action": "Block,Log", "dns_events_feed_name": "Feed1,Feed2", "dns_events_network": "Network1,Network2", } last_run = {} max_fetch = 50 fetch_dns_security_events(blox_client, params, last_run, max_fetch) # Verify API was called with all filter parameters request = requests_mock.request_history[0] assert request.qs["qname"] == ["example.com,test.com"] assert request.qs["policy_name"] == ["policy1,policy2"] assert request.qs["threat_level"] == ["high,medium"] assert request.qs["threat_class"] == ["malware,phishing"] assert request.qs["threat_family"] == ["family1,family2"] assert request.qs["threat_indicator"] == ["indicator1,indicator2"] assert request.qs["policy_action"] == ["block,log"] assert request.qs["feed_name"] == ["feed1,feed2"] assert request.qs["network"] == ["network1,network2"] def test_fetch_dns_security_events_empty_response(self, blox_client, requests_mock): """Test fetch_dns_security_events when API returns empty result""" requests_mock.get(f"{BASE_URL}/api/dnsdata/v2/dns_event", json={"result": []}) params = {"first_fetch": "24 hours"} last_run = {} max_fetch = 50 incidents, updated_last_run = fetch_dns_security_events(blox_client, params, last_run, max_fetch) # Verify no incidents were created assert len(incidents) == 0 # Verify last_run is returned unchanged since no events assert updated_last_run == last_run def test_fetch_dns_security_events_test_mode(self, blox_client, requests_mock, dns_events_response): """Test fetch_dns_security_events in test mode""" requests_mock.get(f"{BASE_URL}/api/dnsdata/v2/dns_event", json={"result": dns_events_response}) params = {"first_fetch": "24 hours"} last_run = {} max_fetch = 50 is_test = True incidents, updated_last_run = fetch_dns_security_events(blox_client, params, last_run, max_fetch, is_test) # In test mode, should return empty incidents and last_run assert incidents == [] assert updated_last_run == {} @pytest.mark.parametrize( "severity, expected_severity_level", [ ("HIGH", 3), ("MEDIUM", 2), ("INFO", 1), ("CRITICAL", 4), ("UNKNOWN", 1), # Default for unmapped severity (None, 1), # Default for missing severity ], ) def test_fetch_dns_security_events_severity_mapping(self, blox_client, requests_mock, severity, expected_severity_level): """Test fetch_dns_security_events correctly maps severity to incident severity""" base_event = util_load_json("dns-security-event-response-success.json")[0] if severity is not None: base_event["severity"] = severity else: base_event.pop("severity", None) requests_mock.get(f"{BASE_URL}/api/dnsdata/v2/dns_event", json={"result": [base_event]}) params = {"first_fetch": "24 hours"} last_run = {} max_fetch = 50 incidents, _ = fetch_dns_security_events(blox_client, params, last_run, max_fetch) assert len(incidents) == 1 assert incidents[0]["severity"] == expected_severity_level def test_fetch_dns_security_events_response_format_variations(self, blox_client, requests_mock, dns_events_response): """Test fetch_dns_security_events handles different response formats""" # Test when response is directly a list (not wrapped in result key) requests_mock.get(f"{BASE_URL}/api/dnsdata/v2/dns_event", json=dns_events_response) params = {"first_fetch": "24 hours"} last_run = {} max_fetch = 50 incidents, _ = fetch_dns_security_events(blox_client, params, last_run, max_fetch) # Should handle both response formats assert len(incidents) == 1 def test_fetch_dns_security_events_time_handling(self, blox_client, requests_mock, dns_events_response, mocker): """Test fetch_dns_security_events properly handles time parameters""" requests_mock.get(f"{BASE_URL}/api/dnsdata/v2/dns_event", json={"result": dns_events_response}) # Mock datetime to control timestamp calculation mock_now = mocker.patch("InfobloxBloxOneThreatDefense.arg_to_datetime") mock_now.side_effect = lambda x: arg_to_datetime("2025-09-18T08:00:00.000Z") if x == "now" else arg_to_datetime(x) params = {"first_fetch": "1 day"} last_run = {"dns_events_last_fetch": "2025-09-17T08:00:00.000Z"} max_fetch = 50 fetch_dns_security_events(blox_client, params, last_run, max_fetch) # Verify time parameters were set correctly in API call request = requests_mock.request_history[0] assert "t0" in request.qs # Start time from last fetch assert "t1" in request.qs # End time (now) def test_fetch_dns_security_events_composite_key_generation(self, blox_client, requests_mock): """Test fetch_dns_security_events generates correct composite keys for deduplication""" # Create event with specific fields for key generation test_event = { "event_time": "2025-09-18T07:45:30.000Z", "qname": "test.example.com.with.very.long.domain.name.that.exceeds.twenty.characters", "device": "10.0.0.1", "feed_name": "Test Feed", "severity": "HIGH", "tclass": "Malware", } requests_mock.get(f"{BASE_URL}/api/dnsdata/v2/dns_event", json={"result": [test_event]}) params = {"first_fetch": "24 hours"} last_run = {} max_fetch = 50 _, updated_last_run = fetch_dns_security_events(blox_client, params, last_run, max_fetch) # Verify composite key format: event_time|qname_truncated|device|feed_name expected_composite_key = "2025-09-18T07:45:30.000Z|test.example.com.wit|10.0.0.1|Test Feed" assert expected_composite_key in updated_last_run["dns_events_ids"] def test_fetch_dns_security_events_integration_with_fetch_incidents( self, blox_client, requests_mock, dns_events_response, mocker ): """Test fetch_dns_security_events integration with main fetch_incidents function""" # Mock demisto methods mock_get_last_run = mocker.patch.object(demisto, "getLastRun", return_value={}) mock_set_last_run = mocker.patch.object(demisto, "setLastRun") mock_incidents = mocker.patch.object(demisto, "incidents") # Mock API response requests_mock.get(f"{BASE_URL}/api/dnsdata/v2/dns_event", json={"result": dns_events_response}) params = {"max_fetch": "50", "ingestion_type": "DNS Security Event", "first_fetch": "24 hours"} fetch_incidents(blox_client, params) # Verify demisto methods were called correctly mock_get_last_run.assert_called_once() mock_set_last_run.assert_called_once() mock_incidents.assert_called_once() # Verify incident was created incidents_call = mock_incidents.call_args[0][0] assert len(incidents_call) == 1 assert incidents_call[0]["name"].startswith("Infoblox DNS Security Event") @patch("InfobloxBloxOneThreatDefense.return_results") def test_test_module_through_main_function_for_event_fetch(self, mock_return, requests_mock, mocker): """Test of test_module through main() function for DNS Security Events fetch""" # Mock API response requests_mock.get(f"{BASE_URL}/api/dnsdata/v2/dns_event", json=util_load_json("dns-security-event-response-success.json")) # Mock demisto command and params patch_command_args_and_params(mocker, "test-module", {}) mocker.patch.object( demisto, "params", return_value={ "credentials": {"password": "test-api-key"}, "isFetch": True, "max_fetch": "10", "soc_insight_status": "open", "ingestion_type": "DNS Security Event", }, ) # Run main function main() # Verify fetch_incidents was executed successfully assert mock_return.call_args.args[0] == "ok" @pytest.mark.parametrize( "dns_events_threat_level,expected_error", [ ("abc", MESSAGES["INVALID_DNS_EVENT_THREAT_LEVEL"].format("abc")), ("lower,high", MESSAGES["INVALID_DNS_EVENT_THREAT_LEVEL"].format("lower")), ], ) def test_fetch_dns_security_events_error_input(self, blox_client, dns_events_threat_level, expected_error): """Test command behavior with error input""" with pytest.raises(ValueError, match=expected_error): fetch_dns_security_events( blox_client, params={"dns_events_threat_level": dns_events_threat_level}, last_run={}, max_fetch=50 ) class TestMacEnrichCommand: def test_mac_enrich_command_success(self, blox_client, requests_mock): """Test successful MAC address enrichment with valid data""" test_mac = "00:00:00:00:00:01" # Load test data mac_response = util_load_json("enrichment_mac_address_response.json") mac_context = util_load_json("mac_command_context.json") mac_hr = util_load_text_data("mac_command_success_hr.md") # Mock API response requests_mock.get( f"{BASE_URL}/api/ddi/v1/dhcp/lease?_filter=hardware=='{test_mac}'&_limit=1", json=mac_response, status_code=200 ) # Execute command command_result = mac_enrich_command(blox_client, args={"mac": test_mac}) # Verify command outputs assert command_result.outputs_prefix == "InfobloxCloud.DHCPLease" assert command_result.outputs_key_field == "hardware" assert command_result.outputs == remove_empty_elements(mac_context) assert command_result.raw_response == mac_response assert command_result.readable_output == mac_hr @pytest.mark.parametrize("mac_address", ["00:00:00:00:00:00", "00-00-00-00-00-00", "0000.0000.0000", "000000000000"]) def test_mac_enrich_command_valid_format(self, blox_client, requests_mock, mac_address): """Test successful MAC address enrichment with valid formats.""" # Load test data mac_response = util_load_json("enrichment_mac_address_response.json") # Mock API response requests_mock.get( f"{BASE_URL}/api/ddi/v1/dhcp/lease?_filter=hardware=='{mac_address}'&_limit=1", json=mac_response, status_code=200 ) # Execute command mac_enrich_command(blox_client, args={"mac": mac_address}) @pytest.mark.parametrize( "mac,expected_error", [("", MESSAGES["REQUIRED_ARGUMENT"].format("mac")), ("123", MESSAGES["INVALID_VALUE"].format("123", "mac"))], ) def test_mac_enrich_command_error_input(self, blox_client, mac, expected_error): """Test command behavior with error input""" with pytest.raises(ValueError, match=expected_error): mac_enrich_command(blox_client, args={"mac": mac}) def test_mac_enrich_command_no_results(self, blox_client, requests_mock): """Test command behavior when no results are returned""" test_mac = "00:11:22:33:44:55" # Mock empty response requests_mock.get( f"{BASE_URL}/api/ddi/v1/dhcp/lease?_filter=hardware=='{test_mac}'&_limit=1", json={"results": []}, status_code=200 ) command_result = mac_enrich_command(blox_client, args={"mac": test_mac}) assert command_result.readable_output == MESSAGES["NO_INFO_FOUND"].format("DHCP lease", "MAC", test_mac) assert command_result.outputs is None def test_mac_enrich_command_options_parsing(self, blox_client, requests_mock): """Test command's options JSON parsing functionality""" test_mac = "00:00:00:00:00:01" # Create a modified response with valid options JSON options_response = deepcopy(util_load_json("enrichment_mac_address_response.json")) options_data = options_response["results"][0] options_data["options"] = '{"Options":[{"Code":"57","Value":"test"}]}' # Mock API response requests_mock.get( f"{BASE_URL}/api/ddi/v1/dhcp/lease?_filter=hardware=='{test_mac}'&_limit=1", json=options_response, status_code=200 ) # Execute command mac_enrich_command(blox_client, args={"mac": test_mac}) # Verify options were returned as a string clean_data = remove_empty_elements_for_hr(options_data) assert isinstance(clean_data.get("options"), str) assert '"Code":"57"' in clean_data.get("options") def test_mac_enrich_command_options_parsing_error(self, blox_client, requests_mock): """Test command's handling of invalid options JSON""" test_mac = "00:00:00:00:00:01" # Create a modified response with invalid options JSON invalid_options_response = deepcopy(util_load_json("enrichment_mac_address_response.json")) invalid_options_response["results"][0]["options"] = "{invalid json}" # Mock API response requests_mock.get( f"{BASE_URL}/api/ddi/v1/dhcp/lease?_filter=hardware=='{test_mac}'&_limit=1", json=invalid_options_response, status_code=200, ) # Execute command - should not raise exception for invalid JSON command_result = mac_enrich_command(blox_client, args={"mac": test_mac}) # Verify command executed without error assert command_result.outputs_prefix == "InfobloxCloud.DHCPLease" assert command_result.outputs_key_field == "hardware" class TestBlockUnblock: """Test cases for block_ip_command, unblock_ip_command, block_domain_command, unblock_domain_command and indicator_remove_command""" # noqa: E501 @pytest.mark.parametrize( "args,error_msg", [ ({"ip": ""}, MESSAGES["REQUIRED_ARGUMENT"].format("ip")), ({"ip": "dummy", "custom_list_name": "test_name", "custom_list_type": "test_type"}, "Invalid IP or CIDR: dummy"), ( {"ip": "0.0.0.0", "custom_list_name": "", "custom_list_type": "test_type"}, MESSAGES["REQUIRED_ARGUMENT"].format("custom_list_name"), ), ( {"ip": "0.0.0.1", "custom_list_type": "", "custom_list_name": "test_name"}, MESSAGES["REQUIRED_ARGUMENT"].format("custom_list_type"), ), ({"ip": "0.0.0.0, 0"}, "Invalid IP or CIDR: 0"), ], ) def test_block_ip_command_and_unblock_ip_command_when_empty_or_invalid_args_provided(self, blox_client, args, error_msg): """Test block_ip_command and unblock_ip_command when provided args are empty or invalid.""" with pytest.raises(ValueError) as e: block_ip_command(blox_client, args) assert str(e.value) == error_msg with pytest.raises(ValueError) as e: unblock_ip_command(blox_client, args) assert str(e.value) == error_msg def test_block_ip_command_success(self, blox_client, requests_mock): """Test successful IP blocking""" # Load test data get_response = util_load_json("block-unblock-ip-command-response.json") readable_output = util_load_text_data("block-unblock-ip-command-readable.md") # Mock the three API calls that generic_named_list_method makes: # 1. Initial get_named_list call to get the list ID requests_mock.get(f"{BASE_URL}/api/atcfw/v1/named_lists/0", json=get_response, status_code=200) # 2. update_named_list API call (POST to add items) requests_mock.post( f"{BASE_URL}/api/atcfw/v1/named_lists/{get_response['results']['id']}/items", json={"success": True}, status_code=200 ) # 3. Final get_named_list call to get updated results requests_mock.get(f"{BASE_URL}/api/atcfw/v1/named_lists/0", json=get_response, status_code=200) result = block_ip_command( blox_client, {"ip": "0.0.0.0, 0.0.0.1", "custom_list_name": "Test Name", "custom_list_type": "test_type"} ) assert result.readable_output == readable_output def test_unblock_ip_command_success(self, blox_client, requests_mock): """Test successful IP unblocking""" # Load test data get_response = util_load_json("block-unblock-ip-command-response.json") readable_output = util_load_text_data("block-unblock-ip-command-readable.md") # Mock the three API calls that generic_named_list_method makes for remove operation: # 1. Initial get_named_list call to get the list ID requests_mock.get(f"{BASE_URL}/api/atcfw/v1/named_lists/0", json=get_response, status_code=200) # 2. remove_named_list_items API call (DELETE to remove items) - needs JSON response requests_mock.post(f"{BASE_URL}/api/atcfw/v1/named_lists/123456/items", json={"success": True}, status_code=200) # 3. Final get_named_list call to get updated results requests_mock.get(f"{BASE_URL}/api/atcfw/v1/named_lists/0", json=get_response, status_code=200) result = unblock_ip_command( blox_client, {"ip": "0.0.0.0, 0.0.0.1", "custom_list_name": "Test Name", "custom_list_type": "test_type"} ) assert result.readable_output == readable_output @pytest.mark.parametrize( "args,error_msg", [ ({"domain": ""}, MESSAGES["REQUIRED_ARGUMENT"].format("domain")), ( {"domain": "example.com", "custom_list_name": "", "custom_list_type": "test_type"}, MESSAGES["REQUIRED_ARGUMENT"].format("custom_list_name"), ), ( {"domain": "example.com", "custom_list_type": "", "custom_list_name": "test_name"}, MESSAGES["REQUIRED_ARGUMENT"].format("custom_list_type"), ), ], ) def test_block_domain_command_and_unblock_domain_command_when_empty_or_invalid_args_provided( self, blox_client, args, error_msg ): """Test block_domain_command and unblock_domain_command when provided args are empty or invalid.""" with pytest.raises(ValueError) as e: block_domain_command(blox_client, args) assert str(e.value) == error_msg with pytest.raises(ValueError) as e: unblock_domain_command(blox_client, args) assert str(e.value) == error_msg def test_block_domain_command_success(self, blox_client, requests_mock): """Test successful domain blocking""" # Load test data get_response = util_load_json("block-unblock-domain-command-response.json") readable_output = util_load_text_data("block-unblock-domain-command-readable.md") # Mock the three API calls that generic_named_list_method makes: # 1. Initial get_named_list call to get the list ID requests_mock.get(f"{BASE_URL}/api/atcfw/v1/named_lists/0", json=get_response, status_code=200) # 2. update_named_list API call (POST to add items) requests_mock.post( f"{BASE_URL}/api/atcfw/v1/named_lists/{get_response['results']['id']}/items", json={"success": True}, status_code=200 ) # 3. Final get_named_list call to get updated results requests_mock.get(f"{BASE_URL}/api/atcfw/v1/named_lists/0", json=get_response, status_code=200) result = block_domain_command( blox_client, {"domain": "test.com, test.org", "custom_list_name": "Test Name", "custom_list_type": "test_type"} ) assert result.readable_output == readable_output def test_unblock_domain_command_success(self, blox_client, requests_mock): """Test successful domain unblocking""" # Load test data get_response = util_load_json("block-unblock-domain-command-response.json") readable_output = util_load_text_data("block-unblock-domain-command-readable.md") # Mock the three API calls that generic_named_list_method makes for remove operation: # 1. Initial get_named_list call to get the list ID requests_mock.get(f"{BASE_URL}/api/atcfw/v1/named_lists/0", json=get_response, status_code=200) # 2. remove_named_list_items API call (DELETE to remove items) - needs JSON response requests_mock.post(f"{BASE_URL}/api/atcfw/v1/named_lists/123456/items", json={"success": True}, status_code=200) # 3. Final get_named_list call to get updated results requests_mock.get(f"{BASE_URL}/api/atcfw/v1/named_lists/0", json=get_response, status_code=200) result = unblock_domain_command( blox_client, {"domain": "test.com, test.org", "custom_list_name": "Test Name", "custom_list_type": "test_type"} ) assert result.readable_output == readable_output @pytest.mark.parametrize( "args,error_msg", [ ({"indicators": ""}, MESSAGES["REQUIRED_ARGUMENT"].format("indicators")), ( {"indicators": "0.0.0.0", "custom_list_name": "", "custom_list_type": "test_type"}, MESSAGES["REQUIRED_ARGUMENT"].format("custom_list_name"), ), ( {"indicators": "0.0.0.1", "custom_list_type": "", "custom_list_name": "test_name"}, MESSAGES["REQUIRED_ARGUMENT"].format("custom_list_type"), ), ], ) def test_infobloxcloud_customlist_indicator_remove_when_empty_or_invalid_args_provided(self, blox_client, args, error_msg): """Test infobloxcloud_customlist_indicator_remove when provided args are empty or invalid.""" with pytest.raises(ValueError) as e: infobloxcloud_customlist_indicator_remove(blox_client, args) assert str(e.value) == error_msg def test_infobloxcloud_customlist_indicator_remove_success(self, blox_client, requests_mock): """Test successful indicator removal""" get_response = util_load_json("infobloxcloud-customlist-indicator-remove-response.json") readable_output = util_load_text_data("infobloxcloud-customlist-indicator-remove-readable.md") # 1. Initial get_named_list call to get the list ID requests_mock.get(f"{BASE_URL}/api/atcfw/v1/named_lists/0", json=get_response, status_code=200) # 2. update_named_list API call (POST to add items) requests_mock.delete( f"{BASE_URL}/api/atcfw/v1/named_lists/{get_response['results']['id']}/items", json={"success": True}, status_code=200 ) # 3. Final get_named_list call to get updated results requests_mock.get(f"{BASE_URL}/api/atcfw/v1/named_lists/0", json=get_response, status_code=200) result = infobloxcloud_customlist_indicator_remove( blox_client, {"indicators": "example.com", "custom_list_name": "Test Name", "custom_list_type": "test_type"} ) assert result.readable_output == readable_output class TestDomainCommand: @patch("InfobloxBloxOneThreatDefense.return_warning") def test_domain_command_success(self, mock_return_warning, blox_client, requests_mock, capfd, mocker): domain = "test.com" not_found_domain = "notfound.com" list_of_domains = ", ".join([domain, not_found_domain]) threat_response = util_load_json("enrichment_domain_threat_response.json") address_response = util_load_json("enrichment_domain_address_response.json") output = util_load_json("domain_command_context.json") domain_hr = util_load_text_data("domain_command_success_hr.md") domain_indicator = util_load_json("domain_command_indicator.json") params = {"integrationReliability": DBotScoreReliability.B, "create_relationships": True} mocker.patch.object(demisto, "params", return_value=params) requests_mock.get( f"{BASE_URL}/tide/api/data/threats?host={domain}&type=host&rlimit=1", json=threat_response, status_code=200 ) requests_mock.get( f"{BASE_URL}/api/ddi/v1/ipam/host?_filter=name=='{domain}'&_limit=1", json=address_response, status_code=200, ) requests_mock.get( f"{BASE_URL}/tide/api/data/threats?host={not_found_domain}&type=host&rlimit=1", json={}, status_code=200 ) requests_mock.get( f"{BASE_URL}/api/ddi/v1/ipam/host?_filter=name=='{not_found_domain}'&_limit=1", json={}, status_code=200 ) capfd.disabled() command_output = domain_command(blox_client, args={"domain": list_of_domains}) # Ensure return_warning is called with the expected message mock_return_warning.assert_has_calls( [ call(MESSAGES["NO_INFO_FOUND"].format("threat and address", "Domain", not_found_domain)), ] ) # Verify command outputs assert output == command_output[0].outputs assert command_output[0].raw_response == {"threat_data": threat_response, "address_data": address_response} assert domain_hr == command_output[0].readable_output assert command_output[0].outputs_key_field == "domain" assert OUTPUT_PREFIX["Domain"] == command_output[0].outputs_prefix assert domain_indicator == command_output[0].indicator.to_context() @pytest.mark.parametrize("threat_level,expected_reputation", [(100, 3), (80, 3), (30, 2), (10, 1), (0, 0)]) def test_domain_command_all_threat(self, blox_client, requests_mock, threat_level, expected_reputation, mocker): success_domain_address = "test.com" address_response = util_load_json("enrichment_domain_address_response.json") threat_response = util_load_json("enrichment_domain_threat_response.json") domain_indicator = util_load_json("domain_command_indicator.json") if threat_level < 80: del domain_indicator[list(domain_indicator.keys())[0]]["Malicious"] domain_indicator[list(domain_indicator.keys())[1]]["Score"] = expected_reputation threat_response["threat"][0]["threat_level"] = threat_level requests_mock.get( f"{BASE_URL}/tide/api/data/threats?host={success_domain_address}&type=host&rlimit=1", json=threat_response, status_code=200, ) requests_mock.get( f"{BASE_URL}/api/ddi/v1/ipam/host?_filter=name=='{success_domain_address}'&_limit=1", json=address_response, status_code=200, ) params = {"integrationReliability": DBotScoreReliability.B, "create_relationships": True} mocker.patch.object(demisto, "params", return_value=params) command_output = domain_command(blox_client, args={"domain": success_domain_address}) # Verify indicator score assert domain_indicator == command_output[0].indicator.to_context() def test_domain_command_invalid_args(self, blox_client, capfd): capfd.disabled() with pytest.raises(ValueError) as error_msg: domain_command(blox_client, args={"domain": " "}) assert str(error_msg.value) == MESSAGES["REQUIRED_ARGUMENT"].format("domain") class TestListSOCInsights: """Tests for list_soc_insights command.""" @pytest.fixture def return_data(self): """Returns test data for insights.""" response = util_load_json("soc-insights-list.json") return response def test_list_soc_insights_with_no_filters(self, return_data, blox_client, requests_mock): """Test list_soc_insights command with no filters applied.""" # Mock the soc_insights_list API call requests_mock.get(f"{BASE_URL}/api/v1/insights", json=return_data, status_code=200) result = list_soc_insights_command(blox_client, {}) assert result.outputs_prefix == "InfobloxCloud.SOCInsight" assert result.outputs_key_field == "insightId" assert len(result.outputs) == 3 assert result.readable_output == util_load_text_data("soc-insights-list-readable.md") assert result.outputs == return_data.get("insightList") def test_list_soc_insights_with_filters(self, return_data, blox_client, requests_mock): """Test list_soc_insights command with filters applied.""" args = {"status": "OPEN", "priority": "HIGH", "threat_type": "MALWARE"} # Mock the soc_insights_list API call requests_mock.get(f"{BASE_URL}/api/v1/insights", json=return_data, status_code=200) list_soc_insights_command(blox_client, args) # Verify the parameters were passed correctly to the API request = requests_mock.request_history[0] assert request.qs["status"] == ["open"] assert request.qs["priority"] == ["high"] assert request.qs["threat_type"] == ["malware"] def test_list_soc_insights_with_empty_response(self, blox_client, requests_mock): """Test list_soc_insights command with empty response.""" # Mock empty API response requests_mock.get(f"{BASE_URL}/api/v1/insights", json={"insightList": []}, status_code=200) result = list_soc_insights_command(blox_client, {}) assert result.raw_response == [] class TestListSOCInsightIndicators: """Tests for list_soc_insight_indicators_command command.""" @pytest.fixture def indicators_data(self): """Load test data for indicators.""" return util_load_json("insight-indicators-list-command-response.json") def test_list_soc_insight_indicators_command_success(self, indicators_data, blox_client, requests_mock): """Test successful listing of insight indicators.""" requests_mock.get( f"{BASE_URL}/api/v1/insights/insight-123/indicators", json=indicators_data, status_code=200, ) args = {"soc_insight_id": "insight-123"} result = list_soc_insight_indicators_command(blox_client, args) expected_readable = util_load_text_data("insight-indicators-list-command-readable.md") assert result.outputs_prefix == "InfobloxCloud.Indicator" assert result.readable_output == expected_readable def test_list_soc_insight_indicators_command_empty_insight_id(self, blox_client): """Test with empty insight ID.""" args = {"soc_insight_id": ""} with pytest.raises(ValueError) as e: list_soc_insight_indicators_command(blox_client, args) assert str(e.value) == MESSAGES["REQUIRED_ARGUMENT"].format("soc_insight_id") def test_list_soc_insight_indicators_command_with_time_range(self, indicators_data, requests_mock, blox_client): """Test filtering indicators by time range.""" requests_mock.get( f"{BASE_URL}/api/v1/insights/insight-123/indicators", json=indicators_data, status_code=200, ) args = {"soc_insight_id": "insight-123", "start_time": "2025-07-01T00:00:00Z", "end_time": "2025-07-31T23:59:59Z"} list_soc_insight_indicators_command(blox_client, args) request = requests_mock.request_history[0] assert request.qs.get("from") == ["2025-07-01t00:00:00.000"] assert request.qs.get("to") == ["2025-07-31t23:59:59.000"] def test_list_soc_insight_indicators_command_with_invalid_time_range(self, blox_client): """Test filtering indicators by time range.""" args = {"soc_insight_id": "insight-123", "start_time": "invalid-time", "end_time": "invalid-time"} with pytest.raises(ValueError) as e: list_soc_insight_indicators_command(blox_client, args) assert str(e.value) == 'Invalid date: "start_time"="invalid-time"' def test_list_soc_insight_indicators_command_empty_response(self, blox_client, requests_mock): """Test handling of empty response.""" requests_mock.get( f"{BASE_URL}/api/v1/insights/insight-123/indicators", json={"indicators": []}, status_code=200, ) args = {"soc_insight_id": "insight-123"} result = list_soc_insight_indicators_command(blox_client, args) assert result.readable_output == "No indicators found." assert result.raw_response == [] class TestListSOCInsightEvents: """Tests for list_soc_insight_events_command command.""" @pytest.fixture def events_data(self): """Load test data for events.""" return util_load_json("insight-events-list-command-response.json") def test_list_soc_insight_events_command_success(self, events_data, blox_client, requests_mock): """Test successful listing of insight events.""" requests_mock.get( f"{BASE_URL}/api/v1/insights/insight-123/events", json=events_data, status_code=200, ) args = {"soc_insight_id": "insight-123"} result = list_soc_insight_events_command(blox_client, args) expected_readable = util_load_text_data("insight-events-list-command-readable.md") assert result.readable_output == expected_readable assert result.outputs_prefix == "InfobloxCloud.Event" def test_list_soc_insight_events_command_with_device_ip(self, events_data, blox_client, requests_mock): """Test filtering events by device IP.""" requests_mock.get( f"{BASE_URL}/api/v1/insights/insight-123/events", json=events_data, status_code=200, ) args = {"soc_insight_id": "insight-123", "device_ip": "0.0.0.0"} list_soc_insight_events_command(blox_client, args) request = requests_mock.request_history[0] assert request.qs.get("device_ip") == ["0.0.0.0"] def test_list_soc_insight_events_command_invalid_ip(self, blox_client): """Test validation of invalid IP address.""" args = {"soc_insight_id": "insight-123", "device_ip": "invalid-ip"} with pytest.raises(ValueError) as e: list_soc_insight_events_command(blox_client, args) assert str(e.value) == MESSAGES["INVALID_VALUE"].format("invalid-ip", "device_ip") def test_list_soc_insight_events_command_empty_insight_id(self, blox_client): """Test with empty insight ID.""" args = {"soc_insight_id": ""} with pytest.raises(ValueError) as e: list_soc_insight_events_command(blox_client, args) assert str(e.value) == MESSAGES["REQUIRED_ARGUMENT"].format("soc_insight_id") def test_list_soc_insight_events_command_with_time_range(self, events_data, requests_mock, blox_client): """Test filtering events by time range.""" requests_mock.get( f"{BASE_URL}/api/v1/insights/insight-123/events", json=events_data, status_code=200, ) args = {"soc_insight_id": "insight-123", "start_time": "2025-07-01T00:00:00Z", "end_time": "2025-07-31T23:59:59Z"} list_soc_insight_events_command(blox_client, args) request = requests_mock.request_history[0] assert request.qs.get("from") == ["2025-07-01t00:00:00.000"] assert request.qs.get("to") == ["2025-07-31t23:59:59.000"] def test_list_soc_insight_events_command_with_invalid_time_range(self, blox_client): """Test filtering events by time range.""" args = {"soc_insight_id": "insight-123", "start_time": "invalid-time", "end_time": "invalid-time"} with pytest.raises(ValueError) as e: list_soc_insight_events_command(blox_client, args) assert str(e.value) == 'Invalid date: "start_time"="invalid-time"' class TestListSOCInsightAssets: """Tests for list_soc_insight_assets_command command.""" @pytest.fixture def assets_data(self): """Load test data for assets.""" return util_load_json("insight-assets-list-command-response.json") def test_list_soc_insight_assets_command_success(self, assets_data, requests_mock, blox_client): """Test successful listing of insight assets.""" requests_mock.get( f"{BASE_URL}/api/v1/insights/insight-123/assets", json=assets_data, status_code=200, ) args = {"soc_insight_id": "insight-123"} result = list_soc_insight_assets_command(blox_client, args) expected_readable = util_load_text_data("insight-assets-list-command-readable.md") assert result.readable_output == expected_readable assert result.outputs_prefix == "InfobloxCloud.Asset" def test_list_soc_insight_assets_command_empty_insight_id(self, blox_client): """Test with empty insight ID.""" args = {"soc_insight_id": ""} with pytest.raises(ValueError) as e: list_soc_insight_assets_command(blox_client, args) assert str(e.value) == MESSAGES["REQUIRED_ARGUMENT"].format("soc_insight_id") def test_list_soc_insight_assets_command_with_ip_filter(self, assets_data, requests_mock, blox_client): """Test filtering assets by IP address.""" requests_mock.get( f"{BASE_URL}/api/v1/insights/insight-123/assets", json=assets_data, status_code=200, ) args = {"soc_insight_id": "insight-123", "qip": "0.0.0.0"} list_soc_insight_assets_command(blox_client, args) request = requests_mock.request_history[0] assert request.qs.get("qip") == ["0.0.0.0"] def test_list_soc_insight_assets_command_with_mac_filter(self, assets_data, requests_mock, blox_client): """Test filtering assets by MAC address.""" requests_mock.get( f"{BASE_URL}/api/v1/insights/insight-123/assets", json=assets_data, status_code=200, ) args = {"soc_insight_id": "insight-123", "cmac": "00:00:00:00:00:00"} list_soc_insight_assets_command(blox_client, args) request = requests_mock.request_history[0] assert request.qs.get("cmac") == ["00:00:00:00:00:00"] def test_list_soc_insight_assets_command_with_time_range(self, assets_data, requests_mock, blox_client): """Test filtering assets by time range.""" requests_mock.get( f"{BASE_URL}/api/v1/insights/insight-123/assets", json=assets_data, status_code=200, ) args = {"soc_insight_id": "insight-123", "start_time": "2025-07-01T00:00:00Z", "end_time": "2025-07-31T23:59:59Z"} list_soc_insight_assets_command(blox_client, args) request = requests_mock.request_history[0] assert request.qs.get("from") == ["2025-07-01t00:00:00.000"] assert request.qs.get("to") == ["2025-07-31t23:59:59.000"] def test_list_soc_insight_assets_command_with_invalid_time_range(self, blox_client): """Test filtering assets by time range.""" args = {"soc_insight_id": "insight-123", "start_time": "invalid-time", "end_time": "invalid-time"} with pytest.raises(ValueError) as e: list_soc_insight_assets_command(blox_client, args) assert str(e.value) == 'Invalid date: "start_time"="invalid-time"' def test_list_soc_insight_assets_command_empty_response(self, requests_mock, blox_client): """Test handling of empty response.""" requests_mock.get( f"{BASE_URL}/api/v1/insights/insight-123/assets", json={"assets": []}, status_code=200, ) args = {"soc_insight_id": "insight-123"} result = list_soc_insight_assets_command(blox_client, args) assert result.readable_output == "No assets found." assert result.raw_response == [] def test_list_soc_insight_assets_command_invalid_ip(self, blox_client): """Test validation of invalid IP address.""" args = {"soc_insight_id": "insight-123", "qip": "invalid-ip"} with pytest.raises(ValueError) as e: list_soc_insight_assets_command(blox_client, args) assert str(e.value) == MESSAGES["INVALID_VALUE"].format("invalid-ip", "qip") def test_list_soc_insight_assets_command_invalid_mac(self, blox_client): """Test validation of invalid MAC address.""" args = {"soc_insight_id": "insight-123", "cmac": "invalid-mac"} with pytest.raises(ValueError) as e: list_soc_insight_assets_command(blox_client, args) assert str(e.value) == MESSAGES["INVALID_VALUE"].format("invalid-mac", "cmac") class TestListSOCInsightComments: """Tests for list_soc_insight_comments_command command.""" @pytest.fixture def comments_data(self): """Load test data for comments.""" return util_load_json("insight-comments-list-command-response.json") def test_list_soc_insight_comments_command_success(self, comments_data, requests_mock, blox_client): """Test successful listing of insight comments.""" requests_mock.get( f"{BASE_URL}/api/v1/insights/insight-123/comments", json=comments_data, status_code=200, ) args = {"soc_insight_id": "insight-123"} result = list_soc_insight_comments_command(blox_client, args) expected_readable = util_load_text_data("insight-comments-list-command-readable.md") assert result.readable_output == expected_readable assert result.outputs_prefix == "InfobloxCloud.Comment" assert len(result.outputs) == 3 def test_list_soc_insight_comments_command_with_limit(self, comments_data, requests_mock, blox_client): """Test limiting the number of comments returned.""" requests_mock.get( f"{BASE_URL}/api/v1/insights/insight-123/comments", json=comments_data, status_code=200, ) args = {"soc_insight_id": "insight-123", "limit": "2"} result = list_soc_insight_comments_command(blox_client, args) assert len(result.outputs) == 2 def test_list_soc_insight_comments_command_with_invalid_limit(self, blox_client): """Test invalid limit value.""" args = {"soc_insight_id": "insight-123", "limit": "-1"} with pytest.raises(ValueError) as e: list_soc_insight_comments_command(blox_client, args) assert str(e.value) == "Limit should not be less than 0." def test_list_soc_insight_comments_with_time_range(self, comments_data, requests_mock, blox_client): """Test filtering comments by time range.""" requests_mock.get( f"{BASE_URL}/api/v1/insights/insight-123/comments", json=comments_data, status_code=200, ) args = {"soc_insight_id": "insight-123", "start_time": "2025-07-01T00:00:00Z", "end_time": "2025-07-31T23:59:59Z"} list_soc_insight_comments_command(blox_client, args) request = requests_mock.request_history[0] assert request.qs.get("from") == ["2025-07-01t00:00:00.000"] assert request.qs.get("to") == ["2025-07-31t23:59:59.000"] def test_list_soc_insight_comments_command_with_invalid_time_range(self, blox_client): """Test filtering comments by time range.""" args = {"soc_insight_id": "insight-123", "start_time": "invalid-time", "end_time": "invalid-time"} with pytest.raises(ValueError) as e: list_soc_insight_comments_command(blox_client, args) assert str(e.value) == 'Invalid date: "start_time"="invalid-time"' def test_list_soc_insight_comments_command_empty_response(self, requests_mock, blox_client): """Test handling of empty response.""" requests_mock.get( f"{BASE_URL}/api/v1/insights/insight-123/comments", json={"comments": []}, status_code=200, ) args = {"soc_insight_id": "insight-123"} result = list_soc_insight_comments_command(blox_client, args) assert result.readable_output == "No comments found." assert result.raw_response == [] def test_list_soc_insight_comments_command_empty_insight_id(self, blox_client): """Test with empty insight ID.""" args = {"soc_insight_id": ""} with pytest.raises(ValueError) as e: list_soc_insight_comments_command(blox_client, args) assert str(e.value) == MESSAGES["REQUIRED_ARGUMENT"].format("soc_insight_id")