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
binalyze_air/apis/interact.py
CHANGED
@@ -1,36 +1,153 @@
|
|
1
|
-
"""
|
2
|
-
Interact API for the Binalyze AIR SDK.
|
3
|
-
"""
|
4
|
-
|
5
|
-
from
|
6
|
-
|
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
|
-
|
1
|
+
"""
|
2
|
+
Interact API for the Binalyze AIR SDK.
|
3
|
+
"""
|
4
|
+
|
5
|
+
from typing import List, Optional, Dict, Any, Union
|
6
|
+
|
7
|
+
from ..http_client import HTTPClient
|
8
|
+
from ..models.interact import (
|
9
|
+
ShellInteraction, AssignInteractiveShellTaskRequest, InteractiveShellTaskResponse,
|
10
|
+
LibraryFile, LibraryFileFilter, ExecuteCommandRequest, ExecuteCommandResponse,
|
11
|
+
InteractCommand, CommandMessage
|
12
|
+
)
|
13
|
+
from ..queries.interact import (
|
14
|
+
GetShellInteractionQuery, ListLibraryFilesQuery, DownloadLibraryFileQuery,
|
15
|
+
CheckFileExistsQuery, GetCommandMessageQuery, ListInteractCommandsQuery
|
16
|
+
)
|
17
|
+
from ..commands.interact import (
|
18
|
+
AssignInteractiveShellTaskCommand, UploadFileToLibraryCommand, DeleteFileFromLibraryCommand,
|
19
|
+
ExecuteCommandCommand, ExecuteAsyncCommandCommand, InterruptCommandCommand, CloseSessionCommand
|
20
|
+
)
|
21
|
+
|
22
|
+
|
23
|
+
class InteractAPI:
|
24
|
+
"""Interact API with CQRS pattern - separated queries and commands."""
|
25
|
+
|
26
|
+
def __init__(self, http_client: HTTPClient):
|
27
|
+
self.http_client = http_client
|
28
|
+
|
29
|
+
# ========================================
|
30
|
+
# LIBRARY FILE OPERATIONS (5 endpoints)
|
31
|
+
# ========================================
|
32
|
+
|
33
|
+
# QUERIES (Read operations)
|
34
|
+
def list_library_files(self, filter_params: Optional[LibraryFileFilter] = None) -> List[LibraryFile]:
|
35
|
+
"""List files in the interact library."""
|
36
|
+
query = ListLibraryFilesQuery(self.http_client, filter_params)
|
37
|
+
return query.execute()
|
38
|
+
|
39
|
+
def download_library_file(self, file_id: str) -> bytes:
|
40
|
+
"""Download a file from the interact library."""
|
41
|
+
query = DownloadLibraryFileQuery(self.http_client, file_id)
|
42
|
+
return query.execute()
|
43
|
+
|
44
|
+
def check_file_exists(self, filename: str, sha256: Optional[str] = None, organization_ids: Optional[List[int]] = None) -> bool:
|
45
|
+
"""Check if a file exists in the interact library."""
|
46
|
+
query = CheckFileExistsQuery(self.http_client, filename, sha256, organization_ids)
|
47
|
+
return query.execute()
|
48
|
+
|
49
|
+
# COMMANDS (Write operations)
|
50
|
+
def upload_file_to_library(self, file_content: bytes, filename: str, organization_ids: Optional[List[int]] = None) -> Optional[LibraryFile]:
|
51
|
+
"""Upload a file to the interact library."""
|
52
|
+
command = UploadFileToLibraryCommand(self.http_client, file_content, filename, organization_ids)
|
53
|
+
return command.execute()
|
54
|
+
|
55
|
+
def delete_file_from_library(self, file_id: str) -> Dict[str, Any]:
|
56
|
+
"""Delete a file from the interact library."""
|
57
|
+
command = DeleteFileFromLibraryCommand(self.http_client, file_id)
|
58
|
+
return command.execute()
|
59
|
+
|
60
|
+
# ========================================
|
61
|
+
# SHELL SESSION OPERATIONS (6 endpoints)
|
62
|
+
# ========================================
|
63
|
+
|
64
|
+
# QUERIES (Read operations)
|
65
|
+
def get_command_message(self, session_id: str, message_id: str) -> CommandMessage:
|
66
|
+
"""Get a command message from a shell session."""
|
67
|
+
query = GetCommandMessageQuery(self.http_client, session_id, message_id)
|
68
|
+
return query.execute()
|
69
|
+
|
70
|
+
def list_interact_commands(self) -> List[InteractCommand]:
|
71
|
+
"""List available interact commands."""
|
72
|
+
query = ListInteractCommandsQuery(self.http_client)
|
73
|
+
return query.execute()
|
74
|
+
|
75
|
+
# COMMANDS (Write operations)
|
76
|
+
def assign_interactive_shell_task(self, request: Union[AssignInteractiveShellTaskRequest, Dict[str, Any]]) -> InteractiveShellTaskResponse:
|
77
|
+
"""Assign an interactive shell task to an asset."""
|
78
|
+
command = AssignInteractiveShellTaskCommand(self.http_client, request)
|
79
|
+
return command.execute()
|
80
|
+
|
81
|
+
def execute_command(self, session_id: str, request: Union[ExecuteCommandRequest, Dict[str, Any]]) -> ExecuteCommandResponse:
|
82
|
+
"""Execute a command in a shell session."""
|
83
|
+
command = ExecuteCommandCommand(self.http_client, session_id, request)
|
84
|
+
return command.execute()
|
85
|
+
|
86
|
+
def execute_async_command(self, session_id: str, request: Union[ExecuteCommandRequest, Dict[str, Any]]) -> ExecuteCommandResponse:
|
87
|
+
"""Execute an async command in a shell session."""
|
88
|
+
command = ExecuteAsyncCommandCommand(self.http_client, session_id, request)
|
89
|
+
return command.execute()
|
90
|
+
|
91
|
+
def interrupt_command(self, session_id: str, message_id: str) -> Dict[str, Any]:
|
92
|
+
"""Interrupt a running command in a shell session."""
|
93
|
+
command = InterruptCommandCommand(self.http_client, session_id, message_id)
|
94
|
+
return command.execute()
|
95
|
+
|
96
|
+
def close_session(self, session_id: str) -> Dict[str, Any]:
|
97
|
+
"""Close a shell session."""
|
98
|
+
command = CloseSessionCommand(self.http_client, session_id)
|
99
|
+
return command.execute()
|
100
|
+
|
101
|
+
# ========================================
|
102
|
+
# LEGACY METHODS (for backward compatibility)
|
103
|
+
# ========================================
|
104
|
+
|
105
|
+
def get_shell_interaction(self, interaction_id: str) -> ShellInteraction:
|
106
|
+
"""Get a specific shell interaction by ID (legacy)."""
|
107
|
+
query = GetShellInteractionQuery(self.http_client, interaction_id)
|
108
|
+
return query.execute()
|
109
|
+
|
110
|
+
# ========================================
|
111
|
+
# CONVENIENCE ALIASES
|
112
|
+
# ========================================
|
113
|
+
|
114
|
+
# Library aliases
|
115
|
+
def list_files(self, filter_params: Optional[LibraryFileFilter] = None) -> List[LibraryFile]:
|
116
|
+
"""List files - alias for list_library_files."""
|
117
|
+
return self.list_library_files(filter_params)
|
118
|
+
|
119
|
+
def download_file(self, file_id: str) -> bytes:
|
120
|
+
"""Download file - alias for download_library_file."""
|
121
|
+
return self.download_library_file(file_id)
|
122
|
+
|
123
|
+
def upload_file(self, file_content: bytes, filename: str, organization_ids: Optional[List[int]] = None) -> Optional[LibraryFile]:
|
124
|
+
"""Upload file - alias for upload_file_to_library."""
|
125
|
+
return self.upload_file_to_library(file_content, filename, organization_ids)
|
126
|
+
|
127
|
+
def delete_file(self, file_id: str) -> Dict[str, Any]:
|
128
|
+
"""Delete file - alias for delete_file_from_library."""
|
129
|
+
return self.delete_file_from_library(file_id)
|
130
|
+
|
131
|
+
# Shell aliases
|
132
|
+
def execute(self, session_id: str, command: str, accept: str = "json") -> ExecuteCommandResponse:
|
133
|
+
"""Execute command - convenience method."""
|
134
|
+
request = ExecuteCommandRequest(command=command, accept=accept)
|
135
|
+
return self.execute_command(session_id, request)
|
136
|
+
|
137
|
+
def execute_async(self, session_id: str, command: str, accept: str = "json") -> ExecuteCommandResponse:
|
138
|
+
"""Execute async command - convenience method."""
|
139
|
+
request = ExecuteCommandRequest(command=command, accept=accept)
|
140
|
+
return self.execute_async_command(session_id, request)
|
141
|
+
|
142
|
+
def get_commands(self) -> List[InteractCommand]:
|
143
|
+
"""Get commands - alias for list_interact_commands."""
|
144
|
+
return self.list_interact_commands()
|
145
|
+
|
146
|
+
def assign_shell_task(self, asset_id: str, case_id: str, task_config: Dict[str, Any]) -> InteractiveShellTaskResponse:
|
147
|
+
"""Assign shell task - convenience method."""
|
148
|
+
request_data = {
|
149
|
+
"assetId": asset_id,
|
150
|
+
"caseId": case_id,
|
151
|
+
"taskConfig": task_config
|
152
|
+
}
|
153
|
+
return self.assign_interactive_shell_task(request_data)
|
@@ -0,0 +1,234 @@
|
|
1
|
+
"""
|
2
|
+
Investigation Hub API for the Binalyze AIR SDK.
|
3
|
+
"""
|
4
|
+
|
5
|
+
from typing import Optional, List, Dict, Any
|
6
|
+
|
7
|
+
from ..http_client import HTTPClient
|
8
|
+
from ..models.investigation_hub import (
|
9
|
+
Investigation, InvestigationAsset, FlagSummary, EvidenceSection,
|
10
|
+
EvidenceStructure, SQLQueryResult, FindingsSummary, FindingsStructure,
|
11
|
+
FindingsResult, FindingsRequest, MitreMatch, InvestigationComment,
|
12
|
+
InvestigationActivity, AdvancedFilter, UpdateInvestigationRequest,
|
13
|
+
FlagEvidenceRequest, AddNoteRequest, CreateCommentRequest,
|
14
|
+
MarkActivityAsReadRequest, CreateAdvancedFilterRequest,
|
15
|
+
UpdateAdvancedFilterRequest, ExportRequest
|
16
|
+
)
|
17
|
+
from ..queries.investigation_hub import (
|
18
|
+
GetInvestigationQuery, GetInvestigationAssetsQuery, GetInvestigationFlagSummaryQuery,
|
19
|
+
GetEvidenceSectionsQuery, GetEvidenceStructureQuery, ExecuteSQLQuery,
|
20
|
+
GetFindingsSummaryQuery, GetFindingsStructureQuery, GetFindingsQuery,
|
21
|
+
GetMitreMatchesQuery, GetInvestigationCommentsQuery,
|
22
|
+
GetInvestigationActivitiesQuery, GetAdvancedFiltersQuery, GetAdvancedFilterQuery,
|
23
|
+
GetEvidenceRecordsQuery
|
24
|
+
)
|
25
|
+
from ..commands.investigation_hub import (
|
26
|
+
UpdateInvestigationCommand, DeleteInvestigationCommand, FlagEvidenceCommand,
|
27
|
+
UnflagEvidenceCommand, AddNoteToEvidenceCommand, CreateCommentCommand,
|
28
|
+
UpdateCommentCommand, DeleteCommentCommand, MarkActivitiesAsReadCommand,
|
29
|
+
CreateAdvancedFilterCommand, UpdateAdvancedFilterCommand, DeleteAdvancedFilterCommand,
|
30
|
+
ExportEvidenceCommand, GenerateReportCommand, RefreshInvestigationCommand,
|
31
|
+
ArchiveInvestigationCommand, RestoreInvestigationCommand
|
32
|
+
)
|
33
|
+
|
34
|
+
|
35
|
+
class InvestigationHubAPI:
|
36
|
+
"""Investigation Hub API with CQRS pattern - separated queries and commands."""
|
37
|
+
|
38
|
+
def __init__(self, http_client: HTTPClient):
|
39
|
+
self.http_client = http_client
|
40
|
+
|
41
|
+
# QUERIES (Read operations)
|
42
|
+
def get_investigation(self, investigation_id: str) -> Investigation:
|
43
|
+
"""Get a specific investigation by ID."""
|
44
|
+
query = GetInvestigationQuery(self.http_client, investigation_id)
|
45
|
+
return query.execute()
|
46
|
+
|
47
|
+
def get_assets(self, investigation_id: str) -> List[InvestigationAsset]:
|
48
|
+
"""Get assets for a specific investigation."""
|
49
|
+
query = GetInvestigationAssetsQuery(self.http_client, investigation_id)
|
50
|
+
return query.execute()
|
51
|
+
|
52
|
+
def get_flag_summary(self, investigation_id: str) -> List[FlagSummary]:
|
53
|
+
"""Get flag summary for a specific investigation."""
|
54
|
+
query = GetInvestigationFlagSummaryQuery(self.http_client, investigation_id)
|
55
|
+
return query.execute()
|
56
|
+
|
57
|
+
def get_evidence_sections(self, investigation_id: str, task_assignment_ids: List[str]) -> List[EvidenceSection]:
|
58
|
+
"""Get evidence sections for a specific investigation with task assignment IDs."""
|
59
|
+
query = GetEvidenceSectionsQuery(self.http_client, investigation_id, task_assignment_ids)
|
60
|
+
return query.execute()
|
61
|
+
|
62
|
+
def get_evidence_structure(self, investigation_id: str, section: str) -> List[EvidenceStructure]:
|
63
|
+
"""Get evidence structure for a specific section."""
|
64
|
+
query = GetEvidenceStructureQuery(self.http_client, investigation_id, section)
|
65
|
+
return query.execute()
|
66
|
+
|
67
|
+
def execute_sql_query(self, investigation_id: str, query: str,
|
68
|
+
page_size: int = 10, page_number: int = 1) -> SQLQueryResult:
|
69
|
+
"""Execute SQL query against investigation database."""
|
70
|
+
sql_query = ExecuteSQLQuery(self.http_client, investigation_id, query, page_size, page_number)
|
71
|
+
return sql_query.execute()
|
72
|
+
|
73
|
+
def get_findings_summary(self, investigation_id: str) -> FindingsSummary:
|
74
|
+
"""Get findings summary for a specific investigation."""
|
75
|
+
query = GetFindingsSummaryQuery(self.http_client, investigation_id)
|
76
|
+
return query.execute()
|
77
|
+
|
78
|
+
def get_findings_structure(self, investigation_id: str) -> FindingsStructure:
|
79
|
+
"""Get findings structure for a specific investigation."""
|
80
|
+
query = GetFindingsStructureQuery(self.http_client, investigation_id)
|
81
|
+
return query.execute()
|
82
|
+
|
83
|
+
def get_findings(self, investigation_id: str, request: Optional[FindingsRequest] = None) -> FindingsResult:
|
84
|
+
"""Get findings for a specific investigation."""
|
85
|
+
if request is None:
|
86
|
+
request = FindingsRequest()
|
87
|
+
query = GetFindingsQuery(self.http_client, investigation_id, request)
|
88
|
+
return query.execute()
|
89
|
+
|
90
|
+
def get_mitre_matches(self, investigation_id: str) -> List[MitreMatch]:
|
91
|
+
"""Get MITRE ATT&CK matches for a specific investigation."""
|
92
|
+
query = GetMitreMatchesQuery(self.http_client, investigation_id)
|
93
|
+
return query.execute()
|
94
|
+
|
95
|
+
def get_comments(self, investigation_id: str, evidence_id: Optional[str] = None) -> List[InvestigationComment]:
|
96
|
+
"""Get comments for a specific investigation."""
|
97
|
+
query = GetInvestigationCommentsQuery(self.http_client, investigation_id, evidence_id)
|
98
|
+
return query.execute()
|
99
|
+
|
100
|
+
def get_activities(self, investigation_id: str, page_size: int = 20,
|
101
|
+
page_number: int = 1) -> List[InvestigationActivity]:
|
102
|
+
"""Get activities for a specific investigation."""
|
103
|
+
query = GetInvestigationActivitiesQuery(self.http_client, investigation_id, page_size, page_number)
|
104
|
+
return query.execute()
|
105
|
+
|
106
|
+
def get_advanced_filters(self, investigation_id: Optional[str] = None) -> List[AdvancedFilter]:
|
107
|
+
"""Get advanced filters (organization-wide, not investigation-specific)."""
|
108
|
+
query = GetAdvancedFiltersQuery(self.http_client, investigation_id)
|
109
|
+
return query.execute()
|
110
|
+
|
111
|
+
def get_advanced_filter(self, investigation_id: str, filter_id: str) -> AdvancedFilter:
|
112
|
+
"""Get a specific advanced filter by ID."""
|
113
|
+
query = GetAdvancedFilterQuery(self.http_client, investigation_id, int(filter_id))
|
114
|
+
return query.execute()
|
115
|
+
|
116
|
+
def get_evidence_records(self, investigation_id: str, section: str,
|
117
|
+
filters: Optional[Dict[str, Any]] = None,
|
118
|
+
page_size: int = 50, page_number: int = 1) -> Dict[str, Any]:
|
119
|
+
"""Get evidence records with filtering."""
|
120
|
+
query = GetEvidenceRecordsQuery(
|
121
|
+
self.http_client, investigation_id, section, filters, page_size, page_number
|
122
|
+
)
|
123
|
+
return query.execute()
|
124
|
+
|
125
|
+
# COMMANDS (Write operations)
|
126
|
+
def update_investigation(self, investigation_id: str, request: UpdateInvestigationRequest) -> Investigation:
|
127
|
+
"""Update an investigation."""
|
128
|
+
command = UpdateInvestigationCommand(self.http_client, investigation_id, request)
|
129
|
+
return command.execute()
|
130
|
+
|
131
|
+
def delete_investigation(self, investigation_id: str) -> Dict[str, Any]:
|
132
|
+
"""Delete an investigation."""
|
133
|
+
command = DeleteInvestigationCommand(self.http_client, investigation_id)
|
134
|
+
return command.execute()
|
135
|
+
|
136
|
+
def flag_evidence(self, investigation_id: str, request: FlagEvidenceRequest) -> Dict[str, Any]:
|
137
|
+
"""Flag evidence records."""
|
138
|
+
command = FlagEvidenceCommand(self.http_client, investigation_id, request)
|
139
|
+
return command.execute()
|
140
|
+
|
141
|
+
def unflag_evidence(self, investigation_id: str, records: List[Dict[str, Any]],
|
142
|
+
section: str) -> Dict[str, Any]:
|
143
|
+
"""Unflag evidence records."""
|
144
|
+
command = UnflagEvidenceCommand(self.http_client, investigation_id, records, section)
|
145
|
+
return command.execute()
|
146
|
+
|
147
|
+
def add_note_to_evidence(self, investigation_id: str, request: AddNoteRequest) -> Dict[str, Any]:
|
148
|
+
"""Add a note to evidence records."""
|
149
|
+
command = AddNoteToEvidenceCommand(self.http_client, investigation_id, request)
|
150
|
+
return command.execute()
|
151
|
+
|
152
|
+
def create_comment(self, investigation_id: str, request: CreateCommentRequest) -> InvestigationComment:
|
153
|
+
"""Create a comment in an investigation."""
|
154
|
+
command = CreateCommentCommand(self.http_client, investigation_id, request)
|
155
|
+
return command.execute()
|
156
|
+
|
157
|
+
def update_comment(self, investigation_id: str, comment_id: str, content: str) -> InvestigationComment:
|
158
|
+
"""Update a comment in an investigation."""
|
159
|
+
command = UpdateCommentCommand(self.http_client, investigation_id, comment_id, content)
|
160
|
+
return command.execute()
|
161
|
+
|
162
|
+
def delete_comment(self, investigation_id: str, comment_id: str) -> Dict[str, Any]:
|
163
|
+
"""Delete a comment from an investigation."""
|
164
|
+
command = DeleteCommentCommand(self.http_client, investigation_id, comment_id)
|
165
|
+
return command.execute()
|
166
|
+
|
167
|
+
def mark_activities_as_read(self, investigation_id: str,
|
168
|
+
request: MarkActivityAsReadRequest) -> Dict[str, Any]:
|
169
|
+
"""Mark activities as read."""
|
170
|
+
command = MarkActivitiesAsReadCommand(self.http_client, investigation_id, request)
|
171
|
+
return command.execute()
|
172
|
+
|
173
|
+
def create_advanced_filter(self, investigation_id: str,
|
174
|
+
request: CreateAdvancedFilterRequest) -> AdvancedFilter:
|
175
|
+
"""Create an advanced filter."""
|
176
|
+
command = CreateAdvancedFilterCommand(self.http_client, investigation_id, request)
|
177
|
+
return command.execute()
|
178
|
+
|
179
|
+
def update_advanced_filter(self, investigation_id: str, filter_id: str,
|
180
|
+
request: UpdateAdvancedFilterRequest) -> AdvancedFilter:
|
181
|
+
"""Update an advanced filter."""
|
182
|
+
command = UpdateAdvancedFilterCommand(self.http_client, investigation_id, int(filter_id), request)
|
183
|
+
return command.execute()
|
184
|
+
|
185
|
+
def delete_advanced_filter(self, investigation_id: str, filter_id: str) -> Dict[str, Any]:
|
186
|
+
"""Delete an advanced filter."""
|
187
|
+
command = DeleteAdvancedFilterCommand(self.http_client, investigation_id, int(filter_id))
|
188
|
+
return command.execute()
|
189
|
+
|
190
|
+
def export_evidence(self, investigation_id: str, request: ExportRequest) -> Dict[str, Any]:
|
191
|
+
"""Export evidence data."""
|
192
|
+
command = ExportEvidenceCommand(self.http_client, investigation_id, request)
|
193
|
+
return command.execute()
|
194
|
+
|
195
|
+
def generate_report(self, investigation_id: str, report_type: str = "comprehensive",
|
196
|
+
include_evidence: bool = True) -> Dict[str, Any]:
|
197
|
+
"""Generate an investigation report."""
|
198
|
+
command = GenerateReportCommand(self.http_client, investigation_id, report_type, include_evidence)
|
199
|
+
return command.execute()
|
200
|
+
|
201
|
+
def refresh_investigation(self, investigation_id: str) -> Investigation:
|
202
|
+
"""Refresh/rebuild an investigation."""
|
203
|
+
command = RefreshInvestigationCommand(self.http_client, investigation_id)
|
204
|
+
return command.execute()
|
205
|
+
|
206
|
+
def archive_investigation(self, investigation_id: str) -> Dict[str, Any]:
|
207
|
+
"""Archive an investigation."""
|
208
|
+
command = ArchiveInvestigationCommand(self.http_client, investigation_id)
|
209
|
+
return command.execute()
|
210
|
+
|
211
|
+
def restore_investigation(self, investigation_id: str) -> Investigation:
|
212
|
+
"""Restore an archived investigation."""
|
213
|
+
command = RestoreInvestigationCommand(self.http_client, investigation_id)
|
214
|
+
return command.execute()
|
215
|
+
|
216
|
+
# Convenience methods
|
217
|
+
def sql_query(self, investigation_id: str, query: str, page_size: int = 10,
|
218
|
+
page_number: int = 1) -> SQLQueryResult:
|
219
|
+
"""Alias for execute_sql_query for convenience."""
|
220
|
+
return self.execute_sql_query(investigation_id, query, page_size, page_number)
|
221
|
+
|
222
|
+
def get_investigation_data(self, investigation_id: str, task_assignment_ids: Optional[List[str]] = None) -> Dict[str, Any]:
|
223
|
+
"""Get comprehensive investigation data including assets, flags, and sections."""
|
224
|
+
result = {
|
225
|
+
"investigation": self.get_investigation(investigation_id),
|
226
|
+
"assets": self.get_assets(investigation_id),
|
227
|
+
"flag_summary": self.get_flag_summary(investigation_id)
|
228
|
+
}
|
229
|
+
|
230
|
+
# Only include evidence sections if task assignment IDs are provided
|
231
|
+
if task_assignment_ids:
|
232
|
+
result["evidence_sections"] = self.get_evidence_sections(investigation_id, task_assignment_ids)
|
233
|
+
|
234
|
+
return result
|
@@ -0,0 +1,104 @@
|
|
1
|
+
"""License API client for Binalyze AIR SDK."""
|
2
|
+
|
3
|
+
from ..http_client import HTTPClient
|
4
|
+
from ..models.license import License
|
5
|
+
from ..queries.license import GetLicenseQuery, SetLicenseQuery
|
6
|
+
from ..commands.license import GetLicenseCommand, SetLicenseCommand
|
7
|
+
|
8
|
+
|
9
|
+
class LicenseAPI:
|
10
|
+
"""License API with CQRS pattern - separated queries and commands.
|
11
|
+
|
12
|
+
This class provides methods for managing license information
|
13
|
+
including retrieving current license details and updating license keys.
|
14
|
+
"""
|
15
|
+
|
16
|
+
def __init__(self, http_client: HTTPClient):
|
17
|
+
"""Initialize License API client.
|
18
|
+
|
19
|
+
Args:
|
20
|
+
http_client: HTTP client for making API requests
|
21
|
+
"""
|
22
|
+
self.http_client = http_client
|
23
|
+
|
24
|
+
# QUERIES (Read operations)
|
25
|
+
def get_license(self) -> License:
|
26
|
+
"""Get current license information.
|
27
|
+
|
28
|
+
Returns:
|
29
|
+
License object with current license information
|
30
|
+
|
31
|
+
Raises:
|
32
|
+
APIError: If the request fails
|
33
|
+
"""
|
34
|
+
command = GetLicenseCommand(self)
|
35
|
+
return command.execute()
|
36
|
+
|
37
|
+
def get_license_status(self) -> dict:
|
38
|
+
"""Get comprehensive license status information.
|
39
|
+
|
40
|
+
Returns:
|
41
|
+
Dictionary with license status, usage, and warnings
|
42
|
+
"""
|
43
|
+
command = GetLicenseCommand(self)
|
44
|
+
return command.get_license_status()
|
45
|
+
|
46
|
+
# COMMANDS (Write operations)
|
47
|
+
def set_license(self, license_key: str) -> bool:
|
48
|
+
"""Set/update license key.
|
49
|
+
|
50
|
+
Args:
|
51
|
+
license_key: The new license key to set
|
52
|
+
|
53
|
+
Returns:
|
54
|
+
True if license was set successfully
|
55
|
+
|
56
|
+
Raises:
|
57
|
+
APIError: If the request fails
|
58
|
+
ValueError: If license key is invalid
|
59
|
+
"""
|
60
|
+
command = SetLicenseCommand(self, license_key)
|
61
|
+
return command.execute()
|
62
|
+
|
63
|
+
def set_and_verify_license(self, license_key: str) -> dict:
|
64
|
+
"""Set license key and verify the operation.
|
65
|
+
|
66
|
+
Args:
|
67
|
+
license_key: The new license key to set
|
68
|
+
|
69
|
+
Returns:
|
70
|
+
Dictionary with operation result and new license status
|
71
|
+
"""
|
72
|
+
command = SetLicenseCommand(self, license_key)
|
73
|
+
return command.set_and_verify()
|
74
|
+
|
75
|
+
# Low-level query methods (for internal use by commands)
|
76
|
+
def _get_license_query(self, query: GetLicenseQuery) -> dict:
|
77
|
+
"""Execute get license query (internal use).
|
78
|
+
|
79
|
+
Args:
|
80
|
+
query: GetLicenseQuery instance
|
81
|
+
|
82
|
+
Returns:
|
83
|
+
Dictionary containing license information
|
84
|
+
"""
|
85
|
+
params = query.build_params()
|
86
|
+
return self.http_client.get('/license', params=params)
|
87
|
+
|
88
|
+
def _set_license_query(self, query: SetLicenseQuery) -> dict:
|
89
|
+
"""Execute set license query (internal use).
|
90
|
+
|
91
|
+
Args:
|
92
|
+
query: SetLicenseQuery instance
|
93
|
+
|
94
|
+
Returns:
|
95
|
+
Dictionary containing operation result
|
96
|
+
"""
|
97
|
+
body = query.build_body()
|
98
|
+
params = query.build_params()
|
99
|
+
|
100
|
+
return self.http_client.post(
|
101
|
+
'/license',
|
102
|
+
data=body,
|
103
|
+
params=params
|
104
|
+
)
|
@@ -0,0 +1,83 @@
|
|
1
|
+
"""Logger API client for Binalyze AIR SDK."""
|
2
|
+
|
3
|
+
from typing import Optional, Dict, Any, Tuple
|
4
|
+
from ..http_client import HTTPClient
|
5
|
+
from ..models.logger import LogDownloadResponse
|
6
|
+
from ..queries.logger import DownloadLogsQuery
|
7
|
+
from ..commands.logger import DownloadLogsCommand
|
8
|
+
|
9
|
+
|
10
|
+
class LoggerAPI:
|
11
|
+
"""Logger API with CQRS pattern - separated queries and commands.
|
12
|
+
|
13
|
+
This class provides methods for downloading application logs
|
14
|
+
and managing log-related operations.
|
15
|
+
"""
|
16
|
+
|
17
|
+
def __init__(self, http_client: HTTPClient):
|
18
|
+
"""Initialize Logger API client.
|
19
|
+
|
20
|
+
Args:
|
21
|
+
http_client: HTTP client for making API requests
|
22
|
+
"""
|
23
|
+
self.http_client = http_client
|
24
|
+
|
25
|
+
# QUERIES (Read operations)
|
26
|
+
def download_logs(self, latest_only: bool = False) -> LogDownloadResponse:
|
27
|
+
"""Download application logs as ZIP file.
|
28
|
+
|
29
|
+
Args:
|
30
|
+
latest_only: Whether to download only the latest log file
|
31
|
+
|
32
|
+
Returns:
|
33
|
+
LogDownloadResponse with downloaded log data
|
34
|
+
|
35
|
+
Raises:
|
36
|
+
APIError: If the request fails
|
37
|
+
"""
|
38
|
+
command = DownloadLogsCommand(self, latest_only)
|
39
|
+
return command.execute()
|
40
|
+
|
41
|
+
def download_and_save_logs(self, save_path: Optional[str] = None,
|
42
|
+
latest_only: bool = False) -> Dict[str, Any]:
|
43
|
+
"""Download logs and save to file.
|
44
|
+
|
45
|
+
Args:
|
46
|
+
save_path: Optional path where to save the logs
|
47
|
+
latest_only: Whether to download only the latest log file
|
48
|
+
|
49
|
+
Returns:
|
50
|
+
Dictionary with download result and file information
|
51
|
+
"""
|
52
|
+
command = DownloadLogsCommand(self, latest_only)
|
53
|
+
return command.download_and_save(save_path)
|
54
|
+
|
55
|
+
def get_log_info(self, latest_only: bool = False) -> Dict[str, Any]:
|
56
|
+
"""Get information about available logs without downloading.
|
57
|
+
|
58
|
+
Args:
|
59
|
+
latest_only: Whether to check only the latest log file
|
60
|
+
|
61
|
+
Returns:
|
62
|
+
Dictionary with log information
|
63
|
+
"""
|
64
|
+
command = DownloadLogsCommand(self, latest_only)
|
65
|
+
return command.get_log_info()
|
66
|
+
|
67
|
+
# Low-level query methods (for internal use by commands)
|
68
|
+
def _download_logs_query(self, query: DownloadLogsQuery) -> Tuple[bytes, Dict[str, str]]:
|
69
|
+
"""Execute download logs query (internal use).
|
70
|
+
|
71
|
+
Args:
|
72
|
+
query: DownloadLogsQuery instance
|
73
|
+
|
74
|
+
Returns:
|
75
|
+
Tuple of (binary_data, headers)
|
76
|
+
"""
|
77
|
+
params = query.build_params()
|
78
|
+
|
79
|
+
# Make the API call and get binary response
|
80
|
+
response = self.http_client.get_binary('/logs', params=params)
|
81
|
+
|
82
|
+
# Extract binary content and headers
|
83
|
+
return response.content, dict(response.headers)
|