diff --git a/.generated-info b/.generated-info index 0244d4f9274..fa72cc258d4 100644 --- a/.generated-info +++ b/.generated-info @@ -1,4 +1,4 @@ { - "spec_repo_commit": "06ccc32", - "generated": "2025-07-21 13:56:48.290" + "spec_repo_commit": "8ca2883", + "generated": "2025-07-22 07:16:27.623" } diff --git a/.generator/schemas/v2/openapi.yaml b/.generator/schemas/v2/openapi.yaml index 28f8b98b025..a4af6732fc7 100644 --- a/.generator/schemas/v2/openapi.yaml +++ b/.generator/schemas/v2/openapi.yaml @@ -34296,9 +34296,22 @@ components: format: int64 minimum: 0 type: integer + flaggedIPType: + $ref: '#/components/schemas/SecurityMonitoringRuleCaseActionOptionsFlaggedIPType' userBehaviorName: $ref: '#/components/schemas/SecurityMonitoringRuleCaseActionOptionsUserBehaviorName' type: object + SecurityMonitoringRuleCaseActionOptionsFlaggedIPType: + description: Used with the case action of type 'flag_ip'. The value specified + in this field is applied as a flag to the IP addresses. + enum: + - SUSPICIOUS + - FLAGGED + example: FLAGGED + type: string + x-enum-varnames: + - SUSPICIOUS + - FLAGGED SecurityMonitoringRuleCaseActionOptionsUserBehaviorName: description: Used with the case action of type 'user_behavior'. The value specified in this field is applied as a risk tag to all users affected by the rule. @@ -34309,11 +34322,13 @@ components: - block_ip - block_user - user_behavior + - flag_ip type: string x-enum-varnames: - BLOCK_IP - BLOCK_USER - USER_BEHAVIOR + - FLAG_IP SecurityMonitoringRuleCaseCreate: description: Case when signal is generated. properties: diff --git a/api/datadogV2/model_security_monitoring_rule_case_action_options.go b/api/datadogV2/model_security_monitoring_rule_case_action_options.go index 7d5cf27c7e4..782a3f8f10b 100644 --- a/api/datadogV2/model_security_monitoring_rule_case_action_options.go +++ b/api/datadogV2/model_security_monitoring_rule_case_action_options.go @@ -12,6 +12,8 @@ import ( type SecurityMonitoringRuleCaseActionOptions struct { // Duration of the action in seconds. 0 indicates no expiration. Duration *int64 `json:"duration,omitempty"` + // Used with the case action of type 'flag_ip'. The value specified in this field is applied as a flag to the IP addresses. + FlaggedIpType *SecurityMonitoringRuleCaseActionOptionsFlaggedIPType `json:"flaggedIPType,omitempty"` // Used with the case action of type 'user_behavior'. The value specified in this field is applied as a risk tag to all users affected by the rule. UserBehaviorName *string `json:"userBehaviorName,omitempty"` // UnparsedObject contains the raw value of the object if there was an error when deserializing into the struct @@ -64,6 +66,34 @@ func (o *SecurityMonitoringRuleCaseActionOptions) SetDuration(v int64) { o.Duration = &v } +// GetFlaggedIpType returns the FlaggedIpType field value if set, zero value otherwise. +func (o *SecurityMonitoringRuleCaseActionOptions) GetFlaggedIpType() SecurityMonitoringRuleCaseActionOptionsFlaggedIPType { + if o == nil || o.FlaggedIpType == nil { + var ret SecurityMonitoringRuleCaseActionOptionsFlaggedIPType + return ret + } + return *o.FlaggedIpType +} + +// GetFlaggedIpTypeOk returns a tuple with the FlaggedIpType field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *SecurityMonitoringRuleCaseActionOptions) GetFlaggedIpTypeOk() (*SecurityMonitoringRuleCaseActionOptionsFlaggedIPType, bool) { + if o == nil || o.FlaggedIpType == nil { + return nil, false + } + return o.FlaggedIpType, true +} + +// HasFlaggedIpType returns a boolean if a field has been set. +func (o *SecurityMonitoringRuleCaseActionOptions) HasFlaggedIpType() bool { + return o != nil && o.FlaggedIpType != nil +} + +// SetFlaggedIpType gets a reference to the given SecurityMonitoringRuleCaseActionOptionsFlaggedIPType and assigns it to the FlaggedIpType field. +func (o *SecurityMonitoringRuleCaseActionOptions) SetFlaggedIpType(v SecurityMonitoringRuleCaseActionOptionsFlaggedIPType) { + o.FlaggedIpType = &v +} + // GetUserBehaviorName returns the UserBehaviorName field value if set, zero value otherwise. func (o *SecurityMonitoringRuleCaseActionOptions) GetUserBehaviorName() string { if o == nil || o.UserBehaviorName == nil { @@ -101,6 +131,9 @@ func (o SecurityMonitoringRuleCaseActionOptions) MarshalJSON() ([]byte, error) { if o.Duration != nil { toSerialize["duration"] = o.Duration } + if o.FlaggedIpType != nil { + toSerialize["flaggedIPType"] = o.FlaggedIpType + } if o.UserBehaviorName != nil { toSerialize["userBehaviorName"] = o.UserBehaviorName } @@ -114,24 +147,36 @@ func (o SecurityMonitoringRuleCaseActionOptions) MarshalJSON() ([]byte, error) { // UnmarshalJSON deserializes the given payload. func (o *SecurityMonitoringRuleCaseActionOptions) UnmarshalJSON(bytes []byte) (err error) { all := struct { - Duration *int64 `json:"duration,omitempty"` - UserBehaviorName *string `json:"userBehaviorName,omitempty"` + Duration *int64 `json:"duration,omitempty"` + FlaggedIpType *SecurityMonitoringRuleCaseActionOptionsFlaggedIPType `json:"flaggedIPType,omitempty"` + UserBehaviorName *string `json:"userBehaviorName,omitempty"` }{} if err = datadog.Unmarshal(bytes, &all); err != nil { return datadog.Unmarshal(bytes, &o.UnparsedObject) } additionalProperties := make(map[string]interface{}) if err = datadog.Unmarshal(bytes, &additionalProperties); err == nil { - datadog.DeleteKeys(additionalProperties, &[]string{"duration", "userBehaviorName"}) + datadog.DeleteKeys(additionalProperties, &[]string{"duration", "flaggedIPType", "userBehaviorName"}) } else { return err } + + hasInvalidField := false o.Duration = all.Duration + if all.FlaggedIpType != nil && !all.FlaggedIpType.IsValid() { + hasInvalidField = true + } else { + o.FlaggedIpType = all.FlaggedIpType + } o.UserBehaviorName = all.UserBehaviorName if len(additionalProperties) > 0 { o.AdditionalProperties = additionalProperties } + if hasInvalidField { + return datadog.Unmarshal(bytes, &o.UnparsedObject) + } + return nil } diff --git a/api/datadogV2/model_security_monitoring_rule_case_action_options_flagged_ip_type.go b/api/datadogV2/model_security_monitoring_rule_case_action_options_flagged_ip_type.go new file mode 100644 index 00000000000..4a45fd4aeaa --- /dev/null +++ b/api/datadogV2/model_security_monitoring_rule_case_action_options_flagged_ip_type.go @@ -0,0 +1,66 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. + +package datadogV2 + +import ( + "fmt" + + "github.com/DataDog/datadog-api-client-go/v2/api/datadog" +) + +// SecurityMonitoringRuleCaseActionOptionsFlaggedIPType Used with the case action of type 'flag_ip'. The value specified in this field is applied as a flag to the IP addresses. +type SecurityMonitoringRuleCaseActionOptionsFlaggedIPType string + +// List of SecurityMonitoringRuleCaseActionOptionsFlaggedIPType. +const ( + SECURITYMONITORINGRULECASEACTIONOPTIONSFLAGGEDIPTYPE_SUSPICIOUS SecurityMonitoringRuleCaseActionOptionsFlaggedIPType = "SUSPICIOUS" + SECURITYMONITORINGRULECASEACTIONOPTIONSFLAGGEDIPTYPE_FLAGGED SecurityMonitoringRuleCaseActionOptionsFlaggedIPType = "FLAGGED" +) + +var allowedSecurityMonitoringRuleCaseActionOptionsFlaggedIPTypeEnumValues = []SecurityMonitoringRuleCaseActionOptionsFlaggedIPType{ + SECURITYMONITORINGRULECASEACTIONOPTIONSFLAGGEDIPTYPE_SUSPICIOUS, + SECURITYMONITORINGRULECASEACTIONOPTIONSFLAGGEDIPTYPE_FLAGGED, +} + +// GetAllowedValues reeturns the list of possible values. +func (v *SecurityMonitoringRuleCaseActionOptionsFlaggedIPType) GetAllowedValues() []SecurityMonitoringRuleCaseActionOptionsFlaggedIPType { + return allowedSecurityMonitoringRuleCaseActionOptionsFlaggedIPTypeEnumValues +} + +// UnmarshalJSON deserializes the given payload. +func (v *SecurityMonitoringRuleCaseActionOptionsFlaggedIPType) UnmarshalJSON(src []byte) error { + var value string + err := datadog.Unmarshal(src, &value) + if err != nil { + return err + } + *v = SecurityMonitoringRuleCaseActionOptionsFlaggedIPType(value) + return nil +} + +// NewSecurityMonitoringRuleCaseActionOptionsFlaggedIPTypeFromValue returns a pointer to a valid SecurityMonitoringRuleCaseActionOptionsFlaggedIPType +// for the value passed as argument, or an error if the value passed is not allowed by the enum. +func NewSecurityMonitoringRuleCaseActionOptionsFlaggedIPTypeFromValue(v string) (*SecurityMonitoringRuleCaseActionOptionsFlaggedIPType, error) { + ev := SecurityMonitoringRuleCaseActionOptionsFlaggedIPType(v) + if ev.IsValid() { + return &ev, nil + } + return nil, fmt.Errorf("invalid value '%v' for SecurityMonitoringRuleCaseActionOptionsFlaggedIPType: valid values are %v", v, allowedSecurityMonitoringRuleCaseActionOptionsFlaggedIPTypeEnumValues) +} + +// IsValid return true if the value is valid for the enum, false otherwise. +func (v SecurityMonitoringRuleCaseActionOptionsFlaggedIPType) IsValid() bool { + for _, existing := range allowedSecurityMonitoringRuleCaseActionOptionsFlaggedIPTypeEnumValues { + if existing == v { + return true + } + } + return false +} + +// Ptr returns reference to SecurityMonitoringRuleCaseActionOptionsFlaggedIPType value. +func (v SecurityMonitoringRuleCaseActionOptionsFlaggedIPType) Ptr() *SecurityMonitoringRuleCaseActionOptionsFlaggedIPType { + return &v +} diff --git a/api/datadogV2/model_security_monitoring_rule_case_action_type.go b/api/datadogV2/model_security_monitoring_rule_case_action_type.go index aa63fbe786b..6cd7c37894c 100644 --- a/api/datadogV2/model_security_monitoring_rule_case_action_type.go +++ b/api/datadogV2/model_security_monitoring_rule_case_action_type.go @@ -18,12 +18,14 @@ const ( SECURITYMONITORINGRULECASEACTIONTYPE_BLOCK_IP SecurityMonitoringRuleCaseActionType = "block_ip" SECURITYMONITORINGRULECASEACTIONTYPE_BLOCK_USER SecurityMonitoringRuleCaseActionType = "block_user" SECURITYMONITORINGRULECASEACTIONTYPE_USER_BEHAVIOR SecurityMonitoringRuleCaseActionType = "user_behavior" + SECURITYMONITORINGRULECASEACTIONTYPE_FLAG_IP SecurityMonitoringRuleCaseActionType = "flag_ip" ) var allowedSecurityMonitoringRuleCaseActionTypeEnumValues = []SecurityMonitoringRuleCaseActionType{ SECURITYMONITORINGRULECASEACTIONTYPE_BLOCK_IP, SECURITYMONITORINGRULECASEACTIONTYPE_BLOCK_USER, SECURITYMONITORINGRULECASEACTIONTYPE_USER_BEHAVIOR, + SECURITYMONITORINGRULECASEACTIONTYPE_FLAG_IP, } // GetAllowedValues reeturns the list of possible values. diff --git a/examples/v2/security-monitoring/CreateSecurityMonitoringRule_1965169892.go b/examples/v2/security-monitoring/CreateSecurityMonitoringRule_1965169892.go index b7650088e55..330217edc2e 100644 --- a/examples/v2/security-monitoring/CreateSecurityMonitoringRule_1965169892.go +++ b/examples/v2/security-monitoring/CreateSecurityMonitoringRule_1965169892.go @@ -48,6 +48,12 @@ func main() { UserBehaviorName: datadog.PtrString("behavior"), }, }, + { + Type: datadogV2.SECURITYMONITORINGRULECASEACTIONTYPE_FLAG_IP.Ptr(), + Options: &datadogV2.SecurityMonitoringRuleCaseActionOptions{ + FlaggedIpType: datadogV2.SECURITYMONITORINGRULECASEACTIONOPTIONSFLAGGEDIPTYPE_FLAGGED.Ptr(), + }, + }, }, }, }, diff --git a/tests/scenarios/cassettes/TestScenarios/v2/Feature_Security_Monitoring/Scenario_Create_a_detection_rule_with_type_application_security_returns_OK_response.freeze b/tests/scenarios/cassettes/TestScenarios/v2/Feature_Security_Monitoring/Scenario_Create_a_detection_rule_with_type_application_security_returns_OK_response.freeze index 3dfeb208e88..543b88fccf5 100644 --- a/tests/scenarios/cassettes/TestScenarios/v2/Feature_Security_Monitoring/Scenario_Create_a_detection_rule_with_type_application_security_returns_OK_response.freeze +++ b/tests/scenarios/cassettes/TestScenarios/v2/Feature_Security_Monitoring/Scenario_Create_a_detection_rule_with_type_application_security_returns_OK_response.freeze @@ -1 +1 @@ -2025-04-09T15:02:05.047Z \ No newline at end of file +2025-07-17T10:35:24.061Z \ No newline at end of file diff --git a/tests/scenarios/cassettes/TestScenarios/v2/Feature_Security_Monitoring/Scenario_Create_a_detection_rule_with_type_application_security_returns_OK_response.yaml b/tests/scenarios/cassettes/TestScenarios/v2/Feature_Security_Monitoring/Scenario_Create_a_detection_rule_with_type_application_security_returns_OK_response.yaml index 6fd9c053699..ae83882b34d 100644 --- a/tests/scenarios/cassettes/TestScenarios/v2/Feature_Security_Monitoring/Scenario_Create_a_detection_rule_with_type_application_security_returns_OK_response.yaml +++ b/tests/scenarios/cassettes/TestScenarios/v2/Feature_Security_Monitoring/Scenario_Create_a_detection_rule_with_type_application_security_returns_OK_response.yaml @@ -1,7 +1,7 @@ interactions: - request: body: | - {"cases":[{"actions":[{"options":{"duration":900},"type":"block_ip"},{"options":{"userBehaviorName":"behavior"},"type":"user_behavior"}],"condition":"a \u003e 100000","name":"","notifications":[],"status":"info"}],"filters":[],"groupSignalsBy":["service"],"isEnabled":true,"message":"Test rule","name":"Test-Create_a_detection_rule_with_type_application_security_returns_OK_response-1744210925_appsec_rule","options":{"detectionMethod":"threshold","evaluationWindow":900,"keepAlive":3600,"maxSignalDuration":86400},"queries":[{"aggregation":"count","distinctFields":[],"groupByFields":["service","@http.client_ip"],"query":"@appsec.security_activity:business_logic.users.login.failure"}],"tags":[],"type":"application_security"} + {"cases":[{"actions":[{"options":{"duration":900},"type":"block_ip"},{"options":{"userBehaviorName":"behavior"},"type":"user_behavior"},{"options":{"flaggedIPType":"FLAGGED"},"type":"flag_ip"}],"condition":"a \u003e 100000","name":"","notifications":[],"status":"info"}],"filters":[],"groupSignalsBy":["service"],"isEnabled":true,"message":"Test rule","name":"Test-Create_a_detection_rule_with_type_application_security_returns_OK_response-1752748524_appsec_rule","options":{"detectionMethod":"threshold","evaluationWindow":900,"keepAlive":3600,"maxSignalDuration":86400},"queries":[{"aggregation":"count","distinctFields":[],"groupByFields":["service","@http.client_ip"],"query":"@appsec.security_activity:business_logic.users.login.failure"}],"tags":[],"type":"application_security"} form: {} headers: Accept: @@ -12,9 +12,9 @@ interactions: method: POST url: https://api.datadoghq.com/api/v2/security_monitoring/rules response: - body: '{"name":"Test-Create_a_detection_rule_with_type_application_security_returns_OK_response-1744210925_appsec_rule","createdAt":1744210925675,"isDefault":false,"isPartner":false,"isEnabled":true,"isBeta":false,"isDeleted":false,"isDeprecated":false,"queries":[{"query":"@appsec.security_activity:business_logic.users.login.failure","groupByFields":["service","@http.client_ip"],"hasOptionalGroupByFields":false,"distinctFields":[],"aggregation":"count","name":"","dataSource":"app_sec_spans"}],"options":{"evaluationWindow":900,"detectionMethod":"threshold","maxSignalDuration":86400,"keepAlive":3600},"cases":[{"name":"","status":"info","notifications":[],"condition":"a - \u003e 100000","actions":[{"type":"block_ip","options":{"duration":900}},{"type":"user_behavior","options":{"userBehaviorName":"behavior"}}]}],"message":"Test - rule","tags":[],"hasExtendedTitle":false,"type":"application_security","filters":[],"version":1,"id":"lfr-zxg-fyc","blocking":true,"groupSignalsBy":["service"],"dependencies":["business_logic.users.login.failure"],"metadata":{"entities":null,"sources":null},"creationAuthorId":2320499,"creator":{"handle":"9919ec9b-ebc7-49ee-8dc8-03626e717cca","name":"CI + body: '{"name":"Test-Create_a_detection_rule_with_type_application_security_returns_OK_response-1752748524_appsec_rule","createdAt":1752748524806,"isDefault":false,"isPartner":false,"isEnabled":true,"isBeta":false,"isDeleted":false,"isDeprecated":false,"queries":[{"query":"@appsec.security_activity:business_logic.users.login.failure","groupByFields":["service","@http.client_ip"],"hasOptionalGroupByFields":false,"distinctFields":[],"aggregation":"count","name":"","dataSource":"app_sec_spans"}],"options":{"evaluationWindow":900,"detectionMethod":"threshold","maxSignalDuration":86400,"keepAlive":3600},"cases":[{"name":"","status":"info","notifications":[],"condition":"a + \u003e 100000","actions":[{"type":"block_ip","options":{"duration":900}},{"type":"user_behavior","options":{"userBehaviorName":"behavior"}},{"type":"flag_ip","options":{"flaggedIPType":"FLAGGED"}}]}],"message":"Test + rule","tags":[],"hasExtendedTitle":false,"type":"application_security","filters":[],"version":1,"id":"wgo-lgy-ajy","blocking":true,"groupSignalsBy":["service"],"dependencies":["business_logic.users.login.failure"],"metadata":{"entities":null,"sources":null},"creationAuthorId":2320499,"creator":{"handle":"9919ec9b-ebc7-49ee-8dc8-03626e717cca","name":"CI Account"},"updater":{"handle":"","name":""}}' code: 200 duration: 0ms @@ -30,7 +30,7 @@ interactions: - '*/*' id: 1 method: DELETE - url: https://api.datadoghq.com/api/v2/security_monitoring/rules/lfr-zxg-fyc + url: https://api.datadoghq.com/api/v2/security_monitoring/rules/wgo-lgy-ajy response: body: '' code: 204 diff --git a/tests/scenarios/features/v2/security_monitoring.feature b/tests/scenarios/features/v2/security_monitoring.feature index 1ec6ed14e58..28df5a06446 100644 --- a/tests/scenarios/features/v2/security_monitoring.feature +++ b/tests/scenarios/features/v2/security_monitoring.feature @@ -225,7 +225,7 @@ Feature: Security Monitoring @skip-validation @team:DataDog/k9-cloud-security-platform Scenario: Create a detection rule with type 'application_security 'returns "OK" response Given new "CreateSecurityMonitoringRule" request - And body with value {"type":"application_security","name":"{{unique}}_appsec_rule","queries":[{"query":"@appsec.security_activity:business_logic.users.login.failure","aggregation":"count","groupByFields":["service","@http.client_ip"],"distinctFields":[]}],"filters":[],"cases":[{"name":"","status":"info","notifications":[],"condition":"a > 100000","actions":[{"type":"block_ip","options":{"duration":900}}, {"type":"user_behavior","options":{"userBehaviorName":"behavior"}}]}],"options":{"keepAlive":3600,"maxSignalDuration":86400,"evaluationWindow":900,"detectionMethod":"threshold"},"isEnabled":true,"message":"Test rule","tags":[],"groupSignalsBy":["service"]} + And body with value {"type":"application_security","name":"{{unique}}_appsec_rule","queries":[{"query":"@appsec.security_activity:business_logic.users.login.failure","aggregation":"count","groupByFields":["service","@http.client_ip"],"distinctFields":[]}],"filters":[],"cases":[{"name":"","status":"info","notifications":[],"condition":"a > 100000","actions":[{"type":"block_ip","options":{"duration":900}}, {"type":"user_behavior","options":{"userBehaviorName":"behavior"}}, {"type":"flag_ip","options":{"flaggedIPType":"FLAGGED"}}]}],"options":{"keepAlive":3600,"maxSignalDuration":86400,"evaluationWindow":900,"detectionMethod":"threshold"},"isEnabled":true,"message":"Test rule","tags":[],"groupSignalsBy":["service"]} When the request is sent Then the response status is 200 OK And the response "name" is equal to "{{ unique }}_appsec_rule"