Skip to content

Commit 99d1ec2

Browse files
INTEG-3173 - add risk indicators
1 parent 509169a commit 99d1ec2

13 files changed

Lines changed: 516 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
- Added the `is_high_value` option to trusted activity methods in the SDK, and the `--high-value` option to trusted activity methods in the CLI.
2020
- Added the ability to specify domain trust for browser destinations, allowing users to specify when users should be allowed to use certain destinations when logged-in using a trusted domain.
2121
- Added the ability to specify trust for file-transfer tools when adding a trusted domain.
22+
- Added the `risk-indicator-categories` client to the SDK, allowing the listing of risk indicator categories, subcategories, and risk indicators.
23+
- Added the `risk-indicator-categories` command to the CLI, allowing the listing of risk indicator categories.
2224

2325
## 2.11.0 - 2026-02-10
2426

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Risk Indicator Categories Commands
2+
3+
::: mkdocs-click
4+
:module: _incydr_cli.cmds.risk_indicator_categories
5+
:command: risk_indicator_categories
6+
:list_subcommands:

docs/sdk/client.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33

44
::: incydr.Client
55
:docstring:
6-
:members: settings session request_history actors agents alerts alert_rules audit_log cases customer departments devices directory_groups file_events sessions trusted_activities users risk_profiles watchlists
6+
:members: settings session request_history actors agents alerts alert_rules audit_log cases customer departments devices directory_groups file_events sessions trusted_activities users risk_profiles watchlists risk_indicator_categories
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Risk Indicator Categories
2+
3+
::: _incydr_sdk.risk_indicator_categories.client.RiskIndicatorCategoriesV1
4+
:docstring:
5+
:members:

docs/sdk/models.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,3 +329,26 @@ ExcludedUsersList is deprecated. Use ExcludedActorsList instead.
329329

330330
::: incydr.models.IncludedDirectoryGroup
331331
:docstring:
332+
333+
## Risk Indicator Categories
334+
---
335+
336+
### `RiskIndicator` model
337+
338+
::: incydr.models.RiskIndicator
339+
:docstring:
340+
341+
### `RiskIndicatorSubcategory` model
342+
343+
::: incydr.models.RiskIndicatorSubcategory
344+
:docstring:
345+
346+
### `RiskIndicatorCategory` model
347+
348+
::: incydr.models.RiskIndicatorCategory
349+
:docstring:
350+
351+
### `RiskIndicatorCategoriesResponsePage` model
352+
353+
::: incydr.models.RiskIndicatorCategoriesResponsePage
354+
:docstring:

mkdocs.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ nav:
5555
- File Event Querying: 'sdk/clients/file_event_queries.md'
5656
- Legal Hold: 'sdk/clients/legal_hold.md'
5757
- Orgs: 'sdk/clients/orgs.md'
58+
- Risk Indicator Categories: 'sdk/clients/risk_indicator_categories.md'
5859
- Sessions: 'sdk/clients/sessions.md'
5960
- Trusted Activites: 'sdk/clients/trusted_activities.md'
6061
- Users: 'sdk/clients/users.md'
@@ -84,6 +85,7 @@ nav:
8485
- Files: 'cli/cmds/files.md'
8586
- Legal Hold: 'cli/cmds/legal_hold.md'
8687
- Orgs: 'cli/cmds/orgs.md'
88+
- Risk Indicator Categories: 'cli/cmds/risk_indicator_categories.md'
8789
- Sessions: 'cli/cmds/sessions.md'
8890
- Trusted Activites: 'cli/cmds/trusted_activities.md'
8991
- Users: 'cli/cmds/users.md'
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import itertools
2+
from typing import Iterator
3+
from typing import Optional
4+
5+
import click
6+
7+
from _incydr_cli import console
8+
from _incydr_cli import logging_options
9+
from _incydr_cli import render
10+
from _incydr_cli.cmds.options.output_options import columns_option
11+
from _incydr_cli.cmds.options.output_options import table_format_option
12+
from _incydr_cli.cmds.options.output_options import TableFormat
13+
from _incydr_cli.core import IncydrCommand
14+
from _incydr_cli.core import IncydrGroup
15+
from _incydr_sdk.core.client import Client
16+
from _incydr_sdk.risk_indicator_categories.models import RiskIndicator
17+
18+
19+
@click.group(cls=IncydrGroup)
20+
@logging_options
21+
def risk_indicator_categories():
22+
"""View and manage risk indicators."""
23+
24+
25+
@risk_indicator_categories.command("list", cls=IncydrCommand)
26+
@table_format_option
27+
@columns_option
28+
@logging_options
29+
def list_categories(
30+
format_: Optional[TableFormat] = None,
31+
columns: Optional[str] = None,
32+
):
33+
"""
34+
List Risk Indicators by category and subcategory.
35+
"""
36+
client = Client()
37+
categories = client.risk_indicator_categories.v1.list_categories().categories
38+
39+
if format_ == TableFormat.table:
40+
columns = columns or [
41+
"id",
42+
"name",
43+
"description",
44+
"category_name",
45+
"category_id",
46+
"subcategory_name",
47+
"subcategory_id",
48+
"type",
49+
]
50+
render.table(
51+
RiskIndicatorTableEntry,
52+
iter_risk_indicator_table_entries(categories),
53+
columns=columns,
54+
flat=False,
55+
)
56+
elif format_ == TableFormat.csv:
57+
render.csv(
58+
RiskIndicatorTableEntry,
59+
iter_risk_indicator_table_entries(categories),
60+
columns=columns,
61+
flat=True,
62+
)
63+
else:
64+
printed = False
65+
for indicator in iter_risk_indicator_table_entries(categories):
66+
printed = True
67+
if format_ == TableFormat.json_pretty:
68+
console.print_json(indicator.json())
69+
else:
70+
click.echo(indicator.json())
71+
if not printed:
72+
console.print("No results found.")
73+
74+
75+
class RiskIndicatorTableEntry(RiskIndicator):
76+
category_name: str
77+
category_id: str
78+
category_description: Optional[str]
79+
subcategory_name: str
80+
subcategory_id: str
81+
subcategory_description: Optional[str]
82+
type: str
83+
84+
85+
def iter_risk_indicator_table_entries(categories) -> Iterator[RiskIndicatorTableEntry]:
86+
for category in categories:
87+
for subcategory in category.subcategories:
88+
for indicator, indicator_type in itertools.chain(
89+
((i, "standard") for i in subcategory.standard_indicators),
90+
((i, "custom") for i in subcategory.custom_indicators),
91+
):
92+
yield RiskIndicatorTableEntry(
93+
id=indicator.id,
94+
name=indicator.name,
95+
description=indicator.description,
96+
category_name=category.name,
97+
category_id=category.id,
98+
category_description=category.description,
99+
subcategory_name=subcategory.name,
100+
subcategory_id=subcategory.id,
101+
subcategory_description=subcategory.description,
102+
type=indicator_type,
103+
)

src/_incydr_cli/main.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from _incydr_cli.cmds.files import files as files_client
2222
from _incydr_cli.cmds.legal_hold import legal_hold
2323
from _incydr_cli.cmds.orgs import orgs
24+
from _incydr_cli.cmds.risk_indicator_categories import risk_indicator_categories
2425
from _incydr_cli.cmds.risk_profiles import risk_profiles
2526
from _incydr_cli.cmds.sessions import sessions
2627
from _incydr_cli.cmds.trusted_activities import trusted_activities
@@ -87,6 +88,7 @@ def incydr(version, python, script_dir):
8788
incydr.add_command(files_client)
8889
incydr.add_command(cases)
8990
incydr.add_command(risk_profiles)
91+
incydr.add_command(risk_indicator_categories)
9092
incydr.add_command(sessions)
9193
incydr.add_command(trusted_activities)
9294
incydr.add_command(users)

src/_incydr_sdk/core/client.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
from _incydr_sdk.files.client import FilesClient
2525
from _incydr_sdk.legal_hold.client import LegalHoldClient
2626
from _incydr_sdk.orgs.client import OrgsClient
27+
from _incydr_sdk.risk_indicator_categories.client import RiskIndicatorCategories
2728
from _incydr_sdk.risk_profiles.client import RiskProfiles
2829
from _incydr_sdk.sessions.client import SessionsClient
2930
from _incydr_sdk.trusted_activities.client import TrustedActivitiesClient
@@ -114,6 +115,7 @@ def response_hook(response, *args, **kwargs):
114115
self._trusted_activities = TrustedActivitiesClient(self)
115116
self._users = UsersClient(self)
116117
self._risk_profiles = RiskProfiles(self)
118+
self._risk_indicator_categories = RiskIndicatorCategories(self)
117119
self._watchlists = WatchlistsClient(self)
118120

119121
if not skip_auth:
@@ -366,6 +368,17 @@ def risk_profiles(self):
366368
"""
367369
return self._risk_profiles
368370

371+
@property
372+
def risk_indicator_categories(self):
373+
"""
374+
Property returning a [`RiskIndicatorCategories`](../risk_indicator_categories) client for interacting
375+
with `/v*/risk_indicator_categories` API endpoints.
376+
377+
Usage:
378+
>>> client.risk_indicator_categories.v1.list_categories(active=True)
379+
"""
380+
return self._risk_indicator_categories
381+
369382
@property
370383
def watchlists(self):
371384
"""
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
from _incydr_sdk.enums import SortDirection
2+
from _incydr_sdk.risk_indicator_categories.models import (
3+
RiskIndicatorCategoriesResponsePage,
4+
)
5+
from _incydr_sdk.risk_indicator_categories.models import RiskIndicatorCategory
6+
from _incydr_sdk.risk_indicator_categories.models import RiskIndicatorSubcategory
7+
8+
9+
class RiskIndicatorCategories:
10+
def __init__(self, parent):
11+
self._parent = parent
12+
self._v1 = None
13+
14+
@property
15+
def v1(self):
16+
if self._v1 is None:
17+
self._v1 = RiskIndicatorCategoriesV1(self._parent)
18+
return self._v1
19+
20+
21+
class RiskIndicatorCategoriesV1:
22+
"""
23+
Client for `/v1/risk-indicator-categories` endpoints.
24+
25+
Usage example:
26+
27+
>>> import incydr
28+
>>> client = incydr.Client(**kwargs)
29+
>>> client.risk_indicators.v1.list_categories()
30+
"""
31+
32+
def __init__(self, parent):
33+
self._parent = parent
34+
35+
def list_categories(
36+
self, active: bool = None, sort_direction: SortDirection = None
37+
) -> RiskIndicatorCategoriesResponsePage:
38+
"""
39+
Returns all risk indicator categories, including their subcategories and associated risk indicators.
40+
Filter results by passing the appropriate parameters:
41+
42+
**Parameters**:
43+
44+
* **active**: `bool` - When provided, returns only those risk indicators which match the provided value (true or false). When not provided, returns both.
45+
* **sort_direction**: `SortDirection` - The order in which to sort the returned list.
46+
47+
**Returns**: A [`RiskIndicatorCategoriesResponsePage`][riskindicatorcategoriesresponsepage-model] object.
48+
"""
49+
response = self._parent.session.get(
50+
"/v1/risk-indicator-categories",
51+
params={"isActive": active, "sort_direction": sort_direction},
52+
)
53+
return RiskIndicatorCategoriesResponsePage.parse_response(response)
54+
55+
def get_category(self, id: str) -> RiskIndicatorCategory:
56+
"""
57+
Returns a single risk indicator category, including its subcategories and associated risk indicators.
58+
59+
**Parameters**:
60+
61+
* **id**: `str` - The unique ID of the category you wish to retrieve.
62+
63+
**Returns**: A [`RiskIndicatorCategory`][riskindicatorcategory-model] object.
64+
"""
65+
response = self._parent.session.get(f"/v1/risk-indicator-categories/{id}")
66+
return RiskIndicatorCategory.parse_response(response)
67+
68+
def get_subcategory(
69+
self, category_id: str, subcategory_id: str
70+
) -> RiskIndicatorSubcategory:
71+
"""
72+
Returns a single risk indicator category, including its subcategories and associated risk indicators.
73+
74+
**Parameters**:
75+
76+
* **category_id**: `str` - The unique ID of the category in which the subcategory lives.
77+
* **subcategory_id**: `str` - The unique ID of the subcategory you wish to retrieve.
78+
79+
**Returns**: A [`RiskIndicatorSubcategory`][riskindicatorsubcategory-model] object.
80+
"""
81+
response = self._parent.session.get(
82+
f"/v1/risk-indicator-categories/{category_id}/subcategories/{subcategory_id}"
83+
)
84+
return RiskIndicatorSubcategory.parse_response(response)

0 commit comments

Comments
 (0)