Skip to content

Commit

Permalink
new resource "azurerm_iot_security_solution" (#10034)
Browse files Browse the repository at this point in the history
intro:

doc docs.microsoft.com/en-us/azure/defender-for-iot
iot security solution is a unified security solution for identifying IoT/OT assets, vulnerabilities, and threats
for the recommendation schema,

if create a iot security solution with no recommendation specified, all recommendation config are auto enabled.
If we only pass few options in recommendation and make it enabled or disabled, all other config are auto enabled.
to handle such matter and avoid diff, I have made each recommendation config as a sub schema, please review and check whether it's ok
  • Loading branch information
njuCZ authored Jan 28, 2021
1 parent 1582b26 commit c0349b7
Show file tree
Hide file tree
Showing 14 changed files with 1,183 additions and 11 deletions.
65 changes: 54 additions & 11 deletions azurerm/internal/services/iothub/iothub_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -602,12 +602,23 @@ func resourceIotHubCreateUpdate(d *schema.ResourceData, meta interface{}) error
props.Properties.MinTLSVersion = utils.String(v.(string))
}

future, err := client.CreateOrUpdate(ctx, resourceGroup, name, props, "")
_, err = client.CreateOrUpdate(ctx, resourceGroup, name, props, "")
if err != nil {
return fmt.Errorf("Error creating/updating IotHub %q (Resource Group %q): %+v", name, resourceGroup, err)
}

if err = future.WaitForCompletionRef(ctx, client.Client); err != nil {
timeout := schema.TimeoutUpdate
if d.IsNewResource() {
timeout = schema.TimeoutCreate
}
stateConf := &resource.StateChangeConf{
Pending: []string{"Activating", "Transitioning"},
Target: []string{"Succeeded"},
Refresh: iothubStateRefreshFunc(ctx, client, resourceGroup, name),
Timeout: d.Timeout(timeout),
}

if _, err := stateConf.WaitForState(); err != nil {
return fmt.Errorf("Error waiting for the completion of the creating/updating of IotHub %q (Resource Group %q): %+v", name, resourceGroup, err)
}

Expand Down Expand Up @@ -642,16 +653,13 @@ func resourceIotHubRead(d *schema.ResourceData, meta interface{}) error {
return fmt.Errorf("retrieving IotHub Client %q (Resource Group %q): %+v", id.Name, id.ResourceGroup, err)
}

keysResp, err := client.ListKeys(ctx, id.ResourceGroup, id.Name)
if err != nil {
return fmt.Errorf("listing keys for IoTHub %q (Resource Group %q): %+v", id.Name, id.ResourceGroup, err)
}

keyList := keysResp.Response()
keys := flattenIoTHubSharedAccessPolicy(keyList.Value)
if keysResp, err := client.ListKeys(ctx, id.ResourceGroup, id.Name); err == nil {
keyList := keysResp.Response()
keys := flattenIoTHubSharedAccessPolicy(keyList.Value)

if err := d.Set("shared_access_policy", keys); err != nil {
return fmt.Errorf("setting `shared_access_policy` in IoTHub %q: %+v", id.Name, err)
if err := d.Set("shared_access_policy", keys); err != nil {
return fmt.Errorf("setting `shared_access_policy` in IoTHub %q: %+v", id.Name, err)
}
}

if properties := hub.Properties; properties != nil {
Expand Down Expand Up @@ -736,6 +744,20 @@ func resourceIotHubDelete(d *schema.ResourceData, meta interface{}) error {
locks.ByName(id.Name, IothubResourceName)
defer locks.UnlockByName(id.Name, IothubResourceName)

// when running acctest of `azurerm_iot_security_solution`, we found after delete the iot security solution, the iothub provisionState is `Transitioning`
// if we delete directly, the func `client.Delete` will throw error
// so first wait for the iotHub state become succeed
stateConf := &resource.StateChangeConf{
Pending: []string{"Activating", "Transitioning"},
Target: []string{"Succeeded"},
Refresh: iothubStateRefreshFunc(ctx, client, id.ResourceGroup, id.Name),
Timeout: d.Timeout(schema.TimeoutDelete),
}

if _, err := stateConf.WaitForState(); err != nil {
return fmt.Errorf("waiting for ProvisioningState of IotHub %q (Resource Group %q) to become `Succeeded`: %+v", id.Name, id.ResourceGroup, err)
}

future, err := client.Delete(ctx, id.ResourceGroup, id.Name)
if err != nil {
if response.WasNotFound(future.Response()) {
Expand Down Expand Up @@ -764,6 +786,27 @@ func waitForIotHubToBeDeleted(ctx context.Context, client *devices.IotHubResourc
return nil
}

func iothubStateRefreshFunc(ctx context.Context, client *devices.IotHubResourceClient, resourceGroup, name string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
res, err := client.Get(ctx, resourceGroup, name)

log.Printf("Retrieving IoTHub %q (Resource Group %q) returned Status %d", resourceGroup, name, res.StatusCode)

if err != nil {
if utils.ResponseWasNotFound(res.Response) {
return res, "NotFound", nil
}
return nil, "", fmt.Errorf("polling for the Provisioning State of the IotHub %q (RG: %q): %+v", name, resourceGroup, err)
}

if res.Properties == nil || res.Properties.ProvisioningState == nil {
return res, "", fmt.Errorf("polling for the Provisioning State of the IotHub %q (RG: %q): %+v", name, resourceGroup, err)
}

return res, *res.Properties.ProvisioningState, nil
}
}

func iothubStateStatusCodeRefreshFunc(ctx context.Context, client *devices.IotHubResourceClient, resourceGroup, name string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
res, err := client.Get(ctx, resourceGroup, name)
Expand Down
5 changes: 5 additions & 0 deletions azurerm/internal/services/securitycenter/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

type Client struct {
ContactsClient *security.ContactsClient
IotSecuritySolutionClient *security.IotSecuritySolutionClient
PricingClient *security.PricingsClient
WorkspaceClient *security.WorkspaceSettingsClient
AdvancedThreatProtectionClient *security.AdvancedThreatProtectionClient
Expand All @@ -21,6 +22,9 @@ func NewClient(o *common.ClientOptions) *Client {
ContactsClient := security.NewContactsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId, ascLocation)
o.ConfigureClient(&ContactsClient.Client, o.ResourceManagerAuthorizer)

IotSecuritySolutionClient := security.NewIotSecuritySolutionClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId, ascLocation)
o.ConfigureClient(&IotSecuritySolutionClient.Client, o.ResourceManagerAuthorizer)

PricingClient := security.NewPricingsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId, ascLocation)
o.ConfigureClient(&PricingClient.Client, o.ResourceManagerAuthorizer)

Expand All @@ -41,6 +45,7 @@ func NewClient(o *common.ClientOptions) *Client {

return &Client{
ContactsClient: &ContactsClient,
IotSecuritySolutionClient: &IotSecuritySolutionClient,
PricingClient: &PricingClient,
WorkspaceClient: &WorkspaceClient,
AdvancedThreatProtectionClient: &AdvancedThreatProtectionClient,
Expand Down
Loading

0 comments on commit c0349b7

Please sign in to comment.