Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
63 changes: 63 additions & 0 deletions .generator/schemas/v2/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1721,6 +1721,15 @@ components:
required: true
schema:
type: string
SecurityMonitoringRuleVersion:
description: The historical version number of the rule.
in: path
name: version
required: true
schema:
example: 1
format: int64
type: integer
SecurityMonitoringSuppressionID:
description: The ID of the suppression rule
in: path
Expand Down Expand Up @@ -169544,6 +169553,60 @@ paths:
operator: OR
permissions:
- security_monitoring_rules_read
/api/v2/security_monitoring/rules/{rule_id}/restore/{version}:
post:
description: |-
Restores a custom detection rule to a previously saved historical version.
Only custom rules can be restored. Default and partner rules return 400.
The restore creates a new version entry; it does not overwrite history.
operationId: RestoreSecurityMonitoringRule
parameters:
- $ref: "#/components/parameters/SecurityMonitoringRuleID"
- $ref: "#/components/parameters/SecurityMonitoringRuleVersion"
responses:
"200":
content:
"application/json":
examples:
default:
value:
cases:
- condition: "a > 0"
name: ""
notifications: []
status: info
id: abc-123
isEnabled: true
message: Test rule
name: My security monitoring rule.
tags: []
type: log_detection
schema:
$ref: "#/components/schemas/SecurityMonitoringRuleResponse"
description: OK
"400":
$ref: "#/components/responses/BadRequestResponse"
"403":
$ref: "#/components/responses/NotAuthorizedResponse"
"404":
$ref: "#/components/responses/NotFoundResponse"
"409":
$ref: "#/components/responses/ConflictResponse"
"429":
$ref: "#/components/responses/TooManyRequestsResponse"
security:
- apiKeyAuth: []
appKeyAuth: []
- AuthZ:
- security_monitoring_rules_write
summary: Restore a rule to a historical version
tags: ["Security Monitoring"]
"x-permission":
operator: OR
permissions:
- security_monitoring_rules_write
x-unstable: |-
**Note**: This endpoint is in beta and may be subject to changes.
/api/v2/security_monitoring/rules/{rule_id}/test:
post:
description: |-
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
"""
Restore a rule to a historical version returns "OK" response
"""

from os import environ
from datadog_api_client import ApiClient, Configuration
from datadog_api_client.v2.api.security_monitoring_api import SecurityMonitoringApi

# there is a valid "security_rule" in the system
SECURITY_RULE_ID = environ["SECURITY_RULE_ID"]

configuration = Configuration()
configuration.unstable_operations["restore_security_monitoring_rule"] = True
with ApiClient(configuration) as api_client:
api_instance = SecurityMonitoringApi(api_client)
response = api_instance.restore_security_monitoring_rule(
rule_id=SECURITY_RULE_ID,
version=1,
)

print(response)
1 change: 1 addition & 0 deletions src/datadog_api_client/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,7 @@ def __init__(
"v2.list_vulnerabilities": False,
"v2.list_vulnerable_assets": False,
"v2.mute_findings": False,
"v2.restore_security_monitoring_rule": False,
"v2.run_historical_job": False,
"v2.search_security_monitoring_histsignals": False,
"v2.update_findings_assignee": False,
Expand Down
53 changes: 53 additions & 0 deletions src/datadog_api_client/v2/api/security_monitoring_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -3510,6 +3510,35 @@ def __init__(self, api_client=None):
api_client=api_client,
)

self._restore_security_monitoring_rule_endpoint = _Endpoint(
settings={
"response_type": (SecurityMonitoringRuleResponse,),
"auth": ["apiKeyAuth", "appKeyAuth", "AuthZ"],
"endpoint_path": "/api/v2/security_monitoring/rules/{rule_id}/restore/{version}",
"operation_id": "restore_security_monitoring_rule",
"http_method": "POST",
"version": "v2",
},
params_map={
"rule_id": {
"required": True,
"openapi_types": (str,),
"attribute": "rule_id",
"location": "path",
},
"version": {
"required": True,
"openapi_types": (int,),
"attribute": "version",
"location": "path",
},
},
headers_map={
"accept": ["application/json"],
},
api_client=api_client,
)

self._run_historical_job_endpoint = _Endpoint(
settings={
"response_type": (JobCreateResponse,),
Expand Down Expand Up @@ -7370,6 +7399,30 @@ def patch_vulnerability_notification_rule(

return self._patch_vulnerability_notification_rule_endpoint.call_with_http_info(**kwargs)

def restore_security_monitoring_rule(
self,
rule_id: str,
version: int,
) -> SecurityMonitoringRuleResponse:
"""Restore a rule to a historical version.

Restores a custom detection rule to a previously saved historical version.
Only custom rules can be restored. Default and partner rules return 400.
The restore creates a new version entry; it does not overwrite history.

:param rule_id: The ID of the rule.
:type rule_id: str
:param version: The historical version number of the rule.
:type version: int
:rtype: SecurityMonitoringRuleResponse
"""
kwargs: Dict[str, Any] = {}
kwargs["rule_id"] = rule_id

kwargs["version"] = version

return self._restore_security_monitoring_rule_endpoint.call_with_http_info(**kwargs)

def run_historical_job(
self,
body: RunHistoricalJobRequest,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
2026-06-12T09:57:22.725Z
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
interactions:
- request:
body: '{"cases":[{"condition":"a > 0","name":"","notifications":[],"status":"info"}],"filters":[],"isEnabled":true,"message":"Test
rule","name":"Test-Restore_a_rule_to_a_historical_version_returns_Conflict_response-1781258242","options":{"evaluationWindow":900,"keepAlive":3600,"maxSignalDuration":86400},"queries":[{"aggregation":"count","distinctFields":[],"groupByFields":[],"metrics":[],"query":"@test:true"}],"tags":[],"type":"log_detection"}'
headers:
accept:
- application/json
content-type:
- application/json
method: POST
uri: https://api.datadoghq.com/api/v2/security_monitoring/rules
response:
body:
string: '{"name":"Test-Restore_a_rule_to_a_historical_version_returns_Conflict_response-1781258242","createdAt":1781258244898,"isDefault":false,"isPartner":false,"isEnabled":true,"isBeta":false,"isDeleted":false,"isDeprecated":false,"queries":[{"query":"@test:true","groupByFields":[],"hasOptionalGroupByFields":false,"distinctFields":[],"aggregation":"count","name":"","dataSource":"logs"}],"options":{"evaluationWindow":900,"detectionMethod":"threshold","maxSignalDuration":86400,"keepAlive":3600},"cases":[{"name":"","status":"info","notifications":[],"condition":"a
\u003e 0"}],"message":"Test rule","tags":[],"hasExtendedTitle":false,"type":"log_detection","filters":[],"version":1,"id":"xrz-jfq-dfm","blocking":false,"metadata":{"entities":null,"sources":null},"creationAuthorId":2320499,"creator":{"handle":"9919ec9b-ebc7-49ee-8dc8-03626e717cca","name":"CI
Account"},"updater":{"handle":"","name":""}}'
headers:
content-type:
- application/json
status:
code: 200
message: OK
- request:
body: '{"cases":[{"condition":"a > 0","name":"","notifications":[],"status":"info"}],"filters":[],"isEnabled":true,"message":"Test
rule updated","name":"Test-Restore_a_rule_to_a_historical_version_returns_Conflict_response-1781258242-updated","options":{"evaluationWindow":900,"keepAlive":3600,"maxSignalDuration":86400},"queries":[{"aggregation":"count","distinctFields":[],"groupByFields":[],"metrics":[],"query":"@test:true"}],"tags":[]}'
headers:
accept:
- application/json
content-type:
- application/json
method: PUT
uri: https://api.datadoghq.com/api/v2/security_monitoring/rules/xrz-jfq-dfm
response:
body:
string: '{"name":"Test-Restore_a_rule_to_a_historical_version_returns_Conflict_response-1781258242-updated","isEnabled":true,"queries":[{"query":"@test:true","groupByFields":[],"hasOptionalGroupByFields":false,"distinctFields":[],"aggregation":"count","name":"","dataSource":"logs"}],"options":{"evaluationWindow":900,"detectionMethod":"threshold","maxSignalDuration":86400,"keepAlive":3600},"cases":[{"name":"","status":"info","notifications":[],"condition":"a
\u003e 0"}],"message":"Test rule updated","tags":[],"hasExtendedTitle":false,"type":"log_detection","filters":[],"id":"xrz-jfq-dfm","version":2,"createdAt":1781258244898,"creationAuthorId":2320499,"updateAuthorId":2320499,"updatedAt":1781258245104,"isDefault":false,"blocking":false,"isBeta":false,"isDeleted":false,"isDeprecated":false,"metadata":{"entities":null,"sources":null}}'
headers:
content-type:
- application/json
status:
code: 200
message: OK
- request:
body: null
headers:
accept:
- application/json
method: POST
uri: https://api.datadoghq.com/api/v2/security_monitoring/rules/xrz-jfq-dfm/restore/2
response:
body:
string: '{"error":{"code":"AlreadyExists","message":"Cannot restore: target
version is the current version."}}'
headers:
content-type:
- application/json
status:
code: 409
message: Conflict
- request:
body: null
headers:
accept:
- '*/*'
method: DELETE
uri: https://api.datadoghq.com/api/v2/security_monitoring/rules/xrz-jfq-dfm
response:
body:
string: ''
headers: {}
status:
code: 204
message: No Content
version: 1
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
2026-06-12T08:39:41.348Z
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
interactions:
- request:
body: '{"cases":[{"condition":"a > 0","name":"","notifications":[],"status":"info"}],"filters":[],"isEnabled":true,"message":"Test
rule","name":"Test-Restore_a_rule_to_a_historical_version_returns_Not_Found_response-1781253581","options":{"evaluationWindow":900,"keepAlive":3600,"maxSignalDuration":86400},"queries":[{"aggregation":"count","distinctFields":[],"groupByFields":[],"metrics":[],"query":"@test:true"}],"tags":[],"type":"log_detection"}'
headers:
accept:
- application/json
content-type:
- application/json
method: POST
uri: https://api.datadoghq.com/api/v2/security_monitoring/rules
response:
body:
string: '{"name":"Test-Restore_a_rule_to_a_historical_version_returns_Not_Found_response-1781253581","createdAt":1781253581645,"isDefault":false,"isPartner":false,"isEnabled":true,"isBeta":false,"isDeleted":false,"isDeprecated":false,"queries":[{"query":"@test:true","groupByFields":[],"hasOptionalGroupByFields":false,"distinctFields":[],"aggregation":"count","name":"","dataSource":"logs"}],"options":{"evaluationWindow":900,"detectionMethod":"threshold","maxSignalDuration":86400,"keepAlive":3600},"cases":[{"name":"","status":"info","notifications":[],"condition":"a
\u003e 0"}],"message":"Test rule","tags":[],"hasExtendedTitle":false,"type":"log_detection","filters":[],"version":1,"id":"uig-ynq-xlh","blocking":false,"metadata":{"entities":null,"sources":null},"creationAuthorId":2320499,"creator":{"handle":"9919ec9b-ebc7-49ee-8dc8-03626e717cca","name":"CI
Account"},"updater":{"handle":"","name":""}}'
headers:
content-type:
- application/json
status:
code: 200
message: OK
- request:
body: null
headers:
accept:
- application/json
method: POST
uri: https://api.datadoghq.com/api/v2/security_monitoring/rules/uig-ynq-xlh/restore/9999
response:
body:
string: '{"error":{"code":"NotFound","message":"Threat detection rule not found:
uig-ynq-xlh, version=9999"}}'
headers:
content-type:
- application/json
status:
code: 404
message: Not Found
- request:
body: null
headers:
accept:
- '*/*'
method: DELETE
uri: https://api.datadoghq.com/api/v2/security_monitoring/rules/uig-ynq-xlh
response:
body:
string: ''
headers: {}
status:
code: 204
message: No Content
version: 1
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
2026-06-12T09:57:25.549Z
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
interactions:
- request:
body: '{"cases":[{"condition":"a > 0","name":"","notifications":[],"status":"info"}],"filters":[],"isEnabled":true,"message":"Test
rule","name":"Test-Restore_a_rule_to_a_historical_version_returns_OK_response-1781258245","options":{"evaluationWindow":900,"keepAlive":3600,"maxSignalDuration":86400},"queries":[{"aggregation":"count","distinctFields":[],"groupByFields":[],"metrics":[],"query":"@test:true"}],"tags":[],"type":"log_detection"}'
headers:
accept:
- application/json
content-type:
- application/json
method: POST
uri: https://api.datadoghq.com/api/v2/security_monitoring/rules
response:
body:
string: '{"name":"Test-Restore_a_rule_to_a_historical_version_returns_OK_response-1781258245","createdAt":1781258245670,"isDefault":false,"isPartner":false,"isEnabled":true,"isBeta":false,"isDeleted":false,"isDeprecated":false,"queries":[{"query":"@test:true","groupByFields":[],"hasOptionalGroupByFields":false,"distinctFields":[],"aggregation":"count","name":"","dataSource":"logs"}],"options":{"evaluationWindow":900,"detectionMethod":"threshold","maxSignalDuration":86400,"keepAlive":3600},"cases":[{"name":"","status":"info","notifications":[],"condition":"a
\u003e 0"}],"message":"Test rule","tags":[],"hasExtendedTitle":false,"type":"log_detection","filters":[],"version":1,"id":"7sm-pyl-xzv","blocking":false,"metadata":{"entities":null,"sources":null},"creationAuthorId":2320499,"creator":{"handle":"9919ec9b-ebc7-49ee-8dc8-03626e717cca","name":"CI
Account"},"updater":{"handle":"","name":""}}'
headers:
content-type:
- application/json
status:
code: 200
message: OK
- request:
body: '{"cases":[{"condition":"a > 0","name":"","notifications":[],"status":"info"}],"filters":[],"isEnabled":true,"message":"Test
rule updated","name":"Test-Restore_a_rule_to_a_historical_version_returns_OK_response-1781258245-updated","options":{"evaluationWindow":900,"keepAlive":3600,"maxSignalDuration":86400},"queries":[{"aggregation":"count","distinctFields":[],"groupByFields":[],"metrics":[],"query":"@test:true"}],"tags":[]}'
headers:
accept:
- application/json
content-type:
- application/json
method: PUT
uri: https://api.datadoghq.com/api/v2/security_monitoring/rules/7sm-pyl-xzv
response:
body:
string: '{"name":"Test-Restore_a_rule_to_a_historical_version_returns_OK_response-1781258245-updated","isEnabled":true,"queries":[{"query":"@test:true","groupByFields":[],"hasOptionalGroupByFields":false,"distinctFields":[],"aggregation":"count","name":"","dataSource":"logs"}],"options":{"evaluationWindow":900,"detectionMethod":"threshold","maxSignalDuration":86400,"keepAlive":3600},"cases":[{"name":"","status":"info","notifications":[],"condition":"a
\u003e 0"}],"message":"Test rule updated","tags":[],"hasExtendedTitle":false,"type":"log_detection","filters":[],"id":"7sm-pyl-xzv","version":2,"createdAt":1781258245670,"creationAuthorId":2320499,"updateAuthorId":2320499,"updatedAt":1781258245844,"isDefault":false,"blocking":false,"isBeta":false,"isDeleted":false,"isDeprecated":false,"metadata":{"entities":null,"sources":null}}'
headers:
content-type:
- application/json
status:
code: 200
message: OK
- request:
body: null
headers:
accept:
- application/json
method: POST
uri: https://api.datadoghq.com/api/v2/security_monitoring/rules/7sm-pyl-xzv/restore/1
response:
body:
string: '{"name":"Test-Restore_a_rule_to_a_historical_version_returns_OK_response-1781258245","createdAt":1781258245670,"isDefault":false,"isPartner":false,"isEnabled":true,"isBeta":false,"isDeleted":false,"isDeprecated":false,"queries":[{"query":"@test:true","groupByFields":[],"hasOptionalGroupByFields":false,"distinctFields":[],"aggregation":"count","name":"","dataSource":"logs"}],"options":{"evaluationWindow":900,"detectionMethod":"threshold","maxSignalDuration":86400,"keepAlive":3600},"cases":[{"name":"","status":"info","notifications":[],"condition":"a
\u003e 0"}],"message":"Test rule","tags":[],"hasExtendedTitle":false,"type":"log_detection","filters":[],"version":3,"id":"7sm-pyl-xzv","updatedAt":1781258246099,"blocking":false,"metadata":{"entities":null,"sources":null},"creationAuthorId":2320499,"updateAuthorId":2320499,"creator":{"handle":"9919ec9b-ebc7-49ee-8dc8-03626e717cca","name":"CI
Account"},"updater":{"handle":"9919ec9b-ebc7-49ee-8dc8-03626e717cca","name":"CI
Account"}}'
headers:
content-type:
- application/json
status:
code: 200
message: OK
- request:
body: null
headers:
accept:
- '*/*'
method: DELETE
uri: https://api.datadoghq.com/api/v2/security_monitoring/rules/7sm-pyl-xzv
response:
body:
string: ''
headers: {}
status:
code: 204
message: No Content
version: 1
Loading
Loading