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
binalyze_air/base.py CHANGED
@@ -1,133 +1,207 @@
1
- """
2
- Base classes for CQRS implementation in the AIR SDK.
3
- """
4
-
5
- from abc import ABC, abstractmethod
6
- from typing import Any, Dict, List, Optional, TypeVar, Generic
7
- from pydantic import BaseModel as PydanticBaseModel, ConfigDict
8
-
9
- T = TypeVar("T")
10
-
11
-
12
- class Query(Generic[T], ABC):
13
- """Base class for all queries (read operations)."""
14
-
15
- @abstractmethod
16
- def execute(self) -> T:
17
- """Execute the query and return the result."""
18
- pass
19
-
20
-
21
- class Command(Generic[T], ABC):
22
- """Base class for all commands (write operations)."""
23
-
24
- @abstractmethod
25
- def execute(self) -> T:
26
- """Execute the command and return the result."""
27
- pass
28
-
29
-
30
- class AIRBaseModel(PydanticBaseModel):
31
- """Base Pydantic model with common configurations."""
32
-
33
- model_config = ConfigDict(
34
- use_enum_values=True,
35
- validate_assignment=True,
36
- arbitrary_types_allowed=True
37
- )
38
-
39
-
40
- class PaginatedResponse(AIRBaseModel, Generic[T]):
41
- """Generic paginated response model."""
42
-
43
- entities: List[T]
44
- total_entity_count: int
45
- current_page: int
46
- page_size: int
47
- total_page_count: int
48
- previous_page: Optional[int] = None
49
- next_page: Optional[int] = None
50
-
51
-
52
- class APIResponse(AIRBaseModel, Generic[T]):
53
- """Generic API response model."""
54
-
55
- success: bool
56
- result: T
57
- status_code: int
58
- errors: List[str] = []
59
-
60
-
61
- class Filter(AIRBaseModel):
62
- """Base filter model for queries with pagination and sorting support."""
63
-
64
- # Basic filter fields
65
- search_term: Optional[str] = None
66
- organization_ids: Optional[List[int]] = None
67
-
68
- # Pagination parameters (match API documentation exactly) - no defaults
69
- page_number: Optional[int] = None
70
- page_size: Optional[int] = None
71
-
72
- # Sorting parameters (match API documentation exactly) - no defaults
73
- sort_by: Optional[str] = None
74
- sort_type: Optional[str] = None
75
-
76
- def to_params(self) -> Dict[str, Any]:
77
- """Convert filter to API parameters."""
78
- params = {}
79
-
80
- # Pagination parameters (not in filter namespace) - only if set
81
- if self.page_number is not None:
82
- params["pageNumber"] = self.page_number
83
- if self.page_size is not None:
84
- params["pageSize"] = self.page_size
85
- if self.sort_by is not None:
86
- params["sortBy"] = self.sort_by
87
- if self.sort_type is not None:
88
- params["sortType"] = self.sort_type
89
-
90
- # Filter parameters (in filter namespace)
91
- for field_name, field_value in self.model_dump(exclude_none=True).items():
92
- # Skip pagination/sorting fields as they're handled above
93
- if field_name in ["page_number", "page_size", "sort_by", "sort_type"]:
94
- continue
95
-
96
- if field_value is not None:
97
- if isinstance(field_value, list):
98
- params[f"filter[{field_name}]"] = ",".join(map(str, field_value))
99
- else:
100
- params[f"filter[{field_name}]"] = str(field_value)
101
- return params
102
-
103
-
104
- class PaginatedList(list):
105
- """List-like container that carries pagination metadata.
106
- This allows SDK query methods to return a normal iterable while still
107
- exposing additional pagination attributes such as total_entity_count.
108
- The class simply subclasses ``list`` and adds attributes during
109
- construction. All standard list operations remain intact.
110
- """
111
- def __init__(
112
- self,
113
- iterable=None,
114
- *,
115
- total_entity_count: int | None = None,
116
- current_page: int | None = None,
117
- page_size: int | None = None,
118
- total_page_count: int | None = None,
119
- ) -> None:
120
- super().__init__(iterable or [])
121
- # Store metadata for caller introspection
122
- self.total_entity_count = total_entity_count
123
- self.current_page = current_page
124
- self.page_size = page_size
125
- self.total_page_count = total_page_count
126
-
127
- # Optional: pretty representation including meta for debugging
128
- def __repr__(self) -> str: # noqa: D401
129
- meta = (
130
- f" total={self.total_entity_count} page={self.current_page} "
131
- f"size={self.page_size} pages={self.total_page_count}"
132
- )
133
- return f"PaginatedList({list.__repr__(self)},{meta})"
1
+ """
2
+ Base classes for CQRS implementation in the AIR SDK.
3
+ """
4
+
5
+ from abc import ABC, abstractmethod
6
+ from typing import Any, Dict, List, Optional, TypeVar, Generic, Union
7
+ from pydantic import BaseModel as PydanticBaseModel, ConfigDict, Field
8
+ from datetime import datetime
9
+
10
+ T = TypeVar("T")
11
+
12
+
13
+ class Query(Generic[T], ABC):
14
+ """Base class for all queries (read operations)."""
15
+
16
+ @abstractmethod
17
+ def execute(self) -> T:
18
+ """Execute the query and return the result."""
19
+ pass
20
+
21
+
22
+ class Command(Generic[T], ABC):
23
+ """Base class for all commands (write operations)."""
24
+
25
+ @abstractmethod
26
+ def execute(self) -> T:
27
+ """Execute the command and return the result."""
28
+ pass
29
+
30
+
31
+ class AIRBaseModel(PydanticBaseModel):
32
+ """Base Pydantic model with common configurations."""
33
+
34
+ model_config = ConfigDict(
35
+ use_enum_values=True,
36
+ validate_assignment=True,
37
+ arbitrary_types_allowed=True,
38
+ populate_by_name=True # Allow using both field names and aliases
39
+ )
40
+
41
+
42
+ class PaginatedResponse(AIRBaseModel, Generic[T]):
43
+ """Generic paginated response model."""
44
+
45
+ entities: List[T]
46
+ total_entity_count: int
47
+ current_page: int
48
+ page_size: int
49
+ total_page_count: int
50
+ previous_page: Optional[int] = None
51
+ next_page: Optional[int] = None
52
+
53
+
54
+ class APIResponse(AIRBaseModel, Generic[T]):
55
+ """Generic API response model."""
56
+
57
+ success: bool
58
+ result: T
59
+ status_code: int
60
+ errors: List[str] = []
61
+
62
+
63
+ class Filter(AIRBaseModel):
64
+ """Base filter model for queries with pagination and sorting support."""
65
+
66
+ # Basic filter fields
67
+ search_term: Optional[str] = None
68
+ organization_ids: Optional[List[int]] = None
69
+
70
+ # Pagination parameters (match API documentation exactly) - no defaults
71
+ page_number: Optional[int] = Field(default=None, alias="pageNumber")
72
+ page_size: Optional[int] = Field(default=None, alias="pageSize")
73
+
74
+ # Sorting parameters (match API documentation exactly) - no defaults
75
+ sort_by: Optional[str] = Field(default=None, alias="sortBy")
76
+ sort_type: Optional[str] = Field(default=None, alias="sortType")
77
+
78
+ def to_params(self) -> Dict[str, Any]:
79
+ """Convert filter to API parameters."""
80
+ params = {}
81
+
82
+ # Pagination parameters (not in filter namespace) - only if set
83
+ if self.page_number is not None:
84
+ params["pageNumber"] = self.page_number
85
+ if self.page_size is not None:
86
+ params["pageSize"] = self.page_size
87
+ if self.sort_by is not None:
88
+ params["sortBy"] = self.sort_by
89
+ if self.sort_type is not None:
90
+ params["sortType"] = self.sort_type
91
+
92
+ # Filter parameters (in filter namespace)
93
+ for field_name, field_value in self.model_dump(exclude_none=True).items():
94
+ # Skip pagination/sorting fields as they're handled above
95
+ if field_name in ["page_number", "page_size", "sort_by", "sort_type"]:
96
+ continue
97
+
98
+ if field_value is not None:
99
+ if isinstance(field_value, list):
100
+ params[f"filter[{field_name}]"] = ",".join([str(x) for x in field_value])
101
+ else:
102
+ params[f"filter[{field_name}]"] = str(field_value)
103
+ return params
104
+
105
+
106
+ class PaginatedList(list):
107
+ """List-like container that carries pagination metadata.
108
+ This allows SDK query methods to return a normal iterable while still
109
+ exposing additional pagination attributes such as total_entity_count.
110
+ The class simply subclasses ``list`` and adds attributes during
111
+ construction. All standard list operations remain intact.
112
+ """
113
+ def __init__(
114
+ self,
115
+ iterable=None,
116
+ *,
117
+ total_entity_count: int | None = None,
118
+ current_page: int | None = None,
119
+ page_size: int | None = None,
120
+ total_page_count: int | None = None,
121
+ ) -> None:
122
+ super().__init__(iterable or [])
123
+ # Store metadata for caller introspection
124
+ self.total_entity_count = total_entity_count
125
+ self.current_page = current_page
126
+ self.page_size = page_size
127
+ self.total_page_count = total_page_count
128
+
129
+ # Optional: pretty representation including meta for debugging
130
+ def __repr__(self) -> str: # noqa: D401
131
+ meta = (
132
+ f" total={self.total_entity_count} page={self.current_page} "
133
+ f"size={self.page_size} pages={self.total_page_count}"
134
+ )
135
+ return f"PaginatedList({list.__repr__(self)},{meta})"
136
+
137
+
138
+ # Utility functions for common SDK operations
139
+ def ensure_organization_ids(organization_ids: Optional[Union[List[int], int]], default_org_id: int = 0) -> List[int]:
140
+ """
141
+ Ensure organization IDs are properly formatted for API requests.
142
+
143
+ Many AIR API endpoints require organizationIds parameter to be non-empty.
144
+ This utility ensures consistent handling across all SDK components.
145
+
146
+ Args:
147
+ organization_ids: Organization ID(s) - can be None, int, or List[int]
148
+ default_org_id: Default organization ID to use if none provided
149
+
150
+ Returns:
151
+ List[int]: Non-empty list of organization IDs
152
+
153
+ Raises:
154
+ ValueError: If organization_ids is explicitly empty list
155
+ """
156
+ if organization_ids is None:
157
+ return [default_org_id]
158
+
159
+ if isinstance(organization_ids, int):
160
+ return [organization_ids]
161
+
162
+ if isinstance(organization_ids, list):
163
+ if len(organization_ids) == 0:
164
+ # API requires non-empty organizationIds - use default
165
+ return [default_org_id]
166
+ return organization_ids
167
+
168
+ # Fallback for other types
169
+ return [default_org_id]
170
+
171
+
172
+ def format_organization_ids_param(organization_ids: Optional[Union[List[int], int]],
173
+ param_name: str = "filter[organizationIds]",
174
+ default_org_id: int = 0) -> Dict[str, str]:
175
+ """
176
+ Format organization IDs for API request parameters.
177
+
178
+ Args:
179
+ organization_ids: Organization ID(s) to format
180
+ param_name: Parameter name to use (default: "filter[organizationIds]")
181
+ default_org_id: Default organization ID if none provided
182
+
183
+ Returns:
184
+ Dict with formatted parameter
185
+ """
186
+ validated_ids = ensure_organization_ids(organization_ids, default_org_id)
187
+ return {param_name: ",".join([str(x) for x in validated_ids])}
188
+
189
+
190
+ def format_single_organization_id_param(organization_id: Optional[int],
191
+ param_name: str = "filter[organizationId]",
192
+ default_org_id: int = 0) -> Dict[str, str]:
193
+ """
194
+ Format single organization ID for API request parameters.
195
+
196
+ Some APIs (like Recent Activities) use singular organizationId instead of plural.
197
+
198
+ Args:
199
+ organization_id: Single organization ID
200
+ param_name: Parameter name to use (default: "filter[organizationId]")
201
+ default_org_id: Default organization ID if none provided
202
+
203
+ Returns:
204
+ Dict with formatted parameter
205
+ """
206
+ final_id = organization_id if organization_id is not None else default_org_id
207
+ return {param_name: str(final_id)}