EclecticIQ Platform Deprecated
Deprecated. No available replacement.
Data Enrichment & Threat Intelligence · EclecticIQ Platform
Details
| ID | EclecticIQ Platform |
|---|---|
| Provider | EclecticIQ |
| Category | Data Enrichment & Threat Intelligence |
| From Version | 5.0.0 |
| Docker Image | demisto/python3:3.10.7.33922 |
| Supported Modules | Agentix XSIAM |
README
Deprecated. No available replacement.
Use Cases
- Get reputation of IOCs (observables).
- Get observables’ related entities.
Configure EclecticIQ Platform on Cortex XSOAR
- Navigate to Settings > Integrations > Servers & Services.
- Search for integration-EclecticIQ_Platform.
- Click Add instance to create and configure a new integration instance.
- Name: a textual name for the integration instance.
- Server URL (e.g. https://192.168.0.1)
- Username
- Trust any certificate (not secure)
- Use system proxy
- IP threshold. Minimum maliciousness confidence level to consider the IP address malicious: High, Medium, Low, Safe, Unknown
- URL threshold. Minimum maliciousness confidence level to consider the URL malicious: High, Medium, Low, Safe, Unknown
- File threshold. Minimum maliciousness confidence level to consider the file malicious: High, Medium, Low, Safe, Unknown
- Email threshold. Minimum maliciousness confidence level to consider the email address malicious: High, Medium, Low, Safe, Unknown
- Domain threshold. Minimum maliciousness confidence level to consider the domain malicious: High, Medium, Low, Safe, Unknown
- Click Test to validate the URLs, token, and connection.
Commands
You can execute these commands from the Cortex XSOAR 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.
- Get the reputation of an IP address observable: ip
- Get the reputation of a URL observable: url
- Get the reputation of a file observable: file
- Get related entities of an observable: eclecticiq-get-observable-related-entity
- Get the reputation of an email observable: email
- Get the reputation of a domain observable: domain
1. Get the reputation of an IP address observable
Gets the reputation of an IP address observable.
Base Command
ip
Input
| Argument Name | Description | Required |
|---|---|---|
| ip | IPv4 to get the reputation of | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| EclecticIQ.IP.Address | String | IP address that was tested |
| EclecticIQ.IP.Created | Date | Observable creation date |
| EclecticIQ.IP.LastUpdate | Date | Observable last updated date |
| EclecticIQ.IP.ID | Number | Observable ID |
| EclecticIQ.IP.Maliciousness | String | Maliciousness confidence level |
| IP.Address | String | IP address that was tested |
| IP.Malcious.Vendor | String | For malicious IPs, the vendor that made the decision |
| IP.Malcious.Description | String | For malicious IPs, the reason that the vendor made the decision |
| DBotScore.Type | String | Indicator type |
| DBotScore.Vendor | String | Vendor used to calculate the score |
| DBotScore.Score | Number | The actual score |
| DBotScore.Indicator | String | The indicator that was tested |
Command Example
ip ip=8.8.8.8
Context Example
{
"IP": [
{
"Address": "8.8.8.8"
}
],
"DBotScore": {
"Vendor": "EclecticIQ",
"Indicator": "8.8.8.8",
"Score": 1,
"Type": "ip"
},
"EclecticIQ.IP": [
{
"Maliciousness": "safe",
"Created": "2019-01-16T11:55:11.732145+00:00",
"ID": 86,
"LastUpdated": "2019-01-16T11:55:11.708640+00:00",
"Address": "8.8.8.8"
}
]
}
Human Readable Output
EclecticIQ IP reputation - 8.8.8.8
| Maliciousness | Created | ID | LastUpdated | Address |
|---|---|---|---|---|
| safe | 2019-01-16T11:55:11.732145+00:00 | 86 | 2019-01-16T11:55:11.708640+00:00 | 8.8.8.8 |
2. Get the reputation of a URL observable
Gets the reputation of a URL observable.
Notice: Submitting indicators using this command might make the indicator data publicly available. See the vendor’s documentation for more details.
Base Command
url
Input
| Argument Name | Description | Required |
|---|---|---|
| url | URL observable to get the reputation of | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| EclecticIQ.URL.Data | String | URL that was tested |
| EclecticIQ.URL.Created | Date | Observable creation date |
| EclecticIQ.URL.LastUpdate | Date | Observable last updated date |
| EclecticIQ.URL.ID | Number | Observable ID |
| EclecticIQ.URL.Maliciousness | String | Maliciousness confidence level |
| URL.Data | String | URL that was tested |
| URL.Malcious.Vendor | String | For malicious URLs, the vendor that made the decision |
| URL.Malcious.Description | String | For malicious URLs, the reason that the vendor made the decision |
| DBotScore.Type | String | Indicator type |
| DBotScore.Vendor | String | Vendor used to calculate the score |
| DBotScore.Score | Number | The actual score |
| DBotScore.Indicator | String | The indicator that was tested |
Command Example
url url=http://chstarkeco.com
Context Example
{
"DBotScore": {
"Vendor": "OpenPhish",
"Indicator": "http://chstarkeco.com",
"Score": 0,
"Type": "url"
}
}{
"URL": {
"Data": "http://chstarkeco.com"
},
"DBotScore": {
"Vendor": "PhishTank",
"Indicator": "http://chstarkeco.com",
"Score": 0,
"Type": "url"
}
}{
"URL": [
{
"Data": "http://chstarkeco.com"
}
],
"DBotScore": {
"Vendor": "EclecticIQ",
"Indicator": "http://chstarkeco.com",
"Score": 2,
"Type": "url"
},
"EclecticIQ.URL": [
{
"Maliciousness": "medium",
"Data": "http://chstarkeco.com",
"ID": 83,
"LastUpdated": "2019-01-16T11:53:51.128167+00:00",
"Created": "2019-01-16T11:52:49.993110+00:00"
}
]
}
Human Readable Output
OpenPhish Database - URL Query
No matches for URL http://chstarkeco.com
PhishTank Database - URL Query
No matches for URL http://chstarkeco.com
EclecticIQ URL reputation - http://chstarkeco.com
| Maliciousness | Data | ID | LastUpdated | Created |
|---|---|---|---|---|
| medium | http://chstarkeco.com | 83 | 2019-01-16T11:53:51.128167+00:00 | 2019-01-16T11:52:49.993110+00:00 |
3. Get the reputation of a file observable
Gets the reputation of a file hash observable.
Base Command
file
Input
| Argument Name | Description | Required |
|---|---|---|
| file | File hash observable to get the reputation of | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| EclecticIQ.File.MD5 | String | File MD5 hash that was tested |
| EclecticIQ.File.SHA1 | String | File SHA-1 hash that was tested |
| EclecticIQ.File.SHA256 | String | File SHA-256 hash that was tested |
| EclecticIQ.File.SHA512 | String | File SHA-512 hash that was tested |
| EclecticIQ.File.Created | Date | Observable creation date |
| EclecticIQ.File.LastUpdate | Date | Observable last updated date |
| EclecticIQ.File.ID | Number | Observable ID |
| EclecticIQ.File.Maliciousness | String | Maliciousness confidence level |
| File.MD5 | String | File MD5 hash that was tested |
| File.SHA1 | String | File SHA-1 hash that was tested |
| File.SHA256 | String | File SHA-256 hash that was tested |
| File.SHA512 | String | File SHA-512 hash that was tested |
| File.Malcious.Vendor | String | For malicious files, the vendor that made the decision |
| File.Malcious.Description | String | For malicious files, the reason that the vendor made the decision |
| DBotScore.Type | String | Indicator type |
| DBotScore.Vendor | String | Vendor used to calculate the score |
| DBotScore.Score | Number | The actual score |
| DBotScore.Indicator | String | The indicator that was tested |
Command Example
file file=00112233445566778899aabbccddeeff
4. Get related entities of an observable
Returns related entities of a single observable.
Base Command
eclecticiq-get-observable-related-entity
Input
| Argument Name | Description | Required |
|---|---|---|
| observable_id | Observable ID to get entity information for (can be retrieved from one of the IOCs commands) | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| EclecticIQ.Entity.Analysis | String | Entity analysis description |
| EclecticIQ.Entity.EstimatedObservedTime | Date | Entity estimated observed time |
| EclecticIQ.Entity.EstimatedStartTime | Date | Entity estimated start time |
| EclecticIQ.Entity.Exposure.Community | Boolean | Is entity in the community feed |
| EclecticIQ.Entity.Exposure.Detection | Boolean | Is entity detected |
| EclecticIQ.Entity.Exposure.Exposed | Boolean | Is entity exposed |
| EclecticIQ.Entity.Exposure.Prevention | Boolean | Is entity in prevented feed |
| EclecticIQ.Entity.Exposure.Sighting | Boolean | Is entity sighted |
| EclecticIQ.Entity.HalfLife | String | The time it takes an entity to decay in intelligence value, expressed in the number of days until a 50% decay |
| EclecticIQ.Entity.ID | String | Entity ID |
| EclecticIQ.Entity.Source.Name | String | Entity source name |
| EclecticIQ.Entity.Source.Reliability | String | Entity source reliability |
| EclecticIQ.Entity.Title | String | Entity title |
| EclecticIQ.Entity.Source.Type | string | Entity source type |
Command Example
eclecticiq-get-observable-related-entity observable_id=63
Context Example
{
"EclecticIQ.Entity": [
{
"HalfLife": "30 Days",
"Title": "Indicator containing malicious file hashes",
"EstimatedObservedTime": "2018-11-21T13:34:35.890076+00:00",
"Analysis": "Indicator that contains malicious file hashes.",
"Source": [
{
"Reliability": null,
"Type": "incoming_feed",
"Name": "TAXII Stand Samples"
}
],
"EstimatedStartTime": "2014-05-08T09:00:00+00:00",
"ID": "56e218b0-3f6b-4237-beca-3b39ab8e96c2",
"Exposure": {
"Detection": false,
"Sighting": false,
"Prevention": false,
"Community": false,
"Exposed": true
}
}
]
}
Human Readable Output
Observable ID 63 related entities
| HalfLife | Title | EstimatedObservedTime | Analysis | EstimatedStartTime | ID |
|---|---|---|---|---|---|
| 30 Days | Indicator containing malicious file hashes | 2018-11-21T13:34:35.890076+00:00 | Indicator that contains malicious file hashes. | 2014-05-08T09:00:00+00:00 | 56e218b0-3f6b-4237-beca-3b39ab8e96c2 |
Sources
| Type | Name |
|---|---|
| incoming_feed | TAXII Stand Samples |
Exposure
| Detection | Sighting | Community | Prevention | Exposed |
|---|---|---|---|---|
| false | false | false | false | true |
5. Get the reputation of an email observable: email
Gets the reputation of an email address observable.
Base Command
email
Input
| Argument Name | Description | Required |
|---|---|---|
| Email address observable to get the reputation of | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| EclecticIQ.Email.Address | String | Email that was tested |
| EclecticIQ.Email.Created | Date | Observable creation date |
| EclecticIQ.Email.LastUpdate | Date | Observable last updated date |
| EclecticIQ.Email.ID | Number | Observable ID |
| EclecticIQ.Email.Maliciousness | String | Maliciousness confidence level |
| Account.Email.Address | String | Email that was tested |
| Account.Email.Malcious.Vendor | String | For malicious email addresses, the vendor that made the decision |
| Account.Email.Malcious.Description | String | For malicious email addresses, the reason that the vendor made the decision |
| DBotScore.Type | String | Indicator type |
| DBotScore.Vendor | String | Vendor used to calculate the score |
| DBotScore.Score | Number | The actual score |
| DBotScore.Indicator | String | The indicator that was tested |
Command Example
email email=disco-team@stealthemail.com
Context Example
{
"EclecticIQ.Email": [
{
"Maliciousness": "unknown",
"Created": "2018-11-21T13:34:31.126027+00:00",
"ID": 42,
"LastUpdated": "2018-11-21T13:34:31.126027+00:00",
"Address": "disco-team@stealthemail.com"
},
{
"Maliciousness": "unknown",
"Created": "2018-11-21T13:34:31.134425+00:00",
"ID": 43,
"LastUpdated": "2018-11-21T13:34:31.134425+00:00",
"Address": "disco-team@stealthemail.com"
}
],
"DBotScore": {
"Vendor": "EclecticIQ",
"Indicator": "disco-team@stealthemail.com",
"Score": 0,
"Type": "email"
},
"Account.Email": [
{
"Address": "disco-team@stealthemail.com"
},
{
"Address": "disco-team@stealthemail.com"
}
]
}
Human Readable Output
EclecticIQ Email reputation - disco-team@stealthemail.com
| Maliciousness | Created | ID | LastUpdated | Address |
|---|---|---|---|---|
| unknown | 2018-11-21T13:34:31.126027+00:00 | 42 | 2018-11-21T13:34:31.126027+00:00 | disco-team@stealthemail.com |
| unknown | 2018-11-21T13:34:31.134425+00:00 | 43 | 2018-11-21T13:34:31.134425+00:00 | disco-team@stealthemail.com |
6. Get the reputation of a domain observable
Gets the reputation of a domain observable.
Notice: Submitting indicators using this command might make the indicator data publicly available. See the vendor’s documentation for more details.
Base Command
domain
Input
| Argument Name | Description | Required |
|---|---|---|
| domain | Domain observable to get the reputation of | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| EclecticIQ.Domain.Name | String | Domain name that was tested |
| EclecticIQ.Domain.Created | Date | Observable creation date |
| EclecticIQ.Domain.LastUpdate | Date | Observable last updated date |
| EclecticIQ.Domain.ID | Number | Observable ID |
| EclecticIQ.Domain.Maliciousness | String | Maliciousness confidence level |
| Domain.Name | String | Domain name that was tested |
| Domain.Malcious.Vendor | String | For malicious domains, the vendor that made the decision |
| Domain.Malcious.Description | String | For malicious domains, the reason that the vendor made the decision |
| DBotScore.Type | String | Indicator type |
| DBotScore.Vendor | String | Vendor used to calculate the score |
| DBotScore.Score | Number | The actual score |
| DBotScore.Indicator | String | The indicator that was tested |
Command Example
domain domain=gooc.om
Context Example
{
"Domain": [
{
"Name": "gooc.om"
}
],
"DBotScore": {
"Vendor": "EclecticIQ",
"Indicator": "gooc.om",
"Score": 0,
"Type": "domain"
},
"EclecticIQ.Domain": [
{
"Maliciousness": "unknown",
"Name": "gooc.om",
"ID": 74,
"LastUpdated": "2018-11-21T13:34:38.964435+00:00",
"Created": "2018-11-21T13:34:38.964435+00:00"
}
]
}
Human Readable Output
EclecticIQ Domain reputation - gooc.om
| ID | Maliciousness | Name | LastUpdated | Created |
|---|---|---|---|---|
| 74 | unknown | gooc.om | 2018-11-21T13:34:38.964435+00:00 | 2018-11-21T13:34:38.964435+00:00 |
Configuration parameters
url— Server URL (e.g. https://192.168.0.1) (required)credentials— Username (required)insecure— Trust any certificate (not secure)proxy— Use system proxy settingsip_threshold— IP threshold. Minimum maliciousness confidence level to consider the IP address malicious: High, Medium, Low, Safe, Unknownurl_threshold— URL threshold. Minimum maliciousness confidence level to consider the URL malicious: High, Medium, Low, Safe, Unknownfile_threshold— File threshold. Minimum maliciousness confidence level to consider the file malicious: High, Medium, Low, Safe, Unknownemail_threshold— Email threshold. Minimum maliciousness confidence level to consider the email address malicious: High, Medium, Low, Safe, Unknowndomain_threshold— Domain threshold. Minimum maliciousness confidence level to consider the domain malicious: High, Medium, Low, Safe, UnknownintegrationReliability— Source ReliabilityfeedExpirationPolicy—feedExpirationInterval—
Commands (6)
-
domainGets the reputation of a domain observable.
-
eclecticiq-get-observable-related-entityReturns related entities of a single observable.
-
emailGets the reputation of an email address observable.
-
fileGets the reputation of a file hash observable.
-
ipGet reputation of IP address observable
-
urlGets the reputation of a URL observable.
import demistomock as demisto # noqa: F401 from CommonServerPython import * # noqa: F401 ''' IMPORTS ''' from typing import Literal from CommonServerUserPython import * import json import requests import urllib3 # Disable insecure warnings urllib3.disable_warnings() ''' GLOBALS/PARAMS ''' USERNAME = demisto.params().get('credentials', {}).get('identifier') PASSWORD = demisto.params().get('credentials', {}).get('password') URL = demisto.params().get('url', '') SERVER = URL[:-1] if (URL and URL.endswith('/')) else URL USE_SSL = not demisto.params().get('insecure', False) HEADERS = {} # type: Dict[str, str] IP_THRESHOLD = demisto.params().get('ip_threshold', '').lower() URL_THRESHOLD = demisto.params().get('url_threshold', '').lower() FILE_THRESHOLD = demisto.params().get('file_threshold', '').lower() EMAIL_THRESHOLD = demisto.params().get('email_threshold', '').lower() DOMAIN_THRESHOLD = demisto.params().get('domain_threshold', '').lower() MALICOUS_LVL = Literal['unknown', 'safe', 'low', 'medium', 'high'] MALICIOUSNESS = { 'unknown': 0, 'safe': 1, 'low': 2, 'medium': 2, 'high': 3 } PROXIES = handle_proxy() ''' HELPER FUNCTIONS ''' def http_request(method, url_suffix, headers=HEADERS, cmd_json=None): # pragma: no cover res = requests.request( method, SERVER + url_suffix, headers=headers, json=cmd_json, proxies=PROXIES, verify=USE_SSL ) if res.status_code not in {200}: if res.status_code == 405: return_error( 'Error in API call to EclecticIQ Integration: [405] - Not Allowed - Might occur cause of an invalid ' 'URL. ' ) try: # Parse the error message errors = json.loads(res.text).get('errors', {})[0] title = errors.get('title', '') detail = errors.get('detail', '') return_error( f'Error in API call to EclecticIQ Integration: [{res.status_code}] - {title} - {detail}' ) except Exception: # In case error message is not in expected format return_error(res.content) try: # Verify we can generate json from the response return res.json() except ValueError: return_error(res) def maliciousness_to_dbotscore(maliciousness: MALICOUS_LVL, threshold: MALICOUS_LVL) -> int: """ Translates EclecticIQ obversable maliciousness confidence level to DBotScore based on given threshold Parameters ---------- maliciousness : str EclecticIQ obversable maliciousness confidence level. threshold : str Minimum maliciousness confidence level to consider the IOC malicious. Returns ------- number Translated DBot Score """ if maliciousness not in MALICIOUSNESS: raise ValueError(f'{maliciousness=} whereas acceptable values are only {MALICIOUSNESS.keys()}') if threshold not in MALICIOUSNESS: raise ValueError(f'{threshold=} whereas acceptable values are only {MALICIOUSNESS.keys()}') if MALICIOUSNESS.get(maliciousness) >= MALICIOUSNESS.get(threshold): # type: ignore return MALICIOUSNESS.get('high') # type: ignore return MALICIOUSNESS.get(maliciousness) # type: ignore ''' COMMANDS + REQUESTS FUNCTIONS ''' def test_module(): # pragma: no cover """ The function which runs when clicking on Test in integration settings Returns ------- str ok if getting observable successfully """ get_observable('8.8.8.8') demisto.results('ok') def login(): # pragma: no cover """ Logins to EclecticIQ API with given credentials and sets the returned token in the headers """ cmd_url = '/api/auth' cmd_json = { 'password': PASSWORD, 'username': USERNAME } response = http_request('POST', cmd_url, cmd_json=cmd_json) if 'token' in response: token = response['token'] else: return_error('Failed to retrieve token') HEADERS['Authorization'] = f'Bearer {token}' def ip_command(): # pragma: no cover """ Gets reputation of an EclecticIQ IPv4 observable Parameters ---------- ip : str IPv4 to get reputation of Returns ------- entry Reputation of given IPv4 """ ip = demisto.args()['ip'] response = get_observable(ip) if 'total_count' in response and response['total_count'] == 0: human_readable = 'No results found' integration_outputs = [] standard_ip_outputs = [] observables = response.get('data') score = 0 for observable in observables: meta = observable.get('meta', {}) maliciousness = meta.get('maliciousness') score = maliciousness_to_dbotscore(maliciousness, IP_THRESHOLD) integration_outputs.append({ 'Address': ip, 'Created': observable.get('created_at'), 'LastUpdated': observable.get('last_updated_at'), 'ID': observable.get('id'), 'Maliciousness': maliciousness }) standard_ip_output = { 'Address': ip } if score == 3: standard_ip_output['Malicious'] = { 'Vendor': 'EclectiqIQ', 'Description': 'EclectiqIQ maliciousness confidence level: ' + maliciousness } standard_ip_outputs.append(standard_ip_output) dbot_output = { 'Type': 'ip', 'Indicator': ip, 'Vendor': 'EclecticIQ', 'Score': score } context = { 'DBotScore': dbot_output } # type: dict if observables: human_readable_title = f'EclecticIQ IP reputation - {ip}' human_readable = tableToMarkdown(human_readable_title, integration_outputs) context['EclecticIQ.IP'] = createContext(data=integration_outputs, id='ID', removeNull=True) context[outputPaths['ip']] = standard_ip_outputs demisto.results({ 'Type': entryTypes['note'], 'Contents': response, 'ContentsFormat': formats['json'], 'ReadableContentsFormat': formats['markdown'], 'HumanReadable': human_readable, 'EntryContext': context }) def url_command(): # pragma: no cover """ Gets reputation of an EclecticIQ URI observable Parameters ---------- url : str URL to get reputation of Returns ------- entry Reputation of given URL """ url = demisto.args()['url'] response = get_observable(url) if 'total_count' in response and response['total_count'] == 0: human_readable = 'No results found.' integration_outputs = [] standard_url_outputs = [] observables = response.get('data') score = 0 for observable in observables: meta = observable.get('meta', {}) maliciousness = meta.get('maliciousness') score = maliciousness_to_dbotscore(maliciousness, URL_THRESHOLD) integration_outputs.append({ 'Data': url, 'Created': observable.get('created_at'), 'LastUpdated': observable.get('last_updated_at'), 'ID': observable.get('id'), 'Maliciousness': maliciousness }) standard_url_output = { 'Data': url } if score == 3: standard_url_output['Malicious'] = { 'Vendor': 'EclectiqIQ', 'Description': 'EclectiqIQ maliciousness confidence level: ' + maliciousness } standard_url_outputs.append(standard_url_output) dbot_output = { 'Type': 'url', 'Indicator': url, 'Vendor': 'EclecticIQ', 'Score': score, 'Reliability': demisto.params().get('integrationReliability') } context = { 'DBotScore': dbot_output } # type: dict if observables: human_readable_title = f'EclecticIQ URL reputation - {url}' human_readable = tableToMarkdown(human_readable_title, integration_outputs) context['EclecticIQ.URL'] = createContext(data=integration_outputs, id='ID', removeNull=True) context[outputPaths['url']] = standard_url_outputs demisto.results({ 'Type': entryTypes['note'], 'Contents': response, 'ContentsFormat': formats['json'], 'ReadableContentsFormat': formats['markdown'], 'HumanReadable': human_readable, 'EntryContext': context }) def file_command(): # pragma: no cover """ Gets reputation of an EclecticIQ hash observable Parameters ---------- file : str File hash to get reputation of Returns ------- entry Reputation of given file hash """ file = demisto.args()['file'] hash_type = get_hash_type(file).upper() response = get_observable(file) if 'total_count' in response and response['total_count'] == 0: human_readable = 'No results found.' integration_outputs = [] standard_file_outputs = [] observables = response.get('data') score = 0 for observable in observables: meta = observable.get('meta', {}) maliciousness = meta.get('maliciousness') score = maliciousness_to_dbotscore(maliciousness, FILE_THRESHOLD) integration_outputs.append({ hash_type: file, 'Created': observable.get('created_at'), 'LastUpdated': observable.get('last_updated_at'), 'ID': observable.get('id'), 'Maliciousness': maliciousness }) standard_file_output = { hash_type: file } if score == 3: standard_file_output['Malicious'] = { 'Vendor': 'EclectiqIQ', 'Description': 'EclectiqIQ maliciousness confidence level: ' + maliciousness } standard_file_outputs.append(standard_file_output) dbot_output = { 'Type': 'file', 'Indicator': file, 'Vendor': 'EclecticIQ', 'Score': score, 'Reliability': demisto.params().get('integrationReliability') } context = { 'DBotScore': dbot_output } # type: dict if observables: human_readable_title = f'EclecticIQ File reputation - {file}' human_readable = tableToMarkdown(human_readable_title, integration_outputs) context['EclecticIQ.File'] = createContext(data=integration_outputs, id='ID', removeNull=True) context[outputPaths['file']] = standard_file_outputs demisto.results({ 'Type': entryTypes['note'], 'Contents': response, 'ContentsFormat': formats['json'], 'ReadableContentsFormat': formats['markdown'], 'HumanReadable': human_readable, 'EntryContext': context }) def email_command(): # pragma: no cover """ Gets reputation of an EclecticIQ email address observable Parameters ---------- email : str Email address to get reputation of Returns ------- entry Reputation of given email address """ email = demisto.args()['email'] response = get_observable(email) if 'total_count' in response and response['total_count'] == 0: human_readable = 'No results found.' integration_outputs = [] standard_email_outputs = [] observables = response.get('data') score = 0 for observable in observables: meta = observable.get('meta', {}) maliciousness = meta.get('maliciousness') score = maliciousness_to_dbotscore(maliciousness, EMAIL_THRESHOLD) integration_outputs.append({ 'Address': email, 'Created': observable.get('created_at'), 'LastUpdated': observable.get('last_updated_at'), 'ID': observable.get('id'), 'Maliciousness': maliciousness }) standard_email_output = { 'Address': email } if score == 3: standard_email_output['Malicious'] = { 'Vendor': 'EclectiqIQ', 'Description': 'EclectiqIQ maliciousness confidence level: ' + maliciousness } standard_email_outputs.append(standard_email_output) dbot_output = { 'Type': 'email', 'Indicator': email, 'Vendor': 'EclecticIQ', 'Score': score, 'Reliability': demisto.params().get('integrationReliability') } context = { 'DBotScore': dbot_output } # type: dict if observables: human_readable_title = f'EclecticIQ Email reputation - {email}' human_readable = tableToMarkdown(human_readable_title, integration_outputs) context['EclecticIQ.Email'] = createContext(data=integration_outputs, id='ID', removeNull=True) context[outputPaths['email']] = standard_email_outputs demisto.results({ 'Type': entryTypes['note'], 'Contents': response, 'ContentsFormat': formats['json'], 'ReadableContentsFormat': formats['markdown'], 'HumanReadable': human_readable, 'EntryContext': context }) def domain_command(): # pragma: no cover """ Gets reputation of an EclecticIQ domain observable Parameters ---------- domain : str Domain address to get reputation of Returns ------- entry Reputation of given domain address """ domain = demisto.args()['domain'] response = get_observable(domain) if 'total_count' in response and response['total_count'] == 0: human_readable = 'No results found.' integration_outputs = [] standard_domain_outputs = [] observables = response.get('data') score = 0 for observable in observables: meta = observable.get('meta', {}) maliciousness = meta.get('maliciousness') score = maliciousness_to_dbotscore(maliciousness, DOMAIN_THRESHOLD) integration_outputs.append({ 'Name': domain, 'Created': observable.get('created_at'), 'LastUpdated': observable.get('last_updated_at'), 'ID': observable.get('id'), 'Maliciousness': maliciousness }) standard_email_output = { 'Name': domain } if score == 3: standard_email_output['Malicious'] = { 'Vendor': 'EclectiqIQ', 'Description': 'EclectiqIQ maliciousness confidence level: ' + maliciousness } standard_domain_outputs.append(standard_email_output) dbot_output = { 'Type': 'domain', 'Indicator': domain, 'Vendor': 'EclecticIQ', 'Score': score, 'Reliability': demisto.params().get('integrationReliability') } context = { 'DBotScore': dbot_output } # type: dict if observables: human_readable_title = f'EclecticIQ Domain reputation - {domain}' human_readable = tableToMarkdown(human_readable_title, integration_outputs) context['EclecticIQ.Domain'] = createContext(data=integration_outputs, id='ID', removeNull=True) context[outputPaths['domain']] = standard_domain_outputs demisto.results({ 'Type': entryTypes['note'], 'Contents': response, 'ContentsFormat': formats['json'], 'ReadableContentsFormat': formats['markdown'], 'HumanReadable': human_readable, 'EntryContext': context }) def get_observable(ioc): # pragma: no cover """ Send API query to EclecticIQ to get reputation of an observable Parameters ---------- ioc : str IOC to get reputation of Returns ------- response Python requests response object """ cmd_url = f'/api/observables?filter[value]={ioc}' response = http_request('GET', cmd_url) return response def get_observable_related_entity_command(): # pragma: no cover """ Get EclecticIQ related entities to an observable Parameters ---------- observable_id : str EclecticIQ observable ID to get related entites of Returns ------- entry Observable related entities data """ observable_id = demisto.args()['observable_id'] processed_extract_response = processed_extract(observable_id) original_extract_response = original_extract(observable_id) response = dict(processed_extract_response) response['data'].extend(original_extract_response['data']) response['total_count'] += original_extract_response['total_count'] if 'total_count' in response and response['total_count'] == 0: demisto.results('No results found') return context_outputs = [] human_readable = '' entities = response.get('data') for entity in entities: # type: ignore entity_data = entity.get('data', {}) test_mechanisms = entity_data.get('test_mechanisms', {}) entity_meta = entity.get('meta', {}) context_output = { 'Title': entity_data.get('title'), 'ID': entity.get('id'), 'Analysis': entity_data.get('description'), 'EstimatedStartTime': entity_meta.get('estimated_threat_start_time'), 'EstimatedObservedTime': entity_meta.get('estimated_observed_time'), 'HalfLife': entity_meta.get('half_life') } if context_output['Analysis']: # Removing unnecessary whitespaces from the string context_output['Analysis'] = ' '.join(context_output['Analysis'].split()) if context_output['HalfLife']: # API returns a number, we add the time format to it context_output['HalfLife'] = str(context_output['HalfLife']) + ' Days' human_readable += tableToMarkdown(f'Observable ID {observable_id} related entities', context_output) test_mechanisms_output = [] for mechanism in test_mechanisms: mechanism_output = { 'Type': mechanism.get('test_mechanism_type') } mechanism_rules = mechanism.get('rules') mechanism_rules_outputs = [] for rule in mechanism_rules: mechanism_rules_outputs.append(rule.get('value')) mechanism_output['Rule'] = mechanism_rules_outputs test_mechanisms_output.append(mechanism_output) if test_mechanisms_output: context_output['TestMechanism'] = test_mechanisms_output human_readable += tableToMarkdown('Test mechanisms', test_mechanisms_output, removeNull=True) sources = entity.get('sources') sources_output = [] for source in sources: sources_output.append({ 'Name': source.get('name'), 'Type': source.get('source_type'), 'Reliability': source.get('source_reliability') }) if sources_output: context_output['Source'] = sources_output human_readable += tableToMarkdown('Sources', sources_output, removeNull=True) exposure = entity.get('exposure') exposure_output = { 'Exposed': True if exposure.get('exposed') is True else False, 'Detection': True if exposure.get('detect_feed') is True else False, 'Prevention': True if exposure.get('prevent_feed') is True else False, 'Community': True if exposure.get('community_feed') is True else False, 'Sighting': True if exposure.get('sighted') is True else False } context_output['Exposure'] = exposure_output human_readable += tableToMarkdown('Exposure', exposure_output, removeNull=True) context_outputs.append(context_output) context = { 'EclecticIQ.Entity': createContext(data=context_outputs, id='ID', removeNull=True) } demisto.results({ 'Type': entryTypes['note'], 'Contents': response, 'ContentsFormat': formats['json'], 'ReadableContentsFormat': formats['markdown'], 'HumanReadable': human_readable, 'EntryContext': context }) def processed_extract(observable_id): # pragma: no cover """ Send API query to EclecticIQ to get extracted processed data of an observable Parameters ---------- observable_id : str EclecticIQ observable ID to get extracted processed data of of Returns ------- response Python requests response object """ cmd_url = f'/private/entities/processed-extract/{observable_id}' response = http_request('GET', cmd_url) return response def original_extract(observable_id): # pragma: no cover """ Send API query to EclecticIQ to get extracted orginial data of an observable Parameters ---------- observable_id : str EclecticIQ observable ID to get extracted orginial data of of Returns ------- response Python requests response object """ cmd_url = f'/private/entities/original-extract/{observable_id}' response = http_request('GET', cmd_url) return response ''' COMMANDS MANAGER / SWITCH PANEL ''' COMMANDS = { 'test-module': test_module, 'url': url_command, 'ip': ip_command, 'email': email_command, 'file': file_command, 'domain': domain_command, 'eclecticiq-get-observable-related-entity': get_observable_related_entity_command } def main(): # pragma: no cover try: LOG(f'Command being called is {demisto.command()}') login() command_func = COMMANDS.get(demisto.command()) if command_func is not None: command_func() except Exception as e: return_error(f'Error has occurred in EclecticIQ integration: {type(e)}\n {e}') if __name__ in ('__main__', '__builtin__', 'builtins'): # pragma: no cover main()