From 7eebf6923d1ec417e3a60a54b8584df38360952d Mon Sep 17 00:00:00 2001 From: neil-yechenwei Date: Thu, 10 Dec 2020 16:21:38 +0800 Subject: [PATCH 1/3] Support new properties for azurerm_sentinel_alert_rule_ms_security_incident --- ...lert_rule_ms_security_incident_resource.go | 39 +++++++-- ...rule_ms_security_incident_resource_test.go | 85 +++++++++++++++++++ ...rt_rule_ms_security_incident.html.markdown | 6 ++ 3 files changed, 124 insertions(+), 6 deletions(-) diff --git a/azurerm/internal/services/sentinel/sentinel_alert_rule_ms_security_incident_resource.go b/azurerm/internal/services/sentinel/sentinel_alert_rule_ms_security_incident_resource.go index 5d1d1f41607c..cd2c21884fd6 100644 --- a/azurerm/internal/services/sentinel/sentinel_alert_rule_ms_security_incident_resource.go +++ b/azurerm/internal/services/sentinel/sentinel_alert_rule_ms_security_incident_resource.go @@ -85,6 +85,13 @@ func resourceArmSentinelAlertRuleMsSecurityIncident() *schema.Resource { }, }, + "alert_rule_template_name": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.IsUUID, + }, + "description": { Type: schema.TypeString, Optional: true, @@ -109,6 +116,16 @@ func resourceArmSentinelAlertRuleMsSecurityIncident() *schema.Resource { }, }, + "display_name_exclude_filter": { + Type: schema.TypeSet, + Optional: true, + MinItems: 1, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validation.StringIsNotEmpty, + }, + }, + "text_whitelist": { Type: schema.TypeSet, Optional: true, @@ -161,12 +178,20 @@ func resourceArmSentinelAlertRuleMsSecurityIncidentCreateUpdate(d *schema.Resour }, } + if v, ok := d.GetOk("alert_rule_template_name"); ok { + param.MicrosoftSecurityIncidentCreationAlertRuleProperties.AlertRuleTemplateName = utils.String(v.(string)) + } + if dnf, ok := d.GetOk("display_name_filter"); ok { param.DisplayNamesFilter = utils.ExpandStringSlice(dnf.(*schema.Set).List()) } else if dnf, ok := d.GetOk("text_whitelist"); ok { param.DisplayNamesFilter = utils.ExpandStringSlice(dnf.(*schema.Set).List()) } + if v, ok := d.GetOk("display_name_exclude_filter"); ok { + param.DisplayNamesExcludeFilter = utils.ExpandStringSlice(v.(*schema.Set).List()) + } + // Service avoid concurrent update of this resource via checking the "etag" to guarantee it is the same value as last Read. if !d.IsNewResource() { resp, err := client.Get(ctx, workspaceID.ResourceGroup, "Microsoft.OperationalInsights", workspaceID.WorkspaceName, name) @@ -198,8 +223,8 @@ func resourceArmSentinelAlertRuleMsSecurityIncidentCreateUpdate(d *schema.Resour } func resourceArmSentinelAlertRuleMsSecurityIncidentRead(d *schema.ResourceData, meta interface{}) error { + subscriptionId := meta.(*clients.Client).Account.SubscriptionId client := meta.(*clients.Client).Sentinel.AlertRulesClient - workspaceClient := meta.(*clients.Client).LogAnalytics.WorkspacesClient ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) defer cancel() @@ -226,16 +251,15 @@ func resourceArmSentinelAlertRuleMsSecurityIncidentRead(d *schema.ResourceData, d.Set("name", id.Name) - workspaceResp, err := workspaceClient.Get(ctx, id.ResourceGroup, id.Workspace) - if err != nil { - return fmt.Errorf("retrieving Log Analytics Workspace %q (Resource Group: %q) where this Alert Rule belongs to: %+v", id.Workspace, id.ResourceGroup, err) - } - d.Set("log_analytics_workspace_id", workspaceResp.ID) + logAnalyticsWorkspaceId := loganalyticsParse.NewLogAnalyticsWorkspaceID(subscriptionId, id.ResourceGroup, id.Workspace) + d.Set("log_analytics_workspace_id", logAnalyticsWorkspaceId.ID(subscriptionId)) + if prop := rule.MicrosoftSecurityIncidentCreationAlertRuleProperties; prop != nil { d.Set("product_filter", string(prop.ProductFilter)) d.Set("display_name", prop.DisplayName) d.Set("description", prop.Description) d.Set("enabled", prop.Enabled) + d.Set("alert_rule_template_name", prop.AlertRuleTemplateName) if err := d.Set("text_whitelist", utils.FlattenStringSlice(prop.DisplayNamesFilter)); err != nil { return fmt.Errorf(`setting "text_whitelist": %+v`, err) @@ -243,6 +267,9 @@ func resourceArmSentinelAlertRuleMsSecurityIncidentRead(d *schema.ResourceData, if err := d.Set("display_name_filter", utils.FlattenStringSlice(prop.DisplayNamesFilter)); err != nil { return fmt.Errorf(`setting "display_name_filter": %+v`, err) } + if err := d.Set("display_name_exclude_filter", utils.FlattenStringSlice(prop.DisplayNamesExcludeFilter)); err != nil { + return fmt.Errorf(`setting "display_name_exclude_filter": %+v`, err) + } if err := d.Set("severity_filter", flattenAlertRuleMsSecurityIncidentSeverityFilter(prop.SeveritiesFilter)); err != nil { return fmt.Errorf(`setting "severity_filter": %+v`, err) } diff --git a/azurerm/internal/services/sentinel/sentinel_alert_rule_ms_security_incident_resource_test.go b/azurerm/internal/services/sentinel/sentinel_alert_rule_ms_security_incident_resource_test.go index 29c38ee993c5..4af2216a9e74 100644 --- a/azurerm/internal/services/sentinel/sentinel_alert_rule_ms_security_incident_resource_test.go +++ b/azurerm/internal/services/sentinel/sentinel_alert_rule_ms_security_incident_resource_test.go @@ -102,6 +102,58 @@ func TestAccAzureRMSentinelAlertRuleMsSecurityIncident_requiresImport(t *testing }) } +func TestAccAzureRMSentinelAlertRuleMsSecurityIncident_withAlertRuleTemplateName(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_sentinel_alert_rule_ms_security_incident", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMSentinelAlertRuleMsSecurityIncidentDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMSentinelAlertRuleMsSecurityIncident_withAlertRuleTemplateName(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMSentinelAlertRuleMsSecurityIncidentExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + +func TestAccAzureRMSentinelAlertRuleMsSecurityIncident_withDisplayNameExcludeFilter(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_sentinel_alert_rule_ms_security_incident", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMSentinelAlertRuleMsSecurityIncidentDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMSentinelAlertRuleMsSecurityIncident_withDisplayNameExcludeFilter(data, "alert3"), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMSentinelAlertRuleMsSecurityIncidentExists(data.ResourceName), + ), + }, + data.ImportStep(), + { + Config: testAccAzureRMSentinelAlertRuleMsSecurityIncident_withDisplayNameExcludeFilter(data, "alert4"), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMSentinelAlertRuleMsSecurityIncidentExists(data.ResourceName), + ), + }, + data.ImportStep(), + { + Config: testAccAzureRMSentinelAlertRuleMsSecurityIncident_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMSentinelAlertRuleMsSecurityIncidentExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + func testCheckAzureRMSentinelAlertRuleMsSecurityIncidentExists(resourceName string) resource.TestCheckFunc { return func(s *terraform.State) error { client := acceptance.AzureProvider.Meta().(*clients.Client).Sentinel.AlertRulesClient @@ -201,6 +253,39 @@ resource "azurerm_sentinel_alert_rule_ms_security_incident" "import" { `, template) } +func testAccAzureRMSentinelAlertRuleMsSecurityIncident_withAlertRuleTemplateName(data acceptance.TestData) string { + template := testAccAzureRMSentinelAlertRuleMsSecurityIncident_template(data) + return fmt.Sprintf(` +%s + +resource "azurerm_sentinel_alert_rule_ms_security_incident" "test" { + name = "acctest-SentinelAlertRule-MSI-%d" + log_analytics_workspace_id = azurerm_log_analytics_workspace.test.id + product_filter = "Microsoft Cloud App Security" + display_name = "some rule" + severity_filter = ["High"] + alert_rule_template_name = "b3cfc7c0-092c-481c-a55b-34a3979758cb" +} +`, template, data.RandomInteger) +} + +func testAccAzureRMSentinelAlertRuleMsSecurityIncident_withDisplayNameExcludeFilter(data acceptance.TestData, displayNameExcludeFilter string) string { + template := testAccAzureRMSentinelAlertRuleMsSecurityIncident_template(data) + return fmt.Sprintf(` +%s + +resource "azurerm_sentinel_alert_rule_ms_security_incident" "test" { + name = "acctest-SentinelAlertRule-MSI-%d" + log_analytics_workspace_id = azurerm_log_analytics_workspace.test.id + product_filter = "Microsoft Cloud App Security" + display_name = "some rule" + severity_filter = ["High"] + display_name_filter = ["alert1"] + display_name_exclude_filter = ["%s"] +} +`, template, data.RandomInteger, displayNameExcludeFilter) +} + func testAccAzureRMSentinelAlertRuleMsSecurityIncident_template(data acceptance.TestData) string { return fmt.Sprintf(` provider "azurerm" { diff --git a/website/docs/r/sentinel_alert_rule_ms_security_incident.html.markdown b/website/docs/r/sentinel_alert_rule_ms_security_incident.html.markdown index d2abd030b510..5314d72598ad 100644 --- a/website/docs/r/sentinel_alert_rule_ms_security_incident.html.markdown +++ b/website/docs/r/sentinel_alert_rule_ms_security_incident.html.markdown @@ -56,12 +56,18 @@ The following arguments are supported: --- +* `alert_rule_template_name` - (Optional) The name of the alert rule template which is used to create this Sentinel Scheduled Alert Rule. Changing this forces a new Sentinel MS Security Incident Alert Rule to be created. + +-> **NOTE** `alert_rule_template_name` should be a valid GUID. + * `description` - (Optional) The description of this Sentinel MS Security Incident Alert Rule. * `enabled` - (Optional) Should this Sentinel MS Security Incident Alert Rule be enabled? Defaults to `true`. * `display_name_filter` - (Optional) Only create incidents when the alert display name contain text from this list, leave empty to apply no filter. +* `display_name_exclude_filter` - (Optional) Only create incidents when the alert display name doesn't contain text from this list. + ## Attributes Reference In addition to the Arguments listed above - the following Attributes are exported: From 6d959a849a0063da31b7f02771a6ec007f6d7259 Mon Sep 17 00:00:00 2001 From: neil-yechenwei Date: Mon, 14 Dec 2020 09:46:06 +0800 Subject: [PATCH 2/3] update code --- .../r/sentinel_alert_rule_ms_security_incident.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/sentinel_alert_rule_ms_security_incident.html.markdown b/website/docs/r/sentinel_alert_rule_ms_security_incident.html.markdown index dfdd882d1d21..c8d9460c66b8 100644 --- a/website/docs/r/sentinel_alert_rule_ms_security_incident.html.markdown +++ b/website/docs/r/sentinel_alert_rule_ms_security_incident.html.markdown @@ -56,7 +56,7 @@ The following arguments are supported: --- -* `alert_rule_template_guid` - (Optional) The name of the alert rule template which is used to create this Sentinel Scheduled Alert Rule. Changing this forces a new Sentinel MS Security Incident Alert Rule to be created. +* `alert_rule_template_guid` - (Optional) The guid of the alert rule template which is used to create this Sentinel Scheduled Alert Rule. Changing this forces a new Sentinel MS Security Incident Alert Rule to be created. * `description` - (Optional) The description of this Sentinel MS Security Incident Alert Rule. From cde140e0ccfb116f99f3ce5d71d91db7d8c7bafc Mon Sep 17 00:00:00 2001 From: neil-yechenwei Date: Mon, 14 Dec 2020 11:07:25 +0800 Subject: [PATCH 3/3] update code --- .../r/sentinel_alert_rule_ms_security_incident.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/sentinel_alert_rule_ms_security_incident.html.markdown b/website/docs/r/sentinel_alert_rule_ms_security_incident.html.markdown index c8d9460c66b8..508d6ab4f4ac 100644 --- a/website/docs/r/sentinel_alert_rule_ms_security_incident.html.markdown +++ b/website/docs/r/sentinel_alert_rule_ms_security_incident.html.markdown @@ -56,7 +56,7 @@ The following arguments are supported: --- -* `alert_rule_template_guid` - (Optional) The guid of the alert rule template which is used to create this Sentinel Scheduled Alert Rule. Changing this forces a new Sentinel MS Security Incident Alert Rule to be created. +* `alert_rule_template_guid` - (Optional) The GUID of the alert rule template which is used to create this Sentinel Scheduled Alert Rule. Changing this forces a new Sentinel MS Security Incident Alert Rule to be created. * `description` - (Optional) The description of this Sentinel MS Security Incident Alert Rule.