From c97a8165a88bb8396df06989e97b543bf3f7e7f4 Mon Sep 17 00:00:00 2001 From: Benjamin Weimer Date: Thu, 27 Jun 2019 11:13:50 +0200 Subject: [PATCH 1/3] Advanced threat protection for storage account --- azurerm/config.go | 10 ++- .../services/securitycenter/client.go | 7 +- azurerm/resource_arm_storage_account.go | 48 +++++++++++++ azurerm/resource_arm_storage_account_test.go | 72 +++++++++++++++++++ website/docs/r/storage_account.html.markdown | 2 + 5 files changed, 133 insertions(+), 6 deletions(-) diff --git a/azurerm/config.go b/azurerm/config.go index ad28fefdbbdd..75a10c39ae80 100644 --- a/azurerm/config.go +++ b/azurerm/config.go @@ -1099,10 +1099,14 @@ func (c *ArmClient) registerSecurityCenterClients(endpoint, subscriptionId strin workspaceSettingsClient := securitySvc.NewWorkspaceSettingsClientWithBaseURI(endpoint, subscriptionId, ascLocation) c.configureClient(&workspaceSettingsClient.Client, auth) + advancedThreatProtectionClient := securitySvc.NewAdvancedThreatProtectionClientWithBaseURI(endpoint, subscriptionId, ascLocation) + c.configureClient(&advancedThreatProtectionClient.Client, auth) + c.securityCenter = &securitycenter.Client{ - ContactsClient: contactsClient, - PricingClient: pricingsClient, - WorkspaceClient: workspaceSettingsClient, + ContactsClient: contactsClient, + PricingClient: pricingsClient, + WorkspaceClient: workspaceSettingsClient, + AdvancedThreatProtectionClient: advancedThreatProtectionClient, } } diff --git a/azurerm/internal/services/securitycenter/client.go b/azurerm/internal/services/securitycenter/client.go index 4cc107dbed87..b7bc64d55d54 100644 --- a/azurerm/internal/services/securitycenter/client.go +++ b/azurerm/internal/services/securitycenter/client.go @@ -3,7 +3,8 @@ package securitycenter import "github.com/Azure/azure-sdk-for-go/services/preview/security/mgmt/v1.0/security" type Client struct { - ContactsClient security.ContactsClient - PricingClient security.PricingsClient - WorkspaceClient security.WorkspaceSettingsClient + ContactsClient security.ContactsClient + PricingClient security.PricingsClient + WorkspaceClient security.WorkspaceSettingsClient + AdvancedThreatProtectionClient security.AdvancedThreatProtectionClient } diff --git a/azurerm/resource_arm_storage_account.go b/azurerm/resource_arm_storage_account.go index 6cdc28777c37..5a418029885b 100644 --- a/azurerm/resource_arm_storage_account.go +++ b/azurerm/resource_arm_storage_account.go @@ -6,6 +6,7 @@ import ( "regexp" "strings" + "github.com/Azure/azure-sdk-for-go/services/preview/security/mgmt/v1.0/security" "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2019-04-01/storage" "github.com/hashicorp/go-getter/helper/url" "github.com/hashicorp/terraform/helper/schema" @@ -153,6 +154,12 @@ func resourceArmStorageAccount() *schema.Resource { ForceNew: true, }, + "enable_advanced_threat_protection": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + "network_rules": { Type: schema.TypeList, MaxItems: 1, @@ -419,6 +426,7 @@ func validateAzureRMStorageAccountTags(v interface{}, _ string) (warnings []stri func resourceArmStorageAccountCreate(d *schema.ResourceData, meta interface{}) error { ctx := meta.(*ArmClient).StopContext client := meta.(*ArmClient).storageServiceClient + advancedThreatProtectionClient := meta.(*ArmClient).securityCenter.AdvancedThreatProtectionClient storageAccountName := d.Get("name").(string) resourceGroupName := d.Get("resource_group_name").(string) @@ -528,6 +536,19 @@ func resourceArmStorageAccountCreate(d *schema.ResourceData, meta interface{}) e log.Printf("[INFO] storage account %q ID: %q", storageAccountName, *account.ID) d.SetId(*account.ID) + enableAdvanceThreatProtection := d.Get("enable_advanced_threat_protection").(bool) + + advancedThreatProtectionSetting := security.AdvancedThreatProtectionSetting{ + AdvancedThreatProtectionProperties: &security.AdvancedThreatProtectionProperties{ + IsEnabled: &enableAdvanceThreatProtection, + }, + } + + _, err = advancedThreatProtectionClient.Create(ctx, d.Id(), advancedThreatProtectionSetting) + if err != nil { + return fmt.Errorf("Error updating Azure Storage Account enable_advanced_threat_protection %q: %+v", storageAccountName, err) + } + return resourceArmStorageAccountRead(d, meta) } @@ -537,6 +558,8 @@ func resourceArmStorageAccountCreate(d *schema.ResourceData, meta interface{}) e func resourceArmStorageAccountUpdate(d *schema.ResourceData, meta interface{}) error { ctx := meta.(*ArmClient).StopContext client := meta.(*ArmClient).storageServiceClient + advancedThreatProtectionClient := meta.(*ArmClient).securityCenter.AdvancedThreatProtectionClient + id, err := parseAzureResourceID(d.Id()) if err != nil { return err @@ -695,6 +718,22 @@ func resourceArmStorageAccountUpdate(d *schema.ResourceData, meta interface{}) e d.SetPartial("network_rules") } + if d.HasChange("enable_advanced_threat_protection") { + enableAdvanceThreatProtection := d.Get("enable_advanced_threat_protection").(bool) + + opts := security.AdvancedThreatProtectionSetting{ + AdvancedThreatProtectionProperties: &security.AdvancedThreatProtectionProperties{ + IsEnabled: &enableAdvanceThreatProtection, + }, + } + + if _, err := advancedThreatProtectionClient.Create(ctx, d.Id(), opts); err != nil { + return fmt.Errorf("Error updating Azure Storage Account enable_advanced_threat_protection %q: %+v", storageAccountName, err) + } + + d.SetPartial("enable_advanced_threat_protection") + } + d.Partial(false) return resourceArmStorageAccountRead(d, meta) } @@ -702,6 +741,7 @@ func resourceArmStorageAccountUpdate(d *schema.ResourceData, meta interface{}) e func resourceArmStorageAccountRead(d *schema.ResourceData, meta interface{}) error { ctx := meta.(*ArmClient).StopContext client := meta.(*ArmClient).storageServiceClient + advancedThreatProtectionClient := meta.(*ArmClient).securityCenter.AdvancedThreatProtectionClient endpointSuffix := meta.(*ArmClient).environment.StorageEndpointSuffix id, err := parseAzureResourceID(d.Id()) @@ -812,6 +852,14 @@ func resourceArmStorageAccountRead(d *schema.ResourceData, meta interface{}) err return err } + advancedThreatProtectionSetting, err := advancedThreatProtectionClient.Get(ctx, d.Id()) + + if err != nil { + return fmt.Errorf("Error reading the advanced threat protection settings of AzureRM Storage Account %q: %+v", name, err) + } + + d.Set("enable_advanced_threat_protection", advancedThreatProtectionSetting.AdvancedThreatProtectionProperties.IsEnabled) + flattenAndSetTags(d, resp.Tags) return nil diff --git a/azurerm/resource_arm_storage_account_test.go b/azurerm/resource_arm_storage_account_test.go index ef83d4a1630a..ad4cf1dceb79 100644 --- a/azurerm/resource_arm_storage_account_test.go +++ b/azurerm/resource_arm_storage_account_test.go @@ -673,6 +673,42 @@ func testCheckAzureRMStorageAccountDestroy(s *terraform.State) error { return nil } +func TestAccAzureRMStorageAccount_enableAdvancedThreatProtection(t *testing.T) { + resourceName := "azurerm_storage_account.testsa" + ri := tf.AccRandTimeInt() + rs := acctest.RandString(4) + location := testLocation() + preConfig := testAccAzureRMStorageAccount_enableAdvancedThreatProtection(ri, rs, location) + postConfig := testAccAzureRMStorageAccount_enableAdvancedThreatProtectionDisabled(ri, rs, location) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMStorageAccountDestroy, + Steps: []resource.TestStep{ + { + Config: preConfig, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMStorageAccountExists(resourceName), + resource.TestCheckResourceAttr("azurerm_storage_account.testsa", "enable_advanced_threat_protection", "true"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: postConfig, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMStorageAccountExists(resourceName), + resource.TestCheckResourceAttr("azurerm_storage_account.testsa", "enable_advanced_threat_protection", "false"), + ), + }, + }, + }) +} + func testAccAzureRMStorageAccount_basic(rInt int, rString string, location string) string { return fmt.Sprintf(` resource "azurerm_resource_group" "testrg" { @@ -1154,3 +1190,39 @@ resource "azurerm_storage_account" "testsa" { } `, rInt, location, rInt, rInt, rString) } + +func testAccAzureRMStorageAccount_enableAdvancedThreatProtection(rInt int, rString string, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "testrg" { + name = "acctestAzureRMSA-%d" + location = "%s" +} + +resource "azurerm_storage_account" "testsa" { + name = "unlikely23exst2acct%s" + resource_group_name = "${azurerm_resource_group.testrg.name}" + location = "${azurerm_resource_group.testrg.location}" + account_tier = "Standard" + account_replication_type = "LRS" + enable_advanced_threat_protection = true +} +`, rInt, location, rString) +} + +func testAccAzureRMStorageAccount_enableAdvancedThreatProtectionDisabled(rInt int, rString string, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "testrg" { + name = "acctestAzureRMSA-%d" + location = "%s" +} + +resource "azurerm_storage_account" "testsa" { + name = "unlikely23exst2acct%s" + resource_group_name = "${azurerm_resource_group.testrg.name}" + location = "${azurerm_resource_group.testrg.location}" + account_tier = "Standard" + account_replication_type = "LRS" + enable_advanced_threat_protection = false +} +`, rInt, location, rString) +} diff --git a/website/docs/r/storage_account.html.markdown b/website/docs/r/storage_account.html.markdown index d6a7f0e137ae..32713ba5f645 100644 --- a/website/docs/r/storage_account.html.markdown +++ b/website/docs/r/storage_account.html.markdown @@ -112,6 +112,8 @@ The following arguments are supported: * `network_rules` - (Optional) A `network_rules` block as documented below. +* `enable_advanced_threat_protection` (Optional) Boolean flag which controls if advanced threat protection is enabled, see [here](https://docs.microsoft.com/en-us/azure/storage/common/storage-advanced-threat-protection) for more information. Defaults to `false`. + * `tags` - (Optional) A mapping of tags to assign to the resource. * `identity` - (Optional) A Managed Service Identity block as defined below. From dc9fb927d961f6f830a4eca8f134610382c9410c Mon Sep 17 00:00:00 2001 From: Benjamin Weimer Date: Thu, 4 Jul 2019 08:53:11 +0200 Subject: [PATCH 2/3] fixing review issues of feature "advanced threat protection for storage account" --- azurerm/resource_arm_storage_account.go | 17 ++++++++--------- azurerm/resource_arm_storage_account_test.go | 5 +++++ 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/azurerm/resource_arm_storage_account.go b/azurerm/resource_arm_storage_account.go index a62f5efa3e7d..538ca18d3f83 100644 --- a/azurerm/resource_arm_storage_account.go +++ b/azurerm/resource_arm_storage_account.go @@ -556,16 +556,13 @@ func resourceArmStorageAccountCreate(d *schema.ResourceData, meta interface{}) e log.Printf("[INFO] storage account %q ID: %q", storageAccountName, *account.ID) d.SetId(*account.ID) - enableAdvanceThreatProtection := d.Get("enable_advanced_threat_protection").(bool) - advancedThreatProtectionSetting := security.AdvancedThreatProtectionSetting{ AdvancedThreatProtectionProperties: &security.AdvancedThreatProtectionProperties{ - IsEnabled: &enableAdvanceThreatProtection, + IsEnabled: utils.Bool(d.Get("enable_advanced_threat_protection").(bool)), }, } - _, err = advancedThreatProtectionClient.Create(ctx, d.Id(), advancedThreatProtectionSetting) - if err != nil { + if _, err = advancedThreatProtectionClient.Create(ctx, d.Id(), advancedThreatProtectionSetting); err != nil { return fmt.Errorf("Error updating Azure Storage Account enable_advanced_threat_protection %q: %+v", storageAccountName, err) } @@ -733,11 +730,10 @@ func resourceArmStorageAccountUpdate(d *schema.ResourceData, meta interface{}) e } if d.HasChange("enable_advanced_threat_protection") { - enableAdvanceThreatProtection := d.Get("enable_advanced_threat_protection").(bool) opts := security.AdvancedThreatProtectionSetting{ AdvancedThreatProtectionProperties: &security.AdvancedThreatProtectionProperties{ - IsEnabled: &enableAdvanceThreatProtection, + IsEnabled: utils.Bool(d.Get("enable_advanced_threat_protection").(bool)), }, } @@ -866,12 +862,15 @@ func resourceArmStorageAccountRead(d *schema.ResourceData, meta interface{}) err } advancedThreatProtectionSetting, err := advancedThreatProtectionClient.Get(ctx, d.Id()) - if err != nil { return fmt.Errorf("Error reading the advanced threat protection settings of AzureRM Storage Account %q: %+v", name, err) } - d.Set("enable_advanced_threat_protection", advancedThreatProtectionSetting.AdvancedThreatProtectionProperties.IsEnabled) + if &advancedThreatProtectionSetting != nil { + if atpp := advancedThreatProtectionSetting.AdvancedThreatProtectionProperties; atpp != nil { + d.Set("enable_advanced_threat_protection", atpp.IsEnabled) + } + } flattenAndSetTags(d, resp.Tags) diff --git a/azurerm/resource_arm_storage_account_test.go b/azurerm/resource_arm_storage_account_test.go index b464445412de..dff371ec063a 100644 --- a/azurerm/resource_arm_storage_account_test.go +++ b/azurerm/resource_arm_storage_account_test.go @@ -745,6 +745,11 @@ func TestAccAzureRMStorageAccount_enableAdvancedThreatProtection(t *testing.T) { resource.TestCheckResourceAttr("azurerm_storage_account.testsa", "enable_advanced_threat_protection", "false"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } From 20fd9acd786891da6faca854427f293d73663cc1 Mon Sep 17 00:00:00 2001 From: Benjamin Weimer Date: Thu, 4 Jul 2019 09:13:31 +0200 Subject: [PATCH 3/3] remove unnecessary nil check --- azurerm/resource_arm_storage_account.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/azurerm/resource_arm_storage_account.go b/azurerm/resource_arm_storage_account.go index 538ca18d3f83..f05e5176b88f 100644 --- a/azurerm/resource_arm_storage_account.go +++ b/azurerm/resource_arm_storage_account.go @@ -866,10 +866,8 @@ func resourceArmStorageAccountRead(d *schema.ResourceData, meta interface{}) err return fmt.Errorf("Error reading the advanced threat protection settings of AzureRM Storage Account %q: %+v", name, err) } - if &advancedThreatProtectionSetting != nil { - if atpp := advancedThreatProtectionSetting.AdvancedThreatProtectionProperties; atpp != nil { - d.Set("enable_advanced_threat_protection", atpp.IsEnabled) - } + if atpp := advancedThreatProtectionSetting.AdvancedThreatProtectionProperties; atpp != nil { + d.Set("enable_advanced_threat_protection", atpp.IsEnabled) } flattenAndSetTags(d, resp.Tags)