BPA Deprecated
Deprecated. Use Palo Alto Networks AIops instead, run aiops-bpa-report-generate command.
Utilities · Best Practice Assessment (BPA) by Palo Alto Networks (Deprecated)
Details
| ID | BPA |
|---|---|
| Provider | BPA Securities |
| Category | Utilities |
| From Version | 5.0.0 |
| Docker Image | demisto/python3:3.11.10.116439 |
| Supported Modules | Agentix XSIAM |
README
Palo Alto Networks Best Practice Assessment (BPA) analyzes NGFW and Panorama configurations and compares them to the best practices.
This integration was integrated and tested with version 1.0 of BPA.
Supported Cortex XSOAR versions: 5.0.0 and later.
Configure BPA in Cortex
| Parameter | Description | Required |
|---|---|---|
| server | Server URL (either Firewall or Panorama). e.g., https:\/\/192.168.0.1 | True |
| key | Panorama API Key | True |
| token | BPA Access Token | True |
| insecure | Trust any certificate (not secure) | False |
| proxy | 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.
pan-os-get-documentation
Gets the documentation of all BPA checks.
Base Command
pan-os-get-documentation
Input
| Argument Name | Description | Required |
|---|---|---|
| doc_ids | A comma-separated list of IDs of the documents to return. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PAN-OS-BPA.Documentation.Document.DocId | Number | The ID of the document. |
| PAN-OS-BPA.Documentation.Document.TopNav | String | The TopNav field of the document. |
| PAN-OS-BPA.Documentation.Document.LeftNav | String | The LeftNav of the document. |
| PAN-OS-BPA.Documentation.Document.Title | String | The title of the document. |
| PAN-OS-BPA.Documentation.Document.DocType | String | The type of the document. |
| PAN-OS-BPA.Documentation.Document.Description | String | The description of the document. |
| PAN-OS-BPA.Documentation.Document.Rationale | String | The rationale of the document. |
| PAN-OS-BPA.Documentation.Document.References | String | The references for the document. |
| PAN-OS-BPA.Documentation.Document.Active | Boolean | Whether the document is active or not. |
| PAN-OS-BPA.Documentation.Document.LastUpdatedDate | String | The date the document was last updated. |
| PAN-OS-BPA.Documentation.Document.CapabilityLabel | Unknown | The capability label of the document. |
| PAN-OS-BPA.Documentation.Document.ClassLabel | Unknown | The class label of the document. |
| PAN-OS-BPA.Documentation.Document.ControlCategory | Unknown | The control category of the document. |
| PAN-OS-BPA.Documentation.Document.Cscv6Control | Unknown | The CSCv6 control of the document. |
| PAN-OS-BPA.Documentation.Document.Cscv7Control | Unknown | The CSCv7 control of the document. |
| PAN-OS-BPA.Documentation | Unknown | The list of BPA checks. |
Command Example
!pan-os-get-documentation doc_ids=4,6,7
Context Example
{
"PAN-OS-BPA": {
"Documentation": [
{
"Document": [
{
"Active": true,
"CapabilityLabel": [
"Preventative",
"Corrective"
],
"ClassLabel": [
"Technical"
],
"Complexity": "Advanced",
"ControlCategory": [
"Access Control"
],
"Cscv6Control": [
"11.1",
"12.1"
],
"Cscv7Control": [
"11.1",
"12.3"
],
"Description": "Do not specify both the source and destination zones as \"any\" on the rule.",
"DocId": 4,
"DocType": "Warning",
"Effort": 60,
"LastUpdatedDate": "2020-10-05T22:46:57.585179Z",
"LeftNav": "Security",
"Rationale": "Use Security policy settings to create rules that exactly define the traffic to which the rules apply (zones, IP addresses, users, applications). Policies that are too general may match traffic you don\u2019t want the policy to match and either permit undesirable traffic or deny legitimate traffic. Defining the source, destination, or both zones prevents potentially malicious traffic that uses evasive or deceptive techniques to avoid detection or appear benign from traversing the entire network, which reduces the attack surface and the threat scope. The exception to this best practice is when the Security policy needs to protect the entire network. For example, a rule that blocks traffic to malware or phishing URL categories can apply to all zones (and all traffic) because the URL Category clearly defines the traffic to block. Another example is blocking all unknown traffic with a block rule that applies to all traffic in all zones and defining the blocked applications as \u201cunknown-tcp\u201d, \u201cunknown-udp\u201d, and \u201cunknown-p2p\u201d.",
"References": "['https://www.paloaltonetworks.com/documentation/81/best-practices/best-practices-internet-gateway/best-practice-internet-gateway-security-policy/define-the-initial-internet-gateway-security-policy']",
"Title": "Source/Destination = any/any",
"TopNav": "Policies"
},
{
"Active": true,
"CapabilityLabel": [
"Performance"
],
"ClassLabel": [
"Technical"
],
"Complexity": "Advanced",
"ControlCategory": [
"Audit and Accountability"
],
"Cscv6Control": [],
"Cscv7Control": [],
"Description": "Don't enable \"Log at Session Start\" in a rule except for troubleshooting purposes.",
"DocId": 6,
"DocType": "Warning",
"Effort": 60,
"LastUpdatedDate": "2020-10-05T22:46:57.596239Z",
"LeftNav": "Security",
"Rationale": "By default, the firewall creates logs at the end of the session for all sessions that match a Security policy rule because the application identification is likely to change as the firewall identifies the specific application and because logging at the session end consumes fewer resources than logging the session start. For example, at the start of a session, the firewall identifies Facebook traffic as web-browsing traffic, but after examining a few packets, the firewall refines the application to Facebook-base. Use \u201cLog at Session Start\u201d only to troubleshoot packet flow and related issues, or for tunnel session logs (only logging at session start shows active GRE tunnels in the Application Command Center).",
"References": "['https://www.paloaltonetworks.com/documentation/81/best-practices/best-practices-data-center/data-center-best-practice-security-policy/log-and-monitor-data-center-traffic/what-data-center-traffic-to-log-and-monitor']",
"Title": "Log at Start of Session",
"TopNav": "Policies"
},
{
"Active": true,
"CapabilityLabel": [
"Recovery",
"Detective"
],
"ClassLabel": [
"Operational",
"Technical"
],
"Complexity": "Advanced",
"ControlCategory": [
"Contingency Planning",
"Audit and Accountability"
],
"Cscv6Control": [
"6.2",
"6.6",
"10.1"
],
"Cscv7Control": [
"6.3",
"6.6",
"10.1"
],
"Description": "Create and enable a Log Forwarding profile on the rule.",
"DocId": 7,
"DocType": "Warning",
"Effort": 60,
"LastUpdatedDate": "2020-10-05T22:46:57.601517Z",
"LeftNav": "Security",
"Rationale": "The firewall has limited log storage space and when the space fills up, the firewall purges the oldest logs. Configure Log Forwarding for the traffic that matches each Security policy rule. You can create profiles that send logs to a dedicated storage device such as Panorama in Log Collector mode, a syslog or SNMP server, or to an email profile, to provide redundant storage for the logs on the firewall and a long-term repository for older logs. You can create profiles to forward logs to one or more external storage devices to remain in compliance, run analytics, and review abnormal activity, threat behaviors, and long-term patterns.",
"References": "['https://www.paloaltonetworks.com/documentation/81/pan-os/pan-os/monitoring/configure-log-forwarding']",
"Title": "Log Forwarding",
"TopNav": "Policies"
}
]
},
{
"active": true,
"capability_label": [
"Preventative",
"Corrective"
],
"class_label": [
"Technical"
],
"complexity": "Advanced",
"control_category": [
"Access Control"
],
"cscv6_control": [
"11.1",
"12.1"
],
"cscv7_control": [
"11.1",
"12.3"
],
"description": "Do not specify both the source and destination zones as \"any\" on the rule.",
"doc_id": 4,
"doc_type": "Warning",
"effort": 60,
"last_updated_date": "2020-10-05T22:46:57.585179Z",
"left_nav": "Security",
"rationale": "Use Security policy settings to create rules that exactly define the traffic to which the rules apply (zones, IP addresses, users, applications). Policies that are too general may match traffic you don\u2019t want the policy to match and either permit undesirable traffic or deny legitimate traffic. Defining the source, destination, or both zones prevents potentially malicious traffic that uses evasive or deceptive techniques to avoid detection or appear benign from traversing the entire network, which reduces the attack surface and the threat scope. The exception to this best practice is when the Security policy needs to protect the entire network. For example, a rule that blocks traffic to malware or phishing URL categories can apply to all zones (and all traffic) because the URL Category clearly defines the traffic to block. Another example is blocking all unknown traffic with a block rule that applies to all traffic in all zones and defining the blocked applications as \u201cunknown-tcp\u201d, \u201cunknown-udp\u201d, and \u201cunknown-p2p\u201d.",
"references": "['https://www.paloaltonetworks.com/documentation/81/best-practices/best-practices-internet-gateway/best-practice-internet-gateway-security-policy/define-the-initial-internet-gateway-security-policy']",
"title": "Source/Destination = any/any",
"top_nav": "Policies"
},
{
"active": true,
"capability_label": [
"Performance"
],
"class_label": [
"Technical"
],
"complexity": "Advanced",
"control_category": [
"Audit and Accountability"
],
"cscv6_control": [],
"cscv7_control": [],
"description": "Don't enable \"Log at Session Start\" in a rule except for troubleshooting purposes.",
"doc_id": 6,
"doc_type": "Warning",
"effort": 60,
"last_updated_date": "2020-10-05T22:46:57.596239Z",
"left_nav": "Security",
"rationale": "By default, the firewall creates logs at the end of the session for all sessions that match a Security policy rule because the application identification is likely to change as the firewall identifies the specific application and because logging at the session end consumes fewer resources than logging the session start. For example, at the start of a session, the firewall identifies Facebook traffic as web-browsing traffic, but after examining a few packets, the firewall refines the application to Facebook-base. Use \u201cLog at Session Start\u201d only to troubleshoot packet flow and related issues, or for tunnel session logs (only logging at session start shows active GRE tunnels in the Application Command Center).",
"references": "['https://www.paloaltonetworks.com/documentation/81/best-practices/best-practices-data-center/data-center-best-practice-security-policy/log-and-monitor-data-center-traffic/what-data-center-traffic-to-log-and-monitor']",
"title": "Log at Start of Session",
"top_nav": "Policies"
},
{
"active": true,
"capability_label": [
"Recovery",
"Detective"
],
"class_label": [
"Operational",
"Technical"
],
"complexity": "Advanced",
"control_category": [
"Contingency Planning",
"Audit and Accountability"
],
"cscv6_control": [
"6.2",
"6.6",
"10.1"
],
"cscv7_control": [
"6.3",
"6.6",
"10.1"
],
"description": "Create and enable a Log Forwarding profile on the rule.",
"doc_id": 7,
"doc_type": "Warning",
"effort": 60,
"last_updated_date": "2020-10-05T22:46:57.601517Z",
"left_nav": "Security",
"rationale": "The firewall has limited log storage space and when the space fills up, the firewall purges the oldest logs. Configure Log Forwarding for the traffic that matches each Security policy rule. You can create profiles that send logs to a dedicated storage device such as Panorama in Log Collector mode, a syslog or SNMP server, or to an email profile, to provide redundant storage for the logs on the firewall and a long-term repository for older logs. You can create profiles to forward logs to one or more external storage devices to remain in compliance, run analytics, and review abnormal activity, threat behaviors, and long-term patterns.",
"references": "['https://www.paloaltonetworks.com/documentation/81/pan-os/pan-os/monitoring/configure-log-forwarding']",
"title": "Log Forwarding",
"top_nav": "Policies"
}
]
}
}
Human Readable Output
BPA documentation
Active CapabilityLabel ClassLabel Complexity ControlCategory Cscv6Control Cscv7Control Description DocId DocType Effort LastUpdatedDate LeftNav Rationale References Title TopNav true Preventative,
CorrectiveTechnical Advanced Access Control 11.1,
12.111.1,
12.3Do not specify both the source and destination zones as “any” on the rule. 4 Warning 60 2020-10-05T22:46:57.585179Z Security Use Security policy settings to create rules that exactly define the traffic to which the rules apply (zones, IP addresses, users, applications). Policies that are too general may match traffic you don’t want the policy to match and either permit undesirable traffic or deny legitimate traffic. Defining the source, destination, or both zones prevents potentially malicious traffic that uses evasive or deceptive techniques to avoid detection or appear benign from traversing the entire network, which reduces the attack surface and the threat scope. The exception to this best practice is when the Security policy needs to protect the entire network. For example, a rule that blocks traffic to malware or phishing URL categories can apply to all zones (and all traffic) because the URL Category clearly defines the traffic to block. Another example is blocking all unknown traffic with a block rule that applies to all traffic in all zones and defining the blocked applications as “unknown-tcp”, “unknown-udp”, and “unknown-p2p”. [‘https://www.paloaltonetworks.com/documentation/81/best-practices/best-practices-internet-gateway/best-practice-internet-gateway-security-policy/define-the-initial-internet-gateway-security-policy’] Source/Destination = any/any Policies true Performance Technical Advanced Audit and Accountability Don’t enable “Log at Session Start” in a rule except for troubleshooting purposes. 6 Warning 60 2020-10-05T22:46:57.596239Z Security By default, the firewall creates logs at the end of the session for all sessions that match a Security policy rule because the application identification is likely to change as the firewall identifies the specific application and because logging at the session end consumes fewer resources than logging the session start. For example, at the start of a session, the firewall identifies Facebook traffic as web-browsing traffic, but after examining a few packets, the firewall refines the application to Facebook-base. Use “Log at Session Start” only to troubleshoot packet flow and related issues, or for tunnel session logs (only logging at session start shows active GRE tunnels in the Application Command Center). [‘https://www.paloaltonetworks.com/documentation/81/best-practices/best-practices-data-center/data-center-best-practice-security-policy/log-and-monitor-data-center-traffic/what-data-center-traffic-to-log-and-monitor’] Log at Start of Session Policies true Recovery,
DetectiveOperational,
TechnicalAdvanced Contingency Planning,
Audit and Accountability6.2,
6.6,
10.16.3,
6.6,
10.1Create and enable a Log Forwarding profile on the rule. 7 Warning 60 2020-10-05T22:46:57.601517Z Security The firewall has limited log storage space and when the space fills up, the firewall purges the oldest logs. Configure Log Forwarding for the traffic that matches each Security policy rule. You can create profiles that send logs to a dedicated storage device such as Panorama in Log Collector mode, a syslog or SNMP server, or to an email profile, to provide redundant storage for the logs on the firewall and a long-term repository for older logs. You can create profiles to forward logs to one or more external storage devices to remain in compliance, run analytics, and review abnormal activity, threat behaviors, and long-term patterns. [‘https://www.paloaltonetworks.com/documentation/81/pan-os/pan-os/monitoring/configure-log-forwarding’] Log Forwarding Policies
pan-os-bpa-submit-job
Submits a job to the BPA job queue. PAN-OS devices with large configuration files may take a few minutes for the job to be submitted.
Base Command
pan-os-bpa-submit-job
Input
| Argument Name | Description | Required |
|---|---|---|
| generate_zip_bundle | Whether to download the Panorama report. Can be “true” or “false”. Default is “false”. | Optional |
| timeout | The timeout for the request. Default is 120. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PAN-OS-BPA.SubmittedJob.JobID | String | Submitted Job ID, used to query results when the job is done. |
Command Example
#### Context Example
```json
{
"PAN-OS-BPA": {
"SubmittedJob": {
"JobID": "ca5dc5a7-c3e5-474a-8d04-e3129c1b0edf"
}
}
}
Human Readable Output
Submitted BPA job ID: ca5dc5a7-c3e5-474a-8d04-e3129c1b0edf
pan-os-bpa-get-job-results
Returns results of BPA job.
Base Command
pan-os-bpa-get-job-results
Input
| Argument Name | Description | Required |
|---|---|---|
| task_id | The job ID for which to return results. | Required |
| exclude_passed_checks | Whether to exclude passed checks. Can be “true” or “false”. Default is “false”. | Optional |
| check_id | A comma-separated list of the BPA IDs of the results to return. | Optional |
| check_name | A comma-separated list of the name of the results to return. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PAN-OS-BPA.JobResults.JobID | String | The submitted job ID. |
| PAN-OS-BPA.JobResults.Status | String | The job status in the queue (in progress or completed). |
| PAN-OS-BPA.JobResults.Checks | Unknown | The list of checks. |
| InfoFile.Name | string | File name. |
| InfoFile.EntryID | string | File entry ID. |
| InfoFile.Size | number | File size. |
| InfoFile.Type | string | File type, e.g., “PE” |
| InfoFile.Info | string | Basic information of the file. |
| InfoFile.Extension | string | File extension. |
Command Example
!pan-os-bpa-get-job-results task_id=b0539068-e1c1-496c-9dfd-a1274947f76e check_id=104,105 check_name="Accelerated Aging"
Context Example
{
"PAN-OS-BPA": {
"JobResults": {
"Checks": [
{
"check_category": "device",
"check_feature": "device_setup_services",
"check_id": 105,
"check_message": "It is recommended to configure a primary and secondary NTP Server Address",
"check_name": "NTP Server Address",
"check_passed": false,
"check_type": "Warning"
},
{
"check_category": "device",
"check_feature": "device_setup_services",
"check_id": 104,
"check_message": null,
"check_name": "Verify Update Server Identity",
"check_passed": true,
"check_type": "Warning"
},
{
"check_category": "device",
"check_feature": "device_setup_session",
"check_id": 121,
"check_message": null,
"check_name": "Accelerated Aging",
"check_passed": true,
"check_type": "Warning"
}
],
"JobID": "b0539068-e1c1-496c-9dfd-a1274947f76e",
"Status": "complete"
}
}
}
Human Readable Output
BPA Results
check_category check_feature check_id check_message check_name check_passed check_type device device_setup_services 105 It is recommended to configure a primary and secondary NTP Server Address NTP Server Address false Warning device device_setup_services 104 Verify Update Server Identity true Warning device device_setup_session 121 Accelerated Aging true Warning
Configuration parameters
server— Server URL (either Firewall or Panorama). e.g., https://192.168.0.1 (required)key— Panorama API Keykey_creds—token— BPA Access Tokentoken_creds—insecure— Trust any certificate (not secure)proxy— Use system proxy settings
Commands (3)
-
pan-os-bpa-get-job-resultsDeprecatedReturns the results of the BPA job.
-
pan-os-bpa-submit-jobDeprecatedSubmits a job to the BPA job queue. PAN-OS devices with large configuration files may take a few minutes for the job to be submitted.
-
pan-os-get-documentationDeprecatedGets the documentation of all BPA checks.
from typing import Dict, Tuple, List import urllib3 from CommonServerPython import * # Disable insecure warnings urllib3.disable_warnings() ''' GLOBALS/PARAMS ''' BPA_HOST = 'https://bpa.paloaltonetworks.com' BPA_VERSION = 'v1' BPA_URL = BPA_HOST + '/api/' + BPA_VERSION + '/' DOWNLOADED_REPORT_NAME_SUFFIX = '_BPA-report.zip' class LightPanoramaClient(BaseClient): ''' This is a client for Panorama API, used by integration commands to issue requests to Panorama API, not the BPA service. ''' def __init__(self, server, port, api_key, verify, proxy): if port is None: super().__init__(server + '/', verify) else: super().__init__(server.rstrip('/:') + ':' + port + '/', verify) self.api_key = api_key if proxy: self.proxies = handle_proxy() else: self.proxies = {} def simple_op_request(self, cmd): params = { 'type': 'op', 'cmd': cmd, 'key': self.api_key } result = self._http_request( 'POST', 'api', params=params, resp_type='text', proxies=self.proxies ) return result @logger def get_system_time(self): return self.simple_op_request('<show><clock></clock></show>') @logger def get_license(self): return self.simple_op_request('<request><license><info></info></license></request>') @logger def get_system_info(self): return self.simple_op_request('<show><system><info></info></system></show>') @logger def get_running_config(self): params = { 'type': 'config', 'action': 'show', 'key': self.api_key } result = self._http_request( 'POST', 'api', params=params, resp_type='text', proxies=self.proxies ) return result class Client(BaseClient): """ Client to use in the BPA integration. This client issues requests to the BPA service, and not Panorama. """ def __init__(self, bpa_token: str, verify: bool, proxy: bool): headers = {'Authorization': f'Token {bpa_token}'} super().__init__(base_url=BPA_URL, verify=verify, headers=headers, proxy=proxy) self.token = bpa_token if proxy: self.proxies = handle_proxy() else: self.proxies = {} def get_documentation_request(self): response = self._http_request('GET', 'documentation/', proxies=self.proxies) return response def submit_task_request(self, running_config, system_info, license_info, system_time, generate_zip_bundle, timeout) -> Dict: data = { 'xml': running_config, 'system_info': system_info, 'license_info': license_info, 'system_time': system_time, 'generate_zip_bundle': generate_zip_bundle } response = self._http_request('POST', 'create/', data=data, proxies=self.proxies, timeout=timeout) return response def get_results_request(self, task_id: str): response = self._http_request('GET', f'results/{task_id}/', proxies=self.proxies) return response def get_download_results_request(self, task_id: str) -> bytes: response = self._http_request('GET', f'results/{task_id}/download', resp_type='content', proxies=self.proxies) return response def create_output(doc: dict): doc_output = {} for key in doc.keys(): doc_output[string_to_context_key(key)] = doc.get(key) return doc_output def get_documentation_command(client: Client, args: Dict) -> Tuple[str, Dict, Dict]: raw = client.get_documentation_request() if not raw: raise Exception('Failed getting documentation from BPA') filter_by_ids = args.get('doc_ids') if filter_by_ids: output = [] old_output = [] # keep old output format in order to not break backwards compatibility id_list = filter_by_ids.split(',') for doc in raw: if str(doc.get('doc_id')) in id_list: output.append(create_output(doc)) old_output.append(doc) else: output = [create_output(doc) for doc in raw] old_output = raw entry_context = { 'PAN-OS-BPA.Documentation.Document': output, 'PAN-OS-BPA.Documentation': old_output # Keep old output path in order to not break backwards compatibility. } human_readable = tableToMarkdown('BPA documentation', output) return human_readable, entry_context, raw def submit_task_command(client: Client, panorama: LightPanoramaClient, args: Dict) -> Tuple[str, Dict, Dict]: try: running_config = panorama.get_running_config() system_info = panorama.get_system_info() license_info = panorama.get_license() system_time = panorama.get_system_time() except Exception: raise Exception('Failed getting response from Panorama') generate_zip_bundle = args.get('generate_zip_bundle') timeout = int(args.get('timeout', '120')) raw = client.submit_task_request(running_config, system_info, license_info, system_time, generate_zip_bundle, timeout) task_id = raw.get('task_id', '') human_readable = f'Submitted BPA job ID: {task_id}' entry_context = {'PAN-OS-BPA.SubmittedJob(val.JobID && val.JobID === obj.JobID)': {'JobID': task_id}} return human_readable, entry_context, raw def transform_check(check, feature, category): # safe to shallow clone since it is a shallow object transformed_check = check.copy() transformed_check['check_category'] = category transformed_check['check_feature'] = feature return transformed_check def get_checks_from_feature(feature, feature_name, category): notes_checks = feature.get('notes', []) warnings_checks = feature.get('warnings', []) return [transform_check(c, feature_name, category) for c in notes_checks + warnings_checks] def get_results_command(client: Client, args: Dict): task_id = args.get('task_id', '') filter_by_check_id = args.get('check_id', '').split(',') if args.get('check_id') else [] filter_by_check_name = args.get('check_name', '').split(',') if args.get('check_name') else [] raw: Dict = client.get_results_request(task_id) status = raw.get('status') results = raw.get('results', {}) exclude_passed_checks = args.get('exclude_passed_checks') == "true" if not status: raise Exception("Invalid response from BPA") job_checks: List[Dict] = [] if status == 'invalid': raise Exception("Job ID not valid or doesn't exist") if status == 'complete': bpa = results.get('bpa', {}) if not bpa: raise Exception("Invalid response from BPA") for category_name, features in bpa.items(): for feature_name, feature_contents in features.items(): if not feature_contents: # Empty list, no checks continue checks = get_checks_from_feature(feature_contents[0], feature_name, category_name) if exclude_passed_checks: job_checks.extend([check for check in checks if not check.get('check_passed')]) elif filter_by_check_id or filter_by_check_name: job_checks.extend([check for check in checks if str(check.get('check_id')) in filter_by_check_id or check.get('check_name') in filter_by_check_name]) else: job_checks.extend(checks) download_url = results.get('download_url') # check that a report was generated, and can be downloaded if download_url: download_report_handler(client, task_id) context = {'PAN-OS-BPA.JobResults(val.JobID && val.JobID === obj.JobID)': { 'JobID': task_id, 'Checks': job_checks, 'Status': status }} headers = ['check_id', 'check_category', 'check_feature', 'check_message', 'check_name', 'check_passed', 'check_type', 'check_severity'] human_readable = tableToMarkdown('BPA Results', job_checks, headers=headers, headerTransform=string_to_table_header) return human_readable, context, results def download_report_handler(client: Client, task_id): downloaded_report = client.get_download_results_request(task_id) demisto.results(fileResult(task_id + DOWNLOADED_REPORT_NAME_SUFFIX, downloaded_report, entryTypes['entryInfoFile'])) def test_module(client, panorama): client.get_documentation_request() panorama.get_system_time() demisto.results('ok') return '', None, None def main(): """ PARSE AND VALIDATE INTEGRATION PARAMS """ params = demisto.params() panorama_server = params.get('server') panorama_port = params.get('port', None) panorama_api_key = params.get('key_creds', {}).get('password') or params.get('key') bpa_token = params.get('token_creds', {}).get('password') or params.get('token') verify = not params.get('insecure', False) proxy = params.get('proxy') try: client = Client(bpa_token, verify, proxy) panorama = LightPanoramaClient(panorama_server, panorama_port, panorama_api_key, verify, proxy) command = demisto.command() LOG(f'Command being called is {command}.') if command == 'pan-os-bpa-submit-job': return_outputs(*submit_task_command(client, panorama, demisto.args())) elif command == 'pan-os-bpa-get-job-results': return_outputs(*get_results_command(client, demisto.args())) elif command == 'pan-os-get-documentation': return_outputs(*get_documentation_command(client, demisto.args())) elif command == 'test-module': return_outputs(*test_module(client, panorama)) else: raise NotImplementedError(f'Command "{command}" is not implemented.') except Exception as err: return_error(str(err)) if __name__ in ['__main__', 'builtin', 'builtins']: main()