Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Resource: azurerm_sentinel_log_analytics_workspace_onboarding #19692

Merged
merged 15 commits into from
Jan 17, 2023
Merged
6 changes: 6 additions & 0 deletions internal/services/sentinel/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package client

import (
alertruletemplates "github.com/Azure/azure-sdk-for-go/services/preview/securityinsight/mgmt/2021-09-01-preview/securityinsight" // nolint: staticcheck
"github.com/hashicorp/go-azure-sdk/resource-manager/securityinsights/2022-11-01/sentinelonboardingstates"
"github.com/hashicorp/terraform-provider-azurerm/internal/common"
securityinsight "github.com/tombuildsstuff/kermit/sdk/securityinsights/2022-10-01-preview/securityinsights"
)
Expand All @@ -13,6 +14,7 @@ type Client struct {
DataConnectorsClient *securityinsight.DataConnectorsClient
WatchlistsClient *securityinsight.WatchlistsClient
WatchlistItemsClient *securityinsight.WatchlistItemsClient
OnboardingStatesClient *sentinelonboardingstates.SentinelOnboardingStatesClient
}

func NewClient(o *common.ClientOptions) *Client {
Expand All @@ -34,12 +36,16 @@ func NewClient(o *common.ClientOptions) *Client {
watchListItemsClient := securityinsight.NewWatchlistItemsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&watchListItemsClient.Client, o.ResourceManagerAuthorizer)

onboardingStatesClient := sentinelonboardingstates.NewSentinelOnboardingStatesClientWithBaseURI(o.ResourceManagerEndpoint)
o.ConfigureClient(&onboardingStatesClient.Client, o.ResourceManagerAuthorizer)

return &Client{
AlertRulesClient: &alertRulesClient,
AlertRuleTemplatesClient: &alertRuleTemplatesClient,
AutomationRulesClient: &automationRulesClient,
DataConnectorsClient: &dataConnectorsClient,
WatchlistsClient: &watchListsClient,
WatchlistItemsClient: &watchListItemsClient,
OnboardingStatesClient: &onboardingStatesClient,
}
}
1 change: 1 addition & 0 deletions internal/services/sentinel/registration.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ func (r Registration) Resources() []sdk.Resource {
DataConnectorOffice365ProjectResource{},
DataConnectorOfficePowerBIResource{},
DataConnectorOfficeIRMResource{},
LogAnalyticsWorkspaceOnboardResource{},
DataConnectorThreatIntelligenceTAXIIResource{},
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
package sentinel

import (
"context"
"fmt"
"strconv"
"time"

"github.com/hashicorp/go-azure-helpers/lang/response"
"github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema"
"github.com/hashicorp/go-azure-sdk/resource-manager/securityinsights/2022-11-01/sentinelonboardingstates"
"github.com/hashicorp/terraform-provider-azurerm/internal/sdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation"
)

type SecurityInsightsSentinelOnboardingStateModel struct {
ResourceGroupName string `tfschema:"resource_group_name"`
WorkspaceName string `tfschema:"workspace_name"`
CustomerManagedKeyEnabled bool `tfschema:"customer_managed_key_enabled"`
}

type LogAnalyticsWorkspaceOnboardResource struct{}

var _ sdk.Resource = LogAnalyticsWorkspaceOnboardResource{}

func (r LogAnalyticsWorkspaceOnboardResource) ResourceType() string {
return "azurerm_sentinel_log_analytics_workspace_onboarding"
}

func (r LogAnalyticsWorkspaceOnboardResource) ModelObject() interface{} {
return &SecurityInsightsSentinelOnboardingStateModel{}
}

func (r LogAnalyticsWorkspaceOnboardResource) IDValidationFunc() pluginsdk.SchemaValidateFunc {
return sentinelonboardingstates.ValidateOnboardingStateID
}

func (r LogAnalyticsWorkspaceOnboardResource) Arguments() map[string]*pluginsdk.Schema {
return map[string]*pluginsdk.Schema{

"resource_group_name": commonschema.ResourceGroupName(),

"workspace_name": {
Type: pluginsdk.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validation.StringIsNotEmpty,
},

"customer_managed_key_enabled": {
Type: pluginsdk.TypeBool,
Optional: true,
Default: false,
ForceNew: true,
},
}
}

func (r LogAnalyticsWorkspaceOnboardResource) Attributes() map[string]*pluginsdk.Schema {
return map[string]*pluginsdk.Schema{}
}

func (r LogAnalyticsWorkspaceOnboardResource) Create() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 30 * time.Minute,
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
var model SecurityInsightsSentinelOnboardingStateModel
if err := metadata.Decode(&model); err != nil {
return fmt.Errorf("decoding: %+v", err)
}

client := metadata.Client.Sentinel.OnboardingStatesClient
subscriptionId := metadata.Client.Account.SubscriptionId
// the service only support `default` state
id := sentinelonboardingstates.NewOnboardingStateID(subscriptionId, model.ResourceGroupName, model.WorkspaceName, "default")
existing, err := client.Get(ctx, id)
if err != nil && !response.WasNotFound(existing.HttpResponse) {
return fmt.Errorf("checking for existing %s: %+v", id, err)
}

if !response.WasNotFound(existing.HttpResponse) {
return metadata.ResourceRequiresImport(r.ResourceType(), id)
}

properties := &sentinelonboardingstates.SentinelOnboardingState{
Properties: &sentinelonboardingstates.SentinelOnboardingStateProperties{
CustomerManagedKey: &model.CustomerManagedKeyEnabled,
},
}

if _, err := client.Create(ctx, id, *properties); err != nil {
return fmt.Errorf("creating %s: %+v", id, err)
}

deadline, ok := ctx.Deadline()
if !ok {
return fmt.Errorf("context has no deadline")
}

stateConf := &pluginsdk.StateChangeConf{
Pending: []string{"404"},
Target: []string{"200"},
Refresh: func() (interface{}, string, error) {
resp, err := client.Get(ctx, id)
if err != nil {
if response.WasNotFound(resp.HttpResponse) {
return resp, "404", nil
}
return resp, "", err
}
if resp.HttpResponse != nil {
return resp, strconv.Itoa(resp.HttpResponse.StatusCode), nil
}
return resp, "", fmt.Errorf("http response is nil")
},
Timeout: time.Until(deadline),
Delay: 15 * time.Second,
}

if _, err = stateConf.WaitForStateContext(ctx); err != nil {
return fmt.Errorf("waiting for %s to be fully onboarded: %+v", id, err)
}

metadata.SetID(id)
return nil
},
}
}

func (r LogAnalyticsWorkspaceOnboardResource) Read() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 5 * time.Minute,
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
client := metadata.Client.Sentinel.OnboardingStatesClient

id, err := sentinelonboardingstates.ParseOnboardingStateID(metadata.ResourceData.Id())
if err != nil {
return err
}

resp, err := client.Get(ctx, *id)
if err != nil {
if response.WasNotFound(resp.HttpResponse) {
return metadata.MarkAsGone(id)
}

return fmt.Errorf("retrieving %s: %+v", *id, err)
}

model := resp.Model
if model == nil {
return fmt.Errorf("retrieving %s: model was nil", id)
}

state := SecurityInsightsSentinelOnboardingStateModel{
ResourceGroupName: id.ResourceGroupName,
WorkspaceName: id.WorkspaceName,
}

if properties := model.Properties; properties != nil {
if properties.CustomerManagedKey != nil {
state.CustomerManagedKeyEnabled = *properties.CustomerManagedKey
}
}

return metadata.Encode(&state)
},
}
}

func (r LogAnalyticsWorkspaceOnboardResource) Delete() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 30 * time.Minute,
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
client := metadata.Client.Sentinel.OnboardingStatesClient

id, err := sentinelonboardingstates.ParseOnboardingStateID(metadata.ResourceData.Id())
if err != nil {
return err
}

if _, err := client.Delete(ctx, *id); err != nil {
return fmt.Errorf("deleting %s: %+v", id, err)
}

return nil
},
}
}
Loading