Skip to content

Commit 6537efe

Browse files
committed
add alert rules commands
1 parent c32bab7 commit 6537efe

12 files changed

Lines changed: 435 additions & 53 deletions

File tree

docs/cli/alert_rules.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Alert Rules Commands
2+
3+
::: mkdocs-click
4+
:module: incydr.cli.cmds.alert_rules
5+
:command: list_
6+
7+
::: mkdocs-click
8+
:module: incydr.cli.cmds.alert_rules
9+
:command: show
10+
11+
::: mkdocs-click
12+
:module: incydr.cli.cmds.alert_rules
13+
:command: enable
14+
15+
::: mkdocs-click
16+
:module: incydr.cli.cmds.alert_rules
17+
:command: disable
18+
19+
::: mkdocs-click
20+
:module: incydr.cli.cmds.alert_rules
21+
:command: remove_all_users
22+
23+
24+
::: mkdocs-click
25+
:module: incydr.cli.cmds.alert_rules
26+
:command: list_users

incydr/_alert_rules/client.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from typing import Union
55

66
from pydantic import parse_obj_as
7+
from requests import HTTPError
78
from requests import Response
89

910
from incydr._alert_rules.models.request import GetRulesRequest
@@ -12,6 +13,13 @@
1213
from incydr._user_risk_profiles.models import UserRiskProfile
1314

1415

16+
class MissingUsernameCriterionError(Exception):
17+
"""An error raised when the date data cannot be parsed."""
18+
19+
def __init__(self, rule_id):
20+
super().__init__(f"Rule '{rule_id}' has no username filter.")
21+
22+
1523
class AlertRulesClient:
1624
def __init__(self, parent):
1725
self._parent = parent
@@ -144,13 +152,22 @@ def get_users(self, rule_id: str) -> RuleUsersList:
144152
"""
145153
Get all users assigned to a rule.
146154
155+
Raises a `MissingUsernameCriterionError` if the rule doesn't have a username filter.
156+
147157
**Parameters**:
148158
149159
* **rule_id**: `str` (required) - The ID of the rule.
150160
151161
**Returns**: A [`RuleUsersList`][ruleuserslist-model] model.
152162
"""
153-
response = self._parent.session.get(url=f"/v2/alert-rules/{rule_id}/users")
163+
try:
164+
response = self._parent.session.get(url=f"/v2/alert-rules/{rule_id}/users")
165+
except HTTPError as e:
166+
# This endpoint doesn't have query params or a request body, so it should
167+
# only return a 400 if there is not username filter for the rule.
168+
if e.response.status_code == 400:
169+
raise MissingUsernameCriterionError(rule_id)
170+
raise e
154171
return RuleUsersList.parse_response(response)
155172

156173
def _get_user_aliases(self, user_id):

incydr/_alert_rules/models/response.py

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66

77
from pydantic import Field
88

9+
from incydr._core.models import Model
910
from incydr._core.models import ResponseModel
11+
from incydr.enums.alerts import MessagingMethod
1012

1113

1214
class RuleUser(ResponseModel):
@@ -54,10 +56,11 @@ class RuleUsersList(ResponseModel):
5456
mode: Optional[str] = Field(
5557
None,
5658
description="Indicates how to filter on the user list. INCLUDE or EXCLUDE.",
59+
table=lambda x: "INCLUDE" if x == "0" else "EXCLUDE",
5760
)
5861

5962

60-
class CloudSharingDetails(ResponseModel):
63+
class CloudSharingDetails(Model):
6164
observe_all: bool = Field(
6265
None,
6366
description="Indicates whether we are watching the cloud sharing connector or not.",
@@ -68,7 +71,7 @@ class CloudSharingDetails(ResponseModel):
6871
direct_share: bool = Field(None, alias="directShare")
6972

7073

71-
class DownloadVector(ResponseModel):
74+
class DownloadVector(Model):
7275
observe_all: Optional[bool] = Field(None, alias="observeAll")
7376
salesforce: Optional[bool] = None
7477
box: Optional[bool] = None
@@ -77,14 +80,14 @@ class DownloadVector(ResponseModel):
7780
criteria_order: int = Field(None, alias="criteriaOrder")
7881

7982

80-
class EmailVector(ResponseModel):
83+
class EmailVector(Model):
8184
observe_all: Optional[bool] = Field(None, alias="observeAll")
8285
gmail: Optional[bool] = None
8386
microsoft365: Optional[bool] = None
8487
criteria_order: int = Field(None, alias="criteriaOrder")
8588

8689

87-
class FileUploadCategory(ResponseModel):
90+
class FileUploadCategory(Model):
8891
observe_all: bool = Field(
8992
None,
9093
description="Indicates whether we are watching all of the destinations in the category.",
@@ -98,11 +101,11 @@ class FileUploadCategory(ResponseModel):
98101
)
99102

100103

101-
class AdvancedSettings(ResponseModel):
104+
class AdvancedSettings(Model):
102105
observe_uncategorized: bool = Field(None, alias="observeUncategorized")
103106

104107

105-
class RemovableMediaVector(ResponseModel):
108+
class RemovableMediaVector(Model):
106109
is_enabled: bool = Field(
107110
None,
108111
description="Indicates whether to watch removable media destinations or not.",
@@ -117,7 +120,7 @@ class RemovableMediaVector(ResponseModel):
117120
)
118121

119122

120-
class FileCategoryFilter(ResponseModel):
123+
class FileCategoryFilter(Model):
121124
categories: Optional[List[str]] = Field(
122125
None,
123126
description="List of file categories to alert on.",
@@ -131,7 +134,7 @@ class FileCategoryFilter(ResponseModel):
131134
)
132135

133136

134-
class FileNameFilter(ResponseModel):
137+
class FileNameFilter(Model):
135138
patterns: Optional[List[str]] = Field(
136139
None,
137140
description="List of file name patterns to alert on.",
@@ -145,7 +148,7 @@ class FileNameFilter(ResponseModel):
145148
)
146149

147150

148-
class FileTypeMismatchFilter(ResponseModel):
151+
class FileTypeMismatchFilter(Model):
149152
is_enabled: bool = Field(
150153
None,
151154
description="Indicates whether or not to alert on file type mismatches only.",
@@ -160,25 +163,25 @@ class FileTypeMismatchFilter(ResponseModel):
160163
)
161164

162165

163-
class RiskIndicatorFilter(ResponseModel):
166+
class RiskIndicatorFilter(Model):
164167
categories: Optional[List[str]] = None
165168
indicators: Optional[List[str]] = None
166169
criteria_order: int = Field(None, alias="criteriaOrder")
167170

168171

169-
class RiskSeverityFilter(ResponseModel):
172+
class RiskSeverityFilter(Model):
170173
low: bool
171174
moderate: bool
172175
high: bool
173176
critical: bool
174177
criteria_order: int = Field(None, alias="criteriaOrder")
175178

176179

177-
class Watchlist(ResponseModel):
180+
class Watchlist(Model):
178181
id: Optional[str] = None
179182

180183

181-
class NotificationContact(ResponseModel):
184+
class NotificationContact(Model):
182185
is_enabled: bool = Field(
183186
None,
184187
description="Indicates whether the notifications for this contact are enabled.",
@@ -195,7 +198,7 @@ class NotificationContact(ResponseModel):
195198
)
196199

197200

198-
class CloudSharingVector(ResponseModel):
201+
class CloudSharingVector(Model):
199202
observe_all: Optional[bool] = Field(
200203
None,
201204
description="Indicates whether to watch all cloud sharing connectors.",
@@ -224,7 +227,7 @@ class CloudSharingVector(ResponseModel):
224227
)
225228

226229

227-
class FileUploadVector(ResponseModel):
230+
class FileUploadVector(Model):
228231
cloud_storage: Optional[FileUploadCategory] = Field(
229232
None,
230233
description="Configuration for which cloud storage destinations to monitor.",
@@ -279,7 +282,7 @@ class FileUploadVector(ResponseModel):
279282
)
280283

281284

282-
class FileVolumeFilter(ResponseModel):
285+
class FileVolumeFilter(Model):
283286
count_greater_than: int = Field(
284287
None,
285288
description="File count threshold that must be exceeded to trigger an alert.",
@@ -304,7 +307,7 @@ class FileVolumeFilter(ResponseModel):
304307
)
305308

306309

307-
class UsernameFilter(ResponseModel):
310+
class UsernameFilter(Model):
308311
mode: Optional[str] = Field(
309312
None, description="Indicates how to filter on the user list. INCLUDE or EXCLUDE"
310313
)
@@ -321,12 +324,12 @@ class UsernameFilter(ResponseModel):
321324
)
322325

323326

324-
class WatchlistFilter(ResponseModel):
327+
class WatchlistFilter(Model):
325328
watchlists: Optional[List[Watchlist]] = None
326329
criteria_order: int = Field(None, alias="criteriaOrder")
327330

328331

329-
class NotificationSettings(ResponseModel):
332+
class NotificationSettings(Model):
330333
is_enabled: bool = Field(
331334
None,
332335
description="Indicates whether notifications are enabled.",
@@ -338,7 +341,7 @@ class NotificationSettings(ResponseModel):
338341
)
339342

340343

341-
class RuleVectors(ResponseModel):
344+
class RuleVectors(Model):
342345
cloud_sharing: Optional[CloudSharingVector] = Field(
343346
None,
344347
description="Configuration for cloud sharing vectors to monitor.",
@@ -358,7 +361,7 @@ class RuleVectors(ResponseModel):
358361
)
359362

360363

361-
class RuleFilters(ResponseModel):
364+
class RuleFilters(Model):
362365
file_category: Optional[FileCategoryFilter] = Field(
363366
None,
364367
description="Configuration for what file categories to monitor.",
@@ -387,6 +390,15 @@ class RuleFilters(ResponseModel):
387390
watchlist: Optional[WatchlistFilter] = None
388391

389392

393+
class EducationSettings(Model):
394+
lesson_id: Optional[str] = Field(
395+
None, description="Instructor lesson ID.", alias="lessonId"
396+
)
397+
messaging_method: Optional[MessagingMethod] = Field(
398+
None, description="Messaging method.", alias="messagingMethod"
399+
)
400+
401+
390402
class RuleDetails(ResponseModel):
391403
"""
392404
A model representing the details of an alert rule.
@@ -399,6 +411,7 @@ class RuleDetails(ResponseModel):
399411
* **is_enabled**: `bool` - Indicates if the rule is currently enabled.
400412
* **source**: `str` - [Deprecated field] Indicates source of rule creation.
401413
* **notifications**: `NotificationSettings` - Notification configuration settings for this rule.
414+
* **education**: `EducationSettings` - Instructor settings for a rule.
402415
* **vectors**: `RuleVectors` - The exfiltration vectors to be watched.
403416
* **filters**: `RuleFilters` - The filters to limit the scope of activity to alert on.
404417
* **id**: `id` - Unique ID of the rule.
@@ -436,6 +449,9 @@ class RuleDetails(ResponseModel):
436449
notifications: Optional[NotificationSettings] = Field(
437450
None, description="Notifications configuration settings for this rule."
438451
)
452+
education: Optional[EducationSettings] = Field(
453+
None, description="Education settings for a rule."
454+
)
439455
vectors: Optional[RuleVectors] = Field(
440456
None, description="The exfiltration vectors to be watched."
441457
)

0 commit comments

Comments
 (0)