QualysCreateIncidentFromReport
Create incidents from a Qualys report (XML), based on the Qualys asset ID and vulnerability ID (QID). Duplicate incidents are not created for the same asset ID and QID.
python · Qualys
Source
import demistomock as demisto # noqa: F401 from CommonServerPython import * # noqa: F401 import json def get_asset_id_for_ip(ip): resp = demisto.executeCommand("qualys-host-list", {"ips": ip}) if isError(resp[0]): demisto.results(resp) sys.exit(0) if isinstance(resp_dict := resp[0], dict) and isinstance(xml_string := resp_dict["Contents"], str): json_string: str = xml2json(xml_string) asset_id = demisto.get(json.loads(json_string), "HOST_LIST_OUTPUT.RESPONSE.HOST_LIST.HOST.ID") else: asset_id = demisto.get(resp[0], "Contents.HOST_LIST_OUTPUT.RESPONSE.HOST_LIST.HOST.ID") return asset_id def main(): incident_type = demisto.args().get("incidentType", "Vulnerability") max_file_size = int(demisto.args().get("maxFileSize", 1024**2)) min_severity = int(demisto.args().get("minSeverity", 1)) file_entry = demisto.getFilePath(demisto.args().get("entryID")) with open(file_entry["path"]) as f: data = f.read(max_file_size) if data: report = json.loads(xml2json(data)) generation_date = demisto.get(report, "ASSET_DATA_REPORT.HEADER.GENERATION_DATETIME") # Get asset list asset_list = demisto.get(report, "ASSET_DATA_REPORT.HOST_LIST.HOST") if not asset_list: demisto.results( {"Type": entryTypes["note"], "ContentsFormat": formats["text"], "Contents": "No vulnerable assets were found"} ) sys.exit(0) if not isinstance(asset_list, list): asset_list = [asset_list] # Get QIDs only if over relevant severity general_vulnerabilities = argToList(demisto.get(report, "ASSET_DATA_REPORT.GLOSSARY.VULN_DETAILS_LIST.VULN_DETAILS")) if not isinstance(general_vulnerabilities, list): general_vulnerabilities = [general_vulnerabilities] # Get list of QID with severity >= min_severity qid_severity = [ demisto.get(vulnerability, "QID.#text") for vulnerability in general_vulnerabilities if demisto.get(vulnerability, "SEVERITY") and (int(demisto.get(vulnerability, "SEVERITY")) >= min_severity) ] for asset in asset_list: # Get Asset ID from Qualys ip = demisto.get(asset, "IP") if not ip: demisto.results( { "Type": entryTypes["error"], "ContentsFormat": formats["text"], "Contents": f"No IP was found for asset {str(asset)}", } ) sys.exit(0) asset_id = get_asset_id_for_ip(ip) if not asset_id: demisto.results( { "Type": entryTypes["error"], "ContentsFormat": formats["text"], "Contents": f"No ID was found for asset {str(asset)}", } ) sys.exit(0) # Get Asset vulnerability list vulnerabilities = argToList(demisto.get(asset, "VULN_INFO_LIST.VULN_INFO")) if not isinstance(vulnerabilities, list): vulnerabilities = [vulnerabilities] qids = (demisto.get(vulnerability, "QID.#text") for vulnerability in vulnerabilities) # Get only the QIDs that exists in asset and has severity >= min_severity qids = list(set(qids) & set(qid_severity)) for qid in qids: # Search for existing open incidents with the same Vendor ID and Asset ID. # Will open a new incident only if such an incident not exists. resp = demisto.executeCommand( "getIncidents", {"query": f"vendorid: {qid} and assetid: {asset_id} and --status:Closed"} ) if isError(resp[0]): demisto.results(resp) sys.exit(0) incident_number = demisto.get(resp[0], "Contents.total") try: incident_number = int(incident_number) except Exception: demisto.results( { "Type": entryTypes["error"], "ContentsFormat": formats["text"], "Contents": "Error while searching the incident repository", } ) sys.exit(0) if incident_number == 0: # Create incident demisto.executeCommand( "createNewIncident", { "name": f"Vulnerability - Asset {asset_id} QID {qid} - {generation_date}", "vendorid": str(qid), "type": incident_type, "assetid": str(asset_id), }, ) demisto.results("Done.") else: demisto.results({"Type": entryTypes["error"], "ContentsFormat": formats["text"], "Contents": "No data could be read."}) if __name__ in ("__main__", "__builtin__", "builtins"): main()
README
Creates incidents from a Qualys report (XML), based on the Qualys asset ID and vulnerability ID (QID).
Duplicates the incidents that are not created for the same asset ID and QID.
Script Data
| Name | Description |
|---|---|
| Script Type | python |
| Tags | qualys |
Dependencies
This script uses the following commands and scripts.
- qualys-host-list
Inputs
| Argument Name | Description |
|---|---|
| entryID | The War Room entryID of the XML report. |
| maxFileSize | The maximum file size to load, in bytes. The default is 1024 KB. |
| minSeverity | The minimum Qualys severity to create incidents for. |
| incidentType | The incident type to create incidents for. The default is “Vulnerability”. |
Outputs
There are no outputs for this script.