from CommonServerPython import * # Disable insecure warnings import urllib3 urllib3.disable_warnings() class Client(BaseClient): """ Client to use in the Threat Vault integration. Overrides BaseClient. """ def __init__(self, api_key: str, verify: bool, proxy: bool, reliability: str): super().__init__(base_url='https://autofocus.paloaltonetworks.com/api/intel/v1', verify=verify, proxy=proxy, headers={'Content-Type': 'application/json'}) self._params = {'api_key': api_key} self.name = 'ThreatVault' self.reliability = reliability @logger def antivirus_signature_get_request(self, sha256: str = '', signature_id: str = '') -> dict: """Get antivirus signature by sending a GET request. Args: sha256: antivirus sha256. signature_id: signature ID. Returns: Response from API. """ if (sha256 and signature_id) or (not sha256 and not signature_id): raise Exception('Please submit a sha256 or a signature_id.') if signature_id: suffix = f'/threatvault/panav/signature/{signature_id}' else: suffix = f'/file/{sha256}/signature' return self._http_request(method='GET', url_suffix=suffix, params=self._params) @logger def dns_signature_get_request(self, dns_signature_id: str) -> dict: """Get DNS signature by sending a GET request. Args: dns_signature_id: DNS signature ID. Returns: Response from API. """ return self._http_request(method='GET', url_suffix=f'/threatvault/dns/signature/{dns_signature_id}', params=self._params) @logger def antispyware_get_by_id_request(self, signature_id: str) -> dict: """Get DNS signature by sending a GET request. Args: signature_id: signature ID. Returns: Response from API. """ return self._http_request(method='GET', url_suffix=f'/threatvault/ips/signature/{signature_id}', params=self._params) @logger def ip_geo_get_request(self, ip_: str) -> dict: """Get IP geolocation by sending a GET request. Args: ip_: ip address. Returns: Response from API. """ return self._http_request(method='GET', url_suffix=f'/ip/{ip_}/geolocation', params=self._params) @logger def search_request(self, path: str, from_: int, to_: int, signature_name: str = '', domain_name: str = '', vendor: str = '', cve: str = '') -> dict: """Initiate a search by sending a POST request. Args: path: API endpoint path to search. from_: from which signature to return results. to_: to which signature to return results. signature_name: signature name. domain_name: domain name. vendor: vendor ID. cve: cve ID. Returns: Response from API. """ if path == 'dns': # DNS search if signature_name and domain_name: raise Exception('Please provide either a signature_name or a domain_name.') elif path == 'ips': # Anti spyware search if (cve and (vendor or signature_name)) or (vendor and (cve or signature_name)) \ or (signature_name and (cve or vendor)): raise Exception('Please provide either a signature_name or a cve or a vendor.') data: Dict[str, Any] = { 'from': from_, 'size': to_ - from_ } if signature_name: data['field'] = 'signatureName' data['value'] = signature_name elif domain_name: data['field'] = 'domainName' data['value'] = domain_name elif cve: data['field'] = 'cve' data['value'] = cve else: # vendor name data['field'] = 'vendor' data['value'] = vendor return self._http_request(method='POST', url_suffix=f'/threatvault/{path}/search', params=self._params, json_data=data) @logger def signature_search_results_request(self, search_type: str, search_request_id: str) -> dict: """Get signature search results by sending a GET request. Args: search_type: search type. search_request_id: signature id. Returns: Response from API. """ return self._http_request(method='GET', url_suffix=f'/threatvault/{search_type}/search/result/{search_request_id}', params=self._params) def antivirus_signature_get(client: Client, args: dict) -> CommandResults: """Get antivirus signature. Args: client: Client object with request. args: Usually demisto.args() Returns: CommandResults. """ sha256 = str(args.get('sha256', '')) signature_id = str(args.get('signature_id', '')) try: response = client.antivirus_signature_get_request(sha256, signature_id) readable_output = tableToMarkdown(name="Antivirus:", t=response, removeNull=True) except Exception as err: if 'Error in API call [404] - Not Found' in str(err): response = {} readable_output = 'Antivirus signature was not found. Please try with a different sha256 or signature_id.' else: raise Exception(err) return CommandResults( outputs_prefix=f'{client.name}.Antivirus', outputs_key_field='signatureId', outputs=response, readable_output=readable_output, raw_response=response ) def file_command(client: Client, args: Dict) -> List[CommandResults]: """Get the reputation of a sha256 representing an antivirus Args: client: Client object with request. args: Usually demisto.args() Returns: list of CommandResults. """ sha256_list = argToList(args.get('file')) command_results_list: List[CommandResults] = [] dbot_reliability = DBotScoreReliability.get_dbot_score_reliability_from_str(client.reliability) for sha256 in sha256_list: try: response = client.antivirus_signature_get_request(sha256) dbot_score = Common.DBotScore( indicator=sha256, indicator_type=DBotScoreType.FILE, integration_name=client.name, score=Common.DBotScore.BAD, reliability=dbot_reliability ) file = Common.File( sha256=sha256, dbot_score=dbot_score ) readable_output = tableToMarkdown(name=f"SHA256 {sha256} Antivirus reputation:", t=response, removeNull=True) except Exception as err: if 'Error in API call [404] - Not Found' in str(err): response = {} dbot_score = Common.DBotScore( indicator=sha256, indicator_type=DBotScoreType.FILE, integration_name=client.name, reliability=dbot_reliability, score=Common.DBotScore.NONE ) file = Common.File( sha256=sha256, dbot_score=dbot_score ) readable_output = f"SHA256 {sha256} Antivirus reputation is unknown to Threat Vault." else: raise Exception(err) command_results = CommandResults( outputs_prefix=f'{client.name}.Antivirus', outputs_key_field='signatureId', outputs=response, readable_output=readable_output, raw_response=response, indicator=file ) command_results_list.append(command_results) return command_results_list def dns_get_by_id(client: Client, args: dict) -> CommandResults: """Get DNS signature. Args: client: Client object with request. args: Usually demisto.args() Returns: CommandResults. """ dns_signature_id = str(args.get('dns_signature_id', '')) try: response = client.dns_signature_get_request(dns_signature_id) headers = ['signatureId', 'signatureName', 'domainName', 'createTime', 'category'] readable_output = tableToMarkdown(name="DNS Signature:", t=response, headers=headers, removeNull=True) except Exception as err: if 'Error in API call [404] - Not Found' in str(err): response = {} readable_output = 'DNS signature was not found. Please try with a different dns_signature_id.' else: raise Exception(err) return CommandResults( outputs_prefix=f'{client.name}.DNS', outputs_key_field='signatureId', outputs=response, readable_output=readable_output, raw_response=response ) def antispyware_get_by_id(client: Client, args: dict) -> CommandResults: """Get anti spyware signature. Args: client: Client object with request. args: Usually demisto.args() Returns: CommandResults. """ signature_id = str(args.get('signature_id', '')) try: response = client.antispyware_get_by_id_request(signature_id) headers = ['signatureId', 'signatureName', 'signatureType', 'status', 'firstReleaseTime', 'latestReleaseTime'] readable_output = tableToMarkdown(name="Anti Spyware Signature:", t=response, headers=headers, removeNull=True) except Exception as err: if 'Error in API call [404] - Not Found' in str(err): response = {} readable_output = 'Anti spyware signature was not found. Please try with a different signature_id.' else: raise Exception(err) return CommandResults( outputs_prefix=f'{client.name}.AntiSpyware', outputs_key_field='signatureId', outputs=response, readable_output=readable_output, raw_response=response ) def ip_geo_get(client: Client, args: dict) -> CommandResults: """Get IP geo location. Args: client: Client object with request. args: Usually demisto.args() Returns: CommandResults. """ ip_ = str(args.get('ip', '')) try: response = client.ip_geo_get_request(ip_) readable_output = tableToMarkdown(name="IP location:", t=response, removeNull=True) except Exception as err: if 'Error in API call [404] - Not Found' in str(err): response = {} readable_output = 'IP location was not found. Please try with a different IP.' else: raise Exception(err) return CommandResults( outputs_prefix=f'{client.name}.IP', outputs_key_field='ipAddress', outputs=response, readable_output=readable_output, raw_response=response ) def ip_command(client: Client, args: dict) -> List[CommandResults]: """Get IP geo location. Args: client: Client object with request. args: Usually demisto.args() Returns: list of CommandResults. """ ip_list = argToList(args.get('ip', '')) command_results_list: List[CommandResults] = [] dbot_reliability = DBotScoreReliability.get_dbot_score_reliability_from_str(client.reliability) for ip_ in ip_list: try: response = client.ip_geo_get_request(ip_) dbot_score = Common.DBotScore( indicator=ip_, indicator_type=DBotScoreType.IP, integration_name=client.name, reliability=dbot_reliability, score=Common.DBotScore.NONE ) ip_obj = Common.IP( ip=ip_, dbot_score=dbot_score, geo_country=response.get('countryName'), ) readable_output = tableToMarkdown(name="IP location:", t=response, removeNull=True) except Exception as err: if 'Error in API call [404] - Not Found' in str(err): response = {} dbot_score = Common.DBotScore( indicator=ip_, indicator_type=DBotScoreType.IP, integration_name=client.name, reliability=dbot_reliability, score=Common.DBotScore.NONE ) ip_obj = Common.IP( ip=ip_, dbot_score=dbot_score ) readable_output = 'IP location was not found. Please try with a different IP.' else: raise Exception(err) command_results = CommandResults( outputs_prefix=f'{client.name}.IP', outputs_key_field='ipAddress', outputs=response, readable_output=readable_output, raw_response=response, indicator=ip_obj ) command_results_list.append(command_results) return command_results_list def antivirus_signature_search(client: Client, args: dict) -> CommandResults: """Initiate antivirus signature search. Args: client: Client object with request. args: Usually demisto.args() Returns: CommandResults. """ signature_name = str(args.get('signature_name', '')) from_ = int(args.get('from', 0)) to_ = from_ + int(args.get('to', 10)) response = client.search_request('panav', from_, to_, signature_name) outputs = response outputs.update({'search_type': 'panav', 'from': from_, 'to': to_}) readable_output = tableToMarkdown(name="Antivirus Signature Search:", t=outputs, removeNull=True) return CommandResults( outputs_prefix=f'{client.name}.Search', outputs_key_field='search_request_id', outputs=outputs, readable_output=readable_output, raw_response=response ) def dns_signature_search(client: Client, args: dict) -> CommandResults: """Initiate DNS signature search. Args: client: Client object with request. args: Usually demisto.args() Returns: CommandResults. """ signature_name = str(args.get('signature_name', '')) from_ = int(args.get('from', 0)) to_ = from_ + int(args.get('to', 10)) domain_name = str(args.get('domain_name', '')) response = client.search_request('dns', from_, to_, signature_name, domain_name=domain_name) outputs = response outputs.update({'search_type': 'dns', 'from': from_, 'to': to_}) readable_output = tableToMarkdown(name="DNS Signature Search:", t=outputs, removeNull=True) return CommandResults( outputs_prefix=f'{client.name}.Search', outputs_key_field='search_request_id', outputs=outputs, readable_output=readable_output, raw_response=response ) def antispyware_signature_search(client: Client, args: dict) -> CommandResults: """Initiate anti spyware signature search. Args: client: Client object with request. args: Usually demisto.args() Returns: CommandResults. """ signature_name = str(args.get('signature_name', '')) from_ = int(args.get('from', 0)) to_ = from_ + int(args.get('to', 10)) vendor = str(args.get('vendor', '')) cve = str(args.get('cve', '')) response = client.search_request('ips', from_, to_, signature_name, vendor=vendor, cve=cve) outputs = response outputs.update({'search_type': 'ips', 'from': from_, 'to': to_}) readable_output = tableToMarkdown(name="Anti Spyware Signature Search:", t=outputs, removeNull=True) return CommandResults( outputs_prefix=f'{client.name}.Search', outputs_key_field='search_request_id', outputs=outputs, readable_output=readable_output, raw_response=response ) def signature_search_results(client: Client, args: dict): """Retrieve signature search results. Args: client: Client object with request. args: Usually demisto.args() Returns: CommandResults. """ search_request_id = str(args.get('search_request_id', '')) search_type = str(args.get('search_type', '')) try: response = client.signature_search_results_request(search_type, search_request_id) outputs = response outputs.update({'search_request_id': search_request_id}) if response.get('status') == 'submitted': # search was not completed readable_output = f'Search {search_request_id} is still in progress.' else: headers = ['signatureId', 'signatureName', 'domainName', 'cve', 'signatureType', 'status', 'category', 'firstReleaseTime', 'latestReleaseTime'] outputs.update({'status': 'completed'}) title = f'Signature search are showing {outputs.get("page_count")} of {outputs.get("total_count")} results:' readable_output = tableToMarkdown(name=title, t=outputs.get('signatures'), headers=headers, removeNull=True) return CommandResults( outputs_prefix=f'{client.name}.Search', outputs_key_field='search_request_id', outputs=outputs, readable_output=readable_output, raw_response=response ) except Exception as err: if 'Not Found' in str(err): return_warning(f'Search request ID {search_request_id} was not found.') else: raise def test_module(client: Client, *_) -> str: """Performs basic get request to get ip geo data. Args: client: Client object with request. Returns: string. """ client.ip_geo_get_request(ip_='1.1.1.1') return 'ok' def main(): """ PARSE AND VALIDATE INTEGRATION PARAMS """ params = demisto.params() auto_focus_key_retriever = AutoFocusKeyRetriever(params.get('api_key')) reliability = params.get('integrationReliability', 'D - Not usually reliable') if not DBotScoreReliability.is_valid_type(reliability): raise Exception("Please provide a valid value for the Source Reliability parameter.") verify = not params.get('insecure', False) proxy = params.get('proxy') try: command = demisto.command() LOG(f'Command being called is {demisto.command()}') client = Client(api_key=auto_focus_key_retriever.key, verify=verify, proxy=proxy, reliability=reliability) commands = { 'threatvault-antivirus-signature-get': antivirus_signature_get, 'file': file_command, 'threatvault-dns-signature-get-by-id': dns_get_by_id, 'threatvault-antispyware-signature-get-by-id': antispyware_get_by_id, 'threatvault-ip-geo-get': ip_geo_get, 'ip': ip_command, 'threatvault-antivirus-signature-search': antivirus_signature_search, 'threatvault-dns-signature-search': dns_signature_search, 'threatvault-antispyware-signature-search': antispyware_signature_search, 'threatvault-signature-search-results': signature_search_results, } if demisto.command() == 'test-module': # This is the call made when pressing the integration Test button. return_results(test_module(client)) elif command in commands: return_results(commands[command](client, demisto.args())) else: raise NotImplementedError(f'Command "{command}" was not implemented.') except Exception as err: return_error(str(err), err) if __name__ in ('__main__', '__builtin__', 'builtins'): main()