pyoaev 1.18.20__tar.gz → 2.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pyoaev-1.18.20/pyoaev.egg-info → pyoaev-2.0.1}/PKG-INFO +1 -1
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/__init__.py +1 -1
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/_version.py +1 -1
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/apis/endpoint.py +9 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/apis/inject_expectation/inject_expectation.py +7 -1
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/contracts/contract_config.py +7 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1/pyoaev.egg-info}/PKG-INFO +1 -1
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev.egg-info/SOURCES.txt +2 -0
- pyoaev-2.0.1/test/apis/endpoint/test_endpoint.py +57 -0
- pyoaev-2.0.1/test/signatures/__init__.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/LICENSE +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/README.md +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/docs/conf.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/apis/__init__.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/apis/attack_pattern.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/apis/collector.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/apis/cve.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/apis/document.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/apis/inject.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/apis/inject_expectation/__init__.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/apis/inject_expectation/model/__init__.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/apis/inject_expectation/model/expectation.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/apis/inject_expectation_trace.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/apis/injector.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/apis/injector_contract.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/apis/inputs/__init__.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/apis/inputs/search.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/apis/kill_chain_phase.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/apis/me.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/apis/organization.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/apis/payload.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/apis/security_platform.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/apis/tag.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/apis/team.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/apis/user.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/backends/__init__.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/backends/backend.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/backends/protocol.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/base.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/client.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/configuration/__init__.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/configuration/configuration.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/configuration/sources.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/contracts/__init__.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/contracts/contract_builder.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/contracts/contract_utils.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/contracts/variable_helper.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/daemons/__init__.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/daemons/base_daemon.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/daemons/collector_daemon.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/exceptions.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/helpers.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/mixins.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/signatures/__init__.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/signatures/signature_match.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/signatures/signature_type.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/signatures/types.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev/utils.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev.egg-info/dependency_links.txt +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev.egg-info/requires.txt +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyoaev.egg-info/top_level.txt +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/pyproject.toml +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/scripts/release.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/setup.cfg +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/test/__init__.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/test/apis/__init__.py +0 -0
- {pyoaev-1.18.20/test/apis/expectation → pyoaev-2.0.1/test/apis/endpoint}/__init__.py +0 -0
- {pyoaev-1.18.20/test/apis/injector_contract → pyoaev-2.0.1/test/apis/expectation}/__init__.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/test/apis/expectation/test_expectation.py +0 -0
- {pyoaev-1.18.20/test/configuration → pyoaev-2.0.1/test/apis/injector_contract}/__init__.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/test/apis/injector_contract/test_injector_contract.py +0 -0
- {pyoaev-1.18.20/test/daemons → pyoaev-2.0.1/test/configuration}/__init__.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/test/configuration/test_configuration.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/test/configuration/test_sources.py +0 -0
- {pyoaev-1.18.20/test/signatures → pyoaev-2.0.1/test/daemons}/__init__.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/test/daemons/test_base_daemon.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/test/daemons/test_collector_daemon.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/test/signatures/test_signature_match.py +0 -0
- {pyoaev-1.18.20 → pyoaev-2.0.1}/test/signatures/test_signature_type.py +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from typing import Any, Dict
|
|
2
2
|
|
|
3
3
|
from pyoaev import exceptions as exc
|
|
4
|
+
from pyoaev.apis.inputs.search import SearchPaginationInput
|
|
4
5
|
from pyoaev.base import RESTManager, RESTObject
|
|
5
6
|
from pyoaev.utils import RequiredOptional
|
|
6
7
|
|
|
@@ -36,3 +37,11 @@ class EndpointManager(RESTManager):
|
|
|
36
37
|
path = f"{self.path}/agentless/upsert"
|
|
37
38
|
result = self.openaev.http_post(path, post_data=endpoint, **kwargs)
|
|
38
39
|
return result
|
|
40
|
+
|
|
41
|
+
@exc.on_http_error(exc.OpenAEVUpdateError)
|
|
42
|
+
def searchTargets(
|
|
43
|
+
self, input: SearchPaginationInput, **kwargs: Any
|
|
44
|
+
) -> Dict[str, Any]:
|
|
45
|
+
path = f"{self.path}/targets"
|
|
46
|
+
result = self.openaev.http_post(path, post_data=input.to_dict(), **kwargs)
|
|
47
|
+
return result
|
|
@@ -28,7 +28,13 @@ class InjectExpectationManager(ListMixin, UpdateMixin, RESTManager):
|
|
|
28
28
|
result = self.openaev.http_get(
|
|
29
29
|
path,
|
|
30
30
|
query_data=(
|
|
31
|
-
{"expiration_time": expiration_time}
|
|
31
|
+
{"expiration_time": expiration_time}
|
|
32
|
+
if expiration_time
|
|
33
|
+
else {
|
|
34
|
+
"expiration_time": 360
|
|
35
|
+
} # 360 minutes (6 hours) - corresponds to the expiration time configured in the Expectations Expiration Manager.
|
|
36
|
+
# Expectations older than this duration will be automatically expired to prevent
|
|
37
|
+
# processing outdated data, particularly important when launching new collectors.
|
|
32
38
|
),
|
|
33
39
|
**kwargs,
|
|
34
40
|
)
|
|
@@ -32,6 +32,11 @@ class ContractFieldType(str, Enum):
|
|
|
32
32
|
Payload: str = "payload"
|
|
33
33
|
|
|
34
34
|
|
|
35
|
+
class ContractFieldKey(str, Enum):
|
|
36
|
+
Asset: str = "assets"
|
|
37
|
+
AssetGroup: str = "asset_groups"
|
|
38
|
+
|
|
39
|
+
|
|
35
40
|
class ContractOutputType(str, Enum):
|
|
36
41
|
Text: str = "text"
|
|
37
42
|
Number: str = "number"
|
|
@@ -270,6 +275,7 @@ class ContractSelect(ContractCardinalityElement):
|
|
|
270
275
|
|
|
271
276
|
@dataclass
|
|
272
277
|
class ContractAsset(ContractCardinalityElement):
|
|
278
|
+
key: str = field(default=ContractFieldKey.Asset.value, init=False)
|
|
273
279
|
|
|
274
280
|
@property
|
|
275
281
|
def get_type(self) -> str:
|
|
@@ -278,6 +284,7 @@ class ContractAsset(ContractCardinalityElement):
|
|
|
278
284
|
|
|
279
285
|
@dataclass
|
|
280
286
|
class ContractAssetGroup(ContractCardinalityElement):
|
|
287
|
+
key: str = field(default=ContractFieldKey.AssetGroup.value, init=False)
|
|
281
288
|
|
|
282
289
|
@property
|
|
283
290
|
def get_type(self) -> str:
|
|
@@ -60,6 +60,8 @@ pyoaev/signatures/types.py
|
|
|
60
60
|
scripts/release.py
|
|
61
61
|
test/__init__.py
|
|
62
62
|
test/apis/__init__.py
|
|
63
|
+
test/apis/endpoint/__init__.py
|
|
64
|
+
test/apis/endpoint/test_endpoint.py
|
|
63
65
|
test/apis/expectation/__init__.py
|
|
64
66
|
test/apis/expectation/test_expectation.py
|
|
65
67
|
test/apis/injector_contract/__init__.py
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
from unittest import TestCase, main, mock
|
|
2
|
+
from unittest.mock import ANY
|
|
3
|
+
|
|
4
|
+
from pyoaev import OpenAEV
|
|
5
|
+
from pyoaev.apis.inputs.search import Filter, FilterGroup, SearchPaginationInput
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def mock_response(**kwargs):
|
|
9
|
+
class MockResponse:
|
|
10
|
+
def __init__(self, json_data, status_code):
|
|
11
|
+
self.json_data = json_data
|
|
12
|
+
self.status_code = status_code
|
|
13
|
+
self.history = None
|
|
14
|
+
self.content = None
|
|
15
|
+
self.headers = {"Content-Type": "application/json"}
|
|
16
|
+
|
|
17
|
+
def json(self):
|
|
18
|
+
return self.json_data
|
|
19
|
+
|
|
20
|
+
return MockResponse(None, 200)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class TestInjectorContract(TestCase):
|
|
24
|
+
@mock.patch("requests.Session.request", side_effect=mock_response)
|
|
25
|
+
def test_search_input_correctly_serialised(self, mock_request):
|
|
26
|
+
api_client = OpenAEV("url", "token")
|
|
27
|
+
|
|
28
|
+
search_input = SearchPaginationInput(
|
|
29
|
+
0,
|
|
30
|
+
20,
|
|
31
|
+
FilterGroup(
|
|
32
|
+
"or",
|
|
33
|
+
[Filter("targets", "and", "eq", ["target_1", "target_2", "target_3"])],
|
|
34
|
+
),
|
|
35
|
+
None,
|
|
36
|
+
None,
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
expected_json = search_input.to_dict()
|
|
40
|
+
api_client.endpoint.searchTargets(search_input)
|
|
41
|
+
|
|
42
|
+
mock_request.assert_called_once_with(
|
|
43
|
+
method="post",
|
|
44
|
+
url="url/api/endpoints/targets",
|
|
45
|
+
params={},
|
|
46
|
+
data=None,
|
|
47
|
+
timeout=None,
|
|
48
|
+
stream=False,
|
|
49
|
+
verify=True,
|
|
50
|
+
json=expected_json,
|
|
51
|
+
headers=ANY,
|
|
52
|
+
auth=ANY,
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
if __name__ == "__main__":
|
|
57
|
+
main()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyoaev-1.18.20/test/apis/injector_contract → pyoaev-2.0.1/test/apis/expectation}/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|