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
@@ -1,70 +1,70 @@
|
|
1
|
-
"""
|
2
|
-
|
3
|
-
"""
|
4
|
-
|
5
|
-
from typing import Optional, List, Dict, Any
|
6
|
-
from datetime import datetime
|
7
|
-
from pydantic import Field
|
8
|
-
|
9
|
-
from ..base import AIRBaseModel
|
10
|
-
|
11
|
-
|
12
|
-
class UserProfile(AIRBaseModel):
|
13
|
-
"""User profile information."""
|
14
|
-
name: Optional[str] = None
|
15
|
-
surname: Optional[str] = None
|
16
|
-
department: Optional[str] = None
|
17
|
-
|
18
|
-
|
19
|
-
class UserRole(AIRBaseModel):
|
20
|
-
"""User role information."""
|
21
|
-
id: Optional[str] = Field(alias="_id", default=None)
|
22
|
-
name: str
|
23
|
-
tag: str
|
24
|
-
created_at: Optional[str] = Field(alias="createdAt", default=None)
|
25
|
-
updated_at: Optional[str] = Field(alias="updatedAt", default=None)
|
26
|
-
created_by: Optional[str] = Field(alias="createdBy", default=None)
|
27
|
-
privilege_types: List[str] = Field(alias="privilegeTypes", default_factory=list)
|
28
|
-
|
29
|
-
|
30
|
-
class User(AIRBaseModel):
|
31
|
-
"""User model."""
|
32
|
-
|
33
|
-
id: str = Field(alias="_id")
|
34
|
-
username: str
|
35
|
-
email: str
|
36
|
-
organization_ids: Optional[str] = Field(alias="organizationIds", default=None) # Can be "ALL"
|
37
|
-
strategy: Optional[str] = None
|
38
|
-
profile: Optional[UserProfile] = None
|
39
|
-
privileges: List[str] = Field(default_factory=list)
|
40
|
-
roles: List[UserRole] = Field(default_factory=list)
|
41
|
-
tfa_enabled: bool = Field(alias="tfaEnabled", default=False)
|
42
|
-
created_at: Optional[str] = Field(alias="createdAt", default=None)
|
43
|
-
updated_at: Optional[str] = Field(alias="updatedAt", default=None)
|
44
|
-
has_password: bool = Field(alias="hasPassword", default=False)
|
45
|
-
photo: Optional[str] = None
|
46
|
-
groups: List[Any] = Field(default_factory=list)
|
47
|
-
user_flow_user_signature: Optional[str] = Field(alias="userFlowUserSignature", default=None)
|
48
|
-
user_flow_group_signature: Optional[str] = Field(alias="userFlowGroupSignature", default=None)
|
49
|
-
|
50
|
-
|
51
|
-
class AuthStatus(AIRBaseModel):
|
52
|
-
"""Authentication status model - matches actual API response."""
|
53
|
-
|
54
|
-
# The API doesn't return authenticated field, we derive it from success
|
55
|
-
authenticated: bool = True # Default to True since if we get a response, we're authenticated
|
56
|
-
user: Optional[User] = None
|
57
|
-
|
58
|
-
|
59
|
-
class LoginRequest(AIRBaseModel):
|
60
|
-
"""Login request model."""
|
61
|
-
|
62
|
-
username: str
|
63
|
-
password: str
|
64
|
-
|
65
|
-
|
66
|
-
class LoginResponse(AIRBaseModel):
|
67
|
-
"""Login response model."""
|
68
|
-
|
69
|
-
access_token: str = Field(alias="accessToken")
|
1
|
+
"""
|
2
|
+
Auth-related data models for the Binalyze AIR SDK.
|
3
|
+
"""
|
4
|
+
|
5
|
+
from typing import Optional, List, Dict, Any
|
6
|
+
from datetime import datetime
|
7
|
+
from pydantic import Field
|
8
|
+
|
9
|
+
from ..base import AIRBaseModel
|
10
|
+
|
11
|
+
|
12
|
+
class UserProfile(AIRBaseModel):
|
13
|
+
"""User profile information."""
|
14
|
+
name: Optional[str] = None
|
15
|
+
surname: Optional[str] = None
|
16
|
+
department: Optional[str] = None
|
17
|
+
|
18
|
+
|
19
|
+
class UserRole(AIRBaseModel):
|
20
|
+
"""User role information."""
|
21
|
+
id: Optional[str] = Field(alias="_id", default=None)
|
22
|
+
name: str
|
23
|
+
tag: str
|
24
|
+
created_at: Optional[str] = Field(alias="createdAt", default=None)
|
25
|
+
updated_at: Optional[str] = Field(alias="updatedAt", default=None)
|
26
|
+
created_by: Optional[str] = Field(alias="createdBy", default=None)
|
27
|
+
privilege_types: List[str] = Field(alias="privilegeTypes", default_factory=list)
|
28
|
+
|
29
|
+
|
30
|
+
class User(AIRBaseModel):
|
31
|
+
"""User model."""
|
32
|
+
|
33
|
+
id: str = Field(alias="_id")
|
34
|
+
username: str
|
35
|
+
email: str
|
36
|
+
organization_ids: Optional[str] = Field(alias="organizationIds", default=None) # Can be "ALL"
|
37
|
+
strategy: Optional[str] = None
|
38
|
+
profile: Optional[UserProfile] = None
|
39
|
+
privileges: List[str] = Field(default_factory=list)
|
40
|
+
roles: List[UserRole] = Field(default_factory=list)
|
41
|
+
tfa_enabled: bool = Field(alias="tfaEnabled", default=False)
|
42
|
+
created_at: Optional[str] = Field(alias="createdAt", default=None)
|
43
|
+
updated_at: Optional[str] = Field(alias="updatedAt", default=None)
|
44
|
+
has_password: bool = Field(alias="hasPassword", default=False)
|
45
|
+
photo: Optional[str] = None
|
46
|
+
groups: List[Any] = Field(default_factory=list)
|
47
|
+
user_flow_user_signature: Optional[str] = Field(alias="userFlowUserSignature", default=None)
|
48
|
+
user_flow_group_signature: Optional[str] = Field(alias="userFlowGroupSignature", default=None)
|
49
|
+
|
50
|
+
|
51
|
+
class AuthStatus(AIRBaseModel):
|
52
|
+
"""Authentication status model - matches actual API response."""
|
53
|
+
|
54
|
+
# The API doesn't return authenticated field, we derive it from success
|
55
|
+
authenticated: bool = True # Default to True since if we get a response, we're authenticated
|
56
|
+
user: Optional[User] = None
|
57
|
+
|
58
|
+
|
59
|
+
class LoginRequest(AIRBaseModel):
|
60
|
+
"""Login request model."""
|
61
|
+
|
62
|
+
username: str
|
63
|
+
password: str
|
64
|
+
|
65
|
+
|
66
|
+
class LoginResponse(AIRBaseModel):
|
67
|
+
"""Login response model."""
|
68
|
+
|
69
|
+
access_token: str = Field(alias="accessToken")
|
70
70
|
refresh_token: str = Field(alias="refreshToken")
|
@@ -1,117 +1,228 @@
|
|
1
|
-
"""
|
2
|
-
Auto Asset Tags-related data models for the Binalyze AIR SDK.
|
3
|
-
"""
|
4
|
-
|
5
|
-
from typing import Optional, List, Dict, Any
|
6
|
-
from datetime import datetime
|
7
|
-
from pydantic import Field
|
8
|
-
from pydantic import ConfigDict
|
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
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
class
|
41
|
-
"""
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
1
|
+
"""
|
2
|
+
Auto Asset Tags-related data models for the Binalyze AIR SDK.
|
3
|
+
"""
|
4
|
+
|
5
|
+
from typing import Optional, List, Dict, Any, Union
|
6
|
+
from datetime import datetime
|
7
|
+
from pydantic import Field
|
8
|
+
from pydantic import ConfigDict
|
9
|
+
from enum import Enum
|
10
|
+
|
11
|
+
from ..base import AIRBaseModel, Filter
|
12
|
+
|
13
|
+
|
14
|
+
class ConditionField(str, Enum):
|
15
|
+
"""Valid condition fields for auto asset tags."""
|
16
|
+
HOSTNAME = "hostname"
|
17
|
+
IP_ADDRESS = "ip-address"
|
18
|
+
SUBNET = "subnet"
|
19
|
+
OSQUERY = "osquery"
|
20
|
+
PROCESS = "process"
|
21
|
+
FILE = "file"
|
22
|
+
DIRECTORY = "directory"
|
23
|
+
|
24
|
+
|
25
|
+
class ConditionOperator(str, Enum):
|
26
|
+
"""Valid condition operators for auto asset tags."""
|
27
|
+
RUNNING = "running"
|
28
|
+
EXIST = "exist"
|
29
|
+
IS = "is"
|
30
|
+
CONTAINS = "contains"
|
31
|
+
STARTS_WITH = "starts-with"
|
32
|
+
ENDS_WITH = "ends-with"
|
33
|
+
IN_RANGE = "in-range"
|
34
|
+
HAS_RESULT = "has-result"
|
35
|
+
NOT_RUNNING = "not-running"
|
36
|
+
NOT_EXIST = "not-exist"
|
37
|
+
HAS_NO_RESULT = "has-no-result"
|
38
|
+
|
39
|
+
|
40
|
+
class LogicalOperator(str, Enum):
|
41
|
+
"""Valid logical operators for condition groups."""
|
42
|
+
AND = "and"
|
43
|
+
OR = "or"
|
44
|
+
|
45
|
+
|
46
|
+
class AutoAssetTagCondition(AIRBaseModel):
|
47
|
+
"""Individual condition for auto asset tag."""
|
48
|
+
|
49
|
+
field: ConditionField
|
50
|
+
operator: ConditionOperator
|
51
|
+
value: str
|
52
|
+
|
53
|
+
|
54
|
+
class AutoAssetTagConditionGroup(AIRBaseModel):
|
55
|
+
"""Group of conditions with logical operator."""
|
56
|
+
|
57
|
+
operator: LogicalOperator
|
58
|
+
conditions: List[AutoAssetTagCondition]
|
59
|
+
|
60
|
+
|
61
|
+
class AutoAssetTagConditions(AIRBaseModel):
|
62
|
+
"""Platform-specific conditions structure."""
|
63
|
+
|
64
|
+
operator: LogicalOperator
|
65
|
+
conditions: List[AutoAssetTagConditionGroup]
|
66
|
+
|
67
|
+
|
68
|
+
class AutoAssetTag(AIRBaseModel):
|
69
|
+
"""Auto asset tag model - handles actual API response format."""
|
70
|
+
|
71
|
+
id: str = Field(alias="_id")
|
72
|
+
tag: str
|
73
|
+
linuxConditions: Optional[Union[AutoAssetTagConditions, Dict[str, Any]]] = None
|
74
|
+
windowsConditions: Optional[Union[AutoAssetTagConditions, Dict[str, Any]]] = None
|
75
|
+
macosConditions: Optional[Union[AutoAssetTagConditions, Dict[str, Any]]] = None
|
76
|
+
organizationIds: Optional[List[int]] = Field(default_factory=list)
|
77
|
+
createdAt: Optional[datetime] = None
|
78
|
+
updatedAt: Optional[datetime] = None
|
79
|
+
createdBy: Optional[str] = None
|
80
|
+
updatedBy: Optional[str] = None
|
81
|
+
conditionIdCounter: Optional[int] = None # API includes this field
|
82
|
+
|
83
|
+
|
84
|
+
class CreateAutoAssetTagRequest(AIRBaseModel):
|
85
|
+
"""Create auto asset tag request model - matches API specification exactly."""
|
86
|
+
|
87
|
+
model_config = ConfigDict(populate_by_name=True)
|
88
|
+
|
89
|
+
tag: str
|
90
|
+
linuxConditions: AutoAssetTagConditions # Required by API
|
91
|
+
windowsConditions: AutoAssetTagConditions # Required by API
|
92
|
+
macosConditions: AutoAssetTagConditions # Required by API
|
93
|
+
organizationIds: List[int] = Field(default_factory=list)
|
94
|
+
|
95
|
+
def model_dump(self, **kwargs):
|
96
|
+
"""Exclude None values from serialization to prevent API validation errors."""
|
97
|
+
# Set exclude_none=True if not explicitly set
|
98
|
+
if 'exclude_none' not in kwargs:
|
99
|
+
kwargs['exclude_none'] = True
|
100
|
+
return super().model_dump(**kwargs)
|
101
|
+
|
102
|
+
|
103
|
+
class UpdateAutoAssetTagRequest(AIRBaseModel):
|
104
|
+
"""Update auto asset tag request model."""
|
105
|
+
|
106
|
+
model_config = ConfigDict(populate_by_name=True)
|
107
|
+
|
108
|
+
tag: Optional[str] = None
|
109
|
+
linuxConditions: Optional[AutoAssetTagConditions] = None
|
110
|
+
windowsConditions: Optional[AutoAssetTagConditions] = None
|
111
|
+
macosConditions: Optional[AutoAssetTagConditions] = None
|
112
|
+
organizationIds: Optional[List[int]] = Field(default_factory=list)
|
113
|
+
|
114
|
+
def model_dump(self, **kwargs):
|
115
|
+
"""Exclude None values from serialization to prevent API validation errors."""
|
116
|
+
# Set exclude_none=True if not explicitly set
|
117
|
+
if 'exclude_none' not in kwargs:
|
118
|
+
kwargs['exclude_none'] = True
|
119
|
+
return super().model_dump(**kwargs)
|
120
|
+
|
121
|
+
|
122
|
+
class StartTaggingSchedulerConfig(AIRBaseModel):
|
123
|
+
"""Scheduler configuration for start tagging."""
|
124
|
+
|
125
|
+
when: str # "now" or "scheduled"
|
126
|
+
timezoneType: Optional[str] = None # "asset" or "custom" - required if scheduled
|
127
|
+
timezone: Optional[str] = None # required if scheduled and custom timezone
|
128
|
+
startDate: Optional[int] = None # unix timestamp - required if scheduled
|
129
|
+
recurrence: Optional[str] = None # "onetime", "daily", "weekly", "monthly" - required if scheduled
|
130
|
+
repeatEvery: Optional[int] = None # required if scheduled and daily/monthly
|
131
|
+
repeatOnWeek: Optional[List[str]] = None # required if scheduled and weekly
|
132
|
+
repeatOnMonth: Optional[int] = None # required if scheduled and monthly
|
133
|
+
endRepeatType: Optional[str] = None # "never", "date", "occurrence" - required if scheduled
|
134
|
+
endDate: Optional[int] = None # unix timestamp - required if end repeat type is date
|
135
|
+
limit: Optional[int] = None # required if end repeat type is occurrence
|
136
|
+
|
137
|
+
|
138
|
+
class StartTaggingFilter(AIRBaseModel):
|
139
|
+
"""Filter for start tagging process - matches API specification exactly."""
|
140
|
+
|
141
|
+
organizationIds: List[int] # Required
|
142
|
+
searchTerm: Optional[str] = ""
|
143
|
+
name: Optional[str] = ""
|
144
|
+
ipAddress: Optional[str] = ""
|
145
|
+
groupId: Optional[str] = ""
|
146
|
+
groupFullPath: Optional[str] = ""
|
147
|
+
label: Optional[str] = ""
|
148
|
+
lastSeen: Optional[str] = ""
|
149
|
+
managedStatus: List[str] = [] # "unmanaged", "managed", "off-network"
|
150
|
+
isolationStatus: List[str] = [] # "isolating", "isolated", "unisolating", "unisolated"
|
151
|
+
platform: List[str] = [] # "windows", "linux", "darwin"
|
152
|
+
issue: Optional[str] = "" # "unreachable", "old-version", "update-required"
|
153
|
+
onlineStatus: List[str] = [] # "online", "offline"
|
154
|
+
tags: List[str] = []
|
155
|
+
version: Optional[str] = ""
|
156
|
+
policy: Optional[str] = ""
|
157
|
+
includedEndpointIds: List[str] = []
|
158
|
+
excludedEndpointIds: List[str] = []
|
159
|
+
caseId: Optional[str] = None
|
160
|
+
|
161
|
+
|
162
|
+
class StartTaggingRequest(AIRBaseModel):
|
163
|
+
"""Start tagging process request model - matches API specification exactly."""
|
164
|
+
|
165
|
+
filter: StartTaggingFilter
|
166
|
+
schedulerConfig: StartTaggingSchedulerConfig
|
167
|
+
|
168
|
+
|
169
|
+
class TaggingResult(AIRBaseModel):
|
170
|
+
"""Tagging process result model."""
|
171
|
+
|
172
|
+
taskId: str
|
173
|
+
message: str
|
174
|
+
processedTags: int
|
175
|
+
affectedAssets: int
|
176
|
+
|
177
|
+
|
178
|
+
class TaggingTask(AIRBaseModel):
|
179
|
+
"""Individual tagging task result from start tagging API."""
|
180
|
+
|
181
|
+
task_id: str = Field(alias="_id")
|
182
|
+
name: str = Field(alias="name")
|
183
|
+
|
184
|
+
|
185
|
+
class TaggingResponse(AIRBaseModel):
|
186
|
+
"""Response from start tagging API containing list of tasks."""
|
187
|
+
|
188
|
+
tasks: List[TaggingTask] = []
|
189
|
+
|
190
|
+
@classmethod
|
191
|
+
def from_api_result(cls, result_list: List[Dict[str, Any]]) -> 'TaggingResponse':
|
192
|
+
"""Create TaggingResponse from API result list."""
|
193
|
+
if not isinstance(result_list, list):
|
194
|
+
raise ValueError("API result must be a list")
|
195
|
+
|
196
|
+
tasks = [TaggingTask(**task) for task in result_list]
|
197
|
+
return cls(tasks=tasks)
|
198
|
+
|
199
|
+
@property
|
200
|
+
def task_count(self) -> int:
|
201
|
+
"""Get the number of tasks created."""
|
202
|
+
return len(self.tasks)
|
203
|
+
|
204
|
+
def get_task_ids(self) -> List[str]:
|
205
|
+
"""Get list of all task IDs."""
|
206
|
+
return [task.task_id for task in self.tasks]
|
207
|
+
|
208
|
+
|
209
|
+
class AutoAssetTagFilter(Filter):
|
210
|
+
"""Filter for auto asset tag queries."""
|
211
|
+
|
212
|
+
tag: Optional[str] = None
|
213
|
+
organization_ids: Optional[List[int]] = None
|
214
|
+
search_term: Optional[str] = None
|
215
|
+
|
216
|
+
def to_params(self) -> Dict[str, Any]:
|
217
|
+
"""Convert filter to API parameters with proper field name mapping."""
|
218
|
+
params = super().to_params()
|
219
|
+
|
220
|
+
# Convert organization_ids to organizationIds for API compatibility
|
221
|
+
if "filter[organization_ids]" in params:
|
222
|
+
params["filter[organizationIds]"] = params.pop("filter[organization_ids]")
|
223
|
+
|
224
|
+
# Convert search_term to searchTerm for API compatibility
|
225
|
+
if "filter[search_term]" in params:
|
226
|
+
params["filter[searchTerm]"] = params.pop("filter[search_term]")
|
227
|
+
|
117
228
|
return params
|
@@ -0,0 +1,138 @@
|
|
1
|
+
"""
|
2
|
+
Backup models for the Binalyze AIR SDK.
|
3
|
+
"""
|
4
|
+
|
5
|
+
from typing import Optional, List, Dict, Any
|
6
|
+
from datetime import datetime
|
7
|
+
from enum import Enum
|
8
|
+
from pydantic import Field
|
9
|
+
|
10
|
+
from ..base import AIRBaseModel
|
11
|
+
|
12
|
+
|
13
|
+
class BackupStatus(str, Enum):
|
14
|
+
"""Backup status enumeration."""
|
15
|
+
IN_PROGRESS = "in-progress"
|
16
|
+
SUCCEEDED = "succeeded"
|
17
|
+
UPLOADING = "uploading"
|
18
|
+
FAILED = "failed"
|
19
|
+
QUEUED = "queued"
|
20
|
+
|
21
|
+
|
22
|
+
class BackupSource(str, Enum):
|
23
|
+
"""Backup source enumeration."""
|
24
|
+
USER = "user"
|
25
|
+
SCHEDULER = "scheduler"
|
26
|
+
|
27
|
+
|
28
|
+
class BackupLocation(str, Enum):
|
29
|
+
"""Backup location enumeration."""
|
30
|
+
LOCAL = "local"
|
31
|
+
SFTP = "sftp"
|
32
|
+
S3 = "s3"
|
33
|
+
|
34
|
+
|
35
|
+
class Backup(AIRBaseModel):
|
36
|
+
"""Backup model."""
|
37
|
+
|
38
|
+
id: str = Field(alias="_id")
|
39
|
+
location: BackupLocation
|
40
|
+
status: BackupStatus
|
41
|
+
size: Optional[int] = None
|
42
|
+
source: BackupSource
|
43
|
+
username: str
|
44
|
+
to: str # Backup file path/location
|
45
|
+
stats: Dict[str, Any] = {}
|
46
|
+
start_date: datetime = Field(alias="startDate")
|
47
|
+
end_date: Optional[datetime] = Field(default=None, alias="endDate")
|
48
|
+
created_at: datetime = Field(alias="createdAt")
|
49
|
+
updated_at: datetime = Field(alias="updatedAt")
|
50
|
+
|
51
|
+
|
52
|
+
class BackupFilter(AIRBaseModel):
|
53
|
+
"""Filter parameters for backup history."""
|
54
|
+
|
55
|
+
page_size: Optional[int] = Field(default=10, alias="pageSize")
|
56
|
+
page_number: Optional[int] = Field(default=1, alias="pageNumber")
|
57
|
+
sort_type: Optional[str] = Field(default="DESC", alias="sortType") # ASC or DESC
|
58
|
+
sort_by: Optional[str] = Field(default="createdAt", alias="sortBy") # source, username, status, startDate, createdAt
|
59
|
+
search_term: Optional[str] = Field(default=None, alias="searchTerm")
|
60
|
+
username: Optional[str] = None
|
61
|
+
source: Optional[BackupSource] = None
|
62
|
+
status: Optional[BackupStatus] = None
|
63
|
+
start_date: Optional[datetime] = Field(default=None, alias="startDate")
|
64
|
+
end_date: Optional[datetime] = Field(default=None, alias="endDate")
|
65
|
+
location: Optional[BackupLocation] = None
|
66
|
+
|
67
|
+
|
68
|
+
class BackupHistoryResponse(AIRBaseModel):
|
69
|
+
"""Paginated response for backup history."""
|
70
|
+
|
71
|
+
entities: List[Backup]
|
72
|
+
filters: List[Dict[str, Any]]
|
73
|
+
sortables: List[str]
|
74
|
+
total_entity_count: int = Field(alias="totalEntityCount")
|
75
|
+
current_page: int = Field(alias="currentPage")
|
76
|
+
page_size: int = Field(alias="pageSize")
|
77
|
+
previous_page: int = Field(alias="previousPage")
|
78
|
+
total_page_count: int = Field(alias="totalPageCount")
|
79
|
+
next_page: int = Field(alias="nextPage")
|
80
|
+
|
81
|
+
|
82
|
+
class BackupNowRequest(AIRBaseModel):
|
83
|
+
"""Request model for creating an immediate backup."""
|
84
|
+
|
85
|
+
# The API appears to use filters for backup scope
|
86
|
+
# Based on the prerequest script, it uses includedEndpointIds
|
87
|
+
include_endpoint_ids: Optional[List[str]] = Field(default=None, alias="includedEndpointIds")
|
88
|
+
exclude_endpoint_ids: Optional[List[str]] = Field(default=None, alias="excludedEndpointIds")
|
89
|
+
organization_ids: Optional[List[int]] = Field(default=None, alias="organizationIds")
|
90
|
+
backup_location: Optional[BackupLocation] = BackupLocation.LOCAL
|
91
|
+
|
92
|
+
|
93
|
+
class BackupConfig(AIRBaseModel):
|
94
|
+
"""Backup configuration model."""
|
95
|
+
|
96
|
+
enabled: bool = True
|
97
|
+
schedule: Optional[str] = None # Cron expression
|
98
|
+
location: BackupLocation = BackupLocation.LOCAL
|
99
|
+
retention_days: Optional[int] = Field(default=30, alias="retentionDays")
|
100
|
+
compression: bool = True
|
101
|
+
encryption: bool = False
|
102
|
+
|
103
|
+
# SFTP configuration
|
104
|
+
sftp_host: Optional[str] = Field(default=None, alias="sftpHost")
|
105
|
+
sftp_port: Optional[int] = Field(default=22, alias="sftpPort")
|
106
|
+
sftp_username: Optional[str] = Field(default=None, alias="sftpUsername")
|
107
|
+
sftp_password: Optional[str] = Field(default=None, alias="sftpPassword")
|
108
|
+
sftp_path: Optional[str] = Field(default=None, alias="sftpPath")
|
109
|
+
|
110
|
+
# S3 configuration
|
111
|
+
s3_bucket: Optional[str] = Field(default=None, alias="s3Bucket")
|
112
|
+
s3_region: Optional[str] = Field(default=None, alias="s3Region")
|
113
|
+
s3_access_key: Optional[str] = Field(default=None, alias="s3AccessKey")
|
114
|
+
s3_secret_key: Optional[str] = Field(default=None, alias="s3SecretKey")
|
115
|
+
s3_path: Optional[str] = Field(default=None, alias="s3Path")
|
116
|
+
|
117
|
+
|
118
|
+
class BackupStats(AIRBaseModel):
|
119
|
+
"""Backup statistics model."""
|
120
|
+
|
121
|
+
total_backups: int = Field(default=0, alias="totalBackups")
|
122
|
+
successful_backups: int = Field(default=0, alias="successfulBackups")
|
123
|
+
failed_backups: int = Field(default=0, alias="failedBackups")
|
124
|
+
in_progress_backups: int = Field(default=0, alias="inProgressBackups")
|
125
|
+
total_size_bytes: int = Field(default=0, alias="totalSizeBytes")
|
126
|
+
average_backup_time_minutes: float = Field(default=0.0, alias="averageBackupTimeMinutes")
|
127
|
+
last_backup_date: Optional[datetime] = Field(default=None, alias="lastBackupDate")
|
128
|
+
next_scheduled_backup: Optional[datetime] = Field(default=None, alias="nextScheduledBackup")
|
129
|
+
|
130
|
+
|
131
|
+
class BackupDownloadInfo(AIRBaseModel):
|
132
|
+
"""Backup download information model."""
|
133
|
+
|
134
|
+
backup_id: str = Field(alias="backupId")
|
135
|
+
filename: str
|
136
|
+
size_bytes: int = Field(alias="sizeBytes")
|
137
|
+
download_url: str = Field(alias="downloadUrl")
|
138
|
+
expires_at: Optional[datetime] = Field(default=None, alias="expiresAt")
|