binalyze-air-sdk 1.0.1__py3-none-any.whl → 1.0.3__py3-none-any.whl
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.
- binalyze_air/__init__.py +77 -77
- binalyze_air/apis/__init__.py +67 -27
- binalyze_air/apis/acquisitions.py +107 -0
- binalyze_air/apis/api_tokens.py +49 -0
- binalyze_air/apis/assets.py +161 -0
- binalyze_air/apis/audit_logs.py +26 -0
- binalyze_air/apis/{authentication.py → auth.py} +29 -27
- binalyze_air/apis/auto_asset_tags.py +79 -75
- binalyze_air/apis/backup.py +177 -0
- binalyze_air/apis/baseline.py +46 -0
- binalyze_air/apis/cases.py +225 -0
- binalyze_air/apis/cloud_forensics.py +116 -0
- binalyze_air/apis/event_subscription.py +96 -96
- binalyze_air/apis/evidence.py +249 -53
- binalyze_air/apis/interact.py +153 -36
- binalyze_air/apis/investigation_hub.py +234 -0
- binalyze_air/apis/license.py +104 -0
- binalyze_air/apis/logger.py +83 -0
- binalyze_air/apis/multipart_upload.py +201 -0
- binalyze_air/apis/notifications.py +115 -0
- binalyze_air/apis/organizations.py +267 -0
- binalyze_air/apis/params.py +44 -39
- binalyze_air/apis/policies.py +186 -0
- binalyze_air/apis/preset_filters.py +79 -0
- binalyze_air/apis/recent_activities.py +71 -0
- binalyze_air/apis/relay_server.py +104 -0
- binalyze_air/apis/settings.py +395 -27
- binalyze_air/apis/tasks.py +80 -0
- binalyze_air/apis/triage.py +197 -0
- binalyze_air/apis/user_management.py +183 -74
- binalyze_air/apis/webhook_executions.py +50 -0
- binalyze_air/apis/webhooks.py +322 -230
- binalyze_air/base.py +207 -133
- binalyze_air/client.py +217 -1337
- binalyze_air/commands/__init__.py +175 -145
- binalyze_air/commands/acquisitions.py +661 -387
- binalyze_air/commands/api_tokens.py +55 -0
- binalyze_air/commands/assets.py +324 -362
- binalyze_air/commands/{authentication.py → auth.py} +36 -36
- binalyze_air/commands/auto_asset_tags.py +230 -230
- binalyze_air/commands/backup.py +47 -0
- binalyze_air/commands/baseline.py +32 -396
- binalyze_air/commands/cases.py +609 -602
- binalyze_air/commands/cloud_forensics.py +88 -0
- binalyze_air/commands/event_subscription.py +101 -101
- binalyze_air/commands/evidences.py +918 -988
- binalyze_air/commands/interact.py +172 -58
- binalyze_air/commands/investigation_hub.py +315 -0
- binalyze_air/commands/license.py +183 -0
- binalyze_air/commands/logger.py +126 -0
- binalyze_air/commands/multipart_upload.py +363 -0
- binalyze_air/commands/notifications.py +45 -0
- binalyze_air/commands/organizations.py +200 -221
- binalyze_air/commands/policies.py +175 -203
- binalyze_air/commands/preset_filters.py +55 -0
- binalyze_air/commands/recent_activities.py +32 -0
- binalyze_air/commands/relay_server.py +144 -0
- binalyze_air/commands/settings.py +431 -29
- binalyze_air/commands/tasks.py +95 -56
- binalyze_air/commands/triage.py +224 -360
- binalyze_air/commands/user_management.py +351 -126
- binalyze_air/commands/webhook_executions.py +77 -0
- binalyze_air/config.py +244 -244
- binalyze_air/exceptions.py +49 -49
- binalyze_air/http_client.py +426 -305
- binalyze_air/models/__init__.py +287 -285
- binalyze_air/models/acquisitions.py +365 -250
- binalyze_air/models/api_tokens.py +73 -0
- binalyze_air/models/assets.py +438 -438
- binalyze_air/models/audit.py +247 -272
- binalyze_air/models/audit_logs.py +14 -0
- binalyze_air/models/{authentication.py → auth.py} +69 -69
- binalyze_air/models/auto_asset_tags.py +227 -116
- binalyze_air/models/backup.py +138 -0
- binalyze_air/models/baseline.py +231 -231
- binalyze_air/models/cases.py +275 -275
- binalyze_air/models/cloud_forensics.py +145 -0
- binalyze_air/models/event_subscription.py +170 -171
- binalyze_air/models/evidence.py +65 -65
- binalyze_air/models/evidences.py +367 -348
- binalyze_air/models/interact.py +266 -135
- binalyze_air/models/investigation_hub.py +265 -0
- binalyze_air/models/license.py +150 -0
- binalyze_air/models/logger.py +83 -0
- binalyze_air/models/multipart_upload.py +352 -0
- binalyze_air/models/notifications.py +138 -0
- binalyze_air/models/organizations.py +293 -293
- binalyze_air/models/params.py +153 -127
- binalyze_air/models/policies.py +260 -249
- binalyze_air/models/preset_filters.py +79 -0
- binalyze_air/models/recent_activities.py +70 -0
- binalyze_air/models/relay_server.py +121 -0
- binalyze_air/models/settings.py +538 -84
- binalyze_air/models/tasks.py +215 -149
- binalyze_air/models/triage.py +141 -142
- binalyze_air/models/user_management.py +200 -97
- binalyze_air/models/webhook_executions.py +33 -0
- binalyze_air/queries/__init__.py +121 -133
- binalyze_air/queries/acquisitions.py +155 -155
- binalyze_air/queries/api_tokens.py +46 -0
- binalyze_air/queries/assets.py +186 -105
- binalyze_air/queries/audit.py +400 -416
- binalyze_air/queries/{authentication.py → auth.py} +55 -55
- binalyze_air/queries/auto_asset_tags.py +59 -59
- binalyze_air/queries/backup.py +66 -0
- binalyze_air/queries/baseline.py +21 -185
- binalyze_air/queries/cases.py +292 -292
- binalyze_air/queries/cloud_forensics.py +137 -0
- binalyze_air/queries/event_subscription.py +54 -54
- binalyze_air/queries/evidence.py +139 -139
- binalyze_air/queries/evidences.py +279 -279
- binalyze_air/queries/interact.py +140 -28
- binalyze_air/queries/investigation_hub.py +329 -0
- binalyze_air/queries/license.py +85 -0
- binalyze_air/queries/logger.py +58 -0
- binalyze_air/queries/multipart_upload.py +180 -0
- binalyze_air/queries/notifications.py +71 -0
- binalyze_air/queries/organizations.py +222 -222
- binalyze_air/queries/params.py +154 -115
- binalyze_air/queries/policies.py +149 -149
- binalyze_air/queries/preset_filters.py +60 -0
- binalyze_air/queries/recent_activities.py +44 -0
- binalyze_air/queries/relay_server.py +42 -0
- binalyze_air/queries/settings.py +533 -20
- binalyze_air/queries/tasks.py +125 -81
- binalyze_air/queries/triage.py +230 -230
- binalyze_air/queries/user_management.py +193 -83
- binalyze_air/queries/webhook_executions.py +39 -0
- binalyze_air_sdk-1.0.3.dist-info/METADATA +752 -0
- binalyze_air_sdk-1.0.3.dist-info/RECORD +132 -0
- {binalyze_air_sdk-1.0.1.dist-info → binalyze_air_sdk-1.0.3.dist-info}/WHEEL +1 -1
- binalyze_air/apis/endpoints.py +0 -22
- binalyze_air/apis/evidences.py +0 -216
- binalyze_air/apis/users.py +0 -68
- binalyze_air/commands/users.py +0 -101
- binalyze_air/models/endpoints.py +0 -76
- binalyze_air/models/users.py +0 -82
- binalyze_air/queries/endpoints.py +0 -25
- binalyze_air/queries/users.py +0 -69
- binalyze_air_sdk-1.0.1.dist-info/METADATA +0 -635
- binalyze_air_sdk-1.0.1.dist-info/RECORD +0 -82
- {binalyze_air_sdk-1.0.1.dist-info → binalyze_air_sdk-1.0.3.dist-info}/top_level.txt +0 -0
@@ -1,156 +1,156 @@
|
|
1
|
-
"""
|
2
|
-
Acquisition-related queries for the Binalyze AIR SDK.
|
3
|
-
"""
|
4
|
-
|
5
|
-
from typing import List, Optional
|
6
|
-
|
7
|
-
from ..base import Query
|
8
|
-
from ..models.acquisitions import (
|
9
|
-
AcquisitionProfile, AcquisitionProfileDetails, AcquisitionFilter,
|
10
|
-
AcquisitionProfilePlatformDetails, NetworkCaptureConfig, EDiscoveryPattern
|
11
|
-
)
|
12
|
-
from ..http_client import HTTPClient
|
13
|
-
|
14
|
-
|
15
|
-
class ListAcquisitionProfilesQuery(Query[List[AcquisitionProfile]]):
|
16
|
-
"""Query to list acquisition profiles with optional filtering."""
|
17
|
-
|
18
|
-
def __init__(
|
19
|
-
self,
|
20
|
-
http_client: HTTPClient,
|
21
|
-
filter_params: Optional[AcquisitionFilter] = None,
|
22
|
-
organization_ids: Optional[List[int]] = None,
|
23
|
-
all_organizations: bool = False
|
24
|
-
):
|
25
|
-
self.http_client = http_client
|
26
|
-
# Initialize filter with default organization IDs if not provided
|
27
|
-
if filter_params is None:
|
28
|
-
filter_params = AcquisitionFilter()
|
29
|
-
|
30
|
-
# Set organization parameters if not already set in filter
|
31
|
-
if filter_params.organization_ids is None and organization_ids is not None:
|
32
|
-
filter_params.organization_ids = organization_ids
|
33
|
-
elif filter_params.organization_ids is None:
|
34
|
-
filter_params.organization_ids = [0] # Default to organization 0
|
35
|
-
|
36
|
-
# Set all_organizations parameter if not already set in filter
|
37
|
-
if filter_params.all_organizations is None and all_organizations:
|
38
|
-
filter_params.all_organizations = all_organizations
|
39
|
-
|
40
|
-
self.filter_params = filter_params
|
41
|
-
|
42
|
-
def execute(self) -> List[AcquisitionProfile]:
|
43
|
-
"""Execute the query to list acquisition profiles."""
|
44
|
-
# Use filter's parameter generation
|
45
|
-
params = self.filter_params.to_params()
|
46
|
-
|
47
|
-
response = self.http_client.get("acquisitions/profiles", params=params)
|
48
|
-
|
49
|
-
entities = response.get("result", {}).get("entities", [])
|
50
|
-
|
51
|
-
# Convert to AcquisitionProfile objects
|
52
|
-
profiles = []
|
53
|
-
for entity_data in entities:
|
54
|
-
mapped_data = {
|
55
|
-
"id": entity_data.get("_id"),
|
56
|
-
"name": entity_data.get("name"),
|
57
|
-
"organization_ids": entity_data.get("organizationIds", []), # Keep as integers
|
58
|
-
"created_at": entity_data.get("createdAt"),
|
59
|
-
"updated_at": entity_data.get("updatedAt"),
|
60
|
-
"created_by": entity_data.get("createdBy"),
|
61
|
-
"deletable": entity_data.get("deletable", True),
|
62
|
-
"average_time": entity_data.get("averageTime"),
|
63
|
-
"last_used_at": entity_data.get("lastUsedAt"),
|
64
|
-
"last_used_by": entity_data.get("lastUsedBy"),
|
65
|
-
"has_event_log_records_evidence": entity_data.get("hasEventLogRecordsEvidence"),
|
66
|
-
}
|
67
|
-
|
68
|
-
# Remove None values
|
69
|
-
mapped_data = {k: v for k, v in mapped_data.items() if v is not None}
|
70
|
-
|
71
|
-
profiles.append(AcquisitionProfile(**mapped_data))
|
72
|
-
|
73
|
-
return profiles
|
74
|
-
|
75
|
-
|
76
|
-
class GetAcquisitionProfileQuery(Query[AcquisitionProfileDetails]):
|
77
|
-
"""Query to get a specific acquisition profile by ID."""
|
78
|
-
|
79
|
-
def __init__(self, http_client: HTTPClient, profile_id: str):
|
80
|
-
self.http_client = http_client
|
81
|
-
self.profile_id = profile_id
|
82
|
-
|
83
|
-
def execute(self) -> AcquisitionProfileDetails:
|
84
|
-
"""Execute the query to get acquisition profile details."""
|
85
|
-
response = self.http_client.get(f"acquisitions/profiles/{self.profile_id}")
|
86
|
-
|
87
|
-
entity_data = response.get("result", {})
|
88
|
-
|
89
|
-
# Parse platform configurations
|
90
|
-
def parse_platform_config(platform_data: dict) -> AcquisitionProfilePlatformDetails:
|
91
|
-
network_capture = None
|
92
|
-
if "networkCapture" in platform_data:
|
93
|
-
nc_data = platform_data["networkCapture"]
|
94
|
-
network_capture = NetworkCaptureConfig(
|
95
|
-
enabled=nc_data.get("enabled", False),
|
96
|
-
duration=nc_data.get("duration", 60),
|
97
|
-
pcap=nc_data.get("pcap", {"enabled": False}),
|
98
|
-
network_flow=nc_data.get("networkFlow", {"enabled": False})
|
99
|
-
)
|
100
|
-
|
101
|
-
return AcquisitionProfilePlatformDetails(
|
102
|
-
evidence_list=platform_data.get("evidenceList", []),
|
103
|
-
artifact_list=platform_data.get("artifactList"),
|
104
|
-
custom_content_profiles=platform_data.get("customContentProfiles", []),
|
105
|
-
network_capture=network_capture
|
106
|
-
)
|
107
|
-
|
108
|
-
# Parse platform configurations
|
109
|
-
windows_config = None
|
110
|
-
linux_config = None
|
111
|
-
macos_config = None
|
112
|
-
aix_config = None
|
113
|
-
|
114
|
-
if "windows" in entity_data:
|
115
|
-
windows_config = parse_platform_config(entity_data["windows"])
|
116
|
-
|
117
|
-
if "linux" in entity_data:
|
118
|
-
linux_config = parse_platform_config(entity_data["linux"])
|
119
|
-
|
120
|
-
if "macos" in entity_data:
|
121
|
-
macos_config = parse_platform_config(entity_data["macos"])
|
122
|
-
|
123
|
-
if "aix" in entity_data:
|
124
|
-
aix_config = parse_platform_config(entity_data["aix"])
|
125
|
-
|
126
|
-
# Parse eDiscovery patterns
|
127
|
-
e_discovery = None
|
128
|
-
if "eDiscovery" in entity_data and "patterns" in entity_data["eDiscovery"]:
|
129
|
-
patterns = [
|
130
|
-
EDiscoveryPattern(
|
131
|
-
pattern=pattern.get("pattern", ""),
|
132
|
-
category=pattern.get("category", "")
|
133
|
-
)
|
134
|
-
for pattern in entity_data["eDiscovery"]["patterns"]
|
135
|
-
]
|
136
|
-
e_discovery = {"patterns": patterns}
|
137
|
-
|
138
|
-
mapped_data = {
|
139
|
-
"id": entity_data.get("_id"),
|
140
|
-
"name": entity_data.get("name"),
|
141
|
-
"organization_ids": [str(org_id) for org_id in entity_data.get("organizationIds", [])],
|
142
|
-
"created_at": entity_data.get("createdAt"),
|
143
|
-
"updated_at": entity_data.get("updatedAt"),
|
144
|
-
"created_by": entity_data.get("createdBy"),
|
145
|
-
"deletable": entity_data.get("deletable", True),
|
146
|
-
"windows": windows_config,
|
147
|
-
"linux": linux_config,
|
148
|
-
"macos": macos_config,
|
149
|
-
"aix": aix_config,
|
150
|
-
"e_discovery": e_discovery,
|
151
|
-
}
|
152
|
-
|
153
|
-
# Remove None values
|
154
|
-
mapped_data = {k: v for k, v in mapped_data.items() if v is not None}
|
155
|
-
|
1
|
+
"""
|
2
|
+
Acquisition-related queries for the Binalyze AIR SDK.
|
3
|
+
"""
|
4
|
+
|
5
|
+
from typing import List, Optional
|
6
|
+
|
7
|
+
from ..base import Query
|
8
|
+
from ..models.acquisitions import (
|
9
|
+
AcquisitionProfile, AcquisitionProfileDetails, AcquisitionFilter,
|
10
|
+
AcquisitionProfilePlatformDetails, NetworkCaptureConfig, EDiscoveryPattern
|
11
|
+
)
|
12
|
+
from ..http_client import HTTPClient
|
13
|
+
|
14
|
+
|
15
|
+
class ListAcquisitionProfilesQuery(Query[List[AcquisitionProfile]]):
|
16
|
+
"""Query to list acquisition profiles with optional filtering."""
|
17
|
+
|
18
|
+
def __init__(
|
19
|
+
self,
|
20
|
+
http_client: HTTPClient,
|
21
|
+
filter_params: Optional[AcquisitionFilter] = None,
|
22
|
+
organization_ids: Optional[List[int]] = None,
|
23
|
+
all_organizations: bool = False
|
24
|
+
):
|
25
|
+
self.http_client = http_client
|
26
|
+
# Initialize filter with default organization IDs if not provided
|
27
|
+
if filter_params is None:
|
28
|
+
filter_params = AcquisitionFilter()
|
29
|
+
|
30
|
+
# Set organization parameters if not already set in filter
|
31
|
+
if filter_params.organization_ids is None and organization_ids is not None:
|
32
|
+
filter_params.organization_ids = organization_ids
|
33
|
+
elif filter_params.organization_ids is None:
|
34
|
+
filter_params.organization_ids = [0] # Default to organization 0
|
35
|
+
|
36
|
+
# Set all_organizations parameter if not already set in filter
|
37
|
+
if filter_params.all_organizations is None and all_organizations:
|
38
|
+
filter_params.all_organizations = all_organizations
|
39
|
+
|
40
|
+
self.filter_params = filter_params
|
41
|
+
|
42
|
+
def execute(self) -> List[AcquisitionProfile]:
|
43
|
+
"""Execute the query to list acquisition profiles."""
|
44
|
+
# Use filter's parameter generation
|
45
|
+
params = self.filter_params.to_params()
|
46
|
+
|
47
|
+
response = self.http_client.get("acquisitions/profiles", params=params)
|
48
|
+
|
49
|
+
entities = response.get("result", {}).get("entities", [])
|
50
|
+
|
51
|
+
# Convert to AcquisitionProfile objects
|
52
|
+
profiles = []
|
53
|
+
for entity_data in entities:
|
54
|
+
mapped_data = {
|
55
|
+
"id": entity_data.get("_id"),
|
56
|
+
"name": entity_data.get("name"),
|
57
|
+
"organization_ids": entity_data.get("organizationIds", []), # Keep as integers
|
58
|
+
"created_at": entity_data.get("createdAt"),
|
59
|
+
"updated_at": entity_data.get("updatedAt"),
|
60
|
+
"created_by": entity_data.get("createdBy"),
|
61
|
+
"deletable": entity_data.get("deletable", True),
|
62
|
+
"average_time": entity_data.get("averageTime"),
|
63
|
+
"last_used_at": entity_data.get("lastUsedAt"),
|
64
|
+
"last_used_by": entity_data.get("lastUsedBy"),
|
65
|
+
"has_event_log_records_evidence": entity_data.get("hasEventLogRecordsEvidence"),
|
66
|
+
}
|
67
|
+
|
68
|
+
# Remove None values
|
69
|
+
mapped_data = {k: v for k, v in mapped_data.items() if v is not None}
|
70
|
+
|
71
|
+
profiles.append(AcquisitionProfile(**mapped_data))
|
72
|
+
|
73
|
+
return profiles
|
74
|
+
|
75
|
+
|
76
|
+
class GetAcquisitionProfileQuery(Query[AcquisitionProfileDetails]):
|
77
|
+
"""Query to get a specific acquisition profile by ID."""
|
78
|
+
|
79
|
+
def __init__(self, http_client: HTTPClient, profile_id: str):
|
80
|
+
self.http_client = http_client
|
81
|
+
self.profile_id = profile_id
|
82
|
+
|
83
|
+
def execute(self) -> AcquisitionProfileDetails:
|
84
|
+
"""Execute the query to get acquisition profile details."""
|
85
|
+
response = self.http_client.get(f"acquisitions/profiles/{self.profile_id}")
|
86
|
+
|
87
|
+
entity_data = response.get("result", {})
|
88
|
+
|
89
|
+
# Parse platform configurations
|
90
|
+
def parse_platform_config(platform_data: dict) -> AcquisitionProfilePlatformDetails:
|
91
|
+
network_capture = None
|
92
|
+
if "networkCapture" in platform_data:
|
93
|
+
nc_data = platform_data["networkCapture"]
|
94
|
+
network_capture = NetworkCaptureConfig(
|
95
|
+
enabled=nc_data.get("enabled", False),
|
96
|
+
duration=nc_data.get("duration", 60),
|
97
|
+
pcap=nc_data.get("pcap", {"enabled": False}),
|
98
|
+
network_flow=nc_data.get("networkFlow", {"enabled": False})
|
99
|
+
)
|
100
|
+
|
101
|
+
return AcquisitionProfilePlatformDetails(
|
102
|
+
evidence_list=platform_data.get("evidenceList", []),
|
103
|
+
artifact_list=platform_data.get("artifactList"),
|
104
|
+
custom_content_profiles=platform_data.get("customContentProfiles", []),
|
105
|
+
network_capture=network_capture
|
106
|
+
)
|
107
|
+
|
108
|
+
# Parse platform configurations
|
109
|
+
windows_config = None
|
110
|
+
linux_config = None
|
111
|
+
macos_config = None
|
112
|
+
aix_config = None
|
113
|
+
|
114
|
+
if "windows" in entity_data:
|
115
|
+
windows_config = parse_platform_config(entity_data["windows"])
|
116
|
+
|
117
|
+
if "linux" in entity_data:
|
118
|
+
linux_config = parse_platform_config(entity_data["linux"])
|
119
|
+
|
120
|
+
if "macos" in entity_data:
|
121
|
+
macos_config = parse_platform_config(entity_data["macos"])
|
122
|
+
|
123
|
+
if "aix" in entity_data:
|
124
|
+
aix_config = parse_platform_config(entity_data["aix"])
|
125
|
+
|
126
|
+
# Parse eDiscovery patterns
|
127
|
+
e_discovery = None
|
128
|
+
if "eDiscovery" in entity_data and "patterns" in entity_data["eDiscovery"]:
|
129
|
+
patterns = [
|
130
|
+
EDiscoveryPattern(
|
131
|
+
pattern=pattern.get("pattern", ""),
|
132
|
+
category=pattern.get("category", "")
|
133
|
+
)
|
134
|
+
for pattern in entity_data["eDiscovery"]["patterns"]
|
135
|
+
]
|
136
|
+
e_discovery = {"patterns": patterns}
|
137
|
+
|
138
|
+
mapped_data = {
|
139
|
+
"id": entity_data.get("_id"),
|
140
|
+
"name": entity_data.get("name"),
|
141
|
+
"organization_ids": [str(org_id) for org_id in entity_data.get("organizationIds", [])],
|
142
|
+
"created_at": entity_data.get("createdAt"),
|
143
|
+
"updated_at": entity_data.get("updatedAt"),
|
144
|
+
"created_by": entity_data.get("createdBy"),
|
145
|
+
"deletable": entity_data.get("deletable", True),
|
146
|
+
"windows": windows_config,
|
147
|
+
"linux": linux_config,
|
148
|
+
"macos": macos_config,
|
149
|
+
"aix": aix_config,
|
150
|
+
"e_discovery": e_discovery,
|
151
|
+
}
|
152
|
+
|
153
|
+
# Remove None values
|
154
|
+
mapped_data = {k: v for k, v in mapped_data.items() if v is not None}
|
155
|
+
|
156
156
|
return AcquisitionProfileDetails(**mapped_data)
|
@@ -0,0 +1,46 @@
|
|
1
|
+
"""
|
2
|
+
API Tokens queries for the Binalyze AIR SDK.
|
3
|
+
"""
|
4
|
+
|
5
|
+
from typing import Optional, Dict, Any
|
6
|
+
|
7
|
+
from ..base import Query
|
8
|
+
from ..models.api_tokens import APIToken, APITokensPaginatedResponse, APITokenFilter
|
9
|
+
from ..http_client import HTTPClient
|
10
|
+
|
11
|
+
|
12
|
+
class ListAPITokensQuery(Query[APITokensPaginatedResponse]):
|
13
|
+
"""Query to list API tokens with optional filtering."""
|
14
|
+
|
15
|
+
def __init__(self, http_client: HTTPClient, filter_params: Optional[APITokenFilter] = None):
|
16
|
+
self.http_client = http_client
|
17
|
+
self.filter_params = filter_params or APITokenFilter()
|
18
|
+
|
19
|
+
def execute(self) -> APITokensPaginatedResponse:
|
20
|
+
"""Execute the query."""
|
21
|
+
params = {}
|
22
|
+
|
23
|
+
if self.filter_params.page_size is not None:
|
24
|
+
params["pageSize"] = self.filter_params.page_size
|
25
|
+
if self.filter_params.page_number is not None:
|
26
|
+
params["pageNumber"] = self.filter_params.page_number
|
27
|
+
if self.filter_params.sort_type is not None:
|
28
|
+
params["sortType"] = self.filter_params.sort_type
|
29
|
+
if self.filter_params.sort_by is not None:
|
30
|
+
params["sortBy"] = self.filter_params.sort_by
|
31
|
+
|
32
|
+
response = self.http_client.get("api-tokens", params=params)
|
33
|
+
return APITokensPaginatedResponse(**response["result"])
|
34
|
+
|
35
|
+
|
36
|
+
class GetAPITokenQuery(Query[APIToken]):
|
37
|
+
"""Query to get a specific API token by ID."""
|
38
|
+
|
39
|
+
def __init__(self, http_client: HTTPClient, token_id: str):
|
40
|
+
self.http_client = http_client
|
41
|
+
self.token_id = token_id
|
42
|
+
|
43
|
+
def execute(self) -> APIToken:
|
44
|
+
"""Execute the query."""
|
45
|
+
response = self.http_client.get(f"api-tokens/{self.token_id}")
|
46
|
+
return APIToken(**response["result"])
|
binalyze_air/queries/assets.py
CHANGED
@@ -1,105 +1,186 @@
|
|
1
|
-
"""
|
2
|
-
Asset-related queries for the Binalyze AIR SDK.
|
3
|
-
"""
|
4
|
-
|
5
|
-
from typing import List, Dict, Any, Optional
|
6
|
-
|
7
|
-
from ..base import Query, PaginatedResponse, APIResponse, PaginatedList
|
8
|
-
from ..models.assets import Asset, AssetDetail, AssetTask, AssetFilter, AssetTaskFilter
|
9
|
-
from ..http_client import HTTPClient
|
10
|
-
|
11
|
-
|
12
|
-
class ListAssetsQuery(Query[List[Asset]]):
|
13
|
-
"""Query to list assets with optional filtering."""
|
14
|
-
|
15
|
-
def __init__(self, http_client: HTTPClient, filter_params: Optional[AssetFilter] = None):
|
16
|
-
self.http_client = http_client
|
17
|
-
self.filter_params = filter_params or AssetFilter()
|
18
|
-
|
19
|
-
def execute(self) -> List[Asset]:
|
20
|
-
"""Execute the query to list assets."""
|
21
|
-
params = self.filter_params.to_params()
|
22
|
-
|
23
|
-
# Set default organization_ids if not provided
|
24
|
-
if not self.filter_params.organization_ids:
|
25
|
-
params["filter[organizationIds]"] = "0"
|
26
|
-
|
27
|
-
# Ensure consistent sorting to match API defaults
|
28
|
-
if "sortBy" not in params:
|
29
|
-
params["sortBy"] = "createdAt"
|
30
|
-
if "sortType" not in params:
|
31
|
-
params["sortType"] = "ASC"
|
32
|
-
|
33
|
-
response = self.http_client.get("assets", params=params)
|
34
|
-
|
35
|
-
# Parse the paginated response
|
36
|
-
entities = response.get("result", {}).get("entities", [])
|
37
|
-
|
38
|
-
# Convert to Asset objects using Pydantic parsing with aliases
|
39
|
-
assets = []
|
40
|
-
for entity_data in entities:
|
41
|
-
# Let Pydantic handle the field mapping via aliases
|
42
|
-
asset = Asset.model_validate(entity_data)
|
43
|
-
assets.append(asset)
|
44
|
-
|
45
|
-
return assets
|
46
|
-
|
47
|
-
|
48
|
-
class GetAssetQuery(Query[AssetDetail]):
|
49
|
-
"""Query to get a specific asset by ID."""
|
50
|
-
|
51
|
-
def __init__(self, http_client: HTTPClient, asset_id: str):
|
52
|
-
self.http_client = http_client
|
53
|
-
self.asset_id = asset_id
|
54
|
-
|
55
|
-
def execute(self) -> AssetDetail:
|
56
|
-
"""Execute the query to get asset details."""
|
57
|
-
response = self.http_client.get(f"assets/{self.asset_id}")
|
58
|
-
|
59
|
-
entity_data = response.get("result", {})
|
60
|
-
|
61
|
-
# Let Pydantic handle the field mapping via aliases
|
62
|
-
return AssetDetail.model_validate(entity_data)
|
63
|
-
|
64
|
-
|
65
|
-
class GetAssetTasksQuery(Query[List[AssetTask]]):
|
66
|
-
"""Query to get tasks for a specific asset with optional filtering."""
|
67
|
-
|
68
|
-
def __init__(self, http_client: HTTPClient, asset_id: str, filter_params: Optional[AssetTaskFilter] = None):
|
69
|
-
self.http_client = http_client
|
70
|
-
self.asset_id = asset_id
|
71
|
-
self.filter_params = filter_params or AssetTaskFilter()
|
72
|
-
|
73
|
-
def execute(self) -> List[AssetTask]:
|
74
|
-
"""Execute the query to get asset tasks."""
|
75
|
-
# Get filter parameters
|
76
|
-
params = self.filter_params.to_params()
|
77
|
-
|
78
|
-
# Provide sensible defaults that mirror the HTTP test defaults if not supplied
|
79
|
-
# Default pagination
|
80
|
-
if "pageNumber" not in params:
|
81
|
-
params["pageNumber"] = 1
|
82
|
-
if "pageSize" not in params:
|
83
|
-
params["pageSize"] = 10
|
84
|
-
# Default sorting
|
85
|
-
if "sortBy" not in params:
|
86
|
-
params["sortBy"] = "createdAt"
|
87
|
-
if "sortType" not in params:
|
88
|
-
params["sortType"] = "ASC"
|
89
|
-
|
90
|
-
# Make request with parameters
|
91
|
-
response = self.http_client.get(f"assets/{self.asset_id}/tasks", params=params)
|
92
|
-
|
93
|
-
result_meta = response.get("result", {})
|
94
|
-
entities_data = result_meta.get("entities", [])
|
95
|
-
|
96
|
-
# Convert to AssetTask objects using Pydantic parsing with aliases
|
97
|
-
paginated_tasks = PaginatedList(
|
98
|
-
[AssetTask.model_validate(entity) for entity in entities_data],
|
99
|
-
total_entity_count=result_meta.get("totalEntityCount"),
|
100
|
-
current_page=result_meta.get("currentPage", params.get("pageNumber", 1)),
|
101
|
-
page_size=result_meta.get("pageSize", params.get("pageSize", len(entities_data))),
|
102
|
-
total_page_count=result_meta.get("totalPageCount"),
|
103
|
-
)
|
104
|
-
|
105
|
-
return paginated_tasks
|
1
|
+
"""
|
2
|
+
Asset-related queries for the Binalyze AIR SDK.
|
3
|
+
"""
|
4
|
+
|
5
|
+
from typing import List, Dict, Any, Optional
|
6
|
+
|
7
|
+
from ..base import Query, PaginatedResponse, APIResponse, PaginatedList
|
8
|
+
from ..models.assets import Asset, AssetDetail, AssetTask, AssetFilter, AssetTaskFilter
|
9
|
+
from ..http_client import HTTPClient
|
10
|
+
|
11
|
+
|
12
|
+
class ListAssetsQuery(Query[List[Asset]]):
|
13
|
+
"""Query to list assets with optional filtering."""
|
14
|
+
|
15
|
+
def __init__(self, http_client: HTTPClient, filter_params: Optional[AssetFilter] = None):
|
16
|
+
self.http_client = http_client
|
17
|
+
self.filter_params = filter_params or AssetFilter()
|
18
|
+
|
19
|
+
def execute(self) -> List[Asset]:
|
20
|
+
"""Execute the query to list assets."""
|
21
|
+
params = self.filter_params.to_params()
|
22
|
+
|
23
|
+
# Set default organization_ids if not provided
|
24
|
+
if not self.filter_params.organization_ids:
|
25
|
+
params["filter[organizationIds]"] = "0"
|
26
|
+
|
27
|
+
# Ensure consistent sorting to match API defaults
|
28
|
+
if "sortBy" not in params:
|
29
|
+
params["sortBy"] = "createdAt"
|
30
|
+
if "sortType" not in params:
|
31
|
+
params["sortType"] = "ASC"
|
32
|
+
|
33
|
+
response = self.http_client.get("assets", params=params)
|
34
|
+
|
35
|
+
# Parse the paginated response
|
36
|
+
entities = response.get("result", {}).get("entities", [])
|
37
|
+
|
38
|
+
# Convert to Asset objects using Pydantic parsing with aliases
|
39
|
+
assets = []
|
40
|
+
for entity_data in entities:
|
41
|
+
# Let Pydantic handle the field mapping via aliases
|
42
|
+
asset = Asset.model_validate(entity_data)
|
43
|
+
assets.append(asset)
|
44
|
+
|
45
|
+
return assets
|
46
|
+
|
47
|
+
|
48
|
+
class GetAssetQuery(Query[AssetDetail]):
|
49
|
+
"""Query to get a specific asset by ID."""
|
50
|
+
|
51
|
+
def __init__(self, http_client: HTTPClient, asset_id: str):
|
52
|
+
self.http_client = http_client
|
53
|
+
self.asset_id = asset_id
|
54
|
+
|
55
|
+
def execute(self) -> AssetDetail:
|
56
|
+
"""Execute the query to get asset details."""
|
57
|
+
response = self.http_client.get(f"assets/{self.asset_id}")
|
58
|
+
|
59
|
+
entity_data = response.get("result", {})
|
60
|
+
|
61
|
+
# Let Pydantic handle the field mapping via aliases
|
62
|
+
return AssetDetail.model_validate(entity_data)
|
63
|
+
|
64
|
+
|
65
|
+
class GetAssetTasksQuery(Query[List[AssetTask]]):
|
66
|
+
"""Query to get tasks for a specific asset with optional filtering."""
|
67
|
+
|
68
|
+
def __init__(self, http_client: HTTPClient, asset_id: str, filter_params: Optional[AssetTaskFilter] = None):
|
69
|
+
self.http_client = http_client
|
70
|
+
self.asset_id = asset_id
|
71
|
+
self.filter_params = filter_params or AssetTaskFilter()
|
72
|
+
|
73
|
+
def execute(self) -> List[AssetTask]:
|
74
|
+
"""Execute the query to get asset tasks."""
|
75
|
+
# Get filter parameters
|
76
|
+
params = self.filter_params.to_params()
|
77
|
+
|
78
|
+
# Provide sensible defaults that mirror the HTTP test defaults if not supplied
|
79
|
+
# Default pagination
|
80
|
+
if "pageNumber" not in params:
|
81
|
+
params["pageNumber"] = 1
|
82
|
+
if "pageSize" not in params:
|
83
|
+
params["pageSize"] = 10
|
84
|
+
# Default sorting
|
85
|
+
if "sortBy" not in params:
|
86
|
+
params["sortBy"] = "createdAt"
|
87
|
+
if "sortType" not in params:
|
88
|
+
params["sortType"] = "ASC"
|
89
|
+
|
90
|
+
# Make request with parameters
|
91
|
+
response = self.http_client.get(f"assets/{self.asset_id}/tasks", params=params)
|
92
|
+
|
93
|
+
result_meta = response.get("result", {})
|
94
|
+
entities_data = result_meta.get("entities", [])
|
95
|
+
|
96
|
+
# Convert to AssetTask objects using Pydantic parsing with aliases
|
97
|
+
paginated_tasks = PaginatedList(
|
98
|
+
[AssetTask.model_validate(entity) for entity in entities_data],
|
99
|
+
total_entity_count=result_meta.get("totalEntityCount"),
|
100
|
+
current_page=result_meta.get("currentPage", params.get("pageNumber", 1)),
|
101
|
+
page_size=result_meta.get("pageSize", params.get("pageSize", len(entities_data))),
|
102
|
+
total_page_count=result_meta.get("totalPageCount"),
|
103
|
+
)
|
104
|
+
|
105
|
+
return paginated_tasks
|
106
|
+
|
107
|
+
|
108
|
+
class GetAssetGroupsByOrganizationIdQuery(Query[List[Dict[str, Any]]]):
|
109
|
+
"""Query to get root asset groups by organization ID."""
|
110
|
+
|
111
|
+
def __init__(self, http_client: HTTPClient, organization_id: int):
|
112
|
+
self.http_client = http_client
|
113
|
+
self.organization_id = organization_id
|
114
|
+
|
115
|
+
def execute(self) -> List[Dict[str, Any]]:
|
116
|
+
"""Execute the query to get asset groups by organization ID."""
|
117
|
+
response = self.http_client.get(f"asset-groups/root/{self.organization_id}")
|
118
|
+
return response.get("result", [])
|
119
|
+
|
120
|
+
|
121
|
+
class GetAssetGroupsByParentIdQuery(Query[List[Dict[str, Any]]]):
|
122
|
+
"""Query to get asset groups by parent ID."""
|
123
|
+
|
124
|
+
def __init__(self, http_client: HTTPClient, group_id: str):
|
125
|
+
self.http_client = http_client
|
126
|
+
self.group_id = group_id
|
127
|
+
|
128
|
+
def execute(self) -> List[Dict[str, Any]]:
|
129
|
+
"""Execute the query to get asset groups by parent ID."""
|
130
|
+
response = self.http_client.get(f"asset-groups/{self.group_id}")
|
131
|
+
return response.get("result", [])
|
132
|
+
|
133
|
+
|
134
|
+
class GetAssetTagsQuery(Query[Dict[str, Any]]):
|
135
|
+
"""Query to get asset tags with filtering."""
|
136
|
+
|
137
|
+
def __init__(self, http_client: HTTPClient, organization_ids: List[int],
|
138
|
+
page_number: int = 1, page_size: int = 10, sort_by: str = "createdAt",
|
139
|
+
search_term: Optional[str] = None):
|
140
|
+
self.http_client = http_client
|
141
|
+
self.organization_ids = organization_ids
|
142
|
+
self.page_number = page_number
|
143
|
+
self.page_size = page_size
|
144
|
+
self.sort_by = sort_by
|
145
|
+
self.search_term = search_term
|
146
|
+
|
147
|
+
def execute(self) -> Dict[str, Any]:
|
148
|
+
"""Execute the query to get asset tags."""
|
149
|
+
params = {
|
150
|
+
"filter[organizationIds]": ",".join(map(str, self.organization_ids)),
|
151
|
+
"pageNumber": self.page_number,
|
152
|
+
"pageSize": self.page_size,
|
153
|
+
"sortBy": self.sort_by
|
154
|
+
}
|
155
|
+
|
156
|
+
if self.search_term:
|
157
|
+
params["filter[searchTerm]"] = self.search_term
|
158
|
+
|
159
|
+
response = self.http_client.get("asset-tags", params=params)
|
160
|
+
return response.get("result", {})
|
161
|
+
|
162
|
+
|
163
|
+
class GetProcessorsByAssetTypeIdQuery(Query[List[Dict[str, Any]]]):
|
164
|
+
"""Query to get processors by asset type ID."""
|
165
|
+
|
166
|
+
def __init__(self, http_client: HTTPClient, asset_type_id: int):
|
167
|
+
self.http_client = http_client
|
168
|
+
self.asset_type_id = asset_type_id
|
169
|
+
|
170
|
+
def execute(self) -> List[Dict[str, Any]]:
|
171
|
+
"""Execute the query to get processors by asset type ID."""
|
172
|
+
response = self.http_client.get(f"processors/asset-type/{self.asset_type_id}")
|
173
|
+
return response.get("result", [])
|
174
|
+
|
175
|
+
|
176
|
+
class GetProcessorTypesByAssetTypeQuery(Query[Dict[str, Any]]):
|
177
|
+
"""Query to get processor types by asset type ID."""
|
178
|
+
|
179
|
+
def __init__(self, http_client: HTTPClient, asset_type_id: int):
|
180
|
+
self.http_client = http_client
|
181
|
+
self.asset_type_id = asset_type_id
|
182
|
+
|
183
|
+
def execute(self) -> Dict[str, Any]:
|
184
|
+
"""Execute the query to get processor types by asset type ID."""
|
185
|
+
response = self.http_client.get(f"processors/type/{self.asset_type_id}")
|
186
|
+
return response.get("result", {})
|