Skip to content

Commit

Permalink
Support new properties alert_rule_template_guid and `display_name_e…
Browse files Browse the repository at this point in the history
…xclude_filter` for azurerm_sentinel_alert_rule_ms_security_incident (#9797)

The purpose of this PR is to support below two new properties for azurerm_sentinel_alert_rule_ms_security_incident.

The first property is alert_rule_template_guid. It is the id of the alert rule template which is used to create this Sentinel Scheduled Alert Rule.

The second property is display_name_exclude_filter. It is used to create incidents when the alert display name doesn't contain text from the specified list.
  • Loading branch information
Neil Ye authored Dec 27, 2020
1 parent c1f0d36 commit 72f06d9
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,13 @@ func resourceSentinelAlertRuleMsSecurityIncident() *schema.Resource {
},
},

"alert_rule_template_guid": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
ValidateFunc: validation.IsUUID,
},

"description": {
Type: schema.TypeString,
Optional: true,
Expand All @@ -109,6 +116,16 @@ func resourceSentinelAlertRuleMsSecurityIncident() *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,
Expand Down Expand Up @@ -161,12 +178,20 @@ func resourceSentinelAlertRuleMsSecurityIncidentCreateUpdate(d *schema.ResourceD
},
}

if v, ok := d.GetOk("alert_rule_template_guid"); 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)
Expand Down Expand Up @@ -232,13 +257,17 @@ func resourceSentinelAlertRuleMsSecurityIncidentRead(d *schema.ResourceData, met
d.Set("display_name", prop.DisplayName)
d.Set("description", prop.Description)
d.Set("enabled", prop.Enabled)
d.Set("alert_rule_template_guid", prop.AlertRuleTemplateName)

if err := d.Set("text_whitelist", utils.FlattenStringSlice(prop.DisplayNamesFilter)); err != nil {
return fmt.Errorf(`setting "text_whitelist": %+v`, err)
}
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)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,50 @@ func TestAccSentinelAlertRuleMsSecurityIncident_requiresImport(t *testing.T) {
})
}

func TestAccSentinelAlertRuleMsSecurityIncident_withAlertRuleTemplateGuid(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_sentinel_alert_rule_ms_security_incident", "test")
r := SentinelAlertRuleMsSecurityIncidentResource{}

data.ResourceTest(t, r, []resource.TestStep{
{
Config: r.alertRuleTemplateGuid(data),
Check: resource.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
})
}

func TestAccSentinelAlertRuleMsSecurityIncident_withDisplayNameExcludeFilter(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_sentinel_alert_rule_ms_security_incident", "test")
r := SentinelAlertRuleMsSecurityIncidentResource{}

data.ResourceTest(t, r, []resource.TestStep{
{
Config: r.displayNameExcludeFilter(data, "alert3"),
Check: resource.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
{
Config: r.displayNameExcludeFilter(data, "alert4"),
Check: resource.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
{
Config: r.basic(data),
Check: resource.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
})
}

func (t SentinelAlertRuleMsSecurityIncidentResource) Exists(ctx context.Context, clients *clients.Client, state *terraform.InstanceState) (*bool, error) {
id, err := parse.SentinelAlertRuleID(state.ID)
if err != nil {
Expand Down Expand Up @@ -155,6 +199,37 @@ resource "azurerm_sentinel_alert_rule_ms_security_incident" "import" {
`, r.basic(data))
}

func (r SentinelAlertRuleMsSecurityIncidentResource) alertRuleTemplateGuid(data acceptance.TestData) string {
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_guid = "b3cfc7c0-092c-481c-a55b-34a3979758cb"
}
`, r.template(data), data.RandomInteger)
}

func (r SentinelAlertRuleMsSecurityIncidentResource) displayNameExcludeFilter(data acceptance.TestData, displayNameExcludeFilter string) string {
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"]
}
`, r.template(data), data.RandomInteger, displayNameExcludeFilter)
}

func (SentinelAlertRuleMsSecurityIncidentResource) template(data acceptance.TestData) string {
return fmt.Sprintf(`
provider "azurerm" {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,16 @@ 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.

* `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:
Expand Down

0 comments on commit 72f06d9

Please sign in to comment.