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.
Files changed (142) hide show
  1. binalyze_air/__init__.py +77 -77
  2. binalyze_air/apis/__init__.py +67 -27
  3. binalyze_air/apis/acquisitions.py +107 -0
  4. binalyze_air/apis/api_tokens.py +49 -0
  5. binalyze_air/apis/assets.py +161 -0
  6. binalyze_air/apis/audit_logs.py +26 -0
  7. binalyze_air/apis/{authentication.py → auth.py} +29 -27
  8. binalyze_air/apis/auto_asset_tags.py +79 -75
  9. binalyze_air/apis/backup.py +177 -0
  10. binalyze_air/apis/baseline.py +46 -0
  11. binalyze_air/apis/cases.py +225 -0
  12. binalyze_air/apis/cloud_forensics.py +116 -0
  13. binalyze_air/apis/event_subscription.py +96 -96
  14. binalyze_air/apis/evidence.py +249 -53
  15. binalyze_air/apis/interact.py +153 -36
  16. binalyze_air/apis/investigation_hub.py +234 -0
  17. binalyze_air/apis/license.py +104 -0
  18. binalyze_air/apis/logger.py +83 -0
  19. binalyze_air/apis/multipart_upload.py +201 -0
  20. binalyze_air/apis/notifications.py +115 -0
  21. binalyze_air/apis/organizations.py +267 -0
  22. binalyze_air/apis/params.py +44 -39
  23. binalyze_air/apis/policies.py +186 -0
  24. binalyze_air/apis/preset_filters.py +79 -0
  25. binalyze_air/apis/recent_activities.py +71 -0
  26. binalyze_air/apis/relay_server.py +104 -0
  27. binalyze_air/apis/settings.py +395 -27
  28. binalyze_air/apis/tasks.py +80 -0
  29. binalyze_air/apis/triage.py +197 -0
  30. binalyze_air/apis/user_management.py +183 -74
  31. binalyze_air/apis/webhook_executions.py +50 -0
  32. binalyze_air/apis/webhooks.py +322 -230
  33. binalyze_air/base.py +207 -133
  34. binalyze_air/client.py +217 -1337
  35. binalyze_air/commands/__init__.py +175 -145
  36. binalyze_air/commands/acquisitions.py +661 -387
  37. binalyze_air/commands/api_tokens.py +55 -0
  38. binalyze_air/commands/assets.py +324 -362
  39. binalyze_air/commands/{authentication.py → auth.py} +36 -36
  40. binalyze_air/commands/auto_asset_tags.py +230 -230
  41. binalyze_air/commands/backup.py +47 -0
  42. binalyze_air/commands/baseline.py +32 -396
  43. binalyze_air/commands/cases.py +609 -602
  44. binalyze_air/commands/cloud_forensics.py +88 -0
  45. binalyze_air/commands/event_subscription.py +101 -101
  46. binalyze_air/commands/evidences.py +918 -988
  47. binalyze_air/commands/interact.py +172 -58
  48. binalyze_air/commands/investigation_hub.py +315 -0
  49. binalyze_air/commands/license.py +183 -0
  50. binalyze_air/commands/logger.py +126 -0
  51. binalyze_air/commands/multipart_upload.py +363 -0
  52. binalyze_air/commands/notifications.py +45 -0
  53. binalyze_air/commands/organizations.py +200 -221
  54. binalyze_air/commands/policies.py +175 -203
  55. binalyze_air/commands/preset_filters.py +55 -0
  56. binalyze_air/commands/recent_activities.py +32 -0
  57. binalyze_air/commands/relay_server.py +144 -0
  58. binalyze_air/commands/settings.py +431 -29
  59. binalyze_air/commands/tasks.py +95 -56
  60. binalyze_air/commands/triage.py +224 -360
  61. binalyze_air/commands/user_management.py +351 -126
  62. binalyze_air/commands/webhook_executions.py +77 -0
  63. binalyze_air/config.py +244 -244
  64. binalyze_air/exceptions.py +49 -49
  65. binalyze_air/http_client.py +426 -305
  66. binalyze_air/models/__init__.py +287 -285
  67. binalyze_air/models/acquisitions.py +365 -250
  68. binalyze_air/models/api_tokens.py +73 -0
  69. binalyze_air/models/assets.py +438 -438
  70. binalyze_air/models/audit.py +247 -272
  71. binalyze_air/models/audit_logs.py +14 -0
  72. binalyze_air/models/{authentication.py → auth.py} +69 -69
  73. binalyze_air/models/auto_asset_tags.py +227 -116
  74. binalyze_air/models/backup.py +138 -0
  75. binalyze_air/models/baseline.py +231 -231
  76. binalyze_air/models/cases.py +275 -275
  77. binalyze_air/models/cloud_forensics.py +145 -0
  78. binalyze_air/models/event_subscription.py +170 -171
  79. binalyze_air/models/evidence.py +65 -65
  80. binalyze_air/models/evidences.py +367 -348
  81. binalyze_air/models/interact.py +266 -135
  82. binalyze_air/models/investigation_hub.py +265 -0
  83. binalyze_air/models/license.py +150 -0
  84. binalyze_air/models/logger.py +83 -0
  85. binalyze_air/models/multipart_upload.py +352 -0
  86. binalyze_air/models/notifications.py +138 -0
  87. binalyze_air/models/organizations.py +293 -293
  88. binalyze_air/models/params.py +153 -127
  89. binalyze_air/models/policies.py +260 -249
  90. binalyze_air/models/preset_filters.py +79 -0
  91. binalyze_air/models/recent_activities.py +70 -0
  92. binalyze_air/models/relay_server.py +121 -0
  93. binalyze_air/models/settings.py +538 -84
  94. binalyze_air/models/tasks.py +215 -149
  95. binalyze_air/models/triage.py +141 -142
  96. binalyze_air/models/user_management.py +200 -97
  97. binalyze_air/models/webhook_executions.py +33 -0
  98. binalyze_air/queries/__init__.py +121 -133
  99. binalyze_air/queries/acquisitions.py +155 -155
  100. binalyze_air/queries/api_tokens.py +46 -0
  101. binalyze_air/queries/assets.py +186 -105
  102. binalyze_air/queries/audit.py +400 -416
  103. binalyze_air/queries/{authentication.py → auth.py} +55 -55
  104. binalyze_air/queries/auto_asset_tags.py +59 -59
  105. binalyze_air/queries/backup.py +66 -0
  106. binalyze_air/queries/baseline.py +21 -185
  107. binalyze_air/queries/cases.py +292 -292
  108. binalyze_air/queries/cloud_forensics.py +137 -0
  109. binalyze_air/queries/event_subscription.py +54 -54
  110. binalyze_air/queries/evidence.py +139 -139
  111. binalyze_air/queries/evidences.py +279 -279
  112. binalyze_air/queries/interact.py +140 -28
  113. binalyze_air/queries/investigation_hub.py +329 -0
  114. binalyze_air/queries/license.py +85 -0
  115. binalyze_air/queries/logger.py +58 -0
  116. binalyze_air/queries/multipart_upload.py +180 -0
  117. binalyze_air/queries/notifications.py +71 -0
  118. binalyze_air/queries/organizations.py +222 -222
  119. binalyze_air/queries/params.py +154 -115
  120. binalyze_air/queries/policies.py +149 -149
  121. binalyze_air/queries/preset_filters.py +60 -0
  122. binalyze_air/queries/recent_activities.py +44 -0
  123. binalyze_air/queries/relay_server.py +42 -0
  124. binalyze_air/queries/settings.py +533 -20
  125. binalyze_air/queries/tasks.py +125 -81
  126. binalyze_air/queries/triage.py +230 -230
  127. binalyze_air/queries/user_management.py +193 -83
  128. binalyze_air/queries/webhook_executions.py +39 -0
  129. binalyze_air_sdk-1.0.3.dist-info/METADATA +752 -0
  130. binalyze_air_sdk-1.0.3.dist-info/RECORD +132 -0
  131. {binalyze_air_sdk-1.0.1.dist-info → binalyze_air_sdk-1.0.3.dist-info}/WHEEL +1 -1
  132. binalyze_air/apis/endpoints.py +0 -22
  133. binalyze_air/apis/evidences.py +0 -216
  134. binalyze_air/apis/users.py +0 -68
  135. binalyze_air/commands/users.py +0 -101
  136. binalyze_air/models/endpoints.py +0 -76
  137. binalyze_air/models/users.py +0 -82
  138. binalyze_air/queries/endpoints.py +0 -25
  139. binalyze_air/queries/users.py +0 -69
  140. binalyze_air_sdk-1.0.1.dist-info/METADATA +0 -635
  141. binalyze_air_sdk-1.0.1.dist-info/RECORD +0 -82
  142. {binalyze_air_sdk-1.0.1.dist-info → binalyze_air_sdk-1.0.3.dist-info}/top_level.txt +0 -0
@@ -1,82 +1,126 @@
1
- """
2
- Task-related queries for the Binalyze AIR SDK.
3
- """
4
-
5
- from typing import List, Optional
6
-
7
- from ..base import Query
8
- from ..models.tasks import Task, TaskFilter, TaskData, PlatformEvidenceConfig, TaskConfig, DroneConfig, TaskAssignment
9
- from ..http_client import HTTPClient
10
-
11
-
12
- class ListTasksQuery(Query[List[Task]]):
13
- """Query to list tasks with optional filtering."""
14
-
15
- def __init__(self, http_client: HTTPClient, filter_params: Optional[TaskFilter] = None, organization_ids: Optional[List[int]] = None):
16
- self.http_client = http_client
17
- self.filter_params = filter_params or TaskFilter()
18
- self.organization_ids = organization_ids or [0]
19
-
20
- def execute(self) -> List[Task]:
21
- """Execute the query to list tasks."""
22
- params = self.filter_params.to_params()
23
-
24
- # Add organization IDs
25
- params["filter[organizationIds]"] = ",".join(map(str, self.organization_ids))
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("tasks", params=params)
34
-
35
- entities = response.get("result", {}).get("entities", [])
36
-
37
- # Use Pydantic parsing with proper field aliasing
38
- tasks = []
39
- for entity_data in entities:
40
- task = Task.model_validate(entity_data)
41
- tasks.append(task)
42
-
43
- return tasks
44
-
45
-
46
- class GetTaskQuery(Query[Task]):
47
- """Query to get a specific task by ID."""
48
-
49
- def __init__(self, http_client: HTTPClient, task_id: str):
50
- self.http_client = http_client
51
- self.task_id = task_id
52
-
53
- def execute(self) -> Task:
54
- """Execute the query to get a task."""
55
- response = self.http_client.get(f"tasks/{self.task_id}")
56
-
57
- task_data = response.get("result", {})
58
-
59
- # Use Pydantic parsing with proper field aliasing
60
- return Task.model_validate(task_data)
61
-
62
-
63
- class GetTaskAssignmentsQuery(Query[List[TaskAssignment]]):
64
- """Query to get task assignments for a specific task."""
65
-
66
- def __init__(self, http_client: HTTPClient, task_id: str):
67
- self.http_client = http_client
68
- self.task_id = task_id
69
-
70
- def execute(self) -> List[TaskAssignment]:
71
- """Execute the query to get task assignments."""
72
- response = self.http_client.get(f"tasks/{self.task_id}/assignments")
73
-
74
- entities = response.get("result", {}).get("entities", [])
75
-
76
- # Use Pydantic parsing with proper field aliasing
77
- assignments = []
78
- for entity_data in entities:
79
- assignment = TaskAssignment.model_validate(entity_data)
80
- assignments.append(assignment)
81
-
1
+ """
2
+ Task-related queries for the Binalyze AIR SDK.
3
+ """
4
+
5
+ from typing import List, Optional
6
+
7
+ from ..base import Query, ensure_organization_ids, format_organization_ids_param
8
+ from ..models.tasks import Task, TaskFilter, TaskData, PlatformEvidenceConfig, TaskConfig, DroneConfig, TaskAssignment
9
+ from ..http_client import HTTPClient
10
+
11
+
12
+ class ListTasksQuery(Query[List[Task]]):
13
+ """Query to list tasks with optional filtering."""
14
+
15
+ def __init__(self, http_client: HTTPClient, filter_params: Optional[TaskFilter] = None, organization_ids: Optional[List[int]] = None):
16
+ self.http_client = http_client
17
+ self.filter_params = filter_params or TaskFilter()
18
+ self.organization_ids = ensure_organization_ids(organization_ids)
19
+
20
+ def execute(self) -> List[Task]:
21
+ """Execute the query to list tasks."""
22
+ params = self.filter_params.to_params()
23
+
24
+ # Add organization IDs using utility function
25
+ org_params = format_organization_ids_param(self.organization_ids)
26
+ params.update(org_params)
27
+
28
+ # Ensure consistent sorting to match API defaults
29
+ if "sortBy" not in params:
30
+ params["sortBy"] = "createdAt"
31
+ if "sortType" not in params:
32
+ params["sortType"] = "ASC"
33
+
34
+ response = self.http_client.get("tasks", params=params)
35
+
36
+ entities = response.get("result", {}).get("entities", [])
37
+
38
+ # Use Pydantic parsing with proper field aliasing and error handling
39
+ tasks = []
40
+ for i, entity_data in enumerate(entities):
41
+ try:
42
+ # Validate data field structure before parsing
43
+ if "data" in entity_data and isinstance(entity_data["data"], list):
44
+ # Fix: API sometimes returns data as list instead of object
45
+ if len(entity_data["data"]) == 1:
46
+ entity_data["data"] = entity_data["data"][0]
47
+ elif len(entity_data["data"]) == 0:
48
+ entity_data["data"] = None
49
+ # If multiple items, keep as is and let validation handle it
50
+
51
+ task = Task.model_validate(entity_data)
52
+ tasks.append(task)
53
+ except Exception as e:
54
+ # Log validation error but continue processing other tasks
55
+ print(f"[WARN] Failed to parse task {i}: {e}")
56
+ print(f"[DEBUG] Task data structure: {type(entity_data.get('data', 'missing'))}")
57
+ # Create a minimal task object to avoid complete failure
58
+ try:
59
+ minimal_data = {
60
+ "_id": entity_data.get("_id", f"unknown-{i}"),
61
+ "name": entity_data.get("name", "Unknown Task"),
62
+ "type": entity_data.get("type", "unknown"),
63
+ "status": entity_data.get("status", "unknown"),
64
+ "createdBy": entity_data.get("createdBy", "unknown"),
65
+ "organizationId": entity_data.get("organizationId", 0),
66
+ # Skip the problematic data field
67
+ "data": None
68
+ }
69
+ task = Task.model_validate(minimal_data)
70
+ tasks.append(task)
71
+ except Exception as inner_e:
72
+ print(f"[ERROR] Could not create minimal task object: {inner_e}")
73
+ continue
74
+
75
+ return tasks
76
+
77
+
78
+ class GetTaskQuery(Query[Task]):
79
+ """Query to get a specific task by ID."""
80
+
81
+ def __init__(self, http_client: HTTPClient, task_id: str):
82
+ self.http_client = http_client
83
+ self.task_id = task_id
84
+
85
+ def execute(self) -> Task:
86
+ """Execute the query to get a task."""
87
+ response = self.http_client.get(f"tasks/{self.task_id}")
88
+
89
+ task_data = response.get("result", {})
90
+
91
+ # Validate and fix data field structure if needed
92
+ if "data" in task_data and isinstance(task_data["data"], list):
93
+ if len(task_data["data"]) == 1:
94
+ task_data["data"] = task_data["data"][0]
95
+ elif len(task_data["data"]) == 0:
96
+ task_data["data"] = None
97
+
98
+ # Use Pydantic parsing with proper field aliasing
99
+ return Task.model_validate(task_data)
100
+
101
+
102
+ class GetTaskAssignmentsQuery(Query[List[TaskAssignment]]):
103
+ """Query to get task assignments for a specific task."""
104
+
105
+ def __init__(self, http_client: HTTPClient, task_id: str):
106
+ self.http_client = http_client
107
+ self.task_id = task_id
108
+
109
+ def execute(self) -> List[TaskAssignment]:
110
+ """Execute the query to get task assignments."""
111
+ response = self.http_client.get(f"tasks/{self.task_id}/assignments")
112
+
113
+ entities = response.get("result", {}).get("entities", [])
114
+
115
+ # Use Pydantic parsing with proper field aliasing and error handling
116
+ assignments = []
117
+ for i, entity_data in enumerate(entities):
118
+ try:
119
+ assignment = TaskAssignment.model_validate(entity_data)
120
+ assignments.append(assignment)
121
+ except Exception as e:
122
+ print(f"[WARN] Failed to parse task assignment {i}: {e}")
123
+ # Continue processing other assignments
124
+ continue
125
+
82
126
  return assignments