binalyze-air-sdk 1.0.1__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.
Files changed (82) hide show
  1. binalyze_air/__init__.py +77 -0
  2. binalyze_air/apis/__init__.py +27 -0
  3. binalyze_air/apis/authentication.py +27 -0
  4. binalyze_air/apis/auto_asset_tags.py +75 -0
  5. binalyze_air/apis/endpoints.py +22 -0
  6. binalyze_air/apis/event_subscription.py +97 -0
  7. binalyze_air/apis/evidence.py +53 -0
  8. binalyze_air/apis/evidences.py +216 -0
  9. binalyze_air/apis/interact.py +36 -0
  10. binalyze_air/apis/params.py +40 -0
  11. binalyze_air/apis/settings.py +27 -0
  12. binalyze_air/apis/user_management.py +74 -0
  13. binalyze_air/apis/users.py +68 -0
  14. binalyze_air/apis/webhooks.py +231 -0
  15. binalyze_air/base.py +133 -0
  16. binalyze_air/client.py +1338 -0
  17. binalyze_air/commands/__init__.py +146 -0
  18. binalyze_air/commands/acquisitions.py +387 -0
  19. binalyze_air/commands/assets.py +363 -0
  20. binalyze_air/commands/authentication.py +37 -0
  21. binalyze_air/commands/auto_asset_tags.py +231 -0
  22. binalyze_air/commands/baseline.py +396 -0
  23. binalyze_air/commands/cases.py +603 -0
  24. binalyze_air/commands/event_subscription.py +102 -0
  25. binalyze_air/commands/evidences.py +988 -0
  26. binalyze_air/commands/interact.py +58 -0
  27. binalyze_air/commands/organizations.py +221 -0
  28. binalyze_air/commands/policies.py +203 -0
  29. binalyze_air/commands/settings.py +29 -0
  30. binalyze_air/commands/tasks.py +56 -0
  31. binalyze_air/commands/triage.py +360 -0
  32. binalyze_air/commands/user_management.py +126 -0
  33. binalyze_air/commands/users.py +101 -0
  34. binalyze_air/config.py +245 -0
  35. binalyze_air/exceptions.py +50 -0
  36. binalyze_air/http_client.py +306 -0
  37. binalyze_air/models/__init__.py +285 -0
  38. binalyze_air/models/acquisitions.py +251 -0
  39. binalyze_air/models/assets.py +439 -0
  40. binalyze_air/models/audit.py +273 -0
  41. binalyze_air/models/authentication.py +70 -0
  42. binalyze_air/models/auto_asset_tags.py +117 -0
  43. binalyze_air/models/baseline.py +232 -0
  44. binalyze_air/models/cases.py +276 -0
  45. binalyze_air/models/endpoints.py +76 -0
  46. binalyze_air/models/event_subscription.py +172 -0
  47. binalyze_air/models/evidence.py +66 -0
  48. binalyze_air/models/evidences.py +349 -0
  49. binalyze_air/models/interact.py +136 -0
  50. binalyze_air/models/organizations.py +294 -0
  51. binalyze_air/models/params.py +128 -0
  52. binalyze_air/models/policies.py +250 -0
  53. binalyze_air/models/settings.py +84 -0
  54. binalyze_air/models/tasks.py +149 -0
  55. binalyze_air/models/triage.py +143 -0
  56. binalyze_air/models/user_management.py +97 -0
  57. binalyze_air/models/users.py +82 -0
  58. binalyze_air/queries/__init__.py +134 -0
  59. binalyze_air/queries/acquisitions.py +156 -0
  60. binalyze_air/queries/assets.py +105 -0
  61. binalyze_air/queries/audit.py +417 -0
  62. binalyze_air/queries/authentication.py +56 -0
  63. binalyze_air/queries/auto_asset_tags.py +60 -0
  64. binalyze_air/queries/baseline.py +185 -0
  65. binalyze_air/queries/cases.py +293 -0
  66. binalyze_air/queries/endpoints.py +25 -0
  67. binalyze_air/queries/event_subscription.py +55 -0
  68. binalyze_air/queries/evidence.py +140 -0
  69. binalyze_air/queries/evidences.py +280 -0
  70. binalyze_air/queries/interact.py +28 -0
  71. binalyze_air/queries/organizations.py +223 -0
  72. binalyze_air/queries/params.py +115 -0
  73. binalyze_air/queries/policies.py +150 -0
  74. binalyze_air/queries/settings.py +20 -0
  75. binalyze_air/queries/tasks.py +82 -0
  76. binalyze_air/queries/triage.py +231 -0
  77. binalyze_air/queries/user_management.py +83 -0
  78. binalyze_air/queries/users.py +69 -0
  79. binalyze_air_sdk-1.0.1.dist-info/METADATA +635 -0
  80. binalyze_air_sdk-1.0.1.dist-info/RECORD +82 -0
  81. binalyze_air_sdk-1.0.1.dist-info/WHEEL +5 -0
  82. binalyze_air_sdk-1.0.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,349 @@
1
+ """
2
+ Evidences/Repositories-related data models for the Binalyze AIR SDK.
3
+ """
4
+
5
+ from typing import Optional, List, Dict, Any
6
+ from datetime import datetime
7
+ from pydantic import Field, field_validator
8
+
9
+ from ..base import AIRBaseModel, Filter
10
+
11
+
12
+ class EvidenceRepository(AIRBaseModel):
13
+ """Base evidence repository model."""
14
+
15
+ id: str = Field(alias="_id")
16
+ name: str
17
+ description: Optional[str] = None
18
+ type: str # "amazon-s3", "azure-storage", "ftps", "sftp", "smb"
19
+ path: Optional[str] = None
20
+ username: Optional[str] = None
21
+ password: Optional[str] = None
22
+ host: Optional[str] = None
23
+ port: Optional[int] = None
24
+ organization_id: Optional[int] = Field(default=None, alias="organizationId")
25
+ organization_ids: Optional[List[int]] = Field(default=None, alias="organizationIds")
26
+ is_active: bool = Field(default=True, alias="isActive")
27
+ is_default: bool = Field(default=False, alias="isDefault")
28
+ created_at: Optional[datetime] = Field(default=None, alias="createdAt")
29
+ updated_at: Optional[datetime] = Field(default=None, alias="updatedAt")
30
+ created_by: Optional[str] = Field(default=None, alias="createdBy")
31
+
32
+ @field_validator('organization_id', mode='after')
33
+ @classmethod
34
+ def derive_organization_id(cls, v, info):
35
+ """Derive organization_id from organization_ids if not provided."""
36
+ if v is None and 'organization_ids' in info.data:
37
+ org_ids = info.data['organization_ids']
38
+ if org_ids and len(org_ids) > 0:
39
+ return org_ids[0]
40
+ return 0 # Default to 0 if no organization IDs
41
+ return v
42
+
43
+
44
+ class AmazonS3Repository(AIRBaseModel):
45
+ """Amazon S3 evidence repository model."""
46
+
47
+ id: str
48
+ name: str
49
+ description: Optional[str] = None
50
+ bucketName: str
51
+ region: str
52
+ accessKeyId: str
53
+ secretAccessKey: str
54
+ prefix: Optional[str] = None
55
+ organizationId: int
56
+ isActive: bool = True
57
+ isDefault: bool = False
58
+ createdAt: Optional[datetime] = None
59
+ updatedAt: Optional[datetime] = None
60
+
61
+
62
+ class CreateAmazonS3RepositoryRequest(AIRBaseModel):
63
+ """Create Amazon S3 repository request model."""
64
+
65
+ name: str
66
+ description: Optional[str] = None
67
+ bucketName: str
68
+ region: str
69
+ accessKeyId: str
70
+ secretAccessKey: str
71
+ prefix: Optional[str] = None
72
+ organizationId: int
73
+ isDefault: bool = False
74
+
75
+
76
+ class UpdateAmazonS3RepositoryRequest(AIRBaseModel):
77
+ """Update Amazon S3 repository request model."""
78
+
79
+ name: Optional[str] = None
80
+ description: Optional[str] = None
81
+ bucketName: Optional[str] = None
82
+ region: Optional[str] = None
83
+ accessKeyId: Optional[str] = None
84
+ secretAccessKey: Optional[str] = None
85
+ prefix: Optional[str] = None
86
+ isDefault: Optional[bool] = None
87
+
88
+
89
+ class AzureStorageRepository(AIRBaseModel):
90
+ """Azure Storage evidence repository model."""
91
+
92
+ id: str
93
+ name: str
94
+ description: Optional[str] = None
95
+ accountName: str
96
+ accountKey: str
97
+ containerName: str
98
+ prefix: Optional[str] = None
99
+ organizationId: int
100
+ isActive: bool = True
101
+ isDefault: bool = False
102
+ createdAt: Optional[datetime] = None
103
+ updatedAt: Optional[datetime] = None
104
+
105
+
106
+ class CreateAzureStorageRepositoryRequest(AIRBaseModel):
107
+ """Create Azure Storage repository request model."""
108
+
109
+ name: str
110
+ description: Optional[str] = None
111
+ accountName: str
112
+ accountKey: str
113
+ containerName: str
114
+ prefix: Optional[str] = None
115
+ organizationId: int
116
+ isDefault: bool = False
117
+
118
+
119
+ class UpdateAzureStorageRepositoryRequest(AIRBaseModel):
120
+ """Update Azure Storage repository request model."""
121
+
122
+ name: Optional[str] = None
123
+ description: Optional[str] = None
124
+ accountName: Optional[str] = None
125
+ accountKey: Optional[str] = None
126
+ containerName: Optional[str] = None
127
+ prefix: Optional[str] = None
128
+ isDefault: Optional[bool] = None
129
+
130
+
131
+ class FTPSRepository(AIRBaseModel):
132
+ """FTPS evidence repository model."""
133
+
134
+ id: str
135
+ name: str
136
+ description: Optional[str] = None
137
+ host: str
138
+ port: int = 21
139
+ username: str
140
+ password: str
141
+ remotePath: Optional[str] = None
142
+ passive: bool = True
143
+ organizationId: int
144
+ isActive: bool = True
145
+ isDefault: bool = False
146
+ createdAt: Optional[datetime] = None
147
+ updatedAt: Optional[datetime] = None
148
+
149
+
150
+ class CreateFTPSRepositoryRequest(AIRBaseModel):
151
+ """Create FTPS repository request model."""
152
+
153
+ name: str
154
+ description: Optional[str] = None
155
+ host: str
156
+ port: int = 21
157
+ username: str
158
+ password: str
159
+ remotePath: Optional[str] = None
160
+ passive: bool = True
161
+ organizationId: int
162
+ isDefault: bool = False
163
+
164
+
165
+ class UpdateFTPSRepositoryRequest(AIRBaseModel):
166
+ """Update FTPS repository request model."""
167
+
168
+ name: Optional[str] = None
169
+ description: Optional[str] = None
170
+ host: Optional[str] = None
171
+ port: Optional[int] = None
172
+ username: Optional[str] = None
173
+ password: Optional[str] = None
174
+ remotePath: Optional[str] = None
175
+ passive: Optional[bool] = None
176
+ isDefault: Optional[bool] = None
177
+
178
+
179
+ class SFTPRepository(AIRBaseModel):
180
+ """SFTP evidence repository model."""
181
+
182
+ id: str
183
+ name: str
184
+ description: Optional[str] = None
185
+ host: str
186
+ port: int = 22
187
+ username: str
188
+ password: Optional[str] = None
189
+ privateKey: Optional[str] = None
190
+ remotePath: Optional[str] = None
191
+ organizationId: int
192
+ isActive: bool = True
193
+ isDefault: bool = False
194
+ createdAt: Optional[datetime] = None
195
+ updatedAt: Optional[datetime] = None
196
+
197
+
198
+ class CreateSFTPRepositoryRequest(AIRBaseModel):
199
+ """Create SFTP repository request model."""
200
+
201
+ name: str
202
+ description: Optional[str] = None
203
+ host: str
204
+ port: int = 22
205
+ username: str
206
+ password: Optional[str] = None
207
+ privateKey: Optional[str] = None
208
+ remotePath: Optional[str] = None
209
+ organizationId: int
210
+ isDefault: bool = False
211
+
212
+
213
+ class UpdateSFTPRepositoryRequest(AIRBaseModel):
214
+ """Update SFTP repository request model."""
215
+
216
+ name: Optional[str] = None
217
+ description: Optional[str] = None
218
+ host: Optional[str] = None
219
+ port: Optional[int] = None
220
+ username: Optional[str] = None
221
+ password: Optional[str] = None
222
+ privateKey: Optional[str] = None
223
+ remotePath: Optional[str] = None
224
+ isDefault: Optional[bool] = None
225
+
226
+
227
+ class SMBRepository(AIRBaseModel):
228
+ """SMB evidence repository model."""
229
+
230
+ id: str
231
+ name: str
232
+ description: Optional[str] = None
233
+ path: str
234
+ username: str
235
+ password: str
236
+ domainName: Optional[str] = None
237
+ organizationId: int
238
+ organizationIds: Optional[List[int]] = None
239
+ isActive: bool = True
240
+ isDefault: bool = False
241
+ createdAt: Optional[datetime] = None
242
+ updatedAt: Optional[datetime] = None
243
+
244
+
245
+ class CreateSMBRepositoryRequest(AIRBaseModel):
246
+ """Create SMB repository request model."""
247
+
248
+ name: str
249
+ description: Optional[str] = None
250
+ path: str
251
+ username: str
252
+ password: str
253
+ domainName: Optional[str] = None
254
+ organizationId: int
255
+ organizationIds: Optional[List[int]] = None
256
+ isDefault: bool = False
257
+
258
+
259
+ class UpdateSMBRepositoryRequest(AIRBaseModel):
260
+ """Update SMB repository request model."""
261
+
262
+ name: Optional[str] = None
263
+ description: Optional[str] = None
264
+ path: Optional[str] = None
265
+ username: Optional[str] = None
266
+ password: Optional[str] = None
267
+ domainName: Optional[str] = None
268
+ isDefault: Optional[bool] = None
269
+
270
+
271
+ class ValidateRepositoryRequest(AIRBaseModel):
272
+ """Validate repository request model."""
273
+
274
+ repositoryType: str # "amazon-s3", "azure-storage", "ftps"
275
+ config: Dict[str, Any] # Repository-specific configuration
276
+
277
+
278
+ class ValidationResult(AIRBaseModel):
279
+ """Repository validation result model."""
280
+
281
+ isValid: bool
282
+ message: str
283
+ errors: List[str] = []
284
+ warnings: List[str] = []
285
+
286
+
287
+ class RepositoryFilter(Filter):
288
+ """Filter for repository queries."""
289
+
290
+ name: Optional[str] = None
291
+ type: Optional[str] = None
292
+ organization_id: Optional[int] = None
293
+ all_organizations: Optional[bool] = None
294
+ path: Optional[str] = None
295
+ username: Optional[str] = None
296
+ host: Optional[str] = None
297
+ is_active: Optional[bool] = None
298
+ is_default: Optional[bool] = None
299
+ created_by: Optional[str] = None
300
+
301
+ def to_params(self) -> Dict[str, Any]:
302
+ """Convert filter to API parameters with proper field mapping."""
303
+ params = {}
304
+
305
+ # Pagination parameters (not in filter namespace)
306
+ if self.page_number is not None:
307
+ params["pageNumber"] = self.page_number
308
+ if self.page_size is not None:
309
+ params["pageSize"] = self.page_size
310
+ if self.sort_by is not None:
311
+ params["sortBy"] = self.sort_by
312
+ if self.sort_type is not None:
313
+ params["sortType"] = self.sort_type
314
+
315
+ # Filter parameters with proper field mapping
316
+ field_mappings = {
317
+ "search_term": "searchTerm",
318
+ "organization_ids": "organizationIds",
319
+ "organization_id": "organizationIds", # Map to organizationIds for API
320
+ "all_organizations": "allOrganizations",
321
+ "name": "name",
322
+ "type": "type",
323
+ "path": "path",
324
+ "username": "username",
325
+ "host": "host",
326
+ "is_active": "isActive",
327
+ "is_default": "isDefault",
328
+ "created_by": "createdBy"
329
+ }
330
+
331
+ for field_name, field_value in self.model_dump(exclude_none=True).items():
332
+ # Skip pagination/sorting fields as they're handled above
333
+ if field_name in ["page_number", "page_size", "sort_by", "sort_type"]:
334
+ continue
335
+
336
+ if field_value is not None:
337
+ api_field_name = field_mappings.get(field_name, field_name)
338
+
339
+ # Special handling for organization_ids - use first ID for organizationIds filter
340
+ if field_name == "organization_ids" and isinstance(field_value, list) and len(field_value) > 0:
341
+ params[f"filter[{api_field_name}]"] = ",".join(map(str, field_value))
342
+ elif field_name == "organization_id":
343
+ params[f"filter[organizationIds]"] = str(field_value)
344
+ elif isinstance(field_value, list):
345
+ params[f"filter[{api_field_name}]"] = ",".join(map(str, field_value))
346
+ else:
347
+ params[f"filter[{api_field_name}]"] = str(field_value)
348
+
349
+ return params
@@ -0,0 +1,136 @@
1
+ """
2
+ Interact API models for the Binalyze AIR SDK.
3
+ """
4
+
5
+ from typing import List, Optional, Dict, Any
6
+ from datetime import datetime
7
+ from enum import Enum
8
+ from pydantic import Field
9
+
10
+ from ..base import AIRBaseModel
11
+
12
+
13
+ class SendToLocation(str, Enum):
14
+ """Send to location options."""
15
+ USER_LOCAL = "user-local"
16
+ REPOSITORY = "repository"
17
+ EVIDENCE_REPOSITORY = "evidence-repository"
18
+
19
+
20
+ class TaskConfigChoice(str, Enum):
21
+ """Task configuration choice options."""
22
+ USE_POLICY = "use-policy"
23
+ USE_CUSTOM_OPTIONS = "use-custom-options"
24
+
25
+
26
+ class SendToConfig(AIRBaseModel):
27
+ """Send to configuration model."""
28
+
29
+ location: SendToLocation
30
+ repository_id: Optional[str] = Field(default=None, alias="repositoryId")
31
+ evidence_repository_id: Optional[str] = Field(default=None, alias="evidenceRepositoryId")
32
+
33
+
34
+ class BandwidthConfig(AIRBaseModel):
35
+ """Bandwidth configuration model."""
36
+
37
+ limit: Optional[int] = None
38
+
39
+
40
+ class DiskSpaceConfig(AIRBaseModel):
41
+ """Disk space configuration model."""
42
+
43
+ reserve: Optional[int] = None
44
+
45
+
46
+ class TaskConfig(AIRBaseModel):
47
+ """Task configuration model."""
48
+
49
+ choice: TaskConfigChoice
50
+ send_to: Optional[SendToConfig] = Field(default=None, alias="sendTo")
51
+ bandwidth: Optional[BandwidthConfig] = None
52
+ disk_space: Optional[DiskSpaceConfig] = Field(default=None, alias="diskSpace")
53
+
54
+
55
+ class AssignInteractiveShellTaskRequest(AIRBaseModel):
56
+ """Request model for assigning interactive shell task."""
57
+
58
+ asset_id: str = Field(alias="assetId")
59
+ case_id: str = Field(alias="caseId")
60
+ task_config: TaskConfig = Field(alias="taskConfig")
61
+
62
+
63
+ class InteractiveShellTaskResponse(AIRBaseModel):
64
+ """Response model for interactive shell task assignment."""
65
+
66
+ session_id: str = Field(alias="sessionId")
67
+ idle_timeout: int = Field(alias="idleTimeout")
68
+ config: TaskConfig
69
+
70
+
71
+ # Legacy models for backward compatibility (deprecated)
72
+ class InteractionType(str, Enum):
73
+ """Interaction types."""
74
+ SHELL = "shell"
75
+ POWERSHELL = "powershell"
76
+ CMD = "cmd"
77
+ BASH = "bash"
78
+
79
+
80
+ class InteractionStatus(str, Enum):
81
+ """Interaction status."""
82
+ PENDING = "pending"
83
+ RUNNING = "running"
84
+ COMPLETED = "completed"
85
+ FAILED = "failed"
86
+ CANCELLED = "cancelled"
87
+ TIMEOUT = "timeout"
88
+
89
+
90
+ class ShellInteraction(AIRBaseModel):
91
+ """Shell interaction model (legacy)."""
92
+
93
+ id: str
94
+ task_id: str
95
+ endpoint_id: str
96
+ endpoint_name: str
97
+ interaction_type: InteractionType
98
+ command: str
99
+ output: Optional[str] = None
100
+ error_output: Optional[str] = None
101
+ exit_code: Optional[int] = None
102
+ status: InteractionStatus = InteractionStatus.PENDING
103
+ timeout: int = 300 # seconds
104
+ organization_id: int
105
+ created_by: Optional[str] = None
106
+ created_at: Optional[datetime] = None
107
+ started_at: Optional[datetime] = None
108
+ completed_at: Optional[datetime] = None
109
+ duration: Optional[int] = None # seconds
110
+ environment_variables: Optional[Dict[str, str]] = None
111
+ working_directory: Optional[str] = None
112
+
113
+
114
+ class AssignShellTaskRequest(AIRBaseModel):
115
+ """Request model for assigning shell interaction tasks (legacy)."""
116
+
117
+ endpoint_ids: List[str]
118
+ command: str
119
+ interaction_type: InteractionType = InteractionType.SHELL
120
+ timeout: Optional[int] = 300
121
+ organization_ids: Optional[List[int]] = None
122
+ case_id: Optional[str] = None
123
+ environment_variables: Optional[Dict[str, str]] = None
124
+ working_directory: Optional[str] = None
125
+ description: Optional[str] = None
126
+
127
+
128
+ class ShellTaskResponse(AIRBaseModel):
129
+ """Response model for shell task assignment (legacy)."""
130
+
131
+ task_id: str
132
+ endpoint_interactions: List[ShellInteraction]
133
+ success_count: int
134
+ failure_count: int
135
+ total_count: int
136
+ errors: Optional[List[Dict[str, Any]]] = None