Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
c6604bb
refactor: Use API version in URL building
PaperMtn Dec 29, 2025
8a47503
refactor: Update variable names
PaperMtn Dec 29, 2025
d8b227c
refactor: Update variable names
PaperMtn Dec 29, 2025
e1b1012
refactor: Refactor to use request helpers
PaperMtn Dec 29, 2025
f0dfb5a
refactor: Update return type
PaperMtn Dec 30, 2025
ef3d6eb
refactor: Refactor paginated request logic to fix issues
PaperMtn Dec 30, 2025
5ec0267
refactor: Update to supply API version only instead of full base path
PaperMtn Dec 30, 2025
e5e97ee
refactor: Update tests to account for use of request helper functions
PaperMtn Dec 30, 2025
600c055
feat: Added tests for request_utils.py
PaperMtn Dec 30, 2025
2d21419
chore: Update formatting
PaperMtn Dec 30, 2025
0ea15ef
feat: Implement optional return as list
PaperMtn Dec 30, 2025
9137f8e
chore: Remove testing prints and commented code
PaperMtn Dec 30, 2025
e069394
chore: Remove testing prints and commented code
PaperMtn Dec 30, 2025
7489e27
feat: Implement optional list output for watchlists
PaperMtn Dec 30, 2025
e7d11e2
chore: Update formatting
PaperMtn Dec 30, 2025
b76b80e
chore: Add variables for as_list
PaperMtn Dec 30, 2025
8d4afaf
feat: Add error checking and exception handling for HTTP requests
PaperMtn Jan 2, 2026
0181408
feat: Update building of url based on endpoint
PaperMtn Jan 2, 2026
5793ead
feat: Additional error messages for exceptions
PaperMtn Jan 2, 2026
2113b3b
feat: Implement additional options for expected status
PaperMtn Jan 2, 2026
b6075de
feat: Implement safe body preview for error messages
PaperMtn Jan 2, 2026
052bd48
feat: Added tests for new features
PaperMtn Jan 2, 2026
cfba388
chore: linting and formatting changes
PaperMtn Jan 2, 2026
fa0278e
chore: linting and formatting changes
PaperMtn Jan 2, 2026
eb0f6b6
feat: refactor to use utils standard request
PaperMtn Jan 2, 2026
50eee86
chore: move validate testing to own module and update for refactor
PaperMtn Jan 2, 2026
fe4756d
Merge branch 'google:main' into feature/request-helper-implementation
PaperMtn Jan 3, 2026
77290d7
feat: add headers to chronicle_request
PaperMtn Jan 3, 2026
8dc0fd1
feat: add headers to chronicle_request
PaperMtn Jan 3, 2026
a45f653
feat: migrate to request helper
PaperMtn Jan 3, 2026
e7103f6
chore: update formatting
PaperMtn Jan 3, 2026
ce8f97e
refactor: move udm search tests to their own module and update for he…
PaperMtn Jan 3, 2026
ca80bec
refactor: refactor to use request helper
PaperMtn Jan 4, 2026
343c783
refactor: refactor to include as_list option
PaperMtn Jan 4, 2026
07aa48b
chore: linting
PaperMtn Jan 4, 2026
bf9e060
chore: update docstrings
PaperMtn Jan 4, 2026
0c1e7f7
refactor: update tests with new request helper variables
PaperMtn Jan 4, 2026
d9e3d11
Merge branch 'main' into feature/request-helper-implementation
mihirvala08 Jan 8, 2026
ee63889
chore: improved type hints and documentation for return types and fun…
mihirvala08 Jan 8, 2026
205d93f
feat: add --as-list flag to CLI commands for list-only output without…
mihirvala08 Jan 9, 2026
9da478f
chore: updated doc
mihirvala08 Jan 9, 2026
fa5a425
chore: version bump
PaperMtn Jan 9, 2026
71754d9
chore: added changelog
mihirvala08 Jan 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,22 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).



## [0.34.0] - 2026-01-12
### Added
- `as_list` parameter for paginated list methods to streamline API requests and automatically fetch all pages
- Supported methods: `list_watchlists`, `list_curated_rules`, `list_curated_rule_sets`, `list_curated_rule_set_categories`, `list_curated_rule_set_deployments`, `list_featured_content_rules`
- CLI `--as-list` flag for corresponding list commands

### Updated
- Refactored modules to use centralized `chronicle_request` helper function for improved code consistency and maintainability
- Watchlist (`watchlist.py`)
- Curated rule set (`rule_set.py`)
- Investigation (`investigations.py`)
- UDM mapping (`udm_mapping.py`)
- UDM search (`udm_search.py`)
- Validation (`validate.py`)

## [0.33.0] - 2026-01-07
### Added
- Support for following investigation methods:
Expand Down
38 changes: 37 additions & 1 deletion CLI.md
Original file line number Diff line number Diff line change
Expand Up @@ -676,9 +676,12 @@ secops parser-extension delete --log-type OKTA --id "1234567890"
List watchlists:

```bash
# List all watchlists
# List all watchlists (returns dict with pagination metadata)
secops watchlist list

# List watchlists as a direct list (fetches all pages automatically)
secops watchlist list --as-list

# List watchlist with pagination
secops watchlist list --page-size 50
```
Expand Down Expand Up @@ -829,10 +832,17 @@ The `rule test` command outputs UDM events as pure JSON objects that can be pipe
### Curated Rule Set Management

List all curated rules:

```bash
# List all curated rules (returns dict with pagination metadata)
secops curated-rule rule list

# List curated rules as a direct list
secops curated-rule rule list --as-list
```

Get curated rules:

```bash
# Get rule by UUID
secops curated-rule rule get --id "ur_ttp_GCP_ServiceAPIDisable"
Expand All @@ -842,6 +852,7 @@ secops curated-rule rule get --name "GCP Service API Disable"
```

Search for curated rule detections:

```bash
secops curated-rule search-detections \
--rule-id "ur_ttp_GCP_MassSecretDeletion" \
Expand All @@ -861,33 +872,54 @@ secops curated-rule search-detections \
```

List all curated rule sets:

```bash
# List all curated rule sets (returns dict with pagination metadata)
secops curated-rule rule-set list

# List curated rule sets as a direct list
secops curated-rule rule-set list --as-list
```

Get specific curated rule set details:

```bash
# Get curated rule set by UUID
secops curated-rule rule-set get --id "f5533b66-9327-9880-93e6-75a738ac2345"

# Get curated rule set by name
secops curated-rule rule-set get --name "Active Breach Priority Host Indicators"
```

List all curated rule set categories:

```bash
# List all curated rule set categories (returns dict with pagination metadata)
secops curated-rule rule-set-category list

# List curated rule set categories as a direct list
secops curated-rule rule-set-category list --as-list
```

Get specific curated rule set category details:

```bash
# Get curated rule set category by UUID
secops curated-rule rule-set-category get --id "db1114d4-569b-5f5d-0fb4-f65aaa766c92"
```

List all curated rule set deployments:

```bash
# List all curated rule set deployments (returns dict with pagination metadata)
secops curated-rule rule-set-deployment list

# List curated rule set deployments as a direct list
secops curated-rule rule-set-deployment list --as-list
```

Get specific curated rule set deployment details:

```bash
# Get curated rule set deployment by UUID
secops curated-rule rule-set-deployment get --id "f5533b66-9327-9880-93e6-75a738ac2345"
Expand Down Expand Up @@ -1308,7 +1340,11 @@ Featured content rules are pre-built detection rules available in the Chronicle
#### List all featured content rules:

```bash
# List all featured content rules (returns dict with pagination metadata)
secops featured-content-rules list

# List featured content rules as a direct list
secops featured-content-rules list --as-list
```

#### List with pagination:
Expand Down
56 changes: 46 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1854,7 +1854,15 @@ watchlist = chronicle.get_watchlist("acb-123-def")
List all watchlists:

```python
# List watchlists (returns dict with pagination metadata)
watchlists = chronicle.list_watchlists()
for watchlist in watchlists.get("watchlists", []):
print(f"Watchlist: {watchlist.get('displayName')}")

# List watchlists as a direct list (automatically fetches all pages)
watchlists = chronicle.list_watchlists(as_list=True)
for watchlist in watchlists:
print(f"Watchlist: {watchlist.get('displayName')}")
```

## Rule Management
Expand Down Expand Up @@ -2164,14 +2172,21 @@ If `tooManyAlerts` is True in the response, consider narrowing your search crite
Query curated rules:

```python
# List all curated rules
rules = chronicle.list_curated_rules()
for rule in rules:
# List all curated rules (returns dict with pagination metadata)
result = chronicle.list_curated_rules()
for rule in result.get("curatedRules", []):
rule_id = rule.get("name", "").split("/")[-1]
display_name = rule.get("description")
description = rule.get("description")
print(f"Rule: {display_name}, Description: {description}")

# List all curated rules as a direct list
rules = chronicle.list_curated_rules(as_list=True)
for rule in rules:
rule_id = rule.get("name", "").split("/")[-1]
display_name = rule.get("description")
print(f"Rule: {display_name}")

# Get a curated rule
rule = chronicle.get_curated_rule("ur_ttp_lol_Atbroker")

Expand Down Expand Up @@ -2218,8 +2233,15 @@ if "nextPageToken" in result:
Query curated rule sets:

```python
# List all curated rule sets
rule_sets = chronicle.list_curated_rule_sets()
# List all curated rule sets (returns dict with pagination metadata)
result = chronicle.list_curated_rule_sets()
for rule_set in result.get("curatedRuleSets", []):
rule_set_id = rule_set.get("name", "").split("/")[-1]
display_name = rule_set.get("displayName")
print(f"Rule Set: {display_name}, ID: {rule_set_id}")

# List all curated rule sets as a direct list
rule_sets = chronicle.list_curated_rule_sets(as_list=True)
for rule_set in rule_sets:
rule_set_id = rule_set.get("name", "").split("/")[-1]
display_name = rule_set.get("displayName")
Expand All @@ -2232,8 +2254,15 @@ rule_set = chronicle.get_curated_rule_set("00ad672e-ebb3-0dd1-2a4d-99bd7c5e5f93"
Query curated rule set categories:

```python
# List all curated rule set categories
rule_set_categories = chronicle.list_curated_rule_set_categories()
# List all curated rule set categories (returns dict with pagination metadata)
result = chronicle.list_curated_rule_set_categories()
for rule_set_category in result.get("curatedRuleSetCategories", []):
rule_set_category_id = rule_set_category.get("name", "").split("/")[-1]
display_name = rule_set_category.get("displayName")
print(f"Rule Set Category: {display_name}, ID: {rule_set_category_id}")

# List all curated rule set categories as a direct list
rule_set_categories = chronicle.list_curated_rule_set_categories(as_list=True)
for rule_set_category in rule_set_categories:
rule_set_category_id = rule_set_category.get("name", "").split("/")[-1]
display_name = rule_set_category.get("displayName")
Expand All @@ -2246,9 +2275,9 @@ rule_set_category = chronicle.get_curated_rule_set_category("110fa43d-7165-2355-
Manage curated rule set deployments (turn alerting on or off (either precise or broad) for curated rule sets):

```python
# List all curated rule set deployments
rule_set_deployments = chronicle.list_curated_rule_set_deployments()
for rs_deployment in rule_set_deployments:
# List all curated rule set deployments (returns dict with pagination metadata)
result = chronicle.list_curated_rule_set_deployments()
for rs_deployment in result.get("curatedRuleSetDeployments", []):
rule_set_id = rs_deployment.get("name", "").split("/")[-3]
category_id = rs_deployment.get("name", "").split("/")[-5]
deployment_status = rs_deployment.get("name", "").split("/")[-1]
Expand All @@ -2262,6 +2291,13 @@ for rs_deployment in rule_set_deployments:
f"Alerting: {alerting}",
)

# List all curated rule set deployments as a direct list
rule_set_deployments = chronicle.list_curated_rule_set_deployments(as_list=True)
for rs_deployment in rule_set_deployments:
rule_set_id = rs_deployment.get("name", "").split("/")[-3]
display_name = rs_deployment.get("displayName")
print(f"Rule Set: {display_name}, ID: {rule_set_id}")

# Get curated rule set deployment by ID
rule_set_deployment = chronicle.get_curated_rule_set_deployment("00ad672e-ebb3-0dd1-2a4d-99bd7c5e5f93")

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "hatchling.build"

[project]
name = "secops"
version = "0.33.0"
version = "0.34.0"
description = "Python SDK for wrapping the Google SecOps API for common use cases"
readme = "README.md"
requires-python = ">=3.10"
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ protobuf
pylint
twine
python-dotenv
requests
Loading