Picus
Run commands on Picus and automate security validation with playbooks.
Network Security · PicusAutomation (Deprecated)
Details
| ID | Picus |
|---|---|
| Provider | Picus Security |
| Category | Network Security |
| From Version | 6.0.0 |
| Docker Image | demisto/python3:3.12.8.3296088 |
| Supported Modules | Agentix XSIAM |
README
Run commands on Picus and automate security validation with playbooks.
This integration was integrated and tested with version 3976 of Picus
Configure Picus in Cortex

| Parameter | Description | Required |
|---|---|---|
| Picus Manager URL | True | |
| Picus Refresh Token | The refresh token will be used to generate access token. | True |
| 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.
picus-get-access-token
Generates an access token for API usage. This function used for other functions inner authentication mechanism. Looks for X-Refresh-Token on the header or refresh-token cookie.
Base Command
picus-get-access-token
Input
There are no input arguments for this command.
Context Output
There is no context output for this command.
picus-get-vector-list
Returns the vector list from PICUS. These vectors can be used for automation processes.
Base Command
picus-get-vector-list
Input
| Argument Name | Description | Required |
|---|---|---|
| add_user_details | Add vectors’ assigned user details to the response. | Optional |
| page | Requested page number. | Optional |
| size | Requested data size. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Picus.vectorlist.description | String | Description info of the vector |
| Picus.vectorlist.heartbeat_results.is_successful | Boolean | Was the heartbeat end successfully? |
| Picus.vectorlist.heartbeat_results.module | String | On which module did the heartbeat executed? |
| Picus.vectorlist.heartbeat_results.result_time | Date | When the heartbeat is executed? (End time) |
| Picus.vectorlist.heartbeat_results.variant | String | On which variant did the heartbeat executed? |
| Picus.vectorlist.is_disabled | Boolean | Is the vector status disabled? |
| Picus.vectorlist.name | String | Name of the vector |
| Picus.vectorlist.trusted | String | Trusted peer name |
| Picus.vectorlist.type | String | Type of the vector, if error is encountered, “Unknown” is returned. Other valid values are: “Network”, “Email, “Endpoint” |
| Picus.vectorlist.untrusted | String | Untrusted peer name |
| Picus.vectorlist.users | Unknown | Users assigned to this vector |
Command Example
!picus-get-vector-list
Human Readable Output
| Name | Trusted | Untrusted | Is Disabled | Type |
|---|---|---|---|---|
| Picus_Attacker_1 - Win10-Det1 | Win10-Det1 | Picus_Attacker_1 | true | Endpoint |
| Picus_Attacker_2 - Win10-Det2 | Win10-Det2 | Picus_Attacker_2 | true | Endpoint |
picus-get-peer-list
Returns the peer list with current statuses. These peers also can be seen on the PICUS Panel ->Settings-> Peers.

Base Command
picus-get-peer-list
Input
There are no input arguments for this command.
Context Output
| Path | Type | Description |
|---|---|---|
| Picus.peerlist.is_alive | Boolean | Is Peer Alive? |
| Picus.peerlist.latest_attack | Date | Latest Attack Time of the Peer |
| Picus.peerlist.name | String | Peer Name |
| Picus.peerlist.registered_ip | String | IP of the peer |
| Picus.peerlist.type | String | Peer’s Type |
Command Example
!picus-get-peer-list
Human Readable Output
| Name | Registered Ip | Type | Is Alive |
|---|---|---|---|
| Picus_Attacker_1 | x.x.x.x | Network | true |
| Picus_Attacker_2 | x.x.x.x | Network | true |
| Win10-Det2 | x.x.x.x | Endpoint | true |
picus-get-attack-results
In the Picus, all attacks are carried out with the logic of the attacker and the victim. This command returns the list of the attack results on specified peers. Time range and result status can be given.
Base Command
picus-get-attack-results
Input
| Argument Name | Description | Required |
|---|---|---|
| attacker_peer | Untrusted peer name. | Required |
| victim_peer | Trusted peer name. | Required |
| days | Set days parameter. Default is 3. | Optional |
| result | This setting can only be insecure,secure and all. Default is all. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Picus.attackresults.results.threat_ids | String | Threat ID List |
| Picus.attackresults.results.begin_time | Date | begin time of the attack |
| Picus.attackresults.results.destination_port | Number | Value “0” indicates it is not applicable such as all vector types except network |
| Picus.attackresults.results.end_time | Date | end time of the attack |
| Picus.attackresults.results.id | Number | id |
| Picus.attackresults.results.l1_category_name | String | Level 1 Category Name of the attack |
| Picus.attackresults.results.scenario_details.action_id | Number | Action ID of the threat scenario action |
| Picus.attackresults.results.scenario_details.action_name | String | Action Name of the threat scenario action |
| Picus.attackresults.results.scenario_details.end | Date | The time attack ended |
| Picus.attackresults.results.scenario_details.id | Number | Primary key |
| Picus.attackresults.results.scenario_details.process_results | Unknown | Process Results(play and rewind) |
| Picus.attackresults.results.scenario_details.result | String | Final result of the scenario action |
| Picus.attackresults.results.scenario_details.technique_id | String | Technique ID of the threat scenario action |
| Picus.attackresults.results.source_port | Number | Value “0” indicates it is not applicable such as all vector types except network and wats attacks |
| Picus.attackresults.results.string | String | Attack Result |
| Picus.attackresults.results.threat_id | Number | Threat ID of the attack |
| Picus.attackresults.results.threat_name | String | Threat Name of the attack |
| Picus.attackresults.results.trusted | String | Trusted peer name |
| Picus.attackresults.results.untrusted | String | Untrusted peer name |
| Picus.attackresults.results.variant | String | Variant info |
Command Example
!picus-get-attack-results attacker_peer="Picus_Attacker_1" victim_peer="net1-det1" days=1 result="insecure"
Human Readable Output
| Begin Time | End Time | String | Threat Id | Threat Name |
|---|---|---|---|---|
| 2021-09-16T23:59:54.738644627Z | 2021-09-16T23:59:54.753408649Z | Insecure | 206450 | HTML5 Web Storage Sensitive Data Exposure |
| 2021-09-16T23:52:52.022470123Z | 2021-09-16T23:52:52.077736344Z | Insecure | 206111 | Zeus PandaBanker Trojan .EXE File Download Variant-11 |
picus-run-attacks
In the Picus, all attacks are carried out with the logic of the attacker and the victim. This command schedules a single attack on the requested vector.
Base Command
picus-run-attacks
Input
| Argument Name | Description | Required |
|---|---|---|
| threat_ids | Threat ID list (“111,222,333,…”) or single threat ID can be given. | Required |
| attacker_peer | Untrusted peer name. | Required |
| victim_peer | Trusted peer name. | Required |
| variant | This parameter can be HTTP or HTTPS. Example variant=HTTP | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Picus.runattacks | String | IDs of the assessed attacks |
Command Example
!picus-run-attacks attacker_peer="Picus_Attacker_1" victim_peer="net1-det1" threat_ids="881728,879812,798283" variant="HTTP"
Human Readable Output
| Threat Id | Result |
|---|---|
| 881728 | success |
| 879812 | success |
| 798283 | success |
picus-get-threat-results
Returns the list of the attack results of a single threat have optional parameters for filtration.
Base Command
picus-get-threat-results
Input
| Argument Name | Description | Required |
|---|---|---|
| threat_ids | Threat ID list (“111,222,333,…”) or single threat ID can be given. | Required |
| attacker_peer | Untrusted peer name. | Required |
| victim_peer | Trusted peer name. | Required |
| variant | This parameter can be HTTP or HTTPS. Example variant=HTTP | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Picus.threatresults.results.threat_results | String | Threat Results(ID and result combination) |
| Picus.threatresults.results.l1_category | String | Level 1 Category Name of the attack |
| Picus.threatresults.results.last_time | Date | Last Threat Result Time |
| Picus.threatresults.results.result | String | Threat Result |
| Picus.threatresults.results.status | String | Status |
| Picus.threatresults.results.threat_id | Number | Threat ID of the attack |
Command Example
!picus-get-threat-results attacker_peer="Picus_Attacker_1" victim_peer="net1-det1" variant="HTTP" threat_ids="562172"
Human Readable Output
| Threat Id | Result | L1 Category | Last Time | Status |
|---|---|---|---|---|
| 562172 | Secure | Vulnerability Exploitation | 2021-09-16T13:26:00.932298Z | success |
picus-set-paramPB
Set parameter on the playbook. (This command is only used on playbook)
Base Command
picus-set-paramPB
Input
| Argument Name | Description | Required |
|---|---|---|
| attacker_peer | Untrusted peer name. | Required |
| victim_peer | Trusted peer name. | Required |
| variant | This parameter can be HTTP or HTTPS. Example variant=HTTP | Required |
| mitigation_product | Products info of the mitigation. This parameter can be Check Point NGFW, ForcepointNGFW, McAfee IPS, PaloAlto IPS, SourceFire IPS, TippingPoint, F5 BIG-IP, Fortigate WAF, FortiWeb, Fortigate IPS, Snort, CitrixWAF, and ModSecurity. | Required |
| days | Set days parameter. Default is 3. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Picus.param.attacker_peer | String | Untrusted peer name |
| Picus.param.days | Number | days |
| Picus.param.mitigation_product | String | Products info of the mitigation |
| Picus.param.variant | String | This parameter can be HTTP or HTTPS. Example variant=HTTP |
| Picus.param.victim_peer | String | Trusted peer name |
filter-insecure-attacks
Filter insecure attacks on the playbook. (This command is only used on playbook)
Base Command
picus-filter-insecure-attacks
Input
| Argument Name | Description | Required |
|---|---|---|
| threatinfo | Threat id and result combine. Used for playbook. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Picus.filterinsecure | String | Insecure Attack List |
picus-get-mitigation-list
Returns the list of the mitigations of threats have optional parameters for filtration, this route may not be used associated with your license.
Base Command
picus-get-mitigation-list
Input
| Argument Name | Description | Required |
|---|---|---|
| threat_ids | Threat ID list (“111,222,333,…”) or single threat ID can be given. | Required |
| product | Products info of the mitigation. This parameter can be Check Point NGFW, ForcepointNGFW, McAfee IPS, PaloAlto IPS, SourceFire IPS, TippingPoint, F5 BIG-IP, Fortigate WAF, FortiWeb, Fortigate IPS, Snort, CitrixWAF, and ModSecurity. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Picus.mitigationresults.signature_id | String | ID of the signature |
| Picus.mitigationresults.signature_name | String | Name of the signature |
| Picus.mitigationresults.threat_id | Number | Threat ID of Picus Attack |
| Picus.mitigationresults.vendor | String | Product name of the mitigation |
Command Example
!picus-get-mitigation-list threat_ids="103847" product="Snort"
Human Readable Output
| Threat Dd | Signature Id | Signature Name |
|---|---|---|
| 103847 | 1.2025644.1 | ET TROJAN Possible Metasploit Payload Common Construct Bind_API (from server) |
| 103847 | 1.44728.3 | INDICATOR-COMPROMISE Meterpreter payload download attempt |
picus-get-vector-compare
Makes a comparison of the given vector’s results.
Base Command
picus-get-vector-compare
Input
| Argument Name | Description | Required |
|---|---|---|
| attacker_peer | Untrusted peer name. | Required |
| victim_peer | Trusted peer name. | Required |
| days | Set days parameter. Default is 3. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Picus.vectorresults.name | String | Name of Picus Attack |
| Picus.vectorresults.status | String | Compare Result |
| Picus.vectorresults.threat_id | String | Threat ID of Picus Attack |
Command Example
!picus-get-vector-compare attacker_peer="Picus_Attacker_1" victim_peer="net1-det1"
Human Readable Output
| Status | Threat Id | Name |
|---|---|---|
| secure | 204923 | XSS Evasion via HTML Encoding Variant-4 |
| insecure | null | null |
| secure_to_insecures | null | null |
| insecure_to_secures | null | null |
picus-version
Returns the current Picus version and the update time config.
Base Command
picus-version
Input
There are no input arguments for this command.
Context Output
| Path | Type | Description |
|---|---|---|
| Picus.versioninfo.last_update_date | Date | When was the last update? |
| Picus.versioninfo.update_time | Number | When to update? |
| Picus.versioninfo.version | Number | Current version |
Command Example
!picus-version
Human Readable Output
| Version | Update Time | Last Update Date |
|---|---|---|
| 4025 | 0 | 20.10.2021 |
picus-trigger-update
Triggers the Picus product update mechanism manually.
Base Command
picus-trigger-update
Input
There are no input arguments for this command.
Context Output
| Path | Type | Description |
|---|---|---|
| Picus.triggerupdate.data | Boolean | Collected data that will be returned |
| Picus.triggerupdate.success | Boolean | Is the operation Succeed? |
Command Example
!picus-trigger-update
Human Readable Output
| Data | Success |
|---|---|
| true | true |
Configuration parameters
picus_server— Picus Manager URL (required)picus_apikey— Picus Refresh Token (required)insecure— Trust any certificate (not secure)proxy— Use system proxy settings
Commands (12)
-
picus-filter-insecure-attacksFilter insecure attacks on playbook. (This command is only used on playbook).
-
picus-get-access-tokenGenerates an access token for api usage. Looks for X-Refresh-Token on header or refresh-token cookie.
-
picus-get-attack-resultsReturns the list of the attack results have optional parameters for filtration.
-
picus-get-mitigation-listReturns the list of the mitigations of threats have optional parameters for filtration, this route may not be used associated with your license.
-
picus-get-peer-listReturns the peer list with current statuses.
-
picus-get-threat-resultsReturns the list of the attack results of a single threat have optional parameters for filtration.
-
picus-get-vector-compareMakes a comparison of the given vector's results.
-
picus-get-vector-listReturns the list of the vectors all disabled and enabled ones have optional parameters for pagination.
-
picus-run-attacksSchedules a single attack on requested vector.
-
picus-set-paramPBSet parameter on playbook. (This command is only used on playbook).
-
picus-trigger-updateTriggers the Picus product update mechanism manually.
-
picus-versionReturns the current Picus version and the update time config.
import demistomock as demisto from CommonServerPython import * from CommonServerUserPython import * import requests import json import traceback from datetime import datetime, timedelta import time import urllib3 # Disable insecure warnings urllib3.disable_warnings() # pylint: disable=no-member # flake8: noqa """ CONSTANTS """ DATE_FORMAT = "%Y-%m-%dT%H:%M:%SZ" # ISO8601 format with UTC, default in XSOAR VALID_VARIANTS = ["HTTP", "HTTPS"] verify_certificate = not demisto.params().get("insecure", False) def test_module() -> str: """Tests API connectivity and authentication' Returning 'ok' indicates that the integration works like it is supposed to. Connection to the service is successful. Raises exceptions if something goes wrong. :type client: ``Client`` :param Client: client to use :return: 'ok' if test passed, anything else will fail the test. :rtype: ``str`` """ message, picus_accessToken = "", None try: picus_server = str(demisto.params().get("picus_server")) picus_server = picus_server[:-1] if picus_server.endswith("/") else picus_server picus_apikey = demisto.params().get("picus_apikey") picus_headers = {"X-Refresh-Token": "", "Content-Type": "application/json"} picus_headers["X-Refresh-Token"] = "Bearer " + str(picus_apikey) picus_auth_endpoint = "/authenticator/v1/access-tokens/generate" picus_req_url = str(picus_server) + picus_auth_endpoint picus_session = requests.Session() if not demisto.params().get("proxy", False): picus_session.trust_env = False picus_auth_response = picus_session.post(picus_req_url, headers=picus_headers, verify=verify_certificate) picus_auth_response.raise_for_status() picus_accessToken = json.loads(picus_auth_response.text)["data"]["access_token"] message = "ok" except Exception as e: if ( "Forbidden" in str(e) or "Authorization" in str(e) or "NewConnectionError" in str(e) or "Unauthorized" in str(e) or picus_accessToken is None ): message = "Authorization Error: make sure API Key or Picus URL is correctly set" else: raise e return message def getAccessToken(): picus_server = str(demisto.params().get("picus_server")) picus_server = picus_server[:-1] if picus_server.endswith("/") else picus_server picus_apikey = demisto.params().get("picus_apikey") picus_headers = {"X-Refresh-Token": "", "Content-Type": "application/json"} picus_headers["X-Refresh-Token"] = "Bearer " + str(picus_apikey) picus_auth_endpoint = "/authenticator/v1/access-tokens/generate" picus_req_url = str(picus_server) + picus_auth_endpoint picus_session = requests.Session() if not demisto.params().get("proxy", False): picus_session.trust_env = False picus_auth_response = picus_session.post(picus_req_url, headers=picus_headers, verify=verify_certificate) if picus_auth_response.status_code != 200: return_error(picus_auth_response.text) picus_accessToken = json.loads(picus_auth_response.text)["data"]["access_token"] return picus_accessToken def getVectorList(): picus_endpoint = "/user-api/v1/vectors/list" picus_req_url, picus_headers = generateEndpointURL(getAccessToken(), picus_endpoint) add_user_details = demisto.args().get("add_user_details") add_user_details = bool(add_user_details) if add_user_details is not None else add_user_details page = arg_to_number(demisto.args().get("page")) size = arg_to_number(demisto.args().get("size")) picus_post_data = {"add_user_details": add_user_details, "size": size, "page": page} picus_post_data = assign_params(**picus_post_data) picus_endpoint_response = requests.post( picus_req_url, headers=picus_headers, data=json.dumps(picus_post_data), verify=verify_certificate ) picus_vectors = json.loads(picus_endpoint_response.text)["data"]["vectors"] table_name = "Picus Vector List" table_headers = ["name", "description", "trusted", "untrusted", "is_disabled", "type"] md_table = tableToMarkdown( table_name, picus_vectors, headers=table_headers, removeNull=True, headerTransform=string_to_table_header ) results = CommandResults(readable_output=md_table, outputs=picus_vectors, outputs_prefix="Picus.vectorlist") return results def getPeerList(): picus_endpoint = "/user-api/v1/peers/list" picus_req_url, picus_headers = generateEndpointURL(getAccessToken(), picus_endpoint) picus_endpoint_response = requests.post(picus_req_url, headers=picus_headers, verify=verify_certificate) picus_peers = json.loads(picus_endpoint_response.text)["data"]["peers"] table_name = "Picus Peer List" table_headers = ["name", "registered_ip", "type", "is_alive"] md_table = tableToMarkdown( table_name, picus_peers, headers=table_headers, removeNull=True, headerTransform=string_to_table_header ) results = CommandResults(readable_output=md_table, outputs=picus_peers, outputs_prefix="Picus.peerlist") return results def getAttackResults(): picus_endpoint = "/user-api/v1/attack-results/list" picus_req_url, picus_headers = generateEndpointURL(getAccessToken(), picus_endpoint) picus_attack_results: List[Any] = [] picus_attack_raw_results: Dict[str, Any] = {"results": []} tmp_secure_list: List[Any] = [] tmp_insecure_list: List[Any] = [] tmp_results: List[Any] = [] threat_ids = "" attacker_peer = demisto.args().get("attacker_peer") victim_peer = demisto.args().get("victim_peer") days = int(demisto.args().get("days")) attack_result = demisto.args().get("result").lower() attack_result = attack_result[0].upper() + attack_result[1:] valid_attack_results = ["Insecure", "Secure", "All"] check_valid = any(result for result in valid_attack_results if (result == attack_result)) if not check_valid: msg = "Wrong result parameter. The result parameter can only be secure,insecure and all" return msg end_date = datetime.now().strftime("%Y-%m-%d") begin_date = (datetime.now() - timedelta(days=days)).strftime("%Y-%m-%d") picus_post_data_secure = { "attack_result": "secure", "begin_date": begin_date, "end_date": end_date, "vectors": [{"trusted": victim_peer, "untrusted": attacker_peer}], } picus_post_data_insecure = { "attack_result": "insecure", "begin_date": begin_date, "end_date": end_date, "vectors": [{"trusted": victim_peer, "untrusted": attacker_peer}], } picus_endpoint_response_secure = requests.post( picus_req_url, headers=picus_headers, data=json.dumps(picus_post_data_secure), verify=verify_certificate ) picus_endpoint_response_insecure = requests.post( picus_req_url, headers=picus_headers, data=json.dumps(picus_post_data_insecure), verify=verify_certificate ) picus_attack_results_secure = json.loads(picus_endpoint_response_secure.text)["data"]["results"] picus_attack_results_insecure = json.loads(picus_endpoint_response_insecure.text)["data"]["results"] if picus_attack_results_secure is not None: picus_attack_results_secure.sort(key=returnListTimeKey, reverse=True) for i in range(len(picus_attack_results_secure)): exists = 0 list_len = len(tmp_secure_list) for j in range(list_len): if picus_attack_results_secure[i]["threat_id"] == tmp_secure_list[j]["threat_id"]: exists = 1 if exists == 0: tmp_secure_list.append(picus_attack_results_secure[i]) if picus_attack_results_insecure is not None: picus_attack_results_insecure.sort(key=returnListTimeKey, reverse=True) for i in range(len(picus_attack_results_insecure)): exists = 0 list_len = len(tmp_insecure_list) for j in range(list_len): if picus_attack_results_insecure[i]["threat_id"] == tmp_insecure_list[j]["threat_id"]: exists = 1 if exists == 0: tmp_insecure_list.append(picus_attack_results_insecure[i]) tmp_results = tmp_secure_list + tmp_insecure_list if len(tmp_results) != 0: tmp_results.sort(key=returnListTimeKey, reverse=True) else: message = "No Results Data." results = CommandResults(readable_output=message) return results for i in range(len(tmp_results)): exists = 0 list_len = len(picus_attack_results) for j in range(list_len): if tmp_results[i]["threat_id"] == picus_attack_results[j]["threat_id"]: exists = 1 if exists == 0: picus_attack_results.append(tmp_results[i]) tmp_results = [] for i in range(len(picus_attack_results)): if attack_result == "All": tmp_results.append(picus_attack_results[i]) elif picus_attack_results[i]["string"] == attack_result: tmp_results.append(picus_attack_results[i]) picus_attack_results = tmp_results for i in range(len(picus_attack_results)): threat_ids += str(picus_attack_results[i]["threat_id"]) + "," threat_ids = threat_ids[:-1] picus_attack_raw_results["results"].append({"threat_ids": threat_ids}) picus_attack_raw_results["results"].append(picus_attack_results) table_name = attack_result + " Attack List" table_headers = ["begin_time", "end_time", "string", "threat_id", "threat_name"] md_table = tableToMarkdown( table_name, picus_attack_results, headers=table_headers, removeNull=True, headerTransform=string_to_table_header ) results = CommandResults( readable_output=md_table, outputs_prefix="Picus.attackresults", outputs=picus_attack_raw_results, outputs_key_field="results.threat_id", ) return results def runAttacks(): picus_endpoint = "/user-api/v1/schedule/attack/single" picus_req_url, picus_headers = generateEndpointURL(getAccessToken(), picus_endpoint) picus_attack_results: Dict[str, Any] = {"results": []} picus_attack_raw_results = "" threat_ids = demisto.args().get("threat_ids") attacker_peer = demisto.args().get("attacker_peer") victim_peer = demisto.args().get("victim_peer") variant = demisto.args().get("variant") if variant not in VALID_VARIANTS: return_error("Unknown variant type - " + variant) threat_ids = list(threat_ids.split(",")) t_count = 0 for threat_id in threat_ids: try: threat_id = int(threat_id) picus_attack_data = {"trusted": victim_peer, "untrusted": attacker_peer, "threat_id": threat_id, "variant": variant} picus_attack_response = requests.post( picus_req_url, headers=picus_headers, data=json.dumps(picus_attack_data), verify=verify_certificate ) attack_result_response = json.loads(picus_attack_response.text)["data"]["result"] picus_attack_result = {"threat_id": threat_id, "result": attack_result_response} picus_attack_results["results"].append(picus_attack_result) if attack_result_response == "success": picus_attack_raw_results += str(threat_id) + "," if t_count == 3: time.sleep(1) t_count = 0 else: t_count += 1 except Exception as e: picus_attack_result = {"threat_id": threat_id, "result": "unknown error"} picus_attack_results["results"].append(picus_attack_result) continue if len(picus_attack_raw_results) != 0: picus_attack_raw_results = picus_attack_raw_results[:-1] picus_attack_results = picus_attack_results["results"] table_name = "Picus Attack Results" table_headers = ["threat_id", "result"] md_table = tableToMarkdown( table_name, picus_attack_results, headers=table_headers, removeNull=True, headerTransform=string_to_table_header ) results = CommandResults(readable_output=md_table, outputs_prefix="Picus.runattacks", outputs=picus_attack_raw_results) return results def getThreatResults(): picus_endpoint = "/user-api/v1/attack-results/threat-specific-latest" picus_req_url, picus_headers = generateEndpointURL(getAccessToken(), picus_endpoint) picus_threat_results: Dict[str, Any] = {"results": []} picus_threat_raw_results = "" threat_raw_output: Dict[str, Any] = {"results": []} threat_ids = demisto.args().get("threat_ids") attacker_peer = demisto.args().get("attacker_peer") victim_peer = demisto.args().get("victim_peer") variant = demisto.args().get("variant") if variant not in VALID_VARIANTS: return_error("Unknown variant type - " + variant) threat_ids = list(threat_ids.split(",")) for threat_id in threat_ids: try: threat_id = int(threat_id) picus_threat_data = {"threat_id": threat_id} picus_threat_response = requests.post( picus_req_url, headers=picus_headers, data=json.dumps(picus_threat_data), verify=verify_certificate ) picus_threat_json_result = json.loads(picus_threat_response.text)["data"]["results"] l1_category = picus_threat_json_result["l1_category_name"] vector_name = attacker_peer + " - " + victim_peer vectors_results = picus_threat_json_result["vectors"] threat_result = "" last_time = "" for i in range(len(vectors_results)): if vectors_results[i]["name"] == vector_name: variants_results = vectors_results[i]["variants"] for j in range(len(variants_results)): if variants_results[j]["name"] == variant: last_time = variants_results[j]["last_time"] threat_result = variants_results[j]["result"] picus_threat_result = { "l1_category": l1_category, "result": threat_result, "threat_id": threat_id, "last_time": last_time, "status": "success", } picus_threat_results["results"].append(picus_threat_result) picus_threat_raw_results += str(threat_id) + "=" + threat_result + "," except Exception as e: picus_threat_result = { "l1_category": "null", "result": "null", "threat_id": threat_id, "last_time": "null", "status": "fail", } picus_threat_results["results"].append(picus_threat_result) continue if len(picus_threat_raw_results) != 0: picus_threat_raw_results = picus_threat_raw_results[:-1] picus_threat_results = picus_threat_results["results"] threat_raw_output["results"].append({"threat_results": picus_threat_raw_results}) threat_raw_output["results"].append(picus_threat_results) table_name = "Picus Threat Results" table_headers = ["threat_id", "result", "l1_category", "last_time", "status"] md_table = tableToMarkdown( table_name, picus_threat_results, headers=table_headers, removeNull=True, headerTransform=string_to_table_header ) results = CommandResults( readable_output=md_table, outputs_prefix="Picus.threatresults", outputs=threat_raw_output, outputs_key_field="results.threat_id", ) return results def filterInsecureAttacks(): threatinfo = demisto.args().get("threatinfo") threat_ids = "" threatinfo = list(threatinfo.split(",")) threatinfo = [th_info for th_info in threatinfo if "Insecure" in th_info] for th_info in threatinfo: threat_id = th_info.split("=")[0] threat_ids += str(threat_id) + "," if len(threat_ids) != 0: threat_ids = threat_ids[:-1] results = CommandResults(readable_output=threat_ids, outputs_prefix="Picus.filterinsecure", outputs=threat_ids) return results def getMitigationList(): picus_endpoint = "/user-api/v1/threats/mitigations/list" picus_req_url, picus_headers = generateEndpointURL(getAccessToken(), picus_endpoint) picus_mitigation_results: Dict[str, Any] = {"results": []} threat_ids = demisto.args().get("threat_ids") product = demisto.args().get("product") product = list(product.split(",")) threat_ids = list(threat_ids.split(",")) for threat_id in threat_ids: try: threat_id = int(threat_id) picus_threat_data = {"threat_id": threat_id, "products": product} picus_mitigation_response = requests.post( picus_req_url, headers=picus_headers, data=json.dumps(picus_threat_data), verify=verify_certificate ) picus_mitigation_result = json.loads(picus_mitigation_response.text)["data"]["mitigations"] picus_mitigation_count = json.loads(picus_mitigation_response.text)["data"]["total_count"] if picus_mitigation_count != 0: for threat_mitigation in picus_mitigation_result: mitigation_data = { "threat_id": threat_mitigation["threat"]["id"], "signature_id": threat_mitigation["signature"]["id"], "signature_name": threat_mitigation["signature"]["name"], "vendor": threat_mitigation["product"], } picus_mitigation_results["results"].append(mitigation_data) except Exception as e: continue picus_mitigation_results = picus_mitigation_results["results"] table_name = "Picus Mitigation List" table_headers = ["threat_id", "signature_id", "signature_name", "vendor"] md_table = tableToMarkdown( table_name, picus_mitigation_results, headers=table_headers, removeNull=True, headerTransform=string_to_table_header ) results = CommandResults( readable_output=md_table, outputs_prefix="Picus.mitigationresults", outputs=picus_mitigation_results, outputs_key_field="signature_id", ) return results def getVectorCompare(): picus_endpoint = "/user-api/v1/attack-results/compare-a-vector" picus_req_url, picus_headers = generateEndpointURL(getAccessToken(), picus_endpoint) all_vector_results: Dict[str, Any] = {"results": []} attacker_peer = demisto.args().get("attacker_peer") victim_peer = demisto.args().get("victim_peer") days = int(demisto.args().get("days")) end_date = datetime.now().strftime("%Y-%m-%d") begin_date = (datetime.now() - timedelta(days=days)).strftime("%Y-%m-%d") picus_post_data_vector = {"trusted": victim_peer, "untrusted": attacker_peer, "begin_date": begin_date, "end_date": end_date} picus_vector_response = requests.post( picus_req_url, headers=picus_headers, data=json.dumps(picus_post_data_vector), verify=verify_certificate ) picus_vector_results = json.loads(picus_vector_response.text)["data"]["variants"][0] picus_vector_secure_results = picus_vector_results["secures"] picus_vector_insecure_results = picus_vector_results["insecures"] picus_vector_secure_to_insecures_results = picus_vector_results["secure_to_insecures"] picus_vector_insecure_to_secures_results = picus_vector_results["insecure_to_secures"] if picus_vector_secure_results is not None: for result in picus_vector_secure_results: tmp_result = {"status": "secure", "threat_id": result["threat_id"], "name": result["name"]} all_vector_results["results"].append(tmp_result) else: tmp_result = {"status": "secure", "threat_id": "null", "name": "null"} all_vector_results["results"].append(tmp_result) if picus_vector_insecure_results is not None: for result in picus_vector_insecure_results: tmp_result = {"status": "insecure", "threat_id": result["threat_id"], "name": result["name"]} all_vector_results["results"].append(tmp_result) else: tmp_result = {"status": "insecure", "threat_id": "null", "name": "null"} all_vector_results["results"].append(tmp_result) if picus_vector_secure_to_insecures_results is not None: for result in picus_vector_secure_to_insecures_results: tmp_result = {"status": "secure_to_insecures", "threat_id": result["threat_id"], "name": result["name"]} all_vector_results["results"].append(tmp_result) else: tmp_result = {"status": "secure_to_insecures", "threat_id": "null", "name": "null"} all_vector_results["results"].append(tmp_result) if picus_vector_insecure_to_secures_results is not None: for result in picus_vector_insecure_to_secures_results: tmp_result = {"status": "insecure_to_secures", "threat_id": result["threat_id"], "name": result["name"]} all_vector_results["results"].append(tmp_result) else: tmp_result = {"status": "insecure_to_secures", "threat_id": "null", "name": "null"} all_vector_results["results"].append(tmp_result) all_vector_results = all_vector_results["results"] table_name = "Picus Vector Compare Result" table_headers = ["status", "threat_id", "name"] md_table = tableToMarkdown( table_name, all_vector_results, headers=table_headers, removeNull=True, headerTransform=string_to_table_header ) results = CommandResults( readable_output=md_table, outputs=all_vector_results, outputs_prefix="Picus.vectorresults", outputs_key_field="threat_id" ) return results def returnListTimeKey(attack_result_list): return attack_result_list.get("end_time") def setParamPB(): attacker_peer = demisto.args().get("attacker_peer") victim_peer = demisto.args().get("victim_peer") variant = demisto.args().get("variant") if variant not in VALID_VARIANTS: return_error("Unknown variant type - " + variant) mitigation_product = demisto.args().get("mitigation_product") days = int(demisto.args().get("days")) param_data = { "attacker_peer": attacker_peer, "victim_peer": victim_peer, "variant": variant, "mitigation_product": mitigation_product, "days": days, } results = CommandResults(outputs=param_data, outputs_prefix="Picus.param") return results def getPicusVersion(): picus_endpoint = "/user-api/v1/settings/version" picus_req_url, picus_headers = generateEndpointURL(getAccessToken(), picus_endpoint) picus_endpoint_response = requests.post(picus_req_url, headers=picus_headers, verify=verify_certificate) picus_version_results = json.loads(picus_endpoint_response.text)["data"] picus_version_info = { "version": picus_version_results["version"], "update_time": picus_version_results["update_time"], "last_update_date": picus_version_results["last_update_date"], } table_name = "Picus Version" table_headers = ["version", "update_time", "last_update_date"] md_table = tableToMarkdown( table_name, picus_version_info, headers=table_headers, removeNull=True, headerTransform=string_to_table_header ) results = CommandResults( readable_output=md_table, outputs=picus_version_info, outputs_prefix="Picus.versioninfo", outputs_key_field="version" ) return results def triggerUpdate(): picus_endpoint = "/user-api/v1/settings/trigger-update" picus_req_url, picus_headers = generateEndpointURL(getAccessToken(), picus_endpoint) picus_endpoint_response = requests.post(picus_req_url, headers=picus_headers, verify=verify_certificate) picus_update_results = json.loads(picus_endpoint_response.text) table_name = "Picus Trigger Update" table_headers = ["data", "success"] md_table = tableToMarkdown( table_name, picus_update_results, headers=table_headers, removeNull=True, headerTransform=string_to_table_header ) results = CommandResults(readable_output=md_table, outputs=picus_update_results, outputs_prefix="Picus.triggerupdate") return results def generateEndpointURL(picus_accessToken, picus_endpoint): picus_server = str(demisto.params().get("picus_server")) endpointURL = picus_server + picus_endpoint picus_headers = {"X-Api-Token": "", "Content-Type": "application/json"} picus_headers["X-Api-Token"] = "Bearer " + picus_accessToken return endpointURL, picus_headers """ MAIN FUNCTION """ def main() -> None: """main function, parses params and runs command functions :return: :rtype: """ demisto.debug(f"Command being called is {demisto.command()}") try: if demisto.command() == "test-module": # This is the call made when pressing the integration Test button. result = test_module() return_results(result) elif demisto.command() == "picus-get-access-token": result = getAccessToken() return_results(result) elif demisto.command() == "picus-get-vector-list": result = getVectorList() return_results(result) elif demisto.command() == "picus-get-peer-list": result = getPeerList() return_results(result) elif demisto.command() == "picus-get-attack-results": result = getAttackResults() return_results(result) elif demisto.command() == "picus-run-attacks": result = runAttacks() return_results(result) elif demisto.command() == "picus-get-threat-results": result = getThreatResults() return_results(result) elif demisto.command() == "picus-set-paramPB": result = setParamPB() return_results(result) elif demisto.command() == "picus-filter-insecure-attacks": result = filterInsecureAttacks() return_results(result) elif demisto.command() == "picus-get-mitigation-list": result = getMitigationList() return_results(result) elif demisto.command() == "picus-get-vector-compare": result = getVectorCompare() return_results(result) elif demisto.command() == "picus-version": result = getPicusVersion() return_results(result) elif demisto.command() == "picus-trigger-update": result = triggerUpdate() return_results(result) # Log exceptions and return errors except Exception as e: demisto.error(traceback.format_exc()) # print the traceback return_error(f"Failed to execute {demisto.command()} command.\nError:\n{str(e)}") """ ENTRY POINT """ if __name__ in ("__main__", "__builtin__", "builtins"): main()