From 8611ed3d0ab965e64187d38f6a6c3362f5709a40 Mon Sep 17 00:00:00 2001 From: Fede Barcelona Date: Tue, 27 Oct 2020 16:26:31 +0100 Subject: [PATCH] feat: Add download_cve_report_csv method to download the csv report (#161) This method takes a while in environments where the amount of images is very high, please use it carefully. --- sdcclient/_scanning.py | 41 ++++++++++++++++++- specs/secure/__init__.py | 0 specs/secure/scanning/__init__.py | 0 .../scanning/scanning_cve_report_spec.py | 41 +++++++++++++++++++ .../scanning_vulnerability_exceptions_spec.py | 0 .../scanning_vulnerability_spec.py | 0 6 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 specs/secure/__init__.py create mode 100644 specs/secure/scanning/__init__.py create mode 100644 specs/secure/scanning/scanning_cve_report_spec.py rename specs/secure/{ => scanning}/scanning_vulnerability_exceptions_spec.py (100%) rename specs/secure/{ => scanning}/scanning_vulnerability_spec.py (100%) diff --git a/sdcclient/_scanning.py b/sdcclient/_scanning.py index 89396305..83bce0b8 100644 --- a/sdcclient/_scanning.py +++ b/sdcclient/_scanning.py @@ -1186,4 +1186,43 @@ def update_vulnerability_exception(self, bundle, id, cve, enabled, note, expirat res_json = res.json() res_json["trigger_id"] = str(res_json["trigger_id"]).rstrip("+*") - return [True, res_json] \ No newline at end of file + return [True, res_json] + + def download_cve_report_csv(self, vuln_type="os", scope_type="static"): + """ + Downloads a CVE report in CSV format + + Args: + vuln_type (str): Vulnerability type, can be either "os" or "non-os". + scope_type (str): Scope type. Can be either "static" or "runtime". + + Returns: + A tuple of (bool, str). + The first parameter, if true, means that the result is correct, while + if false, means that there's been an error. The second parameter + will hold the response of the API call. + """ + url = f"{self.url}/api/scanning/v1/reports/csv" + + params = { + "queryType": "vuln", + "scopeType": scope_type, + "staticScope": + { + "registry": "", + "repository": "", + "tag": "" + }, + "runtimeScope": {}, + "imageQueryFilter": { + "vType": vuln_type + }, + "offset": 0, + "limit": 100000 + } + + res = self.http.post(url, data=json.dumps(params), headers=self.hdrs, verify=self.ssl_verify) + if not self._checkResponse(res): + return [False, self.lasterr] + + return [True, res.content.decode("utf-8")] diff --git a/specs/secure/__init__.py b/specs/secure/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/specs/secure/scanning/__init__.py b/specs/secure/scanning/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/specs/secure/scanning/scanning_cve_report_spec.py b/specs/secure/scanning/scanning_cve_report_spec.py new file mode 100644 index 00000000..850cadc8 --- /dev/null +++ b/specs/secure/scanning/scanning_cve_report_spec.py @@ -0,0 +1,41 @@ +import os + +from expects import * +from mamba import * + +from sdcclient import SdScanningClient +from specs import be_successful_api_call + +with description("CVE Reports", "integration") as self: + with before.all: + self.client = SdScanningClient(sdc_url=os.getenv("SDC_SECURE_URL", "https://secure.sysdig.com"), + token=os.getenv("SDC_SECURE_TOKEN")) + with context("when the CSV of static can be downloaded"): + with it("is able to download it for OS vulnerabilities"): + ok, csv = self.client.download_cve_report_csv(vuln_type="os", scope_type="static") + + expect((ok, csv)).to(be_successful_api_call) + expect(csv).to(start_with("Image Name,Tag,Package Name,Package Version,Package Path,Severity,Fixed In," + "Vulnerability ID,Links,Image Digest,Runtime Metadata")) + + with it("is able to download it for non-OS vulnerabilities"): + ok, csv = self.client.download_cve_report_csv(vuln_type="non-os", scope_type="static") + + expect((ok, csv)).to(be_successful_api_call) + expect(csv).to(start_with("Image Name,Tag,Package Name,Package Version,Package Path,Severity,Fixed In," + "Vulnerability ID,Links,Image Digest,Runtime Metadata")) + + with context("when the CSV of runtime can be downloaded"): + with it("is able to download it for OS vulnerabilities"): + ok, csv = self.client.download_cve_report_csv(vuln_type="os", scope_type="runtime") + + expect((ok, csv)).to(be_successful_api_call) + expect(csv).to(start_with("Image Name,Tag,Package Name,Package Version,Package Path,Severity,Fixed In," + "Vulnerability ID,Links,Image Digest,Runtime Metadata")) + + with it("is able to download it for non-OS vulnerabilities"): + ok, csv = self.client.download_cve_report_csv(vuln_type="non-os", scope_type="runtime") + + expect((ok, csv)).to(be_successful_api_call) + expect(csv).to(start_with("Image Name,Tag,Package Name,Package Version,Package Path,Severity,Fixed In," + "Vulnerability ID,Links,Image Digest,Runtime Metadata")) diff --git a/specs/secure/scanning_vulnerability_exceptions_spec.py b/specs/secure/scanning/scanning_vulnerability_exceptions_spec.py similarity index 100% rename from specs/secure/scanning_vulnerability_exceptions_spec.py rename to specs/secure/scanning/scanning_vulnerability_exceptions_spec.py diff --git a/specs/secure/scanning_vulnerability_spec.py b/specs/secure/scanning/scanning_vulnerability_spec.py similarity index 100% rename from specs/secure/scanning_vulnerability_spec.py rename to specs/secure/scanning/scanning_vulnerability_spec.py