Skip to content

Commit

Permalink
New Resource - sentinel_alert_rule_machine_learning_behavior_analytics (
Browse files Browse the repository at this point in the history
hashicorp#11552)

* azurerm_sentinel_alert_rule_MLBehaviorAnalytics

* Fix line formatting in registration.go

* Fix tflint in tests

* Update website/docs/r/azurerm_sentinel_alert_rule_ml_behavior_analytics.html.markdown

Make more minimal

Co-authored-by: magodo <[email protected]>

* Change Fusion > ML Behavior Analytics

* Put in AlphaNumeric Order

* ML > Machine Learning (Remove Acryonm)

* azurerm_sentinel_alert_rule_ml_behavior_analytics > azurerm_sentinel_alert_rule_machine_learning_behavior_analytics

* Fix fmt

Co-authored-by: magodo <[email protected]>
Co-authored-by: kaovd <[email protected]>
  • Loading branch information
3 people authored and favoretti committed May 26, 2021
1 parent a83d04b commit 253c6c8
Show file tree
Hide file tree
Showing 6 changed files with 487 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
package sentinel

import (
"fmt"
"log"
"time"

"github.com/Azure/azure-sdk-for-go/services/preview/securityinsight/mgmt/2019-01-01-preview/securityinsight"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients"
loganalyticsParse "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/loganalytics/parse"
loganalyticsValidate "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/loganalytics/validate"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/sentinel/parse"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tf/pluginsdk"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)

func resourceSentinelAlertRuleMLBehaviorAnalytics() *schema.Resource {
return &schema.Resource{
Create: resourceSentinelAlertRuleMLBehaviorAnalyticsCreateUpdate,
Read: resourceSentinelAlertRuleMLBehaviorAnalyticsRead,
Update: resourceSentinelAlertRuleMLBehaviorAnalyticsCreateUpdate,
Delete: resourceSentinelAlertRuleMLBehaviorAnalyticsDelete,

Importer: pluginsdk.ImporterValidatingResourceIdThen(func(id string) error {
_, err := parse.AlertRuleID(id)
return err
}, importSentinelAlertRule(securityinsight.AlertRuleKindMLBehaviorAnalytics)),

Timeouts: &schema.ResourceTimeout{
Create: schema.DefaultTimeout(30 * time.Minute),
Read: schema.DefaultTimeout(5 * time.Minute),
Update: schema.DefaultTimeout(30 * time.Minute),
Delete: schema.DefaultTimeout(30 * time.Minute),
},

Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validation.StringIsNotEmpty,
},

"log_analytics_workspace_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: loganalyticsValidate.LogAnalyticsWorkspaceID,
},

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

"enabled": {
Type: schema.TypeBool,
Optional: true,
Default: true,
},
},
}
}

func resourceSentinelAlertRuleMLBehaviorAnalyticsCreateUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*clients.Client).Sentinel.AlertRulesClient
ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d)
defer cancel()

name := d.Get("name").(string)

workspaceID, err := loganalyticsParse.LogAnalyticsWorkspaceID(d.Get("log_analytics_workspace_id").(string))
if err != nil {
return err
}
id := parse.NewAlertRuleID(workspaceID.SubscriptionId, workspaceID.ResourceGroup, workspaceID.WorkspaceName, name)

if d.IsNewResource() {
resp, err := client.Get(ctx, workspaceID.ResourceGroup, OperationalInsightsResourceProvider, workspaceID.WorkspaceName, name)
if err != nil {
if !utils.ResponseWasNotFound(resp.Response) {
return fmt.Errorf("checking for existing Sentinel Alert Rule MLBehaviorAnalytics %q: %+v", id, err)
}
}

id := alertRuleID(resp.Value)
if id != nil && *id != "" {
return tf.ImportAsExistsError("azurerm_sentinel_alert_rule_machine_learning_behavior_analytics", *id)
}
}

params := securityinsight.MLBehaviorAnalyticsAlertRule{
Kind: securityinsight.KindMLBehaviorAnalytics,
MLBehaviorAnalyticsAlertRuleProperties: &securityinsight.MLBehaviorAnalyticsAlertRuleProperties{
AlertRuleTemplateName: utils.String(d.Get("alert_rule_template_guid").(string)),
Enabled: utils.Bool(d.Get("enabled").(bool)),
},
}

// 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, OperationalInsightsResourceProvider, workspaceID.WorkspaceName, name)
if err != nil {
return fmt.Errorf("retrieving Sentinel Alert Rule MLBehaviorAnalytics %q: %+v", id, err)
}

if err := assertAlertRuleKind(resp.Value, securityinsight.AlertRuleKindMLBehaviorAnalytics); err != nil {
return fmt.Errorf("asserting alert rule of %q: %+v", id, err)
}
params.Etag = resp.Value.(securityinsight.MLBehaviorAnalyticsAlertRule).Etag
}

if _, err := client.CreateOrUpdate(ctx, workspaceID.ResourceGroup, OperationalInsightsResourceProvider, workspaceID.WorkspaceName, name, params); err != nil {
return fmt.Errorf("creating Sentinel Alert Rule MLBehaviorAnalytics %q: %+v", id, err)
}

d.SetId(id.ID())

return resourceSentinelAlertRuleMLBehaviorAnalyticsRead(d, meta)
}

func resourceSentinelAlertRuleMLBehaviorAnalyticsRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*clients.Client).Sentinel.AlertRulesClient
ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d)
defer cancel()

id, err := parse.AlertRuleID(d.Id())
if err != nil {
return err
}

resp, err := client.Get(ctx, id.ResourceGroup, OperationalInsightsResourceProvider, id.WorkspaceName, id.Name)
if err != nil {
if utils.ResponseWasNotFound(resp.Response) {
log.Printf("[DEBUG] Sentinel Alert Rule MLBehaviorAnalytics %q was not found - removing from state!", id)
d.SetId("")
return nil
}

return fmt.Errorf("retrieving Sentinel Alert Rule MLBehaviorAnalytics %q: %+v", id, err)
}

if err := assertAlertRuleKind(resp.Value, securityinsight.AlertRuleKindMLBehaviorAnalytics); err != nil {
return fmt.Errorf("asserting alert rule of %q: %+v", id, err)
}
rule := resp.Value.(securityinsight.MLBehaviorAnalyticsAlertRule)

d.Set("name", id.Name)

workspaceId := loganalyticsParse.NewLogAnalyticsWorkspaceID(id.SubscriptionId, id.ResourceGroup, id.WorkspaceName)
d.Set("log_analytics_workspace_id", workspaceId.ID())

if prop := rule.MLBehaviorAnalyticsAlertRuleProperties; prop != nil {
d.Set("enabled", prop.Enabled)
d.Set("alert_rule_template_guid", prop.AlertRuleTemplateName)
}

return nil
}

func resourceSentinelAlertRuleMLBehaviorAnalyticsDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*clients.Client).Sentinel.AlertRulesClient
ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d)
defer cancel()

id, err := parse.AlertRuleID(d.Id())
if err != nil {
return err
}

if _, err := client.Delete(ctx, id.ResourceGroup, OperationalInsightsResourceProvider, id.WorkspaceName, id.Name); err != nil {
return fmt.Errorf("deleting Sentinel Alert Rule MLBehaviorAnalytics %q: %+v", id, err)
}

return nil
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
package sentinel_test

import (
"context"
"fmt"
"testing"

"github.com/Azure/azure-sdk-for-go/services/preview/securityinsight/mgmt/2019-01-01-preview/securityinsight"

"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/terraform"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance/check"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/sentinel/parse"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)

type SentinelAlertRuleMLBehaviorAnalyticsResource struct{}

func TestAccSentinelAlertRuleMLBehaviorAnalytics_basic(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_sentinel_alert_rule_machine_learning_behavior_analytics", "test")
r := SentinelAlertRuleMLBehaviorAnalyticsResource{}

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

func TestAccSentinelAlertRuleMLBehaviorAnalytics_complete(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_sentinel_alert_rule_machine_learning_behavior_analytics", "test")
r := SentinelAlertRuleMLBehaviorAnalyticsResource{}

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

func TestAccSentinelAlertRuleMLBehaviorAnalytics_update(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_sentinel_alert_rule_machine_learning_behavior_analytics", "test")
r := SentinelAlertRuleMLBehaviorAnalyticsResource{}

data.ResourceTest(t, r, []resource.TestStep{
{
Config: r.basic(data),
Check: resource.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
{
Config: r.complete(data),
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 TestAccSentinelAlertRuleMLBehaviorAnalytics_requiresImport(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_sentinel_alert_rule_machine_learning_behavior_analytics", "test")
r := SentinelAlertRuleMLBehaviorAnalyticsResource{}

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

func (r SentinelAlertRuleMLBehaviorAnalyticsResource) Exists(ctx context.Context, client *clients.Client, state *terraform.InstanceState) (*bool, error) {
alertRuleClient := client.Sentinel.AlertRulesClient
id, err := parse.AlertRuleID(state.ID)
if err != nil {
return nil, err
}

resp, err := alertRuleClient.Get(ctx, id.ResourceGroup, "Microsoft.OperationalInsights", id.WorkspaceName, id.Name)
if err != nil {
if utils.ResponseWasNotFound(resp.Response) {
return utils.Bool(false), nil
}

return nil, fmt.Errorf("retrieving Sentinel Alert Rule MLBehaviorAnalytics (%q): %+v", state.String(), err)
}

rule, ok := resp.Value.(securityinsight.MLBehaviorAnalyticsAlertRule)
if !ok {
return nil, fmt.Errorf("the Alert Rule %q is not a MLBehaviorAnalytics Alert Rule", id)
}

return utils.Bool(rule.ID != nil), nil
}

func (r SentinelAlertRuleMLBehaviorAnalyticsResource) basic(data acceptance.TestData) string {
return fmt.Sprintf(`
%s
data "azurerm_sentinel_alert_rule_template" "test" {
display_name = "(Preview) Anomalous SSH Login Detection"
log_analytics_workspace_id = azurerm_log_analytics_solution.test.workspace_resource_id
}
resource "azurerm_sentinel_alert_rule_machine_learning_behavior_analytics" "test" {
name = "acctest-SentinelAlertRule-MLBehaviorAnalytics-%d"
log_analytics_workspace_id = azurerm_log_analytics_solution.test.workspace_resource_id
alert_rule_template_guid = data.azurerm_sentinel_alert_rule_template.test.name
}
`, r.template(data), data.RandomInteger)
}

func (r SentinelAlertRuleMLBehaviorAnalyticsResource) complete(data acceptance.TestData) string {
return fmt.Sprintf(`
%s
data "azurerm_sentinel_alert_rule_template" "test" {
display_name = "(Preview) Anomalous SSH Login Detection"
log_analytics_workspace_id = azurerm_log_analytics_solution.test.workspace_resource_id
}
resource "azurerm_sentinel_alert_rule_machine_learning_behavior_analytics" "test" {
name = "acctest-SentinelAlertRule-MLBehaviorAnalytics-%d"
log_analytics_workspace_id = azurerm_log_analytics_solution.test.workspace_resource_id
alert_rule_template_guid = data.azurerm_sentinel_alert_rule_template.test.name
enabled = false
}
data "azurerm_sentinel_alert_rule_template" "test2" {
display_name = "(Preview) Anomalous RDP Login Detections"
log_analytics_workspace_id = azurerm_log_analytics_solution.test.workspace_resource_id
}
resource "azurerm_sentinel_alert_rule_machine_learning_behavior_analytics" "test2" {
name = "acctest-SentinelAlertRule-MLBehaviorAnalytics-2-%d"
log_analytics_workspace_id = azurerm_log_analytics_solution.test.workspace_resource_id
alert_rule_template_guid = data.azurerm_sentinel_alert_rule_template.test2.name
enabled = false
}
`, r.template(data), data.RandomInteger, data.RandomInteger)
}

func (r SentinelAlertRuleMLBehaviorAnalyticsResource) requiresImport(data acceptance.TestData) string {
return fmt.Sprintf(`
%s
resource "azurerm_sentinel_alert_rule_machine_learning_behavior_analytics" "import" {
name = azurerm_sentinel_alert_rule_machine_learning_behavior_analytics.test.name
log_analytics_workspace_id = azurerm_sentinel_alert_rule_machine_learning_behavior_analytics.test.log_analytics_workspace_id
alert_rule_template_guid = azurerm_sentinel_alert_rule_machine_learning_behavior_analytics.test.alert_rule_template_guid
}
`, r.basic(data))
}

func (r SentinelAlertRuleMLBehaviorAnalyticsResource) template(data acceptance.TestData) string {
return fmt.Sprintf(`
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "test" {
name = "acctestRG-sentinel-%d"
location = "%s"
}
resource "azurerm_log_analytics_workspace" "test" {
name = "acctestLAW-%d"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
sku = "PerGB2018"
}
resource "azurerm_log_analytics_solution" "test" {
solution_name = "SecurityInsights"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
workspace_resource_id = azurerm_log_analytics_workspace.test.id
workspace_name = azurerm_log_analytics_workspace.test.name
plan {
publisher = "Microsoft"
product = "OMSGallery/SecurityInsights"
}
}
`, data.RandomInteger, data.Locations.Primary, data.RandomInteger)
}
Loading

0 comments on commit 253c6c8

Please sign in to comment.