binalyze-air-sdk 1.0.2__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.2.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.2.dist-info/METADATA +0 -706
- binalyze_air_sdk-1.0.2.dist-info/RECORD +0 -82
- {binalyze_air_sdk-1.0.2.dist-info → binalyze_air_sdk-1.0.3.dist-info}/top_level.txt +0 -0
@@ -1,251 +1,366 @@
|
|
1
|
-
"""
|
2
|
-
Acquisition-related data models for the Binalyze AIR SDK.
|
3
|
-
"""
|
4
|
-
|
5
|
-
from typing import List, Optional, Dict, Any
|
6
|
-
from datetime import datetime
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
#
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
#
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
1
|
+
"""
|
2
|
+
Acquisition-related data models for the Binalyze AIR SDK.
|
3
|
+
"""
|
4
|
+
|
5
|
+
from typing import List, Optional, Dict, Any
|
6
|
+
from datetime import datetime
|
7
|
+
from pydantic import Field
|
8
|
+
|
9
|
+
from ..base import AIRBaseModel, Filter
|
10
|
+
|
11
|
+
|
12
|
+
class NetworkCaptureConfig(AIRBaseModel):
|
13
|
+
"""Network capture configuration - matches API specification exactly."""
|
14
|
+
|
15
|
+
enabled: bool = False
|
16
|
+
duration: int = 60
|
17
|
+
pcap: Dict[str, bool] = {"enabled": False}
|
18
|
+
networkFlow: Dict[str, bool] = {"enabled": False} # API uses camelCase
|
19
|
+
|
20
|
+
|
21
|
+
class EDiscoveryPattern(AIRBaseModel):
|
22
|
+
"""eDiscovery pattern model."""
|
23
|
+
|
24
|
+
pattern: str
|
25
|
+
category: str
|
26
|
+
|
27
|
+
|
28
|
+
class EDiscoveryConfig(AIRBaseModel):
|
29
|
+
"""eDiscovery configuration matching API specification exactly."""
|
30
|
+
|
31
|
+
patterns: List[EDiscoveryPattern] = []
|
32
|
+
|
33
|
+
def model_dump(self, **kwargs):
|
34
|
+
"""Override to serialize patterns under 'edPatterns' key for API."""
|
35
|
+
data = super().model_dump(**kwargs)
|
36
|
+
if 'patterns' in data:
|
37
|
+
data['edPatterns'] = data.pop('patterns')
|
38
|
+
return data
|
39
|
+
|
40
|
+
|
41
|
+
class SaveLocationConfig(AIRBaseModel):
|
42
|
+
"""Save location configuration."""
|
43
|
+
|
44
|
+
location: str
|
45
|
+
use_most_free_volume: bool = False
|
46
|
+
repository_id: Optional[str] = None
|
47
|
+
path: str
|
48
|
+
volume: Optional[str] = None
|
49
|
+
tmp: str = "tmp"
|
50
|
+
direct_collection: bool = False
|
51
|
+
|
52
|
+
|
53
|
+
class TaskConfig(AIRBaseModel):
|
54
|
+
"""Task configuration."""
|
55
|
+
|
56
|
+
choice: str
|
57
|
+
save_to: Dict[str, SaveLocationConfig]
|
58
|
+
cpu: Dict[str, int] = {"limit": 50}
|
59
|
+
bandwidth: Optional[Dict[str, int]] = None
|
60
|
+
compression: Dict[str, Any] = {
|
61
|
+
"enabled": False,
|
62
|
+
"encryption": {"enabled": False, "password": ""}
|
63
|
+
}
|
64
|
+
|
65
|
+
|
66
|
+
class DroneConfig(AIRBaseModel):
|
67
|
+
"""Drone configuration."""
|
68
|
+
|
69
|
+
auto_pilot: bool = False
|
70
|
+
enabled: bool = False
|
71
|
+
analyzers: List[str] = []
|
72
|
+
keywords: List[str] = []
|
73
|
+
|
74
|
+
|
75
|
+
class FilterConfig(AIRBaseModel):
|
76
|
+
"""Filter configuration for acquisition tasks - matches API specification exactly."""
|
77
|
+
|
78
|
+
# Basic search and identification
|
79
|
+
search_term: Optional[str] = None
|
80
|
+
name: Optional[str] = None
|
81
|
+
ip_address: Optional[str] = None
|
82
|
+
group_id: Optional[str] = None
|
83
|
+
group_full_path: Optional[str] = None
|
84
|
+
label: Optional[str] = None # NEW - Missing from API spec
|
85
|
+
|
86
|
+
# Status filters (arrays as per API)
|
87
|
+
managed_status: List[str] = []
|
88
|
+
isolation_status: List[str] = []
|
89
|
+
platform: List[str] = []
|
90
|
+
issue: Optional[str] = None # API expects string, not array
|
91
|
+
online_status: List[str] = []
|
92
|
+
|
93
|
+
# Tags and policies
|
94
|
+
tags: List[str] = []
|
95
|
+
version: Optional[str] = None
|
96
|
+
policy: Optional[str] = None
|
97
|
+
|
98
|
+
# Endpoint targeting
|
99
|
+
included_endpoint_ids: List[str] = []
|
100
|
+
excluded_endpoint_ids: List[str] = []
|
101
|
+
|
102
|
+
# Organization and case
|
103
|
+
organization_ids: List[int] = [] # Required by API
|
104
|
+
case_id: Optional[str] = None # NEW - Missing from API spec
|
105
|
+
|
106
|
+
# Date/time filters
|
107
|
+
last_seen: Optional[str] = None # NEW - Missing from API spec (ISO 8601 format)
|
108
|
+
|
109
|
+
# Cloud provider filters
|
110
|
+
aws_regions: Optional[List[str]] = None # NEW - Missing from API spec
|
111
|
+
azure_regions: Optional[List[str]] = None # NEW - Missing from API spec
|
112
|
+
|
113
|
+
|
114
|
+
class AcquisitionProfilePlatformDetails(AIRBaseModel):
|
115
|
+
"""Platform-specific acquisition profile details - matches API specification exactly."""
|
116
|
+
|
117
|
+
evidenceList: List[str] = [] # API uses camelCase
|
118
|
+
artifactList: Optional[List[str]] = None # API uses camelCase
|
119
|
+
customContentProfiles: List[Any] = [] # API uses camelCase
|
120
|
+
osQueries: List[str] = [] # FIXED: Added missing required field
|
121
|
+
networkCapture: Optional[NetworkCaptureConfig] = None # API uses camelCase
|
122
|
+
|
123
|
+
# Windows-specific fields
|
124
|
+
eventLogRecordsConfig: Optional[Dict[str, List[str]]] = None # FIXED: Added for Windows platform
|
125
|
+
|
126
|
+
@classmethod
|
127
|
+
def create_windows_config(cls, evidence_list: Optional[List[str]] = None, artifact_list: Optional[List[str]] = None) -> "AcquisitionProfilePlatformDetails":
|
128
|
+
"""Create a proper Windows platform configuration with all required fields."""
|
129
|
+
return cls(
|
130
|
+
evidenceList=evidence_list or [], # FIXED: Empty by default
|
131
|
+
artifactList=artifact_list or [], # FIXED: Empty by default
|
132
|
+
customContentProfiles=[],
|
133
|
+
osQueries=[],
|
134
|
+
networkCapture=NetworkCaptureConfig(
|
135
|
+
enabled=False,
|
136
|
+
duration=600,
|
137
|
+
pcap={"enabled": False},
|
138
|
+
networkFlow={"enabled": False}
|
139
|
+
),
|
140
|
+
eventLogRecordsConfig={"types": []}
|
141
|
+
)
|
142
|
+
|
143
|
+
@classmethod
|
144
|
+
def create_linux_config(cls, evidence_list: Optional[List[str]] = None, artifact_list: Optional[List[str]] = None) -> "AcquisitionProfilePlatformDetails":
|
145
|
+
"""Create a proper Linux platform configuration with all required fields."""
|
146
|
+
return cls(
|
147
|
+
evidenceList=evidence_list or [], # FIXED: Empty by default
|
148
|
+
artifactList=artifact_list or [], # FIXED: Empty by default
|
149
|
+
customContentProfiles=[],
|
150
|
+
osQueries=[],
|
151
|
+
networkCapture=NetworkCaptureConfig(
|
152
|
+
enabled=False,
|
153
|
+
duration=600,
|
154
|
+
pcap={"enabled": False},
|
155
|
+
networkFlow={"enabled": False}
|
156
|
+
)
|
157
|
+
)
|
158
|
+
|
159
|
+
@classmethod
|
160
|
+
def create_macos_config(cls, evidence_list: Optional[List[str]] = None, artifact_list: Optional[List[str]] = None) -> "AcquisitionProfilePlatformDetails":
|
161
|
+
"""Create a proper macOS platform configuration with all required fields."""
|
162
|
+
return cls(
|
163
|
+
evidenceList=evidence_list or [], # FIXED: Empty by default
|
164
|
+
artifactList=artifact_list or [], # FIXED: Empty by default
|
165
|
+
customContentProfiles=[],
|
166
|
+
osQueries=[],
|
167
|
+
networkCapture=NetworkCaptureConfig(
|
168
|
+
enabled=False,
|
169
|
+
duration=600,
|
170
|
+
pcap={"enabled": False},
|
171
|
+
networkFlow={"enabled": False}
|
172
|
+
)
|
173
|
+
)
|
174
|
+
|
175
|
+
|
176
|
+
class AcquisitionProfileAIXDetails(AIRBaseModel):
|
177
|
+
"""AIX-specific acquisition profile details - AIX doesn't support osQueries or networkCapture."""
|
178
|
+
|
179
|
+
evidenceList: List[str] = [] # API uses camelCase
|
180
|
+
artifactList: Optional[List[str]] = None # API uses camelCase
|
181
|
+
customContentProfiles: List[Any] = [] # API uses camelCase
|
182
|
+
# Note: AIX doesn't have osQueries, networkCapture, or eventLogRecordsConfig
|
183
|
+
|
184
|
+
@classmethod
|
185
|
+
def create_aix_config(cls, evidence_list: Optional[List[str]] = None, artifact_list: Optional[List[str]] = None) -> "AcquisitionProfileAIXDetails":
|
186
|
+
"""Create a proper AIX platform configuration with all required fields."""
|
187
|
+
return cls(
|
188
|
+
evidenceList=evidence_list or [], # FIXED: Empty by default
|
189
|
+
artifactList=artifact_list or [], # FIXED: Empty by default
|
190
|
+
customContentProfiles=[],
|
191
|
+
# Note: AIX doesn't have osQueries or networkCapture
|
192
|
+
)
|
193
|
+
|
194
|
+
|
195
|
+
class AcquisitionProfile(AIRBaseModel):
|
196
|
+
"""Acquisition profile model."""
|
197
|
+
|
198
|
+
id: str
|
199
|
+
name: str
|
200
|
+
organization_ids: List[int] = []
|
201
|
+
created_at: Optional[datetime] = None
|
202
|
+
updated_at: Optional[datetime] = None
|
203
|
+
created_by: str
|
204
|
+
deletable: bool = True
|
205
|
+
artifacts: List[str] = [] # Added for test compatibility
|
206
|
+
|
207
|
+
# Additional fields from API response
|
208
|
+
average_time: Optional[int] = None
|
209
|
+
last_used_at: Optional[datetime] = None
|
210
|
+
last_used_by: Optional[str] = None
|
211
|
+
has_event_log_records_evidence: Optional[bool] = None
|
212
|
+
|
213
|
+
|
214
|
+
class AcquisitionProfileDetails(AcquisitionProfile):
|
215
|
+
"""Detailed acquisition profile with platform configurations."""
|
216
|
+
|
217
|
+
windows: Optional[AcquisitionProfilePlatformDetails] = None
|
218
|
+
linux: Optional[AcquisitionProfilePlatformDetails] = None
|
219
|
+
macos: Optional[AcquisitionProfilePlatformDetails] = None
|
220
|
+
aix: Optional[AcquisitionProfilePlatformDetails] = None
|
221
|
+
e_discovery: Optional[Dict[str, List[EDiscoveryPattern]]] = None
|
222
|
+
settings: Optional[Dict[str, Any]] = None # Added for test compatibility
|
223
|
+
|
224
|
+
|
225
|
+
class EndpointVolumeConfig(AIRBaseModel):
|
226
|
+
"""Endpoint and volume configuration for disk image acquisition."""
|
227
|
+
|
228
|
+
endpointId: str # API uses camelCase
|
229
|
+
volumes: List[str] = []
|
230
|
+
|
231
|
+
|
232
|
+
class DiskImageOptions(AIRBaseModel):
|
233
|
+
"""Disk image options - API field names in camelCase."""
|
234
|
+
|
235
|
+
chunkSize: int # API uses camelCase
|
236
|
+
chunkCount: int = 0 # API uses camelCase
|
237
|
+
startOffset: int # API uses camelCase
|
238
|
+
imageType: str = "dd" # API uses camelCase
|
239
|
+
singleFile: bool = False # API uses camelCase
|
240
|
+
endpoints: List[EndpointVolumeConfig] = []
|
241
|
+
|
242
|
+
|
243
|
+
class SchedulerConfig(AIRBaseModel):
|
244
|
+
"""Scheduler configuration for acquisition tasks."""
|
245
|
+
|
246
|
+
when: str = "now"
|
247
|
+
timezone_type: Optional[str] = None
|
248
|
+
timezone: Optional[str] = None
|
249
|
+
start_date: Optional[int] = None
|
250
|
+
recurrence: Optional[str] = None
|
251
|
+
repeat_every: Optional[int] = None
|
252
|
+
repeat_on_week: Optional[List[str]] = None
|
253
|
+
repeat_on_month: Optional[int] = None
|
254
|
+
end_repeat_type: Optional[str] = None
|
255
|
+
end_date: Optional[int] = None
|
256
|
+
limit: Optional[int] = None
|
257
|
+
|
258
|
+
|
259
|
+
class AcquisitionTaskRequest(AIRBaseModel):
|
260
|
+
"""Acquisition task request."""
|
261
|
+
|
262
|
+
case_id: str
|
263
|
+
drone_config: DroneConfig
|
264
|
+
task_config: TaskConfig
|
265
|
+
acquisition_profile_id: str
|
266
|
+
filter: FilterConfig
|
267
|
+
|
268
|
+
|
269
|
+
class ImageAcquisitionTaskRequest(AIRBaseModel):
|
270
|
+
"""Image acquisition task request."""
|
271
|
+
|
272
|
+
case_id: Optional[str] = None
|
273
|
+
task_config: TaskConfig
|
274
|
+
disk_image_options: DiskImageOptions
|
275
|
+
filter: FilterConfig
|
276
|
+
scheduler_config: SchedulerConfig = SchedulerConfig()
|
277
|
+
|
278
|
+
|
279
|
+
class CreateAcquisitionProfileRequest(AIRBaseModel):
|
280
|
+
"""Create acquisition profile request - matches API specification exactly."""
|
281
|
+
|
282
|
+
name: str
|
283
|
+
organizationIds: List[int] = [0] # FIXED: Default to [0] instead of []
|
284
|
+
windows: AcquisitionProfilePlatformDetails # Required by API
|
285
|
+
linux: AcquisitionProfilePlatformDetails # Required by API
|
286
|
+
macos: AcquisitionProfilePlatformDetails # Required by API
|
287
|
+
aix: AcquisitionProfileAIXDetails # FIXED: Use AIX-specific model
|
288
|
+
eDiscovery: EDiscoveryConfig = EDiscoveryConfig(patterns=[
|
289
|
+
EDiscoveryPattern(pattern="**/*.7z", category="Archives")
|
290
|
+
]) # API requires this field to be non-empty
|
291
|
+
|
292
|
+
|
293
|
+
# Simplified request models for testing
|
294
|
+
class CreateAcquisitionRequest(AIRBaseModel):
|
295
|
+
"""Simplified acquisition request for testing."""
|
296
|
+
|
297
|
+
filter: Dict[str, Any]
|
298
|
+
profileId: str
|
299
|
+
name: Optional[str] = None
|
300
|
+
|
301
|
+
|
302
|
+
class CreateImageAcquisitionRequest(AIRBaseModel):
|
303
|
+
"""Simplified image acquisition request for testing - FIXED with required fields."""
|
304
|
+
|
305
|
+
filter: Dict[str, Any]
|
306
|
+
name: Optional[str] = None
|
307
|
+
fullDisk: bool = False
|
308
|
+
repository_id: Optional[str] = None
|
309
|
+
volumes: Optional[List[str]] = None
|
310
|
+
|
311
|
+
# FIXED: Add required fields for image acquisition
|
312
|
+
case_id: Optional[str] = None
|
313
|
+
task_config: Optional[Dict[str, Any]] = None
|
314
|
+
disk_image_options: Optional[Dict[str, Any]] = None
|
315
|
+
scheduler_config: Optional[Dict[str, Any]] = None
|
316
|
+
|
317
|
+
# API expects imageFormat for disk image type (e.g., dd, e01)
|
318
|
+
image_format: Optional[str] = Field(default=None, alias="imageFormat")
|
319
|
+
|
320
|
+
|
321
|
+
class AcquisitionFilter(Filter):
|
322
|
+
"""Filter for acquisition profile queries - matches API specification exactly."""
|
323
|
+
|
324
|
+
# Search and identification
|
325
|
+
search_term: Optional[str] = None
|
326
|
+
name: Optional[str] = None
|
327
|
+
|
328
|
+
# Organization parameters
|
329
|
+
organization_ids: Optional[List[int]] = None # Required by API
|
330
|
+
all_organizations: Optional[bool] = None # true/false
|
331
|
+
|
332
|
+
# Profile metadata (for backwards compatibility)
|
333
|
+
created_by: Optional[str] = None
|
334
|
+
deletable: Optional[bool] = None
|
335
|
+
|
336
|
+
def to_params(self) -> Dict[str, Any]:
|
337
|
+
"""Convert filter to API parameters."""
|
338
|
+
params = {}
|
339
|
+
|
340
|
+
# Pagination parameters (not in filter namespace) - only if set
|
341
|
+
if self.page_number is not None:
|
342
|
+
params["pageNumber"] = self.page_number
|
343
|
+
if self.page_size is not None:
|
344
|
+
params["pageSize"] = self.page_size
|
345
|
+
if self.sort_by is not None:
|
346
|
+
params["sortBy"] = self.sort_by
|
347
|
+
if self.sort_type is not None:
|
348
|
+
params["sortType"] = self.sort_type
|
349
|
+
|
350
|
+
# Add acquisition-specific filter parameters (use API field names)
|
351
|
+
if self.search_term is not None:
|
352
|
+
params["filter[searchTerm]"] = self.search_term
|
353
|
+
if self.name is not None:
|
354
|
+
params["filter[name]"] = self.name
|
355
|
+
if self.organization_ids is not None:
|
356
|
+
params["filter[organizationIds]"] = ",".join([str(x) for x in self.organization_ids])
|
357
|
+
if self.all_organizations is not None:
|
358
|
+
params["filter[allOrganizations]"] = "true" if self.all_organizations else "false"
|
359
|
+
|
360
|
+
# Backwards compatibility fields (not in API spec but may be used)
|
361
|
+
if self.created_by is not None:
|
362
|
+
params["filter[createdBy]"] = self.created_by
|
363
|
+
if self.deletable is not None:
|
364
|
+
params["filter[deletable]"] = "true" if self.deletable else "false"
|
365
|
+
|
251
366
|
return params
|