def _test_connectivity(self, param): # Progress self.save_progress(PASSIVETOTAL_USING_BASE_URL, base_url=self._base_url) # Connectivity self.save_progress(phantom.APP_PROG_CONNECTING_TO_ELLIPSES, self._host) endpoint = '/enrichment' action_result = ActionResult() self.save_progress(PASSIVETOTAL_MSG_GET_DOMAIN_TEST) ret_val, response, status_code = self._make_rest_call( endpoint, {'query': 'phantomcyber.com'}, action_result) if (phantom.is_fail(ret_val)): self.debug_print(action_result.get_message()) self.set_status(phantom.APP_ERROR, action_result.get_message()) self.append_to_message(PASSIVETOTAL_ERR_CONNECTIVITY_TEST) return phantom.APP_ERROR return self.set_status_save_progress( phantom.APP_SUCCESS, PASSIVETOTAL_SUCC_CONNECTIVITY_TEST)
def _test_connectivity(self, param): # Progress self.save_progress(CISCOUMB_USING_BASE_URL, base_url=self._base_url) # Connectivity self.save_progress(phantom.APP_PROG_CONNECTING_TO_ELLIPSES, self._host) endpoint = '/domains' action_result = ActionResult() self.save_progress(CISCOUMB_MSG_GET_DOMAIN_LIST_TEST) ret_val, response, status_code = self._make_rest_call( endpoint, action_result, { 'page': 1, 'limit': 1 }) if (phantom.is_fail(ret_val)): self.debug_print(action_result.get_message()) self.set_status(phantom.APP_ERROR, action_result.get_message()) self.append_to_message(CISCOUMB_ERR_CONNECTIVITY_TEST) return self.get_status() return self.set_status_save_progress(phantom.APP_SUCCESS, CISCOUMB_SUCC_CONNECTIVITY_TEST)
def _make_rest_call_abstract(self, endpoint, action_result, data=None, params=None, method="post", accept_headers=None): """ This method generates a new token if it is not available or if the existing token has expired and makes the call using _make_rest_call method. :param endpoint: REST endpoint :param action_result: object of ActionResult class :param data: request body :param params: request params :param method: GET/POST/PUT/DELETE (Default will be POST) :param accept_headers: requests headers :return: status phantom.APP_SUCCESS/phantom.APP_ERROR (along with appropriate message) and API response """ # Use this object for _make_rest_call # Final status of action_result will be determined after retry, in case the token is expired intermediate_action_result = ActionResult() response_data = None # Generate new token if not available if not self._token: ret_code = self._generate_api_token(action_result) if phantom.is_fail(ret_code): return action_result.get_status(), response_data # Prepare request headers headers = {'Content-Type': 'application/json', "Authorization": "AR-JWT {}".format(self._token)} # Updating headers if Content-Type is 'multipart/formdata' if accept_headers: headers.update(accept_headers) # Make call rest_ret_code, response_data, response = self._make_rest_call(endpoint, intermediate_action_result, headers=headers, params=params, data=data, method=method) # If token is invalid in case of API call, generate new token and retry if str(consts.BMCREMEDY_REST_RESP_UNAUTHORIZED) in str(intermediate_action_result.get_message()): ret_code = self._generate_api_token(action_result) if phantom.is_fail(ret_code): return action_result.get_status(), response_data # Update headers with new token headers["Authorization"] = "AR-JWT {}".format(self._token) # Retry the REST call with new token generated rest_ret_code, response_data, response = self._make_rest_call(endpoint, intermediate_action_result, headers=headers, params=params, data=data, method=method) # Assigning intermediate action_result to action_result, since no further invocation required if phantom.is_fail(rest_ret_code): action_result.set_status(rest_ret_code, intermediate_action_result.get_message()) return action_result.get_status(), response_data return phantom.APP_SUCCESS, response_data
def _make_rest_call_abstract(self, endpoint, action_result, data=None, params=None, auth_mode="Bearer", method="post"): # Use this object for make_rest_call # Final status of action_result would be determined # after retry if token expired intermediate_action_result = ActionResult() response = None headers = { 'Content-Type': 'application/json', 'Accept': 'application/json' } # Generate new token if not available if not self._token: ret_code = self._generate_api_token(action_result) if phantom.is_fail(ret_code): return action_result.get_status(), response # Make rest call rest_ret_code, response = self._make_rest_call( endpoint, intermediate_action_result, headers, data, params, auth_mode, method) # If token is invalid in case of api calls other than generate token, generate new token and retry if auth_mode != "Basic" and 'Detail: invalid_token' in str( intermediate_action_result.get_message()): ret_code = self._generate_api_token(action_result) if phantom.is_fail(ret_code): return action_result.get_status(), response # Retry the rest call with new token generated rest_ret_code, response = self._make_rest_call( endpoint, intermediate_action_result, headers, data, params, auth_mode, method) # Assigning intermediate action_result to action_result, # since no further invocation required if phantom.is_fail(rest_ret_code): action_result.set_status(rest_ret_code, intermediate_action_result.get_message()) return action_result.get_status(), response return phantom.APP_SUCCESS, response
def _list_tickets(self, param): # Create the action result action_result = self.add_action_result(ActionResult(param)) # Create RT session if phantom.is_fail(self._create_rt_session(action_result)): return action_result.get_status() queue = param.get(RT_JSON_QUEUE, DEFAULT_QUEUE) query = param.get(RT_JSON_QUERY, '').strip() if query and not query.startswith('AND'): query = ' AND {0}'.format(query) # Set up the query query = "Queue='{0}'{1}".format(queue, query) # Query the device for the list of tickets ret_val, resp_text = self._make_rest_call("search/ticket", action_result, params={'query': query}) if phantom.is_fail(ret_val): return ret_val if 'No matching results.' in resp_text: return action_result.set_status(phantom.APP_SUCCESS, 'Query returned no results') # Get ticket ID for each line in response tickets = [x.split(':')[0] for x in resp_text.strip().split('\n')[2:]] if tickets and "Invalid query" in tickets[0]: return action_result.set_status( phantom.APP_ERROR, 'Given query is invalid. Details:\n\n{0}'.format(resp_text)) # Tickets will be a list of tuples, where the first element will be the ticket ID and the second element will be the subject for ticket in tickets: ar = ActionResult() if phantom.is_fail(self._get_ticket_details(ticket, ar)): self.debug_print( 'Could not get ticket details for ID {0}: {1}'.format( ticket, ar.get_message())) continue action_result.add_data(ar.get_data()[0]) action_result.set_summary({RT_TOTAL_ISSUES: len(tickets)}) return action_result.set_status(phantom.APP_SUCCESS)
def _test_connectivity(self, param): """ Called when the user depresses the test connectivity button on the Phantom UI. Use a basic query to determine if the device IP/hostname, username and password is correct """ action_result = ActionResult() self.save_progress(FORTIGATE_TEST_CONNECTIVITY_MSG) self.save_progress("Configured URL: {}".format(self._device)) ret_val = self._login(action_result) if phantom.is_fail(ret_val): # self.save_progress("Test Connectivity Failed") self.save_progress(action_result.get_message()) # return action_result.get_status() # If SSL is enabled and URL configuration has IP address if self._verify_server_cert and (phantom.is_ip(self._device) or self._is_ipv6(self._device)): # The failure could be due to IP provided in URL instead of hostname self.save_progress(FORTIGATE_TEST_WARN_MSG) self.set_status(phantom.APP_ERROR, FORTIGATE_TEST_CONN_FAIL) return action_result.get_status() self.save_progress(FORTIGATE_TEST_ENDPOINT_MSG) # Querying endpoint to check connection to device status, _ = self._make_rest_call(FORTIGATE_BLOCKED_IPS, action_result) if phantom.is_fail(status): self.save_progress(action_result.get_message()) self.set_status(phantom.APP_ERROR, FORTIGATE_TEST_CONN_FAIL) return action_result.get_status() self.set_status_save_progress(phantom.APP_SUCCESS, FORTIGATE_TEST_CONN_SUCC) return action_result.get_status()
def _test_asset_connectivity(self, param): action_result = ActionResult() self.save_progress(PHISHME_CONNECTION_TEST_MSG) params = {'threatType': 'malware'} return_value, json_resp = self._make_rest_call(PHISHME_ENDPOINT, action_result, params=params) if phantom.is_fail(return_value): self.save_progress(action_result.get_message()) self.set_status(phantom.APP_ERROR, PHISHME_CONNECTION_TEST_ERR_MSG) return action_result.get_status() self.set_status_save_progress(phantom.APP_SUCCESS, PHISHME_CONNECTION_TEST_SUCC_MSG) return action_result.get_status()
def _test_connectivity(self, param): action_result = ActionResult() self.save_progress(DEEPSIGHT_TEST_ENDPOINT) return_val, json_resp = self._make_rest_call( DEEPSIGHT_ENDPOINT_USAGE_LIMIT, action_result) if (phantom.is_fail(return_val)): self.save_progress(action_result.get_message()) self.set_status(phantom.APP_ERROR, DEEPSIGHT_TEST_CONNECTIVITY_FAIL) return action_result.get_status() self.set_status_save_progress(phantom.APP_SUCCESS, DEEPSIGHT_TEST_CONNECTIVITY_PASS) return action_result.get_status()
def _test_connectivity(self): action_result = ActionResult() self.save_progress("Starting connectivity test") ret_val = self._init_api(action_result) if (phantom.is_fail(ret_val)): return self.set_status_save_progress(phantom.APP_ERROR, "Connectivity test failed") # Now we need to send a command to test if creds are valid self.save_progress("Making a request to PAN AutoFocus") r = self._afapi.export() ret_val = self._validate_api_call(r, action_result) if (phantom.is_fail(ret_val)): self.save_progress(action_result.get_message()) self.save_progress("Test Connectivity failed") return self.set_status(phantom.APP_ERROR) j = r.json['bucket_info'] self.save_progress("{}/{} daily points remaining".format(j['daily_points_remaining'], j['daily_points'])) return self.set_status_save_progress(phantom.APP_SUCCESS, "Connectivity test passed")
def _test_connectivity(self, param): action_result = ActionResult() self.save_progress(DNSDB_TEST_CONNECTIVITY_MSG) ret_val, json_resp = self._make_rest_call( (DNSDB_ENDPOINT_DOMAIN).format(domain=DNSDB_TEST_CONN_DOMAIN), action_result) # Forcefully set the status of the BaseConnector to failure, since # action_result is not added to the BaseConnector. if (phantom.is_fail(ret_val)): self.save_progress(action_result.get_message()) self.set_status(phantom.APP_ERROR, DNSDB_TEST_CONN_FAIL) return action_result.get_status() self.set_status_save_progress(phantom.APP_SUCCESS, DNSDB_TEST_CONN_SUCC) return action_result.get_status()
def _test_connectivity(self, param): action_result = ActionResult() self.save_progress(SYMANTEC_CONNECTION_TEST_MSG) response_status = self._generate_api_token(action_result) if phantom.is_fail(response_status): self.save_progress( SYMANTEC_CONNECTION_TEST_INVALID_URL_MSG.format( url=self._base_url)) self.save_progress(action_result.get_message()) self.set_status(phantom.APP_ERROR, SYMANTEC_CONNECTION_TEST_ERR_MSG) return action_result.get_status() self.set_status_save_progress(phantom.APP_SUCCESS, SYMANTEC_CONNECTION_TEST_SUCC_MSG) return action_result.get_status()
def _test_asset_connectivity(self, param): """ This function tests the connectivity of an asset with given credentials. :param param: dictionary of input parameters :return: status phantom.APP_SUCCESS/phantom.APP_ERROR (along with appropriate message) """ action_result = ActionResult() self.save_progress(consts.BMCREMEDY_TEST_CONNECTIVITY_MSG) self.save_progress("Configured URL: {}".format(self._base_url)) response_status = self._generate_api_token(action_result) if phantom.is_fail(response_status): self.save_progress(action_result.get_message()) self.set_status(phantom.APP_ERROR, consts.BMCREMEDY_TEST_CONNECTIVITY_FAIL) return action_result.get_status() self.set_status_save_progress(phantom.APP_SUCCESS, consts.BMCREMEDY_TEST_CONNECTIVITY_PASS) return action_result.get_status()
def _ingest_report_data(self, report_data): # Not adding action_result to base connector, use this object for rest calls only # even if individual report ingestion fails, ingestion should continue for other reports action_result = ActionResult() # Not adding summary_data to action_result of base connector # use this object for download pdf function call summary_data = {} container = {} # Getting report details return_val, resp = self._make_rest_call( DEEPSIGHT_ENDPOINT_MATI_REPORT.format(mati_id=report_data['id']), action_result) # Something went wrong with the request if phantom.is_fail(return_val): self.debug_print( DEEPSIGHT_REPORT_ERROR.format( report=report_data['id'], message=action_result.get_message())) self.save_progress(DEEPSIGHT_REPORT_ERROR, report=report_data['id'], message=action_result.get_message()) return action_result.get_status() if (resp.get(DEEPSIGHT_JSON_RESOURCE_NOT_FOUND)): return phantom.APP_SUCCESS report_detail = resp.get(DEEPSIGHT_JSON_RESPONSE) container["name"] = report_data['title'] container['data'] = report_detail container['description'] = 'Report ID {report}'.format( report=str(report_data['id'])) container['source_data_identifier'] = str(report_data['id']) ret_val, response, container_id = self.save_container(container) # Create Report Artifact with report id self._create_report_artifact(str(report_data['id']), container_id) # Something went wrong while creating container if phantom.is_fail(ret_val): self.debug_print( DEEPSIGHT_CONTAINER_ERROR.format(report=report_data['id']), response) self.save_progress(DEEPSIGHT_CONTAINER_ERROR, report=report_data['id']) return action_result.set_status(phantom.APP_ERROR) # Create File Artifacts self._create_file_artifacts(report_detail, container_id) # Get Discrete entities ip, url, domain and email discrete_urls, discrete_ips, discrete_domains, discrete_emails = self._get_descrete_entities( report_detail) # Create URL Artifacts self._create_url_artifacts(discrete_urls, container_id) # Create IP Artifacts self._create_ip_artifacts(discrete_ips, container_id) # Create Domain Artifacts self._create_domain_artifacts(discrete_domains, container_id) # Create Email Artifacts self._create_email_artifacts(discrete_emails, container_id) # Download report pdf if enabled # Save the pdf to vault if self._download_pdf_config: # Fetching summary data summ_return_val, summ_resp = self._make_rest_call( DEEPSIGHT_ENDPOINT_MATI_REPORT_SUMMARY.format( mati_id=report_data['id']), action_result) # Something went wrong with the request if phantom.is_fail(summ_return_val): self.debug_print( DEEPSIGHT_REPORT_PDF_ERROR.format( report=report_data['id'], message=action_result.get_message())) self.save_progress(DEEPSIGHT_REPORT_PDF_ERROR, report=report_data['id'], message=action_result.get_message()) return action_result.get_status() if summ_resp.get(DEEPSIGHT_JSON_RESPONSE): summ_report_detail = summ_resp.get(DEEPSIGHT_JSON_RESPONSE) report_detail[ DEEPSIGHT_JSON_REPORT_SUMMARY_DATA] = summ_report_detail action_result.add_data(report_detail) download_ret_value = self._download_report_pdf( report_data['id'], container_id, action_result, summary_data) if phantom.is_fail(download_ret_value): return action_result.get_status() return phantom.APP_SUCCESS
def _ingest_threat_data(self, endpoint, threat_id): # Not adding action_result to base connector, use this object for rest calls only # even if individual threat ingestion fails, ingestion should continue for other threats action_result = ActionResult() container = {} # dictionary used to determine severity of artifacts phantom_severity_mapping = { "Major": "high", "Moderate": "medium" } # Getting report details return_value, json_resp = self._make_rest_call(endpoint + threat_id, action_result, method="get") # Something went wrong with the request if phantom.is_fail(return_value): self.save_progress(PHISHME_THREAT_DATA_ERROR.format(id=str(threat_id), message=action_result.get_message())) self.debug_print(PHISHME_THREAT_DATA_ERROR.format(id=str(threat_id), message=action_result.get_message())) return action_result.get_status() # Resource not found is treated as app success if json_resp.get(PHISHME_JSON_RESOURCE_NOT_FOUND): self.save_progress(PHISHME_REST_RESP_RESOURCE_NOT_FOUND_MSG) return phantom.APP_SUCCESS # getting name and description of container from threat report obtained if json_resp.get("data"): container_details = { "container_name": json_resp["data"].get("label"), "container_description": json_resp["data"].get("executiveSummary") } # default value of name and description of container else: container_details = { "container_name": "threat_" + str(threat_id), "container_description": PHISHME_CONTAINER_DESC.format( str(threat_id) ) } # Creating container container["name"] = container_details["container_name"] container["description"] = container_details["container_description"] container['data'] = json_resp container['source_data_identifier'] = threat_id return_value, response, container_id = self.save_container( container ) # Something went wrong while creating container if phantom.is_fail(return_value): self.debug_print(PHISHME_CONTAINER_ERROR, container) # Not setting action_result to error, as there may be other data to ingest return phantom.APP_ERROR # This dictionary contains the mapping of cefs to create. It lists down all the keys to look for in # response object and map it with potential cefs to create. This dictionary contains mappings for # executableSet key # Key: executableSet # Value: {child key name: {cef name of value, contains for cef name}} executableset_cef_mapping = { "md5Hex": {"cef_name": "fileHashMd5", "cef_contains": ["hash", "md5"]}, "sha1Hex": {"cef_name": "fileHashSha1", "cef_contains": ["hash", "sha1"]}, "sha384Hex": {"cef_name": "fileHashSha384", "cef_contains": ["hash"]}, "sha512Hex": {"cef_name": "fileHashSha512", "cef_contains": ["hash"]}, "sha224Hex": {"cef_name": "fileHashSha224", "cef_contains": ["hash"]}, "sha256Hex": {"cef_name": "fileHashSha256", "cef_contains": ["hash", "sha256"]}, "fileName": {"cef_name": "fileName", "cef_contains": ["file name"]}, "type": {"cef_name": "fileType", "cef_contains": []}, "dateEntered": {"cef_name": "fileModificationTime", "cef_contains": []} } response_data = json_resp["data"] # Iterate through the executableSet key from response data and # look for applicable cef to create in an artifact for executableset_data in response_data.get("executableSet", []): cef = {} cef_types = {} for threat_data_key in list(executableset_cef_mapping.keys()): cef_details = executableset_cef_mapping[threat_data_key] # Adding cef if found from executableSet key if executableset_data.get(threat_data_key): cef_value = executableset_data[threat_data_key] # Converting date from epoch format to human readable format if threat_data_key == "dateEntered": cef_value = datetime.fromtimestamp( int(cef_value) / 1000.0).strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z' cef[cef_details["cef_name"]] = cef_value cef_types[cef_details["cef_name"]] = cef_details["cef_contains"] # Making artifacts after gathering data for artifacts return_value, artifact = self._create_artifact("File Artifact", cef, cef_types, container_id) # Something went wrong while creating artifacts # continue creating next artifact if phantom.is_fail(return_value): self.debug_print(PHISHME_ARTIFACTS_ERROR, artifact) # dictionary containing details of blockSet key from the response obtained # Key: Value of blockType key in elements of blockSet key # Value: {artifact name, cef name of value, contains for cef name} blockset_cef_mapping = { "IPv4 Address": {"artifact_name": "IP Artifact", "cef_name": "destinationAddress", "cef_contains": ["ip"]}, "Domain Name": {"artifact_name": "Domain Artifact", "cef_name": "destinationDnsDomain", "cef_contains": ["domain"]}, "URL": {"artifact_name": "URL Artifact", "cef_name": "requestURL", "cef_contains": ["url"]} } # creating artifacts from data in blockSet key. # Checking if blockType key is present # Checking if value of blockType is any one of 'IPv4 Address', 'Domain Name' or 'URL' # Checking if impact key is present and its value must be 'Major' or 'Moderate' for blockset_data in response_data.get("blockSet", []): if blockset_data.get('blockType') in blockset_cef_mapping and \ blockset_data.get("impact") in ["Major", "Moderate"]: cef_details = blockset_cef_mapping[blockset_data["blockType"]] cef = {cef_details["cef_name"]: blockset_data["data"]} cef_types = {cef_details["cef_name"]: cef_details["cef_contains"]} severity = phantom_severity_mapping[blockset_data.get("impact")] return_value, artifact = self._create_artifact(cef_details["artifact_name"], cef, cef_types, container_id, severity) # Something went wrong while creating artifacts # continue creating next artifact if phantom.is_fail(return_value): self.debug_print(PHISHME_ARTIFACTS_ERROR, artifact) continue # Adding threat details as artifact cef = {"CofenseIntelligenceThreatId": threat_id, "threatType": response_data.get("threatType")} cef_types = {"CofenseIntelligenceThreatId": ["cofense intelligence threat id"]} return_value, artifact = self._create_artifact("Threat Artifact", cef, cef_types, container_id) # Something went wrong while creating artifacts # continue creating next artifact if phantom.is_fail(return_value): self.debug_print(PHISHME_ARTIFACTS_ERROR, artifact) return phantom.APP_SUCCESS