Skip to content
Merged
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
47 changes: 47 additions & 0 deletions .generator/schemas/v2/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20470,6 +20470,8 @@ components:
$ref: '#/components/schemas/SecurityMonitoringRuleMaxSignalDuration'
newValueOptions:
$ref: '#/components/schemas/SecurityMonitoringRuleNewValueOptions'
sequenceDetectionOptions:
$ref: '#/components/schemas/SecurityMonitoringRuleSequenceDetectionOptions'
thirdPartyRuleOptions:
$ref: '#/components/schemas/SecurityMonitoringRuleThirdPartyOptions'
type: object
Expand Down Expand Up @@ -40786,6 +40788,7 @@ components:
- hardcoded
- third_party
- anomaly_threshold
- sequence_detection
type: string
x-enum-varnames:
- THRESHOLD
Expand All @@ -40795,6 +40798,7 @@ components:
- HARDCODED
- THIRD_PARTY
- ANOMALY_THRESHOLD
- SEQUENCE_DETECTION
SecurityMonitoringRuleEvaluationWindow:
description: 'A time window is specified to match when at least one of the cases
matches true. This is a sliding window
Expand Down Expand Up @@ -41008,6 +41012,8 @@ components:
$ref: '#/components/schemas/SecurityMonitoringRuleMaxSignalDuration'
newValueOptions:
$ref: '#/components/schemas/SecurityMonitoringRuleNewValueOptions'
sequenceDetectionOptions:
$ref: '#/components/schemas/SecurityMonitoringRuleSequenceDetectionOptions'
thirdPartyRuleOptions:
$ref: '#/components/schemas/SecurityMonitoringRuleThirdPartyOptions'
type: object
Expand Down Expand Up @@ -41083,6 +41089,47 @@ components:
oneOf:
- $ref: '#/components/schemas/SecurityMonitoringStandardRuleResponse'
- $ref: '#/components/schemas/SecurityMonitoringSignalRuleResponse'
SecurityMonitoringRuleSequenceDetectionOptions:
description: Options on sequence detection method.
properties:
stepTransitions:
description: Transitions defining the allowed order of steps and their evaluation
windows.
items:
$ref: '#/components/schemas/SecurityMonitoringRuleSequenceDetectionStepTransition'
type: array
steps:
description: Steps that define the conditions to be matched in sequence.
items:
$ref: '#/components/schemas/SecurityMonitoringRuleSequenceDetectionStep'
type: array
type: object
SecurityMonitoringRuleSequenceDetectionStep:
description: Step definition for sequence detection containing the step name,
condition, and evaluation window.
properties:
condition:
description: Condition referencing rule queries (e.g., `a > 0`).
type: string
evaluationWindow:
$ref: '#/components/schemas/SecurityMonitoringRuleEvaluationWindow'
name:
description: Unique name identifying the step.
type: string
type: object
SecurityMonitoringRuleSequenceDetectionStepTransition:
description: Transition from a parent step to a child step within a sequence
detection rule.
properties:
child:
description: Name of the child step.
type: string
evaluationWindow:
$ref: '#/components/schemas/SecurityMonitoringRuleEvaluationWindow'
parent:
description: Name of the parent step.
type: string
type: object
SecurityMonitoringRuleSeverity:
description: Severity of the Security Signal.
enum:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"2025-09-12T15:45:55.719Z"
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
{
"log": {
"_recordingName": "Security Monitoring/Create a detection rule with detection method 'sequence_detection' returns \"OK\" response",
"creator": {
"comment": "persister:fs",
"name": "Polly.JS",
"version": "6.0.5"
},
"entries": [
{
"_id": "faa8ed427532bf09665284cdbb2daf9c",
"_order": 0,
"cache": {},
"request": {
"bodySize": 1000,
"cookies": [],
"headers": [
{
"_fromType": "array",
"name": "accept",
"value": "application/json"
},
{
"_fromType": "array",
"name": "content-type",
"value": "application/json"
}
],
"headersSize": 589,
"httpVersion": "HTTP/1.1",
"method": "POST",
"postData": {
"mimeType": "application/json",
"params": [],
"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\"}"
},
"queryString": [],
"url": "https://api.datadoghq.com/api/v2/security_monitoring/rules"
},
"response": {
"bodySize": 1378,
"content": {
"mimeType": "application/json",
"size": 1378,
"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\":\"frog@datadoghq.com\",\"name\":\"frog\"},\"updater\":{\"handle\":\"\",\"name\":\"\"}}"
},
"cookies": [],
"headers": [
{
"name": "content-type",
"value": "application/json"
}
],
"headersSize": 655,
"httpVersion": "HTTP/1.1",
"redirectURL": "",
"status": 200,
"statusText": "OK"
},
"startedDateTime": "2025-09-12T15:45:55.723Z",
"time": 207
},
{
"_id": "d7239dc51220cdcb7c3c9788a4feafa5",
"_order": 0,
"cache": {},
"request": {
"bodySize": 0,
"cookies": [],
"headers": [
{
"_fromType": "array",
"name": "accept",
"value": "*/*"
}
],
"headersSize": 536,
"httpVersion": "HTTP/1.1",
"method": "DELETE",
"queryString": [],
"url": "https://api.datadoghq.com/api/v2/security_monitoring/rules/k0l-txb-xxx"
},
"response": {
"bodySize": 0,
"content": {
"mimeType": "text/plain",
"size": 0
},
"cookies": [],
"headers": [],
"headersSize": 601,
"httpVersion": "HTTP/1.1",
"redirectURL": "",
"status": 204,
"statusText": "No Content"
},
"startedDateTime": "2025-09-12T15:45:55.938Z",
"time": 232
}
],
"pages": [],
"version": "1.2"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"2025-09-12T15:43:48.016Z"
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
{
"log": {
"_recordingName": "Security Monitoring/Validate a detection rule with detection method 'sequence_detection' returns \"OK\" response",
"creator": {
"comment": "persister:fs",
"name": "Polly.JS",
"version": "6.0.5"
},
"entries": [
{
"_id": "7c3af95d617e9512f01309e2f2ec4f07",
"_order": 0,
"cache": {},
"request": {
"bodySize": 856,
"cookies": [],
"headers": [
{
"_fromType": "array",
"name": "accept",
"value": "*/*"
},
{
"_fromType": "array",
"name": "content-type",
"value": "application/json"
}
],
"headersSize": 588,
"httpVersion": "HTTP/1.1",
"method": "POST",
"postData": {
"mimeType": "application/json",
"params": [],
"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\"}"
},
"queryString": [],
"url": "https://api.datadoghq.com/api/v2/security_monitoring/rules/validation"
},
"response": {
"bodySize": 0,
"content": {
"mimeType": "text/plain",
"size": 0
},
"cookies": [],
"headers": [],
"headersSize": 601,
"httpVersion": "HTTP/1.1",
"redirectURL": "",
"status": 204,
"statusText": "No Content"
},
"startedDateTime": "2025-09-12T15:43:48.019Z",
"time": 114
}
],
"pages": [],
"version": "1.2"
}
}
17 changes: 17 additions & 0 deletions features/v2/security_monitoring.feature
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,16 @@ Feature: Security Monitoring
And the response "message" is equal to "Test rule"
And the response "referenceTables" is equal to [{"tableName": "synthetics_test_reference_table_dont_delete", "columnName": "value", "logFieldPath":"testtag", "checkPresence":true, "ruleQueryName":"a"}]

@team:DataDog/k9-cloud-security-platform
Scenario: Create a detection rule with detection method 'sequence_detection' returns "OK" response
Given new "CreateSecurityMonitoringRule" request
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":[]}
When the request is sent
Then the response status is 200 OK
And the response "name" is equal to "{{ unique }}"
And the response "type" is equal to "log_detection"
And the response "options.detectionMethod" is equal to "sequence_detection"

@team:DataDog/k9-cloud-security-platform
Scenario: Create a detection rule with detection method 'third_party' returns "OK" response
Given new "CreateSecurityMonitoringRule" request
Expand Down Expand Up @@ -1483,6 +1493,13 @@ Feature: Security Monitoring
When the request is sent
Then the response status is 204 OK

@team:DataDog/k9-cloud-security-platform
Scenario: Validate a detection rule with detection method 'sequence_detection' returns "OK" response
Given new "ValidateSecurityMonitoringRule" request
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"}
When the request is sent
Then the response status is 204 OK

@team:DataDog/k9-cloud-security-platform
Scenario: Validate a suppression rule returns "Bad Request" response
Given new "ValidateSecurityMonitoringSuppression" request
Expand Down
3 changes: 3 additions & 0 deletions services/security_monitoring/src/v2/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,9 @@ export { SecurityMonitoringRuleQueryAggregation } from "./models/SecurityMonitor
export { SecurityMonitoringRuleQueryPayload } from "./models/SecurityMonitoringRuleQueryPayload";
export { SecurityMonitoringRuleQueryPayloadData } from "./models/SecurityMonitoringRuleQueryPayloadData";
export { SecurityMonitoringRuleResponse } from "./models/SecurityMonitoringRuleResponse";
export { SecurityMonitoringRuleSequenceDetectionOptions } from "./models/SecurityMonitoringRuleSequenceDetectionOptions";
export { SecurityMonitoringRuleSequenceDetectionStep } from "./models/SecurityMonitoringRuleSequenceDetectionStep";
export { SecurityMonitoringRuleSequenceDetectionStepTransition } from "./models/SecurityMonitoringRuleSequenceDetectionStepTransition";
export { SecurityMonitoringRuleSeverity } from "./models/SecurityMonitoringRuleSeverity";
export { SecurityMonitoringRuleTestPayload } from "./models/SecurityMonitoringRuleTestPayload";
export { SecurityMonitoringRuleTestRequest } from "./models/SecurityMonitoringRuleTestRequest";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { SecurityMonitoringRuleImpossibleTravelOptions } from "./SecurityMonitor
import { SecurityMonitoringRuleKeepAlive } from "./SecurityMonitoringRuleKeepAlive";
import { SecurityMonitoringRuleMaxSignalDuration } from "./SecurityMonitoringRuleMaxSignalDuration";
import { SecurityMonitoringRuleNewValueOptions } from "./SecurityMonitoringRuleNewValueOptions";
import { SecurityMonitoringRuleSequenceDetectionOptions } from "./SecurityMonitoringRuleSequenceDetectionOptions";
import { SecurityMonitoringRuleThirdPartyOptions } from "./SecurityMonitoringRuleThirdPartyOptions";

/**
Expand Down Expand Up @@ -39,6 +40,10 @@ export class HistoricalJobOptions {
* Options on new value detection method.
*/
"newValueOptions"?: SecurityMonitoringRuleNewValueOptions;
/**
* Options on sequence detection method.
*/
"sequenceDetectionOptions"?: SecurityMonitoringRuleSequenceDetectionOptions;
/**
* Options on third party detection method.
*/
Expand Down Expand Up @@ -85,6 +90,10 @@ export class HistoricalJobOptions {
baseName: "newValueOptions",
type: "SecurityMonitoringRuleNewValueOptions",
},
sequenceDetectionOptions: {
baseName: "sequenceDetectionOptions",
type: "SecurityMonitoringRuleSequenceDetectionOptions",
},
thirdPartyRuleOptions: {
baseName: "thirdPartyRuleOptions",
type: "SecurityMonitoringRuleThirdPartyOptions",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export type SecurityMonitoringRuleDetectionMethod =
| typeof HARDCODED
| typeof THIRD_PARTY
| typeof ANOMALY_THRESHOLD
| typeof SEQUENCE_DETECTION
| UnparsedObject;
export const THRESHOLD = "threshold";
export const NEW_VALUE = "new_value";
Expand All @@ -19,3 +20,4 @@ export const IMPOSSIBLE_TRAVEL = "impossible_travel";
export const HARDCODED = "hardcoded";
export const THIRD_PARTY = "third_party";
export const ANOMALY_THRESHOLD = "anomaly_threshold";
export const SEQUENCE_DETECTION = "sequence_detection";
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { SecurityMonitoringRuleImpossibleTravelOptions } from "./SecurityMonitor
import { SecurityMonitoringRuleKeepAlive } from "./SecurityMonitoringRuleKeepAlive";
import { SecurityMonitoringRuleMaxSignalDuration } from "./SecurityMonitoringRuleMaxSignalDuration";
import { SecurityMonitoringRuleNewValueOptions } from "./SecurityMonitoringRuleNewValueOptions";
import { SecurityMonitoringRuleSequenceDetectionOptions } from "./SecurityMonitoringRuleSequenceDetectionOptions";
import { SecurityMonitoringRuleThirdPartyOptions } from "./SecurityMonitoringRuleThirdPartyOptions";

/**
Expand Down Expand Up @@ -56,6 +57,10 @@ export class SecurityMonitoringRuleOptions {
* Options on new value detection method.
*/
"newValueOptions"?: SecurityMonitoringRuleNewValueOptions;
/**
* Options on sequence detection method.
*/
"sequenceDetectionOptions"?: SecurityMonitoringRuleSequenceDetectionOptions;
/**
* Options on third party detection method.
*/
Expand Down Expand Up @@ -114,6 +119,10 @@ export class SecurityMonitoringRuleOptions {
baseName: "newValueOptions",
type: "SecurityMonitoringRuleNewValueOptions",
},
sequenceDetectionOptions: {
baseName: "sequenceDetectionOptions",
type: "SecurityMonitoringRuleSequenceDetectionOptions",
},
thirdPartyRuleOptions: {
baseName: "thirdPartyRuleOptions",
type: "SecurityMonitoringRuleThirdPartyOptions",
Expand Down
Loading