From 95011bedf0925f46cd2cb5c4231262eb4a1b1743 Mon Sep 17 00:00:00 2001 From: savacano28 Date: Thu, 9 Oct 2025 15:18:56 +0200 Subject: [PATCH 01/12] [client] Add endpoint to fetch targets to nuclei and nmap injectors --- pyoaev/apis/endpoint.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pyoaev/apis/endpoint.py b/pyoaev/apis/endpoint.py index ead70a6..4d190da 100644 --- a/pyoaev/apis/endpoint.py +++ b/pyoaev/apis/endpoint.py @@ -1,6 +1,7 @@ from typing import Any, Dict from pyoaev import exceptions as exc +from pyoaev.apis.inputs.search import SearchPaginationInput from pyoaev.base import RESTManager, RESTObject from pyoaev.utils import RequiredOptional @@ -36,3 +37,11 @@ def upsert(self, endpoint: Dict[str, Any], **kwargs: Any) -> Dict[str, Any]: path = f"{self.path}/agentless/upsert" result = self.openaev.http_post(path, post_data=endpoint, **kwargs) return result + + @exc.on_http_error(exc.OpenAEVUpdateError) + def search( + self, input: SearchPaginationInput, **kwargs: Any + ) -> Dict[str, Any]: + path = f"{self.path}/targets" + result = self.openaev.http_post(path, post_data=input.to_dict(), **kwargs) + return result From bd61d9f9a275d4fb7968d2b205860fac9fa78e2a Mon Sep 17 00:00:00 2001 From: savacano28 Date: Thu, 9 Oct 2025 15:21:42 +0200 Subject: [PATCH 02/12] [client] Add endpoint to fetch targets to nuclei and nmap injectors --- pyoaev/apis/endpoint.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyoaev/apis/endpoint.py b/pyoaev/apis/endpoint.py index 4d190da..b7cdd12 100644 --- a/pyoaev/apis/endpoint.py +++ b/pyoaev/apis/endpoint.py @@ -39,7 +39,7 @@ def upsert(self, endpoint: Dict[str, Any], **kwargs: Any) -> Dict[str, Any]: return result @exc.on_http_error(exc.OpenAEVUpdateError) - def search( + def searchTargets( self, input: SearchPaginationInput, **kwargs: Any ) -> Dict[str, Any]: path = f"{self.path}/targets" From 7d335c92b4596256ee18c3ff8b06e6c20377fdd5 Mon Sep 17 00:00:00 2001 From: savacano28 Date: Thu, 9 Oct 2025 15:23:09 +0200 Subject: [PATCH 03/12] [client] Add endpoint to fetch targets to nuclei and nmap injectors --- test/apis/endpoint/__init__.py | 0 test/apis/endpoint/test_endpoint.py | 58 +++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 test/apis/endpoint/__init__.py create mode 100644 test/apis/endpoint/test_endpoint.py diff --git a/test/apis/endpoint/__init__.py b/test/apis/endpoint/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/test/apis/endpoint/test_endpoint.py b/test/apis/endpoint/test_endpoint.py new file mode 100644 index 0000000..61b3d3c --- /dev/null +++ b/test/apis/endpoint/test_endpoint.py @@ -0,0 +1,58 @@ +from unittest import TestCase, main, mock +from unittest.mock import ANY + +from pyoaev import OpenAEV +from pyoaev.apis.inputs.search import ( + Filter, + FilterGroup, + InjectorContractSearchPaginationInput, +) + + +def mock_response(**kwargs): + class MockResponse: + def __init__(self, json_data, status_code): + self.json_data = json_data + self.status_code = status_code + self.history = None + self.content = None + self.headers = {"Content-Type": "application/json"} + + def json(self): + return self.json_data + + return MockResponse(None, 200) + + +class TestInjectorContract(TestCase): + @mock.patch("requests.Session.request", side_effect=mock_response) + def test_search_input_correctly_serialised(self, mock_request): + api_client = OpenAEV("url", "token") + + search_input = InjectorContractSearchPaginationInput( + 0, + 20, + FilterGroup("or", [Filter("prop", "and", "eq", ["titi", "toto"])]), + None, + None, + ) + + expected_json = search_input.to_dict() + api_client.injector_contract.search(search_input) + + mock_request.assert_called_once_with( + method="post", + url="url/api/injector_contracts/search", + params={}, + data=None, + timeout=None, + stream=False, + verify=True, + json=expected_json, + headers=ANY, + auth=ANY, + ) + + +if __name__ == "__main__": + main() From 86d9c137e8c21b48b18d7931e957dc1f75798757 Mon Sep 17 00:00:00 2001 From: savacano28 Date: Thu, 9 Oct 2025 15:24:55 +0200 Subject: [PATCH 04/12] [client] Add tests --- test/apis/endpoint/test_endpoint.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/apis/endpoint/test_endpoint.py b/test/apis/endpoint/test_endpoint.py index 61b3d3c..3af8c66 100644 --- a/test/apis/endpoint/test_endpoint.py +++ b/test/apis/endpoint/test_endpoint.py @@ -5,7 +5,7 @@ from pyoaev.apis.inputs.search import ( Filter, FilterGroup, - InjectorContractSearchPaginationInput, + SearchPaginationInput, ) @@ -29,7 +29,7 @@ class TestInjectorContract(TestCase): def test_search_input_correctly_serialised(self, mock_request): api_client = OpenAEV("url", "token") - search_input = InjectorContractSearchPaginationInput( + search_input = SearchPaginationInput( 0, 20, FilterGroup("or", [Filter("prop", "and", "eq", ["titi", "toto"])]), @@ -38,11 +38,11 @@ def test_search_input_correctly_serialised(self, mock_request): ) expected_json = search_input.to_dict() - api_client.injector_contract.search(search_input) + api_client.endpoint.searchTargets(search_input) mock_request.assert_called_once_with( method="post", - url="url/api/injector_contracts/search", + url="url/api/endpoints/targets", params={}, data=None, timeout=None, From 9e5efd23172a3233926c7d26e9e8ad27725e7356 Mon Sep 17 00:00:00 2001 From: savacano28 Date: Thu, 9 Oct 2025 15:30:36 +0200 Subject: [PATCH 05/12] [client] Add tests --- pyoaev/apis/endpoint.py | 2 +- test/apis/endpoint/test_endpoint.py | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/pyoaev/apis/endpoint.py b/pyoaev/apis/endpoint.py index b7cdd12..f9683cc 100644 --- a/pyoaev/apis/endpoint.py +++ b/pyoaev/apis/endpoint.py @@ -40,7 +40,7 @@ def upsert(self, endpoint: Dict[str, Any], **kwargs: Any) -> Dict[str, Any]: @exc.on_http_error(exc.OpenAEVUpdateError) def searchTargets( - self, input: SearchPaginationInput, **kwargs: Any + self, input: SearchPaginationInput, **kwargs: Any ) -> Dict[str, Any]: path = f"{self.path}/targets" result = self.openaev.http_post(path, post_data=input.to_dict(), **kwargs) diff --git a/test/apis/endpoint/test_endpoint.py b/test/apis/endpoint/test_endpoint.py index 3af8c66..7eb531d 100644 --- a/test/apis/endpoint/test_endpoint.py +++ b/test/apis/endpoint/test_endpoint.py @@ -2,11 +2,7 @@ from unittest.mock import ANY from pyoaev import OpenAEV -from pyoaev.apis.inputs.search import ( - Filter, - FilterGroup, - SearchPaginationInput, -) +from pyoaev.apis.inputs.search import Filter, FilterGroup, SearchPaginationInput def mock_response(**kwargs): From 41d87a62581a94b65b0992efb6bec851412f2f8e Mon Sep 17 00:00:00 2001 From: savacano28 Date: Thu, 9 Oct 2025 15:34:26 +0200 Subject: [PATCH 06/12] [client] Add tests --- pyoaev/apis/endpoint.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyoaev/apis/endpoint.py b/pyoaev/apis/endpoint.py index f9683cc..e73c8a3 100644 --- a/pyoaev/apis/endpoint.py +++ b/pyoaev/apis/endpoint.py @@ -38,7 +38,7 @@ def upsert(self, endpoint: Dict[str, Any], **kwargs: Any) -> Dict[str, Any]: result = self.openaev.http_post(path, post_data=endpoint, **kwargs) return result - @exc.on_http_error(exc.OpenAEVUpdateError) + @exc.on_http_error(exc.OpenAEVListError) def searchTargets( self, input: SearchPaginationInput, **kwargs: Any ) -> Dict[str, Any]: From 4e83f4f7114919ab0cda2602cd7b54045269749b Mon Sep 17 00:00:00 2001 From: savacano28 Date: Thu, 9 Oct 2025 15:37:04 +0200 Subject: [PATCH 07/12] [client] Add tests --- test/apis/endpoint/test_endpoint.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/apis/endpoint/test_endpoint.py b/test/apis/endpoint/test_endpoint.py index 7eb531d..a234450 100644 --- a/test/apis/endpoint/test_endpoint.py +++ b/test/apis/endpoint/test_endpoint.py @@ -28,7 +28,7 @@ def test_search_input_correctly_serialised(self, mock_request): search_input = SearchPaginationInput( 0, 20, - FilterGroup("or", [Filter("prop", "and", "eq", ["titi", "toto"])]), + FilterGroup("or", [Filter("targets", "and", "eq", ["target_1", "target_2", "target_3"])]), None, None, ) From 8d2029484051f2538ff63ce4943e38760e361ee3 Mon Sep 17 00:00:00 2001 From: savacano28 Date: Thu, 9 Oct 2025 16:03:41 +0200 Subject: [PATCH 08/12] [client] Clean --- pyoaev/apis/endpoint.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pyoaev/apis/endpoint.py b/pyoaev/apis/endpoint.py index e73c8a3..5055b98 100644 --- a/pyoaev/apis/endpoint.py +++ b/pyoaev/apis/endpoint.py @@ -39,9 +39,7 @@ def upsert(self, endpoint: Dict[str, Any], **kwargs: Any) -> Dict[str, Any]: return result @exc.on_http_error(exc.OpenAEVListError) - def searchTargets( - self, input: SearchPaginationInput, **kwargs: Any - ) -> Dict[str, Any]: + def searchTargets(self, input: SearchPaginationInput, **kwargs: Any) -> Dict[str, Any]: path = f"{self.path}/targets" result = self.openaev.http_post(path, post_data=input.to_dict(), **kwargs) return result From ea60b8e14cc745d18a2532c781826ae73121fa89 Mon Sep 17 00:00:00 2001 From: savacano28 Date: Thu, 9 Oct 2025 16:15:26 +0200 Subject: [PATCH 09/12] [client] Clean --- pyoaev/apis/endpoint.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyoaev/apis/endpoint.py b/pyoaev/apis/endpoint.py index 5055b98..0042c4b 100644 --- a/pyoaev/apis/endpoint.py +++ b/pyoaev/apis/endpoint.py @@ -38,7 +38,7 @@ def upsert(self, endpoint: Dict[str, Any], **kwargs: Any) -> Dict[str, Any]: result = self.openaev.http_post(path, post_data=endpoint, **kwargs) return result - @exc.on_http_error(exc.OpenAEVListError) + @exc.on_http_error(exc.OpenAEVUpdateError) def searchTargets(self, input: SearchPaginationInput, **kwargs: Any) -> Dict[str, Any]: path = f"{self.path}/targets" result = self.openaev.http_post(path, post_data=input.to_dict(), **kwargs) From 7bdb53785565304669dae4efbf86fa3e72ac273a Mon Sep 17 00:00:00 2001 From: MarineLM Date: Mon, 13 Oct 2025 17:20:36 +0200 Subject: [PATCH 10/12] [client] set contract asset and asset-group key --- pyoaev/contracts/contract_config.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pyoaev/contracts/contract_config.py b/pyoaev/contracts/contract_config.py index 60d6937..59467c3 100644 --- a/pyoaev/contracts/contract_config.py +++ b/pyoaev/contracts/contract_config.py @@ -31,6 +31,9 @@ class ContractFieldType(str, Enum): AssetGroup: str = "asset-group" Payload: str = "payload" +class ContractFieldKey(str, Enum): + Asset: str = "assets" + AssetGroup: str = "asset_groups" class ContractOutputType(str, Enum): Text: str = "text" @@ -270,14 +273,15 @@ def get_type(self) -> str: @dataclass class ContractAsset(ContractCardinalityElement): + key: str = field(default=ContractFieldKey.Asset.value, init=False) @property def get_type(self) -> str: return ContractFieldType.Asset.value - @dataclass class ContractAssetGroup(ContractCardinalityElement): + key: str = field(default=ContractFieldKey.AssetGroup.value, init=False) @property def get_type(self) -> str: From 96616d02679e14dc7c93b062c0cf09f1787a4570 Mon Sep 17 00:00:00 2001 From: savacano28 Date: Tue, 14 Oct 2025 11:04:32 +0200 Subject: [PATCH 11/12] [client] linter --- pyoaev/apis/endpoint.py | 4 +++- pyoaev/contracts/contract_config.py | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/pyoaev/apis/endpoint.py b/pyoaev/apis/endpoint.py index 0042c4b..f9683cc 100644 --- a/pyoaev/apis/endpoint.py +++ b/pyoaev/apis/endpoint.py @@ -39,7 +39,9 @@ def upsert(self, endpoint: Dict[str, Any], **kwargs: Any) -> Dict[str, Any]: return result @exc.on_http_error(exc.OpenAEVUpdateError) - def searchTargets(self, input: SearchPaginationInput, **kwargs: Any) -> Dict[str, Any]: + def searchTargets( + self, input: SearchPaginationInput, **kwargs: Any + ) -> Dict[str, Any]: path = f"{self.path}/targets" result = self.openaev.http_post(path, post_data=input.to_dict(), **kwargs) return result diff --git a/pyoaev/contracts/contract_config.py b/pyoaev/contracts/contract_config.py index 59467c3..56de12f 100644 --- a/pyoaev/contracts/contract_config.py +++ b/pyoaev/contracts/contract_config.py @@ -31,10 +31,12 @@ class ContractFieldType(str, Enum): AssetGroup: str = "asset-group" Payload: str = "payload" + class ContractFieldKey(str, Enum): Asset: str = "assets" AssetGroup: str = "asset_groups" + class ContractOutputType(str, Enum): Text: str = "text" Number: str = "number" @@ -279,6 +281,7 @@ class ContractAsset(ContractCardinalityElement): def get_type(self) -> str: return ContractFieldType.Asset.value + @dataclass class ContractAssetGroup(ContractCardinalityElement): key: str = field(default=ContractFieldKey.AssetGroup.value, init=False) From 8679127d622b110ec647ffb2a17d2c6268e904b5 Mon Sep 17 00:00:00 2001 From: savacano28 Date: Tue, 14 Oct 2025 11:07:31 +0200 Subject: [PATCH 12/12] [client] linter --- test/apis/endpoint/test_endpoint.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/apis/endpoint/test_endpoint.py b/test/apis/endpoint/test_endpoint.py index a234450..dcf081e 100644 --- a/test/apis/endpoint/test_endpoint.py +++ b/test/apis/endpoint/test_endpoint.py @@ -28,7 +28,10 @@ def test_search_input_correctly_serialised(self, mock_request): search_input = SearchPaginationInput( 0, 20, - FilterGroup("or", [Filter("targets", "and", "eq", ["target_1", "target_2", "target_3"])]), + FilterGroup( + "or", + [Filter("targets", "and", "eq", ["target_1", "target_2", "target_3"])], + ), None, None, )