Skip to content

Commit

Permalink
New resource/data source: `azurerm_sentinel_alert_rule_ms_security_in…
Browse files Browse the repository at this point in the history
…cident` (#6606)
  • Loading branch information
magodo committed Apr 27, 2020
1 parent d269242 commit 232b14e
Show file tree
Hide file tree
Showing 29 changed files with 7,176 additions and 23 deletions.
3 changes: 3 additions & 0 deletions azurerm/internal/clients/client.go
Expand Up @@ -66,6 +66,7 @@ import (
resource "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/resource/client"
search "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/search/client"
securityCenter "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/securitycenter/client"
sentinel "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/sentinel/client"
serviceBus "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/servicebus/client"
serviceFabric "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/servicefabric/client"
signalr "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/signalr/client"
Expand Down Expand Up @@ -144,6 +145,7 @@ type Client struct {
Resource *resource.Client
Search *search.Client
SecurityCenter *securityCenter.Client
Sentinel *sentinel.Client
ServiceBus *serviceBus.Client
ServiceFabric *serviceFabric.Client
SignalR *signalr.Client
Expand Down Expand Up @@ -223,6 +225,7 @@ func (client *Client) Build(ctx context.Context, o *common.ClientOptions) error
client.Resource = resource.NewClient(o)
client.Search = search.NewClient(o)
client.SecurityCenter = securityCenter.NewClient(o)
client.Sentinel = sentinel.NewClient(o)
client.ServiceBus = serviceBus.NewClient(o)
client.ServiceFabric = serviceFabric.NewClient(o)
client.SignalR = signalr.NewClient(o)
Expand Down
1 change: 1 addition & 0 deletions azurerm/internal/provider/required_resource_providers.go
Expand Up @@ -67,6 +67,7 @@ func RequiredResourceProviders() map[string]struct{} {
"Microsoft.Resources": {},
"Microsoft.Search": {},
"Microsoft.Security": {},
"Microsoft.SecurityInsights": {},
"Microsoft.ServiceBus": {},
"Microsoft.ServiceFabric": {},
"Microsoft.Sql": {},
Expand Down
2 changes: 2 additions & 0 deletions azurerm/internal/provider/services.go
Expand Up @@ -62,6 +62,7 @@ import (
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/resource"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/search"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/securitycenter"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/sentinel"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/servicebus"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/servicefabric"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/signalr"
Expand Down Expand Up @@ -137,6 +138,7 @@ func SupportedServices() []common.ServiceRegistration {
resource.Registration{},
search.Registration{},
securitycenter.Registration{},
sentinel.Registration{},
servicebus.Registration{},
servicefabric.Registration{},
signalr.Registration{},
Expand Down
@@ -0,0 +1,33 @@
package parse

import (
"fmt"

"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure"
)

type LogAnalyticsWorkspaceId struct {
ResourceGroup string
Name string
}

func LogAnalyticsWorkspaceID(input string) (*LogAnalyticsWorkspaceId, error) {
id, err := azure.ParseAzureResourceID(input)
if err != nil {
return nil, fmt.Errorf("parsing Log Analytics Workspace ID %q: %+v", input, err)
}

server := LogAnalyticsWorkspaceId{
ResourceGroup: id.ResourceGroup,
}

if server.Name, err = id.PopSegment("workspaces"); err != nil {
return nil, err
}

if err := id.ValidateNoEmptySegments(input); err != nil {
return nil, err
}

return &server, nil
}
@@ -0,0 +1,70 @@
package parse

import (
"testing"
)

func TestLogAnalyticsWorkspaceID(t *testing.T) {
testData := []struct {
Name string
Input string
Error bool
Expect *LogAnalyticsWorkspaceId
}{
{
Name: "Empty",
Input: "",
Error: true,
},
{
Name: "No Resource Groups Segment",
Input: "/subscriptions/00000000-0000-0000-0000-000000000000",
Error: true,
},
{
Name: "No Resource Groups Value",
Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/",
Error: true,
},
{
Name: "Resource Group ID",
Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/resGroup1/",
Error: true,
},
{
Name: "Missing Workspace Value",
Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/resGroup1/providers/Microsoft.OperationalInsights/workspaces",
Error: true,
},
{
Name: "Workspace Value",
Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/resGroup1/providers/Microsoft.OperationalInsights/workspaces/workspace1",
Error: true,
Expect: &LogAnalyticsWorkspaceId{
ResourceGroup: "resGroup1",
Name: "workspace1",
},
},
}

for _, v := range testData {
t.Logf("[DEBUG] Testing %q", v.Name)

actual, err := LogAnalyticsWorkspaceID(v.Input)
if err != nil {
if v.Error {
continue
}

t.Fatalf("Expected a value but got an error: %s", err)
}

if actual.ResourceGroup != v.Expect.ResourceGroup {
t.Fatalf("Expected %q but got %q for Resource Group", v.Expect.ResourceGroup, actual.ResourceGroup)
}

if actual.Name != v.Expect.Name {
t.Fatalf("Expected %q but got %q for Name", v.Expect.Name, actual.Name)
}
}
}
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/loganalytics/parse"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
Expand Down Expand Up @@ -167,24 +168,22 @@ func resourceArmLogAnalyticsWorkspaceRead(d *schema.ResourceData, meta interface
client := meta.(*clients.Client).LogAnalytics.WorkspacesClient
ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d)
defer cancel()
id, err := azure.ParseAzureResourceID(d.Id())
id, err := parse.LogAnalyticsWorkspaceID(d.Id())
if err != nil {
return err
}
resGroup := id.ResourceGroup
name := id.Path["workspaces"]

resp, err := client.Get(ctx, resGroup, name)
resp, err := client.Get(ctx, id.ResourceGroup, id.Name)
if err != nil {
if utils.ResponseWasNotFound(resp.Response) {
d.SetId("")
return nil
}
return fmt.Errorf("Error making Read request on AzureRM Log Analytics workspaces '%s': %+v", name, err)
return fmt.Errorf("Error making Read request on AzureRM Log Analytics workspaces '%s': %+v", id.Name, err)
}

d.Set("name", resp.Name)
d.Set("resource_group_name", resGroup)
d.Set("resource_group_name", id.ResourceGroup)
if location := resp.Location; location != nil {
d.Set("location", azure.NormalizeLocation(*location))
}
Expand All @@ -196,9 +195,9 @@ func resourceArmLogAnalyticsWorkspaceRead(d *schema.ResourceData, meta interface
}
d.Set("retention_in_days", resp.RetentionInDays)

sharedKeys, err := client.GetSharedKeys(ctx, resGroup, name)
sharedKeys, err := client.GetSharedKeys(ctx, id.ResourceGroup, id.Name)
if err != nil {
log.Printf("[ERROR] Unable to List Shared keys for Log Analytics workspaces %s: %+v", name, err)
log.Printf("[ERROR] Unable to List Shared keys for Log Analytics workspaces %s: %+v", id.Name, err)
} else {
d.Set("primary_shared_key", sharedKeys.PrimarySharedKey)
d.Set("secondary_shared_key", sharedKeys.SecondarySharedKey)
Expand All @@ -211,21 +210,18 @@ func resourceArmLogAnalyticsWorkspaceDelete(d *schema.ResourceData, meta interfa
client := meta.(*clients.Client).LogAnalytics.WorkspacesClient
ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d)
defer cancel()
id, err := azure.ParseAzureResourceID(d.Id())
id, err := parse.LogAnalyticsWorkspaceID(d.Id())
if err != nil {
return err
}
resGroup := id.ResourceGroup
name := id.Path["workspaces"]

resp, err := client.Delete(ctx, resGroup, name)
resp, err := client.Delete(ctx, id.ResourceGroup, id.Name)

if err != nil {
if utils.ResponseWasNotFound(resp) {
return nil
}

return fmt.Errorf("Error issuing AzureRM delete request for Log Analytics Workspaces '%s': %+v", name, err)
return fmt.Errorf("Error issuing AzureRM delete request for Log Analytics Workspaces '%s': %+v", id.Name, err)
}

return nil
Expand Down
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/loganalytics"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/loganalytics/parse"
)

func TestAccAzureRmLogAnalyticsWorkspaceName_validation(t *testing.T) {
Expand Down Expand Up @@ -123,10 +124,12 @@ func testCheckAzureRMLogAnalyticsWorkspaceDestroy(s *terraform.State) error {
continue
}

name := rs.Primary.Attributes["name"]
resourceGroup := rs.Primary.Attributes["resource_group_name"]
id, err := parse.LogAnalyticsWorkspaceID(rs.Primary.ID)
if err != nil {
return err
}

resp, err := conn.Get(ctx, resourceGroup, name)
resp, err := conn.Get(ctx, id.ResourceGroup, id.Name)

if err != nil {
return nil
Expand All @@ -151,19 +154,18 @@ func testCheckAzureRMLogAnalyticsWorkspaceExists(resourceName string) resource.T
return fmt.Errorf("Not found: %s", resourceName)
}

name := rs.Primary.Attributes["name"]
resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"]
if !hasResourceGroup {
return fmt.Errorf("Bad: no resource group found in state for Log Analytics Workspace: '%s'", name)
id, err := parse.LogAnalyticsWorkspaceID(rs.Primary.ID)
if err != nil {
return err
}

resp, err := conn.Get(ctx, resourceGroup, name)
resp, err := conn.Get(ctx, id.ResourceGroup, id.Name)
if err != nil {
return fmt.Errorf("Bad: Get on Log Analytics Workspace Client: %+v", err)
}

if resp.StatusCode == http.StatusNotFound {
return fmt.Errorf("Bad: Log Analytics Workspace '%s' (resource group: '%s') does not exist", name, resourceGroup)
return fmt.Errorf("Bad: Log Analytics Workspace '%s' (resource group: '%s') does not exist", id.Name, id.ResourceGroup)
}

return nil
Expand Down
@@ -0,0 +1,22 @@
package validate

import (
"fmt"

"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/loganalytics/parse"
)

func LogAnalyticsWorkspaceID(i interface{}, k string) (warnings []string, errors []error) {
v, ok := i.(string)
if !ok {
errors = append(errors, fmt.Errorf("expected type of %q to be string", k))
return
}

if _, err := parse.LogAnalyticsWorkspaceID(v); err != nil {
errors = append(errors, fmt.Errorf("parsing %q as a resource id: %v", k, err))
return
}

return warnings, errors
}
19 changes: 19 additions & 0 deletions azurerm/internal/services/sentinel/client/client.go
@@ -0,0 +1,19 @@
package client

import (
"github.com/Azure/azure-sdk-for-go/services/preview/securityinsight/mgmt/2017-08-01-preview/securityinsight"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/common"
)

type Client struct {
AlertRulesClient *securityinsight.AlertRulesClient
}

func NewClient(o *common.ClientOptions) *Client {
alertRulesClient := securityinsight.NewAlertRulesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&alertRulesClient.Client, o.ResourceManagerAuthorizer)

return &Client{
AlertRulesClient: &alertRulesClient,
}
}
@@ -0,0 +1,67 @@
package sentinel

import (
"fmt"
"time"

"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
"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/timeouts"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)

func dataSourceArmSentinelAlertRule() *schema.Resource {
return &schema.Resource{
Read: dataSourceArmSentinelAlertRuleRead,

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

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

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

func dataSourceArmSentinelAlertRuleRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*clients.Client).Sentinel.AlertRulesClient
ctx, cancel := timeouts.ForRead(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
}

resp, err := client.Get(ctx, workspaceID.ResourceGroup, workspaceID.Name, name)
if err != nil {
if utils.ResponseWasNotFound(resp.Response) {
return fmt.Errorf("Sentinel Alert Rule %q (Resource Group %q / Workspace: %q) was not found", name, workspaceID.ResourceGroup, workspaceID.Name)
}

return fmt.Errorf("retrieving Sentinel Alert Rule %q (Resource Group %q / Workspace: %q): %+v", name, workspaceID.ResourceGroup, workspaceID.Name, err)
}

id := alertRuleID(resp.Value)
if id == nil || *id == "" {
return fmt.Errorf("nil or empty ID of Sentinel Alert Rule %q (Resource Group %q / Workspace: %q)", name, workspaceID.ResourceGroup, workspaceID.Name)
}
d.SetId(*id)

return nil
}

0 comments on commit 232b14e

Please sign in to comment.