diff --git a/azurerm/config.go b/azurerm/config.go index 1a4f539fd14a..047cec52dc04 100644 --- a/azurerm/config.go +++ b/azurerm/config.go @@ -1034,10 +1034,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 5d793809714f..f05e5176b88f 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" @@ -155,6 +156,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, @@ -434,6 +441,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) @@ -548,6 +556,16 @@ func resourceArmStorageAccountCreate(d *schema.ResourceData, meta interface{}) e log.Printf("[INFO] storage account %q ID: %q", storageAccountName, *account.ID) d.SetId(*account.ID) + advancedThreatProtectionSetting := security.AdvancedThreatProtectionSetting{ + AdvancedThreatProtectionProperties: &security.AdvancedThreatProtectionProperties{ + IsEnabled: utils.Bool(d.Get("enable_advanced_threat_protection").(bool)), + }, + } + + 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) + } + return resourceArmStorageAccountRead(d, meta) } @@ -557,6 +575,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 @@ -709,6 +729,21 @@ func resourceArmStorageAccountUpdate(d *schema.ResourceData, meta interface{}) e d.SetPartial("network_rules") } + if d.HasChange("enable_advanced_threat_protection") { + + opts := security.AdvancedThreatProtectionSetting{ + AdvancedThreatProtectionProperties: &security.AdvancedThreatProtectionProperties{ + IsEnabled: utils.Bool(d.Get("enable_advanced_threat_protection").(bool)), + }, + } + + 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) } @@ -716,6 +751,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()) @@ -825,6 +861,15 @@ 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) + } + + if atpp := advancedThreatProtectionSetting.AdvancedThreatProtectionProperties; atpp != nil { + d.Set("enable_advanced_threat_protection", atpp.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 377e842d2c30..dff371ec063a 100644 --- a/azurerm/resource_arm_storage_account_test.go +++ b/azurerm/resource_arm_storage_account_test.go @@ -713,6 +713,47 @@ 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"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func testAccAzureRMStorageAccount_basic(rInt int, rString string, location string) string { return fmt.Sprintf(` resource "azurerm_resource_group" "testrg" { @@ -1286,3 +1327,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 704c4fe45d51..300e22be710d 100644 --- a/website/docs/r/storage_account.html.markdown +++ b/website/docs/r/storage_account.html.markdown @@ -107,6 +107,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.