From fc3493151cc1ed221a86b6a759c429d46d6948b4 Mon Sep 17 00:00:00 2001 From: ziyeqf Date: Mon, 30 Jan 2023 15:59:37 +0800 Subject: [PATCH 1/3] `azurerm_sentinel_alert_rule_nrt`, `azurerm_sentinel_alert_rule_scheduled`: support `dynamic_properties` --- .../services/sentinel/sentinel_alert_rule.go | 51 +++++++++++++++++++ .../sentinel_alert_rule_nrt_resource.go | 35 +++++++++++++ .../sentinel_alert_rule_nrt_resource_test.go | 4 ++ .../sentinel_alert_rule_scheduled_resource.go | 35 +++++++++++++ ...inel_alert_rule_scheduled_resource_test.go | 4 ++ .../r/sentinel_alert_rule_nrt.html.markdown | 10 ++++ ...entinel_alert_rule_scheduled.html.markdown | 10 ++++ 7 files changed, 149 insertions(+) diff --git a/internal/services/sentinel/sentinel_alert_rule.go b/internal/services/sentinel/sentinel_alert_rule.go index 272ba444b19b..cf76e825162d 100644 --- a/internal/services/sentinel/sentinel_alert_rule.go +++ b/internal/services/sentinel/sentinel_alert_rule.go @@ -11,6 +11,14 @@ import ( securityinsight "github.com/tombuildsstuff/kermit/sdk/securityinsights/2022-10-01-preview/securityinsights" ) +type AlertRuleDynamicPropertiesValue string + +const ( + AlertRuleDynamicPropertiesValueCaller AlertRuleDynamicPropertiesValue = "Caller" + AlertRuleDynamicPropertiesValueDcountResourceId AlertRuleDynamicPropertiesValue = "dcount_ResourceId" + AlertRuleDynamicPropertiesValueEventSubmissionTimestamp AlertRuleDynamicPropertiesValue = "EventSubmissionTimestamp" +) + func alertRuleID(rule securityinsight.BasicAlertRule) *string { if rule == nil { return nil @@ -268,6 +276,9 @@ func expandAlertRuleAlertDetailsOverride(input []interface{}) *securityinsight.A if v := b["tactics_column_name"]; v != "" { output.AlertTacticsColumnName = utils.String(v.(string)) } + if v := b["dynamic_properties"]; v != nil && len(v.([]interface{})) > 0 { + output.AlertDynamicProperties = expandAlertRuleAlertDynamicProperties(v.([]interface{})) + } return output } @@ -297,16 +308,56 @@ func flattenAlertRuleAlertDetailsOverride(input *securityinsight.AlertDetailsOve tacticsColumnName = *input.AlertTacticsColumnName } + var dynamicProperties []interface{} + if input.AlertDynamicProperties != nil { + dynamicProperties = flattenAlertRuleAlertDynamicProperties(input.AlertDynamicProperties) + } + return []interface{}{ map[string]interface{}{ "description_format": descriptionFormat, "display_name_format": displayNameFormat, "severity_column_name": severityColumnName, "tactics_column_name": tacticsColumnName, + "dynamic_properties": dynamicProperties, }, } } +func expandAlertRuleAlertDynamicProperties(input []interface{}) *[]securityinsight.AlertPropertyMapping { + if len(input) == 0 || input[0] == nil { + return nil + } + + var output []securityinsight.AlertPropertyMapping + + for _, v := range input { + b := v.(map[string]interface{}) + output = append(output, securityinsight.AlertPropertyMapping{ + AlertProperty: securityinsight.AlertProperty(b["name"].(string)), + Value: utils.String(b["value"].(string)), + }) + } + + return &output +} + +func flattenAlertRuleAlertDynamicProperties(input *[]securityinsight.AlertPropertyMapping) []interface{} { + output := make([]interface{}, 0) + if input == nil || len(*input) == 0 { + return output + } + + for _, i := range *input { + output = append(output, map[string]interface{}{ + "name": string(i.AlertProperty), + "value": i.Value, + }) + } + + return output +} + func expandAlertRuleEntityMapping(input []interface{}) *[]securityinsight.EntityMapping { if len(input) == 0 { return nil diff --git a/internal/services/sentinel/sentinel_alert_rule_nrt_resource.go b/internal/services/sentinel/sentinel_alert_rule_nrt_resource.go index eeeeb9a60498..1122ad841e59 100644 --- a/internal/services/sentinel/sentinel_alert_rule_nrt_resource.go +++ b/internal/services/sentinel/sentinel_alert_rule_nrt_resource.go @@ -6,6 +6,7 @@ import ( "time" "github.com/hashicorp/go-azure-sdk/resource-manager/operationalinsights/2020-08-01/workspaces" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-provider-azurerm/helpers/tf" "github.com/hashicorp/terraform-provider-azurerm/helpers/validate" "github.com/hashicorp/terraform-provider-azurerm/internal/clients" @@ -267,6 +268,40 @@ func resourceSentinelAlertRuleNrt() *pluginsdk.Resource { Optional: true, ValidateFunc: validation.StringIsNotEmpty, }, + "dynamic_properties": { + Type: pluginsdk.TypeList, + Optional: true, + Elem: &pluginsdk.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice( + []string{ + string(securityinsight.AlertPropertyAlertLink), + string(securityinsight.AlertPropertyConfidenceLevel), + string(securityinsight.AlertPropertyConfidenceScore), + string(securityinsight.AlertPropertyExtendedLinks), + string(securityinsight.AlertPropertyProductComponentName), + string(securityinsight.AlertPropertyProductName), + string(securityinsight.AlertPropertyProviderName), + string(securityinsight.AlertPropertyRemediationSteps), + string(securityinsight.AlertPropertyTechniques), + }, false), + }, + "value": { + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice( + []string{ + string(AlertRuleDynamicPropertiesValueCaller), + string(AlertRuleDynamicPropertiesValueDcountResourceId), + string(AlertRuleDynamicPropertiesValueEventSubmissionTimestamp), + }, false), + }, + }, + }, + }, }, }, }, diff --git a/internal/services/sentinel/sentinel_alert_rule_nrt_resource_test.go b/internal/services/sentinel/sentinel_alert_rule_nrt_resource_test.go index e3d3244d7b7e..75ca8fb2cb7a 100644 --- a/internal/services/sentinel/sentinel_alert_rule_nrt_resource_test.go +++ b/internal/services/sentinel/sentinel_alert_rule_nrt_resource_test.go @@ -176,6 +176,10 @@ resource "azurerm_sentinel_alert_rule_nrt" "test" { display_name_format = "Suspicious activity was made by {{ComputerIP}}" severity_column_name = "Computer" tactics_column_name = "Computer" + dynamic_properties { + name = "AlertLink" + value = "dcount_ResourceId" + } } entity_mapping { entity_type = "Host" diff --git a/internal/services/sentinel/sentinel_alert_rule_scheduled_resource.go b/internal/services/sentinel/sentinel_alert_rule_scheduled_resource.go index 18a0fdea0977..313ae600d25b 100644 --- a/internal/services/sentinel/sentinel_alert_rule_scheduled_resource.go +++ b/internal/services/sentinel/sentinel_alert_rule_scheduled_resource.go @@ -6,6 +6,7 @@ import ( "time" "github.com/hashicorp/go-azure-sdk/resource-manager/operationalinsights/2020-08-01/workspaces" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-provider-azurerm/helpers/tf" "github.com/hashicorp/terraform-provider-azurerm/helpers/validate" "github.com/hashicorp/terraform-provider-azurerm/internal/clients" @@ -328,6 +329,40 @@ func resourceSentinelAlertRuleScheduled() *pluginsdk.Resource { Optional: true, ValidateFunc: validation.StringIsNotEmpty, }, + "dynamic_properties": { + Type: pluginsdk.TypeList, + Optional: true, + Elem: &pluginsdk.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice( + []string{ + string(securityinsight.AlertPropertyAlertLink), + string(securityinsight.AlertPropertyConfidenceLevel), + string(securityinsight.AlertPropertyConfidenceScore), + string(securityinsight.AlertPropertyExtendedLinks), + string(securityinsight.AlertPropertyProductComponentName), + string(securityinsight.AlertPropertyProductName), + string(securityinsight.AlertPropertyProviderName), + string(securityinsight.AlertPropertyRemediationSteps), + string(securityinsight.AlertPropertyTechniques), + }, false), + }, + "value": { + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice( + []string{ + string(AlertRuleDynamicPropertiesValueCaller), + string(AlertRuleDynamicPropertiesValueDcountResourceId), + string(AlertRuleDynamicPropertiesValueEventSubmissionTimestamp), + }, false), + }, + }, + }, + }, }, }, }, diff --git a/internal/services/sentinel/sentinel_alert_rule_scheduled_resource_test.go b/internal/services/sentinel/sentinel_alert_rule_scheduled_resource_test.go index 1305e632ae97..0a10daf119dc 100644 --- a/internal/services/sentinel/sentinel_alert_rule_scheduled_resource_test.go +++ b/internal/services/sentinel/sentinel_alert_rule_scheduled_resource_test.go @@ -202,6 +202,10 @@ resource "azurerm_sentinel_alert_rule_scheduled" "test" { display_name_format = "Suspicious activity was made by {{ComputerIP}}" severity_column_name = "Computer" tactics_column_name = "Computer" + dynamic_properties { + name = "AlertLink" + value = "dcount_ResourceId" + } } entity_mapping { entity_type = "Host" diff --git a/website/docs/r/sentinel_alert_rule_nrt.html.markdown b/website/docs/r/sentinel_alert_rule_nrt.html.markdown index 4779e5b9015e..799f8c958662 100644 --- a/website/docs/r/sentinel_alert_rule_nrt.html.markdown +++ b/website/docs/r/sentinel_alert_rule_nrt.html.markdown @@ -108,6 +108,16 @@ An `alert_details_override` block supports the following: * `tactics_column_name` - (Optional) The column name to take the alert tactics from. +* `dynamic_properties` - (Optional) A list of `dynamic_property` blocks as defined below. + +--- + +A `dynamic_properties` block supports the following: + +* `name` - (Required) The name of the dynamic property. Possible Values are `AlertLink`, `ConfidenceLevel`, `ConfidenceScore`, `ExtendedLinks`, `ProductComponentName`, `ProductName`, `ProviderName`, `RemediationSteps` and `Techniques`. + +* `value` - (Required) The value of the dynamic property. Pssible Values are `Caller`, `dcount_ResourceId` and `EventSubmissionTimestamp`. + --- An `entity_mapping` block supports the following: diff --git a/website/docs/r/sentinel_alert_rule_scheduled.html.markdown b/website/docs/r/sentinel_alert_rule_scheduled.html.markdown index d9675052a9bc..fd5a4be2572b 100644 --- a/website/docs/r/sentinel_alert_rule_scheduled.html.markdown +++ b/website/docs/r/sentinel_alert_rule_scheduled.html.markdown @@ -122,6 +122,16 @@ An `alert_details_override` block supports the following: * `tactics_column_name` - (Optional) The column name to take the alert tactics from. +* `dynamic_properties` - (Optional) A list of `dynamic_property` blocks as defined below. + +--- + +A `dynamic_properties` block supports the following: + +* `name` - (Required) The name of the dynamic property. Possible Values are `AlertLink`, `ConfidenceLevel`, `ConfidenceScore`, `ExtendedLinks`, `ProductComponentName`, `ProductName`, `ProviderName`, `RemediationSteps` and `Techniques`. + +* `value` - (Required) The value of the dynamic property. Pssible Values are `Caller`, `dcount_ResourceId` and `EventSubmissionTimestamp`. + --- An `entity_mapping` block supports the following: From 841f695d8adc58bf21e973f8c381fe8c4c83ce33 Mon Sep 17 00:00:00 2001 From: ziyeqf Date: Mon, 30 Jan 2023 16:47:57 +0800 Subject: [PATCH 2/3] update validation --- internal/services/sentinel/sentinel_alert_rule.go | 8 -------- .../sentinel/sentinel_alert_rule_nrt_resource.go | 11 +++-------- .../sentinel_alert_rule_scheduled_resource.go | 11 +++-------- 3 files changed, 6 insertions(+), 24 deletions(-) diff --git a/internal/services/sentinel/sentinel_alert_rule.go b/internal/services/sentinel/sentinel_alert_rule.go index cf76e825162d..e193e382b540 100644 --- a/internal/services/sentinel/sentinel_alert_rule.go +++ b/internal/services/sentinel/sentinel_alert_rule.go @@ -11,14 +11,6 @@ import ( securityinsight "github.com/tombuildsstuff/kermit/sdk/securityinsights/2022-10-01-preview/securityinsights" ) -type AlertRuleDynamicPropertiesValue string - -const ( - AlertRuleDynamicPropertiesValueCaller AlertRuleDynamicPropertiesValue = "Caller" - AlertRuleDynamicPropertiesValueDcountResourceId AlertRuleDynamicPropertiesValue = "dcount_ResourceId" - AlertRuleDynamicPropertiesValueEventSubmissionTimestamp AlertRuleDynamicPropertiesValue = "EventSubmissionTimestamp" -) - func alertRuleID(rule securityinsight.BasicAlertRule) *string { if rule == nil { return nil diff --git a/internal/services/sentinel/sentinel_alert_rule_nrt_resource.go b/internal/services/sentinel/sentinel_alert_rule_nrt_resource.go index 1122ad841e59..0519a7cb55da 100644 --- a/internal/services/sentinel/sentinel_alert_rule_nrt_resource.go +++ b/internal/services/sentinel/sentinel_alert_rule_nrt_resource.go @@ -290,14 +290,9 @@ func resourceSentinelAlertRuleNrt() *pluginsdk.Resource { }, false), }, "value": { - Type: pluginsdk.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice( - []string{ - string(AlertRuleDynamicPropertiesValueCaller), - string(AlertRuleDynamicPropertiesValueDcountResourceId), - string(AlertRuleDynamicPropertiesValueEventSubmissionTimestamp), - }, false), + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validation.StringIsNotEmpty, }, }, }, diff --git a/internal/services/sentinel/sentinel_alert_rule_scheduled_resource.go b/internal/services/sentinel/sentinel_alert_rule_scheduled_resource.go index 313ae600d25b..4e79fae31a3f 100644 --- a/internal/services/sentinel/sentinel_alert_rule_scheduled_resource.go +++ b/internal/services/sentinel/sentinel_alert_rule_scheduled_resource.go @@ -351,14 +351,9 @@ func resourceSentinelAlertRuleScheduled() *pluginsdk.Resource { }, false), }, "value": { - Type: pluginsdk.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice( - []string{ - string(AlertRuleDynamicPropertiesValueCaller), - string(AlertRuleDynamicPropertiesValueDcountResourceId), - string(AlertRuleDynamicPropertiesValueEventSubmissionTimestamp), - }, false), + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validation.StringIsNotEmpty, }, }, }, From baf878be8bd4b8547104f90b49162f927f933ec1 Mon Sep 17 00:00:00 2001 From: ziyeqf Date: Tue, 31 Jan 2023 10:29:30 +0800 Subject: [PATCH 3/3] rename to `dynamic_property` --- internal/services/sentinel/sentinel_alert_rule.go | 4 ++-- .../services/sentinel/sentinel_alert_rule_nrt_resource.go | 2 +- .../sentinel/sentinel_alert_rule_nrt_resource_test.go | 2 +- .../sentinel/sentinel_alert_rule_scheduled_resource.go | 2 +- .../sentinel/sentinel_alert_rule_scheduled_resource_test.go | 2 +- website/docs/r/sentinel_alert_rule_nrt.html.markdown | 4 ++-- website/docs/r/sentinel_alert_rule_scheduled.html.markdown | 4 ++-- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/internal/services/sentinel/sentinel_alert_rule.go b/internal/services/sentinel/sentinel_alert_rule.go index e193e382b540..d9d96f1df729 100644 --- a/internal/services/sentinel/sentinel_alert_rule.go +++ b/internal/services/sentinel/sentinel_alert_rule.go @@ -268,7 +268,7 @@ func expandAlertRuleAlertDetailsOverride(input []interface{}) *securityinsight.A if v := b["tactics_column_name"]; v != "" { output.AlertTacticsColumnName = utils.String(v.(string)) } - if v := b["dynamic_properties"]; v != nil && len(v.([]interface{})) > 0 { + if v := b["dynamic_property"]; v != nil && len(v.([]interface{})) > 0 { output.AlertDynamicProperties = expandAlertRuleAlertDynamicProperties(v.([]interface{})) } @@ -311,7 +311,7 @@ func flattenAlertRuleAlertDetailsOverride(input *securityinsight.AlertDetailsOve "display_name_format": displayNameFormat, "severity_column_name": severityColumnName, "tactics_column_name": tacticsColumnName, - "dynamic_properties": dynamicProperties, + "dynamic_property": dynamicProperties, }, } } diff --git a/internal/services/sentinel/sentinel_alert_rule_nrt_resource.go b/internal/services/sentinel/sentinel_alert_rule_nrt_resource.go index 0519a7cb55da..05d2821e0043 100644 --- a/internal/services/sentinel/sentinel_alert_rule_nrt_resource.go +++ b/internal/services/sentinel/sentinel_alert_rule_nrt_resource.go @@ -268,7 +268,7 @@ func resourceSentinelAlertRuleNrt() *pluginsdk.Resource { Optional: true, ValidateFunc: validation.StringIsNotEmpty, }, - "dynamic_properties": { + "dynamic_property": { Type: pluginsdk.TypeList, Optional: true, Elem: &pluginsdk.Resource{ diff --git a/internal/services/sentinel/sentinel_alert_rule_nrt_resource_test.go b/internal/services/sentinel/sentinel_alert_rule_nrt_resource_test.go index 75ca8fb2cb7a..a55a467cb697 100644 --- a/internal/services/sentinel/sentinel_alert_rule_nrt_resource_test.go +++ b/internal/services/sentinel/sentinel_alert_rule_nrt_resource_test.go @@ -176,7 +176,7 @@ resource "azurerm_sentinel_alert_rule_nrt" "test" { display_name_format = "Suspicious activity was made by {{ComputerIP}}" severity_column_name = "Computer" tactics_column_name = "Computer" - dynamic_properties { + dynamic_property { name = "AlertLink" value = "dcount_ResourceId" } diff --git a/internal/services/sentinel/sentinel_alert_rule_scheduled_resource.go b/internal/services/sentinel/sentinel_alert_rule_scheduled_resource.go index 4e79fae31a3f..ba712ebfad2c 100644 --- a/internal/services/sentinel/sentinel_alert_rule_scheduled_resource.go +++ b/internal/services/sentinel/sentinel_alert_rule_scheduled_resource.go @@ -329,7 +329,7 @@ func resourceSentinelAlertRuleScheduled() *pluginsdk.Resource { Optional: true, ValidateFunc: validation.StringIsNotEmpty, }, - "dynamic_properties": { + "dynamic_property": { Type: pluginsdk.TypeList, Optional: true, Elem: &pluginsdk.Resource{ diff --git a/internal/services/sentinel/sentinel_alert_rule_scheduled_resource_test.go b/internal/services/sentinel/sentinel_alert_rule_scheduled_resource_test.go index 0a10daf119dc..52f89971ad1b 100644 --- a/internal/services/sentinel/sentinel_alert_rule_scheduled_resource_test.go +++ b/internal/services/sentinel/sentinel_alert_rule_scheduled_resource_test.go @@ -202,7 +202,7 @@ resource "azurerm_sentinel_alert_rule_scheduled" "test" { display_name_format = "Suspicious activity was made by {{ComputerIP}}" severity_column_name = "Computer" tactics_column_name = "Computer" - dynamic_properties { + dynamic_property { name = "AlertLink" value = "dcount_ResourceId" } diff --git a/website/docs/r/sentinel_alert_rule_nrt.html.markdown b/website/docs/r/sentinel_alert_rule_nrt.html.markdown index 799f8c958662..99b6ddee9250 100644 --- a/website/docs/r/sentinel_alert_rule_nrt.html.markdown +++ b/website/docs/r/sentinel_alert_rule_nrt.html.markdown @@ -108,11 +108,11 @@ An `alert_details_override` block supports the following: * `tactics_column_name` - (Optional) The column name to take the alert tactics from. -* `dynamic_properties` - (Optional) A list of `dynamic_property` blocks as defined below. +* `dynamic_property` - (Optional) A list of `dynamic_property` blocks as defined below. --- -A `dynamic_properties` block supports the following: +A `dynamic_property` block supports the following: * `name` - (Required) The name of the dynamic property. Possible Values are `AlertLink`, `ConfidenceLevel`, `ConfidenceScore`, `ExtendedLinks`, `ProductComponentName`, `ProductName`, `ProviderName`, `RemediationSteps` and `Techniques`. diff --git a/website/docs/r/sentinel_alert_rule_scheduled.html.markdown b/website/docs/r/sentinel_alert_rule_scheduled.html.markdown index fd5a4be2572b..908ff002ac5d 100644 --- a/website/docs/r/sentinel_alert_rule_scheduled.html.markdown +++ b/website/docs/r/sentinel_alert_rule_scheduled.html.markdown @@ -122,11 +122,11 @@ An `alert_details_override` block supports the following: * `tactics_column_name` - (Optional) The column name to take the alert tactics from. -* `dynamic_properties` - (Optional) A list of `dynamic_property` blocks as defined below. +* `dynamic_property` - (Optional) A list of `dynamic_property` blocks as defined below. --- -A `dynamic_properties` block supports the following: +A `dynamic_property` block supports the following: * `name` - (Required) The name of the dynamic property. Possible Values are `AlertLink`, `ConfidenceLevel`, `ConfidenceScore`, `ExtendedLinks`, `ProductComponentName`, `ProductName`, `ProviderName`, `RemediationSteps` and `Techniques`.