From ef4a103e36d5440975eb5f30831c61fc89d4b41d Mon Sep 17 00:00:00 2001 From: ozgen Date: Thu, 17 Sep 2026 14:17:16 +0200 Subject: [PATCH] add: add export_delta_audit_report request support --- gvm/protocols/gmp/_gmpnext.py | 53 ++++++ .../gmp/requests/next/_audit_report.py | 82 ++++++++ .../gmpnext/entities/audit_report/__init__.py | 4 + .../test_export_delta_audit_report.py | 179 ++++++++++++++++++ .../gmpnext/entities/test_audit_report.py | 7 + 5 files changed, 325 insertions(+) create mode 100644 tests/protocols/gmpnext/entities/audit_report/test_export_delta_audit_report.py diff --git a/gvm/protocols/gmp/_gmpnext.py b/gvm/protocols/gmp/_gmpnext.py index b2a702e9..0487354e 100644 --- a/gvm/protocols/gmp/_gmpnext.py +++ b/gvm/protocols/gmp/_gmpnext.py @@ -1916,6 +1916,59 @@ def export_audit_report( ) ) + def export_delta_audit_report( + self, + report_id: EntityID, + delta_report_id: EntityID, + format_id: EntityID, + *, + config_id: EntityID | None = None, + filter_string: str | None = None, + ignore_pagination: bool = False, + lean: bool = False, + notes_details: bool = False, + overrides_details: bool = False, + result_tags: bool = False, + ) -> T: + """Request an asynchronous export of a delta audit report. + + If an identical export is already pending or running, the existing + report export is returned instead of creating a duplicate. + + Args: + report_id: UUID of the audit report to export. + delta_report_id: UUID of the report used for delta comparison. + format_id: UUID of the report format to apply. + config_id: UUID of an optional report configuration. + filter_string: Filter term to apply while generating the report. + ignore_pagination: Whether pagination settings in the filter + should be ignored. + lean: Whether lean report data should be generated. + notes_details: Whether note details should be included. + overrides_details: Whether override details should be included. + result_tags: Whether result tags should be included. + + Returns: + A request for the export_delta_audit_report GMP command. + + Raises: + RequiredArgument: If report_id or delta_report_id is not provided. + """ + return self._send_request_and_transform_response( + AuditReport.export_delta_audit_report( + report_id=report_id, + delta_report_id=delta_report_id, + format_id=format_id, + config_id=config_id, + filter_string=filter_string, + ignore_pagination=ignore_pagination, + lean=lean, + notes_details=notes_details, + overrides_details=overrides_details, + result_tags=result_tags, + ) + ) + def get_report_exports( self, ) -> T: diff --git a/gvm/protocols/gmp/requests/next/_audit_report.py b/gvm/protocols/gmp/requests/next/_audit_report.py index 46ee7902..144c5957 100644 --- a/gvm/protocols/gmp/requests/next/_audit_report.py +++ b/gvm/protocols/gmp/requests/next/_audit_report.py @@ -111,3 +111,85 @@ def export_audit_report( ) return cmd + + @classmethod + def export_delta_audit_report( + cls, + report_id: EntityID, + delta_report_id: EntityID, + format_id: EntityID, + *, + config_id: EntityID | None = None, + filter_string: str | None = None, + ignore_pagination: bool = False, + lean: bool = False, + notes_details: bool = False, + overrides_details: bool = False, + result_tags: bool = False, + ) -> Request: + """Request an asynchronous export of a delta audit report. + + If an identical export is already pending or running, the existing + report export is returned instead of creating a duplicate. + + Args: + report_id: UUID of the audit report to export. + delta_report_id: UUID of the report used for delta comparison. + format_id: UUID of the report format to apply. + config_id: UUID of an optional report configuration. + filter_string: Filter term to apply while generating the report. + ignore_pagination: Whether pagination settings in the filter + should be ignored. + lean: Whether lean report data should be generated. + notes_details: Whether note details should be included. + overrides_details: Whether override details should be included. + result_tags: Whether result tags should be included. + + Returns: + A request for the export_delta_audit_report GMP command. + + Raises: + RequiredArgument: If report_id or delta_report_id is not provided. + """ + if not report_id: + raise RequiredArgument( + function=cls.export_delta_audit_report.__name__, + argument="report_id", + ) + + if not delta_report_id: + raise RequiredArgument( + function=cls.export_delta_audit_report.__name__, + argument="delta_report_id", + ) + + cmd = XmlCommand("export_delta_audit_report") + cmd.set_attribute("report_id", str(report_id)) + cmd.set_attribute("delta_report_id", str(delta_report_id)) + cmd.set_attribute("format_id", str(format_id)) + + if config_id: + cmd.set_attribute("config_id", str(config_id)) + + if filter_string is not None: + cmd.set_attribute("filter", filter_string) + + cmd.set_attribute( + "ignore_pagination", + to_bool(ignore_pagination), + ) + cmd.set_attribute("lean", to_bool(lean)) + cmd.set_attribute( + "notes_details", + to_bool(notes_details), + ) + cmd.set_attribute( + "overrides_details", + to_bool(overrides_details), + ) + cmd.set_attribute( + "result_tags", + to_bool(result_tags), + ) + + return cmd diff --git a/tests/protocols/gmpnext/entities/audit_report/__init__.py b/tests/protocols/gmpnext/entities/audit_report/__init__.py index f7e2ed9a..3ab14f40 100644 --- a/tests/protocols/gmpnext/entities/audit_report/__init__.py +++ b/tests/protocols/gmpnext/entities/audit_report/__init__.py @@ -6,6 +6,9 @@ from .test_export_audit_report import ( GmpExportAuditReportTestMixin, ) +from .test_export_delta_audit_report import ( + GmpExportDeltaAuditReportTestMixin, +) from .test_get_audit_report import ( GmpGetAuditReportTestMixin, ) @@ -15,6 +18,7 @@ __all__ = ( "GmpExportAuditReportTestMixin", + "GmpExportDeltaAuditReportTestMixin", "GmpGetAuditReportLegacyTestMixin", "GmpGetAuditReportTestMixin", ) diff --git a/tests/protocols/gmpnext/entities/audit_report/test_export_delta_audit_report.py b/tests/protocols/gmpnext/entities/audit_report/test_export_delta_audit_report.py new file mode 100644 index 00000000..38d6d25b --- /dev/null +++ b/tests/protocols/gmpnext/entities/audit_report/test_export_delta_audit_report.py @@ -0,0 +1,179 @@ +# SPDX-FileCopyrightText: 2026 Greenbone AG +# +# SPDX-License-Identifier: GPL-3.0-or-later + +from gvm.errors import RequiredArgument + + +class GmpExportDeltaAuditReportTestMixin: + def test_export_delta_audit_report_without_report_id(self): + with self.assertRaises(RequiredArgument): + self.gmp.export_delta_audit_report( + None, + delta_report_id="d1", + format_id="f1", + ) + + with self.assertRaises(RequiredArgument): + self.gmp.export_delta_audit_report( + "", + delta_report_id="d1", + format_id="f1", + ) + + def test_export_delta_audit_report_without_delta_report_id(self): + with self.assertRaises(RequiredArgument): + self.gmp.export_delta_audit_report( + report_id="r1", + delta_report_id=None, + format_id="f1", + ) + + with self.assertRaises(RequiredArgument): + self.gmp.export_delta_audit_report( + report_id="r1", + delta_report_id="", + format_id="f1", + ) + + def test_export_delta_audit_report(self): + self.gmp.export_delta_audit_report( + report_id="r1", + delta_report_id="d1", + format_id="f1", + ) + + self.connection.send.has_been_called_with( + b'' + ) + + def test_export_delta_audit_report_with_config_id(self): + self.gmp.export_delta_audit_report( + report_id="r1", + delta_report_id="d1", + format_id="f1", + config_id="c1", + ) + + self.connection.send.has_been_called_with( + b'' + ) + + def test_export_delta_audit_report_with_filter_string(self): + self.gmp.export_delta_audit_report( + report_id="r1", + delta_report_id="d1", + format_id="f1", + filter_string="compliance_levels=yniu", + ) + + self.connection.send.has_been_called_with( + b'' + ) + + def test_export_delta_audit_report_with_ignore_pagination(self): + self.gmp.export_delta_audit_report( + report_id="r1", + delta_report_id="d1", + format_id="f1", + ignore_pagination=True, + ) + + self.connection.send.has_been_called_with( + b'' + ) + + def test_export_delta_audit_report_with_lean(self): + self.gmp.export_delta_audit_report( + report_id="r1", + delta_report_id="d1", + format_id="f1", + lean=True, + ) + + self.connection.send.has_been_called_with( + b'' + ) + + def test_export_delta_audit_report_with_notes_details(self): + self.gmp.export_delta_audit_report( + report_id="r1", + delta_report_id="d1", + format_id="f1", + notes_details=True, + ) + + self.connection.send.has_been_called_with( + b'' + ) + + def test_export_delta_audit_report_with_overrides_details(self): + self.gmp.export_delta_audit_report( + report_id="r1", + delta_report_id="d1", + format_id="f1", + overrides_details=True, + ) + + self.connection.send.has_been_called_with( + b'' + ) + + def test_export_delta_audit_report_with_result_tags(self): + self.gmp.export_delta_audit_report( + report_id="r1", + delta_report_id="d1", + format_id="f1", + result_tags=True, + ) + + self.connection.send.has_been_called_with( + b'' + ) + + def test_export_delta_audit_report_with_all_arguments(self): + self.gmp.export_delta_audit_report( + report_id="r1", + delta_report_id="d1", + format_id="f1", + config_id="c1", + filter_string="compliance_levels=yniu", + ignore_pagination=True, + lean=True, + notes_details=True, + overrides_details=True, + result_tags=True, + ) + + self.connection.send.has_been_called_with( + b'' + ) diff --git a/tests/protocols/gmpnext/entities/test_audit_report.py b/tests/protocols/gmpnext/entities/test_audit_report.py index 35dd4730..31fc02cb 100644 --- a/tests/protocols/gmpnext/entities/test_audit_report.py +++ b/tests/protocols/gmpnext/entities/test_audit_report.py @@ -6,6 +6,7 @@ from ...gmpnext import GMPTestCase from ...gmpnext.entities.audit_report import ( GmpExportAuditReportTestMixin, + GmpExportDeltaAuditReportTestMixin, GmpGetAuditReportLegacyTestMixin, GmpGetAuditReportTestMixin, ) @@ -23,3 +24,9 @@ class GmpGetAuditReportLegacyTestCase( class GmpExportAuditReportTestCase(GmpExportAuditReportTestMixin, GMPTestCase): pass + + +class GmpExportDeltaAuditReportTestCase( + GmpExportDeltaAuditReportTestMixin, GMPTestCase +): + pass