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.
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.2.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.2.dist-info/METADATA +0 -706
  141. binalyze_air_sdk-1.0.2.dist-info/RECORD +0 -82
  142. {binalyze_air_sdk-1.0.2.dist-info → binalyze_air_sdk-1.0.3.dist-info}/top_level.txt +0 -0
@@ -1,36 +1,153 @@
1
- """
2
- Interact API for the Binalyze AIR SDK.
3
- """
4
-
5
- from ..http_client import HTTPClient
6
- from ..models.interact import (
7
- ShellInteraction, AssignShellTaskRequest, ShellTaskResponse, # Legacy models
8
- AssignInteractiveShellTaskRequest, InteractiveShellTaskResponse # New models
9
- )
10
- from ..queries.interact import GetShellInteractionQuery
11
- from ..commands.interact import AssignShellTaskCommand, AssignInteractiveShellTaskCommand
12
-
13
-
14
- class InteractAPI:
15
- """Interact API with CQRS pattern - separated queries and commands."""
16
-
17
- def __init__(self, http_client: HTTPClient):
18
- self.http_client = http_client
19
-
20
- # QUERIES (Read operations)
21
- def get_shell_interaction(self, interaction_id: str) -> ShellInteraction:
22
- """Get a specific shell interaction by ID."""
23
- query = GetShellInteractionQuery(self.http_client, interaction_id)
24
- return query.execute()
25
-
26
- # COMMANDS (Write operations)
27
- def assign_interactive_shell_task(self, request: AssignInteractiveShellTaskRequest) -> InteractiveShellTaskResponse:
28
- """Assign an interactive shell task to an asset."""
29
- command = AssignInteractiveShellTaskCommand(self.http_client, request)
30
- return command.execute()
31
-
32
- # Legacy methods for backward compatibility (deprecated)
33
- def assign_shell_task(self, request: AssignShellTaskRequest) -> ShellTaskResponse:
34
- """Assign a shell interaction task to endpoints (legacy)."""
35
- command = AssignShellTaskCommand(self.http_client, request)
36
- return command.execute()
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)