Skip to content

Commit e741108

Browse files
api-clients-generation-pipeline[bot]ci.datadog-api-spec
andauthored
Add sequence detection to security monitoring rules (#2789)
Co-authored-by: ci.datadog-api-spec <[email protected]>
1 parent 9867c6f commit e741108

File tree

14 files changed

+447
-0
lines changed

14 files changed

+447
-0
lines changed

.generator/schemas/v2/openapi.yaml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20470,6 +20470,8 @@ components:
2047020470
$ref: '#/components/schemas/SecurityMonitoringRuleMaxSignalDuration'
2047120471
newValueOptions:
2047220472
$ref: '#/components/schemas/SecurityMonitoringRuleNewValueOptions'
20473+
sequenceDetectionOptions:
20474+
$ref: '#/components/schemas/SecurityMonitoringRuleSequenceDetectionOptions'
2047320475
thirdPartyRuleOptions:
2047420476
$ref: '#/components/schemas/SecurityMonitoringRuleThirdPartyOptions'
2047520477
type: object
@@ -40786,6 +40788,7 @@ components:
4078640788
- hardcoded
4078740789
- third_party
4078840790
- anomaly_threshold
40791+
- sequence_detection
4078940792
type: string
4079040793
x-enum-varnames:
4079140794
- THRESHOLD
@@ -40795,6 +40798,7 @@ components:
4079540798
- HARDCODED
4079640799
- THIRD_PARTY
4079740800
- ANOMALY_THRESHOLD
40801+
- SEQUENCE_DETECTION
4079840802
SecurityMonitoringRuleEvaluationWindow:
4079940803
description: 'A time window is specified to match when at least one of the cases
4080040804
matches true. This is a sliding window
@@ -41008,6 +41012,8 @@ components:
4100841012
$ref: '#/components/schemas/SecurityMonitoringRuleMaxSignalDuration'
4100941013
newValueOptions:
4101041014
$ref: '#/components/schemas/SecurityMonitoringRuleNewValueOptions'
41015+
sequenceDetectionOptions:
41016+
$ref: '#/components/schemas/SecurityMonitoringRuleSequenceDetectionOptions'
4101141017
thirdPartyRuleOptions:
4101241018
$ref: '#/components/schemas/SecurityMonitoringRuleThirdPartyOptions'
4101341019
type: object
@@ -41083,6 +41089,47 @@ components:
4108341089
oneOf:
4108441090
- $ref: '#/components/schemas/SecurityMonitoringStandardRuleResponse'
4108541091
- $ref: '#/components/schemas/SecurityMonitoringSignalRuleResponse'
41092+
SecurityMonitoringRuleSequenceDetectionOptions:
41093+
description: Options on sequence detection method.
41094+
properties:
41095+
stepTransitions:
41096+
description: Transitions defining the allowed order of steps and their evaluation
41097+
windows.
41098+
items:
41099+
$ref: '#/components/schemas/SecurityMonitoringRuleSequenceDetectionStepTransition'
41100+
type: array
41101+
steps:
41102+
description: Steps that define the conditions to be matched in sequence.
41103+
items:
41104+
$ref: '#/components/schemas/SecurityMonitoringRuleSequenceDetectionStep'
41105+
type: array
41106+
type: object
41107+
SecurityMonitoringRuleSequenceDetectionStep:
41108+
description: Step definition for sequence detection containing the step name,
41109+
condition, and evaluation window.
41110+
properties:
41111+
condition:
41112+
description: Condition referencing rule queries (e.g., `a > 0`).
41113+
type: string
41114+
evaluationWindow:
41115+
$ref: '#/components/schemas/SecurityMonitoringRuleEvaluationWindow'
41116+
name:
41117+
description: Unique name identifying the step.
41118+
type: string
41119+
type: object
41120+
SecurityMonitoringRuleSequenceDetectionStepTransition:
41121+
description: Transition from a parent step to a child step within a sequence
41122+
detection rule.
41123+
properties:
41124+
child:
41125+
description: Name of the child step.
41126+
type: string
41127+
evaluationWindow:
41128+
$ref: '#/components/schemas/SecurityMonitoringRuleEvaluationWindow'
41129+
parent:
41130+
description: Name of the parent step.
41131+
type: string
41132+
type: object
4108641133
SecurityMonitoringRuleSeverity:
4108741134
description: Severity of the Security Signal.
4108841135
enum:
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"2025-09-12T15:45:55.719Z"
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
{
2+
"log": {
3+
"_recordingName": "Security Monitoring/Create a detection rule with detection method 'sequence_detection' returns \"OK\" response",
4+
"creator": {
5+
"comment": "persister:fs",
6+
"name": "Polly.JS",
7+
"version": "6.0.5"
8+
},
9+
"entries": [
10+
{
11+
"_id": "faa8ed427532bf09665284cdbb2daf9c",
12+
"_order": 0,
13+
"cache": {},
14+
"request": {
15+
"bodySize": 1000,
16+
"cookies": [],
17+
"headers": [
18+
{
19+
"_fromType": "array",
20+
"name": "accept",
21+
"value": "application/json"
22+
},
23+
{
24+
"_fromType": "array",
25+
"name": "content-type",
26+
"value": "application/json"
27+
}
28+
],
29+
"headersSize": 589,
30+
"httpVersion": "HTTP/1.1",
31+
"method": "POST",
32+
"postData": {
33+
"mimeType": "application/json",
34+
"params": [],
35+
"text": "{\"cases\":[{\"condition\":\"step_b > 0\",\"name\":\"\",\"notifications\":[],\"status\":\"info\"}],\"isEnabled\":true,\"message\":\"Logs and signals asdf\",\"name\":\"Test-Create_a_detection_rule_with_detection_method_sequence_detection_returns_OK_response-1757691955\",\"options\":{\"detectionMethod\":\"sequence_detection\",\"evaluationWindow\":0,\"keepAlive\":300,\"maxSignalDuration\":600,\"sequenceDetectionOptions\":{\"stepTransitions\":[{\"child\":\"step_b\",\"evaluationWindow\":900,\"parent\":\"step_a\"}],\"steps\":[{\"condition\":\"a > 0\",\"evaluationWindow\":60,\"name\":\"step_a\"},{\"condition\":\"b > 0\",\"evaluationWindow\":60,\"name\":\"step_b\"}]}},\"queries\":[{\"aggregation\":\"count\",\"dataSource\":\"logs\",\"distinctFields\":[],\"groupByFields\":[],\"hasOptionalGroupByFields\":false,\"name\":\"\",\"query\":\"service:logs-rule-reducer source:paul test2\"},{\"aggregation\":\"count\",\"dataSource\":\"logs\",\"distinctFields\":[],\"groupByFields\":[],\"hasOptionalGroupByFields\":false,\"name\":\"\",\"query\":\"service:logs-rule-reducer source:paul test1\"}],\"tags\":[],\"type\":\"log_detection\"}"
36+
},
37+
"queryString": [],
38+
"url": "https://api.datadoghq.com/api/v2/security_monitoring/rules"
39+
},
40+
"response": {
41+
"bodySize": 1378,
42+
"content": {
43+
"mimeType": "application/json",
44+
"size": 1378,
45+
"text": "{\"name\":\"Test-Create_a_detection_rule_with_detection_method_sequence_detection_returns_OK_response-1757691955\",\"createdAt\":1757691955862,\"isDefault\":false,\"isPartner\":false,\"isEnabled\":true,\"isBeta\":false,\"isDeleted\":false,\"isDeprecated\":false,\"queries\":[{\"query\":\"service:logs-rule-reducer source:paul test2\",\"groupByFields\":[],\"hasOptionalGroupByFields\":false,\"distinctFields\":[],\"aggregation\":\"count\",\"name\":\"\",\"dataSource\":\"logs\"},{\"query\":\"service:logs-rule-reducer source:paul test1\",\"groupByFields\":[],\"hasOptionalGroupByFields\":false,\"distinctFields\":[],\"aggregation\":\"count\",\"name\":\"\",\"dataSource\":\"logs\"}],\"options\":{\"evaluationWindow\":0,\"detectionMethod\":\"sequence_detection\",\"maxSignalDuration\":600,\"keepAlive\":300,\"sequenceDetectionOptions\":{\"steps\":[{\"name\":\"step_a\",\"condition\":\"a \\u003e 0\",\"evaluationWindow\":60},{\"name\":\"step_b\",\"condition\":\"b \\u003e 0\",\"evaluationWindow\":60}],\"stepTransitions\":[{\"parent\":\"step_a\",\"child\":\"step_b\",\"evaluationWindow\":900}]}},\"cases\":[{\"name\":\"\",\"status\":\"info\",\"notifications\":[],\"condition\":\"step_b \\u003e 0\"}],\"message\":\"Logs and signals asdf\",\"tags\":[],\"hasExtendedTitle\":false,\"type\":\"log_detection\",\"filters\":[],\"version\":1,\"id\":\"k0l-txb-xxx\",\"blocking\":false,\"metadata\":{\"entities\":null,\"sources\":null},\"creationAuthorId\":1445416,\"creator\":{\"handle\":\"[email protected]\",\"name\":\"frog\"},\"updater\":{\"handle\":\"\",\"name\":\"\"}}"
46+
},
47+
"cookies": [],
48+
"headers": [
49+
{
50+
"name": "content-type",
51+
"value": "application/json"
52+
}
53+
],
54+
"headersSize": 655,
55+
"httpVersion": "HTTP/1.1",
56+
"redirectURL": "",
57+
"status": 200,
58+
"statusText": "OK"
59+
},
60+
"startedDateTime": "2025-09-12T15:45:55.723Z",
61+
"time": 207
62+
},
63+
{
64+
"_id": "d7239dc51220cdcb7c3c9788a4feafa5",
65+
"_order": 0,
66+
"cache": {},
67+
"request": {
68+
"bodySize": 0,
69+
"cookies": [],
70+
"headers": [
71+
{
72+
"_fromType": "array",
73+
"name": "accept",
74+
"value": "*/*"
75+
}
76+
],
77+
"headersSize": 536,
78+
"httpVersion": "HTTP/1.1",
79+
"method": "DELETE",
80+
"queryString": [],
81+
"url": "https://api.datadoghq.com/api/v2/security_monitoring/rules/k0l-txb-xxx"
82+
},
83+
"response": {
84+
"bodySize": 0,
85+
"content": {
86+
"mimeType": "text/plain",
87+
"size": 0
88+
},
89+
"cookies": [],
90+
"headers": [],
91+
"headersSize": 601,
92+
"httpVersion": "HTTP/1.1",
93+
"redirectURL": "",
94+
"status": 204,
95+
"statusText": "No Content"
96+
},
97+
"startedDateTime": "2025-09-12T15:45:55.938Z",
98+
"time": 232
99+
}
100+
],
101+
"pages": [],
102+
"version": "1.2"
103+
}
104+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"2025-09-12T15:43:48.016Z"
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
{
2+
"log": {
3+
"_recordingName": "Security Monitoring/Validate a detection rule with detection method 'sequence_detection' returns \"OK\" response",
4+
"creator": {
5+
"comment": "persister:fs",
6+
"name": "Polly.JS",
7+
"version": "6.0.5"
8+
},
9+
"entries": [
10+
{
11+
"_id": "7c3af95d617e9512f01309e2f2ec4f07",
12+
"_order": 0,
13+
"cache": {},
14+
"request": {
15+
"bodySize": 856,
16+
"cookies": [],
17+
"headers": [
18+
{
19+
"_fromType": "array",
20+
"name": "accept",
21+
"value": "*/*"
22+
},
23+
{
24+
"_fromType": "array",
25+
"name": "content-type",
26+
"value": "application/json"
27+
}
28+
],
29+
"headersSize": 588,
30+
"httpVersion": "HTTP/1.1",
31+
"method": "POST",
32+
"postData": {
33+
"mimeType": "application/json",
34+
"params": [],
35+
"text": "{\"cases\":[{\"condition\":\"step_b > 0\",\"name\":\"\",\"notifications\":[],\"status\":\"info\"}],\"hasExtendedTitle\":true,\"isEnabled\":true,\"message\":\"My security monitoring rule\",\"name\":\"My security monitoring rule\",\"options\":{\"detectionMethod\":\"sequence_detection\",\"evaluationWindow\":0,\"keepAlive\":300,\"maxSignalDuration\":600,\"sequenceDetectionOptions\":{\"stepTransitions\":[{\"child\":\"step_b\",\"evaluationWindow\":900,\"parent\":\"step_a\"}],\"steps\":[{\"condition\":\"a > 0\",\"evaluationWindow\":60,\"name\":\"step_a\"},{\"condition\":\"b > 0\",\"evaluationWindow\":60,\"name\":\"step_b\"}]}},\"queries\":[{\"aggregation\":\"count\",\"distinctFields\":[],\"groupByFields\":[\"@userIdentity.assumed_role\"],\"name\":\"\",\"query\":\"source:source_here\"},{\"aggregation\":\"count\",\"distinctFields\":[],\"groupByFields\":[],\"name\":\"\",\"query\":\"source:source_here2\"}],\"tags\":[\"env:prod\",\"team:security\"],\"type\":\"log_detection\"}"
36+
},
37+
"queryString": [],
38+
"url": "https://api.datadoghq.com/api/v2/security_monitoring/rules/validation"
39+
},
40+
"response": {
41+
"bodySize": 0,
42+
"content": {
43+
"mimeType": "text/plain",
44+
"size": 0
45+
},
46+
"cookies": [],
47+
"headers": [],
48+
"headersSize": 601,
49+
"httpVersion": "HTTP/1.1",
50+
"redirectURL": "",
51+
"status": 204,
52+
"statusText": "No Content"
53+
},
54+
"startedDateTime": "2025-09-12T15:43:48.019Z",
55+
"time": 114
56+
}
57+
],
58+
"pages": [],
59+
"version": "1.2"
60+
}
61+
}

features/v2/security_monitoring.feature

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,16 @@ Feature: Security Monitoring
211211
And the response "message" is equal to "Test rule"
212212
And the response "referenceTables" is equal to [{"tableName": "synthetics_test_reference_table_dont_delete", "columnName": "value", "logFieldPath":"testtag", "checkPresence":true, "ruleQueryName":"a"}]
213213

214+
@team:DataDog/k9-cloud-security-platform
215+
Scenario: Create a detection rule with detection method 'sequence_detection' returns "OK" response
216+
Given new "CreateSecurityMonitoringRule" request
217+
And body with value {"name":"{{ unique }}","type":"log_detection","isEnabled":true,"queries":[{"aggregation":"count","dataSource":"logs","distinctFields":[],"groupByFields":[],"hasOptionalGroupByFields":false,"name":"","query":"service:logs-rule-reducer source:paul test2"},{"aggregation":"count","dataSource":"logs","distinctFields":[],"groupByFields":[],"hasOptionalGroupByFields":false,"name":"","query":"service:logs-rule-reducer source:paul test1"}],"cases":[{"name":"","status":"info","notifications":[],"condition":"step_b > 0"}],"message":"Logs and signals asdf","options":{"detectionMethod":"sequence_detection","evaluationWindow":0,"keepAlive":300,"maxSignalDuration":600,"sequenceDetectionOptions":{"stepTransitions":[{"child":"step_b","evaluationWindow":900,"parent":"step_a"}],"steps":[{"condition":"a > 0","evaluationWindow":60,"name":"step_a"},{"condition":"b > 0","evaluationWindow":60,"name":"step_b"}]}},"tags":[]}
218+
When the request is sent
219+
Then the response status is 200 OK
220+
And the response "name" is equal to "{{ unique }}"
221+
And the response "type" is equal to "log_detection"
222+
And the response "options.detectionMethod" is equal to "sequence_detection"
223+
214224
@team:DataDog/k9-cloud-security-platform
215225
Scenario: Create a detection rule with detection method 'third_party' returns "OK" response
216226
Given new "CreateSecurityMonitoringRule" request
@@ -1483,6 +1493,13 @@ Feature: Security Monitoring
14831493
When the request is sent
14841494
Then the response status is 204 OK
14851495

1496+
@team:DataDog/k9-cloud-security-platform
1497+
Scenario: Validate a detection rule with detection method 'sequence_detection' returns "OK" response
1498+
Given new "ValidateSecurityMonitoringRule" request
1499+
And body with value {"cases":[{"name":"","status":"info","notifications":[],"condition":"step_b > 0"}],"hasExtendedTitle":true,"isEnabled":true,"message":"My security monitoring rule","name":"My security monitoring rule","options":{"evaluationWindow":0,"keepAlive":300,"maxSignalDuration":600,"detectionMethod":"sequence_detection","sequenceDetectionOptions":{"stepTransitions":[{"child":"step_b","evaluationWindow":900,"parent":"step_a"}],"steps":[{"condition":"a > 0","evaluationWindow":60,"name":"step_a"},{"condition":"b > 0","evaluationWindow":60,"name":"step_b"}]}},"queries":[{"query":"source:source_here","groupByFields":["@userIdentity.assumed_role"],"distinctFields":[],"aggregation":"count","name":""},{"query":"source:source_here2","groupByFields":[],"distinctFields":[],"aggregation":"count","name":""}],"tags":["env:prod","team:security"],"type":"log_detection"}
1500+
When the request is sent
1501+
Then the response status is 204 OK
1502+
14861503
@team:DataDog/k9-cloud-security-platform
14871504
Scenario: Validate a suppression rule returns "Bad Request" response
14881505
Given new "ValidateSecurityMonitoringSuppression" request

services/security_monitoring/src/v2/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,9 @@ export { SecurityMonitoringRuleQueryAggregation } from "./models/SecurityMonitor
239239
export { SecurityMonitoringRuleQueryPayload } from "./models/SecurityMonitoringRuleQueryPayload";
240240
export { SecurityMonitoringRuleQueryPayloadData } from "./models/SecurityMonitoringRuleQueryPayloadData";
241241
export { SecurityMonitoringRuleResponse } from "./models/SecurityMonitoringRuleResponse";
242+
export { SecurityMonitoringRuleSequenceDetectionOptions } from "./models/SecurityMonitoringRuleSequenceDetectionOptions";
243+
export { SecurityMonitoringRuleSequenceDetectionStep } from "./models/SecurityMonitoringRuleSequenceDetectionStep";
244+
export { SecurityMonitoringRuleSequenceDetectionStepTransition } from "./models/SecurityMonitoringRuleSequenceDetectionStepTransition";
242245
export { SecurityMonitoringRuleSeverity } from "./models/SecurityMonitoringRuleSeverity";
243246
export { SecurityMonitoringRuleTestPayload } from "./models/SecurityMonitoringRuleTestPayload";
244247
export { SecurityMonitoringRuleTestRequest } from "./models/SecurityMonitoringRuleTestRequest";

services/security_monitoring/src/v2/models/HistoricalJobOptions.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { SecurityMonitoringRuleImpossibleTravelOptions } from "./SecurityMonitor
66
import { SecurityMonitoringRuleKeepAlive } from "./SecurityMonitoringRuleKeepAlive";
77
import { SecurityMonitoringRuleMaxSignalDuration } from "./SecurityMonitoringRuleMaxSignalDuration";
88
import { SecurityMonitoringRuleNewValueOptions } from "./SecurityMonitoringRuleNewValueOptions";
9+
import { SecurityMonitoringRuleSequenceDetectionOptions } from "./SecurityMonitoringRuleSequenceDetectionOptions";
910
import { SecurityMonitoringRuleThirdPartyOptions } from "./SecurityMonitoringRuleThirdPartyOptions";
1011

1112
/**
@@ -39,6 +40,10 @@ export class HistoricalJobOptions {
3940
* Options on new value detection method.
4041
*/
4142
"newValueOptions"?: SecurityMonitoringRuleNewValueOptions;
43+
/**
44+
* Options on sequence detection method.
45+
*/
46+
"sequenceDetectionOptions"?: SecurityMonitoringRuleSequenceDetectionOptions;
4247
/**
4348
* Options on third party detection method.
4449
*/
@@ -85,6 +90,10 @@ export class HistoricalJobOptions {
8590
baseName: "newValueOptions",
8691
type: "SecurityMonitoringRuleNewValueOptions",
8792
},
93+
sequenceDetectionOptions: {
94+
baseName: "sequenceDetectionOptions",
95+
type: "SecurityMonitoringRuleSequenceDetectionOptions",
96+
},
8897
thirdPartyRuleOptions: {
8998
baseName: "thirdPartyRuleOptions",
9099
type: "SecurityMonitoringRuleThirdPartyOptions",

services/security_monitoring/src/v2/models/SecurityMonitoringRuleDetectionMethod.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export type SecurityMonitoringRuleDetectionMethod =
1111
| typeof HARDCODED
1212
| typeof THIRD_PARTY
1313
| typeof ANOMALY_THRESHOLD
14+
| typeof SEQUENCE_DETECTION
1415
| UnparsedObject;
1516
export const THRESHOLD = "threshold";
1617
export const NEW_VALUE = "new_value";
@@ -19,3 +20,4 @@ export const IMPOSSIBLE_TRAVEL = "impossible_travel";
1920
export const HARDCODED = "hardcoded";
2021
export const THIRD_PARTY = "third_party";
2122
export const ANOMALY_THRESHOLD = "anomaly_threshold";
23+
export const SEQUENCE_DETECTION = "sequence_detection";

services/security_monitoring/src/v2/models/SecurityMonitoringRuleOptions.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { SecurityMonitoringRuleImpossibleTravelOptions } from "./SecurityMonitor
88
import { SecurityMonitoringRuleKeepAlive } from "./SecurityMonitoringRuleKeepAlive";
99
import { SecurityMonitoringRuleMaxSignalDuration } from "./SecurityMonitoringRuleMaxSignalDuration";
1010
import { SecurityMonitoringRuleNewValueOptions } from "./SecurityMonitoringRuleNewValueOptions";
11+
import { SecurityMonitoringRuleSequenceDetectionOptions } from "./SecurityMonitoringRuleSequenceDetectionOptions";
1112
import { SecurityMonitoringRuleThirdPartyOptions } from "./SecurityMonitoringRuleThirdPartyOptions";
1213

1314
/**
@@ -56,6 +57,10 @@ export class SecurityMonitoringRuleOptions {
5657
* Options on new value detection method.
5758
*/
5859
"newValueOptions"?: SecurityMonitoringRuleNewValueOptions;
60+
/**
61+
* Options on sequence detection method.
62+
*/
63+
"sequenceDetectionOptions"?: SecurityMonitoringRuleSequenceDetectionOptions;
5964
/**
6065
* Options on third party detection method.
6166
*/
@@ -114,6 +119,10 @@ export class SecurityMonitoringRuleOptions {
114119
baseName: "newValueOptions",
115120
type: "SecurityMonitoringRuleNewValueOptions",
116121
},
122+
sequenceDetectionOptions: {
123+
baseName: "sequenceDetectionOptions",
124+
type: "SecurityMonitoringRuleSequenceDetectionOptions",
125+
},
117126
thirdPartyRuleOptions: {
118127
baseName: "thirdPartyRuleOptions",
119128
type: "SecurityMonitoringRuleThirdPartyOptions",

0 commit comments

Comments
 (0)