Skip to content

Commit ca4fe82

Browse files
committed
Use custom duration type
1 parent ca37831 commit ca4fe82

File tree

6 files changed

+205
-132
lines changed

6 files changed

+205
-132
lines changed

internal/kibana/security_detection_rule/acc_test.go

Lines changed: 19 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,7 @@ func TestAccResourceSecurityDetectionRule_Query(t *testing.T) {
134134
resource.TestCheckResourceAttr(resourceName, "alert_suppression.group_by.#", "2"),
135135
resource.TestCheckResourceAttr(resourceName, "alert_suppression.group_by.0", "user.name"),
136136
resource.TestCheckResourceAttr(resourceName, "alert_suppression.group_by.1", "host.name"),
137-
resource.TestCheckResourceAttr(resourceName, "alert_suppression.duration.value", "5"),
138-
resource.TestCheckResourceAttr(resourceName, "alert_suppression.duration.unit", "m"),
137+
resource.TestCheckResourceAttr(resourceName, "alert_suppression.duration", "5m"),
139138
resource.TestCheckResourceAttr(resourceName, "alert_suppression.missing_fields_strategy", "suppress"),
140139

141140
// Verify building_block_type is not set by default
@@ -399,8 +398,7 @@ func TestAccResourceSecurityDetectionRule_EQL(t *testing.T) {
399398
resource.TestCheckResourceAttr(resourceName, "alert_suppression.group_by.#", "2"),
400399
resource.TestCheckResourceAttr(resourceName, "alert_suppression.group_by.0", "process.parent.name"),
401400
resource.TestCheckResourceAttr(resourceName, "alert_suppression.group_by.1", "host.name"),
402-
resource.TestCheckResourceAttr(resourceName, "alert_suppression.duration.value", "45"),
403-
resource.TestCheckResourceAttr(resourceName, "alert_suppression.duration.unit", "m"),
401+
resource.TestCheckResourceAttr(resourceName, "alert_suppression.duration", "45m"),
404402
resource.TestCheckResourceAttr(resourceName, "alert_suppression.missing_fields_strategy", "doNotSuppress"),
405403
),
406404
},
@@ -485,8 +483,7 @@ func TestAccResourceSecurityDetectionRule_ESQL(t *testing.T) {
485483
resource.TestCheckResourceAttr(resourceName, "alert_suppression.group_by.#", "2"),
486484
resource.TestCheckResourceAttr(resourceName, "alert_suppression.group_by.0", "user.name"),
487485
resource.TestCheckResourceAttr(resourceName, "alert_suppression.group_by.1", "user.domain"),
488-
resource.TestCheckResourceAttr(resourceName, "alert_suppression.duration.value", "15"),
489-
resource.TestCheckResourceAttr(resourceName, "alert_suppression.duration.unit", "m"),
486+
resource.TestCheckResourceAttr(resourceName, "alert_suppression.duration", "15m"),
490487
resource.TestCheckResourceAttr(resourceName, "alert_suppression.missing_fields_strategy", "doNotSuppress"),
491488

492489
resource.TestCheckResourceAttrSet(resourceName, "id"),
@@ -639,8 +636,7 @@ func TestAccResourceSecurityDetectionRule_MachineLearning(t *testing.T) {
639636
// Check alert suppression
640637
resource.TestCheckResourceAttr(resourceName, "alert_suppression.group_by.#", "1"),
641638
resource.TestCheckResourceAttr(resourceName, "alert_suppression.group_by.0", "ml.job_id"),
642-
resource.TestCheckResourceAttr(resourceName, "alert_suppression.duration.value", "30"),
643-
resource.TestCheckResourceAttr(resourceName, "alert_suppression.duration.unit", "m"),
639+
resource.TestCheckResourceAttr(resourceName, "alert_suppression.duration", "30m"),
644640
resource.TestCheckResourceAttr(resourceName, "alert_suppression.missing_fields_strategy", "suppress"),
645641

646642
resource.TestCheckResourceAttrSet(resourceName, "id"),
@@ -812,8 +808,7 @@ func TestAccResourceSecurityDetectionRule_NewTerms(t *testing.T) {
812808
resource.TestCheckResourceAttr(resourceName, "alert_suppression.group_by.#", "2"),
813809
resource.TestCheckResourceAttr(resourceName, "alert_suppression.group_by.0", "user.name"),
814810
resource.TestCheckResourceAttr(resourceName, "alert_suppression.group_by.1", "user.type"),
815-
resource.TestCheckResourceAttr(resourceName, "alert_suppression.duration.value", "20"),
816-
resource.TestCheckResourceAttr(resourceName, "alert_suppression.duration.unit", "m"),
811+
resource.TestCheckResourceAttr(resourceName, "alert_suppression.duration", "20m"),
817812
resource.TestCheckResourceAttr(resourceName, "alert_suppression.missing_fields_strategy", "doNotSuppress"),
818813

819814
resource.TestCheckResourceAttrSet(resourceName, "id"),
@@ -960,8 +955,7 @@ func TestAccResourceSecurityDetectionRule_SavedQuery(t *testing.T) {
960955
resource.TestCheckResourceAttr(resourceName, "alert_suppression.group_by.#", "2"),
961956
resource.TestCheckResourceAttr(resourceName, "alert_suppression.group_by.0", "event.category"),
962957
resource.TestCheckResourceAttr(resourceName, "alert_suppression.group_by.1", "event.action"),
963-
resource.TestCheckResourceAttr(resourceName, "alert_suppression.duration.value", "8"),
964-
resource.TestCheckResourceAttr(resourceName, "alert_suppression.duration.unit", "h"),
958+
resource.TestCheckResourceAttr(resourceName, "alert_suppression.duration", "8h"),
965959
resource.TestCheckResourceAttr(resourceName, "alert_suppression.missing_fields_strategy", "suppress"),
966960

967961
resource.TestCheckResourceAttrSet(resourceName, "id"),
@@ -1142,8 +1136,7 @@ func TestAccResourceSecurityDetectionRule_ThreatMatch(t *testing.T) {
11421136
resource.TestCheckResourceAttr(resourceName, "alert_suppression.group_by.#", "2"),
11431137
resource.TestCheckResourceAttr(resourceName, "alert_suppression.group_by.0", "destination.ip"),
11441138
resource.TestCheckResourceAttr(resourceName, "alert_suppression.group_by.1", "source.ip"),
1145-
resource.TestCheckResourceAttr(resourceName, "alert_suppression.duration.value", "1"),
1146-
resource.TestCheckResourceAttr(resourceName, "alert_suppression.duration.unit", "h"),
1139+
resource.TestCheckResourceAttr(resourceName, "alert_suppression.duration", "1h"),
11471140
resource.TestCheckResourceAttr(resourceName, "alert_suppression.missing_fields_strategy", "doNotSuppress"),
11481141

11491142
resource.TestCheckResourceAttrSet(resourceName, "id"),
@@ -1314,8 +1307,7 @@ func TestAccResourceSecurityDetectionRule_Threshold(t *testing.T) {
13141307
resource.TestCheckResourceAttr(resourceName, "response_actions.0.params.ecs_mapping.event.outcome", "outcome"),
13151308

13161309
// Check alert suppression (threshold rules only support duration)
1317-
resource.TestCheckResourceAttr(resourceName, "alert_suppression.duration.value", "30"),
1318-
resource.TestCheckResourceAttr(resourceName, "alert_suppression.duration.unit", "m"),
1310+
resource.TestCheckResourceAttr(resourceName, "alert_suppression.duration", "30m"),
13191311

13201312
resource.TestCheckResourceAttrSet(resourceName, "id"),
13211313
resource.TestCheckResourceAttrSet(resourceName, "rule_id"),
@@ -1400,8 +1392,7 @@ func TestAccResourceSecurityDetectionRule_Threshold(t *testing.T) {
14001392
resource.TestCheckResourceAttr(resourceName, "response_actions.1.params.comment", "Isolate host due to multiple failed login attempts"),
14011393

14021394
// Check updated alert suppression (threshold rules only support duration)
1403-
resource.TestCheckResourceAttr(resourceName, "alert_suppression.duration.value", "45"),
1404-
resource.TestCheckResourceAttr(resourceName, "alert_suppression.duration.unit", "h"),
1395+
resource.TestCheckResourceAttr(resourceName, "alert_suppression.duration", "45h"),
14051396
),
14061397
},
14071398
},
@@ -1568,10 +1559,7 @@ resource "elasticstack_kibana_security_detection_rule" "test" {
15681559
15691560
alert_suppression = {
15701561
group_by = ["user.name", "host.name"]
1571-
duration = {
1572-
value = 5
1573-
unit = "m"
1574-
}
1562+
duration = "5m"
15751563
missing_fields_strategy = "suppress"
15761564
}
15771565
@@ -1837,10 +1825,7 @@ resource "elasticstack_kibana_security_detection_rule" "test" {
18371825
18381826
alert_suppression = {
18391827
group_by = ["process.name", "user.name"]
1840-
duration = {
1841-
value = 10
1842-
unit = "m"
1843-
}
1828+
duration = "10m"
18441829
missing_fields_strategy = "suppress"
18451830
}
18461831
@@ -1945,10 +1930,7 @@ resource "elasticstack_kibana_security_detection_rule" "test" {
19451930
19461931
alert_suppression = {
19471932
group_by = ["process.parent.name", "host.name"]
1948-
duration = {
1949-
value = 45
1950-
unit = "m"
1951-
}
1933+
duration = "45m"
19521934
missing_fields_strategy = "doNotSuppress"
19531935
}
19541936
@@ -2039,10 +2021,7 @@ resource "elasticstack_kibana_security_detection_rule" "test" {
20392021
20402022
alert_suppression = {
20412023
group_by = ["user.name", "user.domain"]
2042-
duration = {
2043-
value = 15
2044-
unit = "m"
2045-
}
2024+
duration = "15m"
20462025
missing_fields_strategy = "doNotSuppress"
20472026
}
20482027
@@ -2238,10 +2217,7 @@ resource "elasticstack_kibana_security_detection_rule" "test" {
22382217
22392218
alert_suppression = {
22402219
group_by = ["ml.job_id"]
2241-
duration = {
2242-
value = 30
2243-
unit = "m"
2244-
}
2220+
duration = "30m"
22452221
missing_fields_strategy = "suppress"
22462222
}
22472223
@@ -2469,10 +2445,7 @@ resource "elasticstack_kibana_security_detection_rule" "test" {
24692445
24702446
alert_suppression = {
24712447
group_by = ["user.name", "user.type"]
2472-
duration = {
2473-
value = 20
2474-
unit = "m"
2475-
}
2448+
duration = "20m"
24762449
missing_fields_strategy = "doNotSuppress"
24772450
}
24782451
@@ -2695,10 +2668,7 @@ resource "elasticstack_kibana_security_detection_rule" "test" {
26952668
26962669
alert_suppression = {
26972670
group_by = ["event.category", "event.action"]
2698-
duration = {
2699-
value = 8
2700-
unit = "h"
2701-
}
2671+
duration = "8h"
27022672
missing_fields_strategy = "suppress"
27032673
}
27042674
@@ -2942,10 +2912,7 @@ resource "elasticstack_kibana_security_detection_rule" "test" {
29422912
29432913
alert_suppression = {
29442914
group_by = ["destination.ip", "source.ip"]
2945-
duration = {
2946-
value = 1
2947-
unit = "h"
2948-
}
2915+
duration = "1h"
29492916
missing_fields_strategy = "doNotSuppress"
29502917
}
29512918
@@ -3204,10 +3171,7 @@ resource "elasticstack_kibana_security_detection_rule" "test" {
32043171
]
32053172
32063173
alert_suppression = {
3207-
duration = {
3208-
value = 30
3209-
unit = "m"
3210-
}
3174+
duration = "30m"
32113175
}
32123176
32133177
response_actions = [
@@ -3328,10 +3292,7 @@ resource "elasticstack_kibana_security_detection_rule" "test" {
33283292
]
33293293
33303294
alert_suppression = {
3331-
duration = {
3332-
value = 45
3333-
unit = "h"
3334-
}
3295+
duration = "45h"
33353296
}
33363297
33373298
response_actions = [

internal/kibana/security_detection_rule/models.go

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"github.com/elastic/terraform-provider-elasticstack/generated/kbapi"
77
"github.com/elastic/terraform-provider-elasticstack/internal/clients"
88
"github.com/elastic/terraform-provider-elasticstack/internal/utils"
9+
"github.com/elastic/terraform-provider-elasticstack/internal/utils/customtypes"
910
"github.com/hashicorp/go-version"
1011
"github.com/hashicorp/terraform-plugin-framework-jsontypes/jsontypes"
1112
"github.com/hashicorp/terraform-plugin-framework/diag"
@@ -148,14 +149,9 @@ type ThresholdModel struct {
148149
}
149150

150151
type AlertSuppressionModel struct {
151-
GroupBy types.List `tfsdk:"group_by"`
152-
Duration types.Object `tfsdk:"duration"`
153-
MissingFieldsStrategy types.String `tfsdk:"missing_fields_strategy"`
154-
}
155-
156-
type AlertSuppressionDurationModel struct {
157-
Value types.Int64 `tfsdk:"value"`
158-
Unit types.String `tfsdk:"unit"`
152+
GroupBy types.List `tfsdk:"group_by"`
153+
Duration customtypes.Duration `tfsdk:"duration"`
154+
MissingFieldsStrategy types.String `tfsdk:"missing_fields_strategy"`
159155
}
160156

161157
type CardinalityModel struct {

internal/kibana/security_detection_rule/models_from_api_type_utils.go

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ import (
44
"context"
55
"encoding/json"
66
"fmt"
7+
"strconv"
78

89
"github.com/elastic/terraform-provider-elasticstack/generated/kbapi"
910
"github.com/elastic/terraform-provider-elasticstack/internal/utils"
11+
"github.com/elastic/terraform-provider-elasticstack/internal/utils/customtypes"
1012
"github.com/hashicorp/terraform-plugin-framework-jsontypes/jsontypes"
1113
"github.com/hashicorp/terraform-plugin-framework/attr"
1214
"github.com/hashicorp/terraform-plugin-framework/diag"
@@ -897,15 +899,9 @@ func (d *SecurityDetectionRuleData) updateAlertSuppressionFromApi(ctx context.Co
897899

898900
// Convert duration (optional)
899901
if apiSuppression.Duration != nil {
900-
durationModel := AlertSuppressionDurationModel{
901-
Value: types.Int64Value(int64(apiSuppression.Duration.Value)),
902-
Unit: types.StringValue(string(apiSuppression.Duration.Unit)),
903-
}
904-
durationObj, durationDiags := types.ObjectValueFrom(ctx, getDurationType(), durationModel)
905-
diags.Append(durationDiags...)
906-
model.Duration = durationObj
902+
model.Duration = parseDurationFromApi(*apiSuppression.Duration)
907903
} else {
908-
model.Duration = types.ObjectNull(getDurationType())
904+
model.Duration = customtypes.NewDurationNull()
909905
}
910906

911907
// Convert missing_fields_strategy (optional)
@@ -938,13 +934,7 @@ func (d *SecurityDetectionRuleData) updateThresholdAlertSuppressionFromApi(ctx c
938934
model.MissingFieldsStrategy = types.StringNull()
939935

940936
// Convert duration (always present in threshold alert suppression)
941-
durationModel := AlertSuppressionDurationModel{
942-
Value: types.Int64Value(int64(apiSuppression.Duration.Value)),
943-
Unit: types.StringValue(string(apiSuppression.Duration.Unit)),
944-
}
945-
durationObj, durationDiags := types.ObjectValueFrom(ctx, getDurationType(), durationModel)
946-
diags.Append(durationDiags...)
947-
model.Duration = durationObj
937+
model.Duration = parseDurationFromApi(apiSuppression.Duration)
948938

949939
alertSuppressionObj, objDiags := types.ObjectValueFrom(ctx, getAlertSuppressionType(), model)
950940
diags.Append(objDiags...)
@@ -1018,3 +1008,10 @@ func (d *SecurityDetectionRuleData) updateRequiredFieldsFromApi(ctx context.Cont
10181008

10191009
return diags
10201010
}
1011+
1012+
// parseDurationFromApi converts an API duration to customtypes.Duration
1013+
func parseDurationFromApi(apiDuration kbapi.SecurityDetectionsAPIAlertSuppressionDuration) customtypes.Duration {
1014+
// Convert the API's Value + Unit format back to a duration string
1015+
durationStr := strconv.Itoa(apiDuration.Value) + string(apiDuration.Unit)
1016+
return customtypes.NewDurationValue(durationStr)
1017+
}

0 commit comments

Comments
 (0)