From 3f98f8d37219d42384fd8d5206e69380ea33caf8 Mon Sep 17 00:00:00 2001 From: Tilen Faganel Date: Mon, 23 Jul 2018 11:15:01 +0100 Subject: [PATCH 1/8] Added SQL Threat Detection Policy properties to the `azurerm_sql_server` resource --- azurerm/config.go | 36 ++-- azurerm/resource_arm_sql_database.go | 192 ++++++++++++++++++++++ azurerm/resource_arm_sql_database_test.go | 86 ++++++++++ website/docs/r/sql_database.html.markdown | 13 ++ 4 files changed, 313 insertions(+), 14 deletions(-) diff --git a/azurerm/config.go b/azurerm/config.go index 941a5b15a0ba..821a20360041 100644 --- a/azurerm/config.go +++ b/azurerm/config.go @@ -127,20 +127,21 @@ type ArmClient struct { iothubResourceClient devices.IotHubResourceClient // Databases - mysqlConfigurationsClient mysql.ConfigurationsClient - mysqlDatabasesClient mysql.DatabasesClient - mysqlFirewallRulesClient mysql.FirewallRulesClient - mysqlServersClient mysql.ServersClient - postgresqlConfigurationsClient postgresql.ConfigurationsClient - postgresqlDatabasesClient postgresql.DatabasesClient - postgresqlFirewallRulesClient postgresql.FirewallRulesClient - postgresqlServersClient postgresql.ServersClient - sqlDatabasesClient sql.DatabasesClient - sqlElasticPoolsClient sql.ElasticPoolsClient - sqlFirewallRulesClient sql.FirewallRulesClient - sqlServersClient sql.ServersClient - sqlServerAzureADAdministratorsClient sql.ServerAzureADAdministratorsClient - sqlVirtualNetworkRulesClient sql.VirtualNetworkRulesClient + mysqlConfigurationsClient mysql.ConfigurationsClient + mysqlDatabasesClient mysql.DatabasesClient + mysqlFirewallRulesClient mysql.FirewallRulesClient + mysqlServersClient mysql.ServersClient + postgresqlConfigurationsClient postgresql.ConfigurationsClient + postgresqlDatabasesClient postgresql.DatabasesClient + postgresqlFirewallRulesClient postgresql.FirewallRulesClient + postgresqlServersClient postgresql.ServersClient + sqlDatabasesClient sql.DatabasesClient + sqlDatabaseThreatDetectionPoliciesClient sql.DatabaseThreatDetectionPoliciesClient + sqlElasticPoolsClient sql.ElasticPoolsClient + sqlFirewallRulesClient sql.FirewallRulesClient + sqlServersClient sql.ServersClient + sqlServerAzureADAdministratorsClient sql.ServerAzureADAdministratorsClient + sqlVirtualNetworkRulesClient sql.VirtualNetworkRulesClient // Data Lake Store dataLakeStoreAccountClient account.AccountsClient @@ -630,6 +631,13 @@ func (c *ArmClient) registerDatabases(endpoint, subscriptionId string, auth auto sqlDBClient.SkipResourceProviderRegistration = c.skipProviderRegistration c.sqlDatabasesClient = sqlDBClient + sqlDTDPClient := sql.NewDatabaseThreatDetectionPoliciesClientWithBaseURI(endpoint, subscriptionId) + setUserAgent(&sqlDTDPClient.Client) + sqlDTDPClient.Authorizer = auth + sqlDTDPClient.Sender = sender + sqlDTDPClient.SkipResourceProviderRegistration = c.skipProviderRegistration + c.sqlDatabaseThreatDetectionPoliciesClient = sqlDTDPClient + sqlFWClient := sql.NewFirewallRulesClientWithBaseURI(endpoint, subscriptionId) setUserAgent(&sqlFWClient.Client) sqlFWClient.Authorizer = auth diff --git a/azurerm/resource_arm_sql_database.go b/azurerm/resource_arm_sql_database.go index e9fcce7881d6..bcc6ae56d2e1 100644 --- a/azurerm/resource_arm_sql_database.go +++ b/azurerm/resource_arm_sql_database.go @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/terraform/helper/schema" "github.com/hashicorp/terraform/helper/validation" "github.com/satori/go.uuid" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/suppress" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) @@ -196,8 +197,98 @@ func resourceArmSqlDatabase() *schema.Resource { Computed: true, }, + "threat_detection_policy": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "disabled_alerts": { + Type: schema.TypeString, + Optional: true, + DiffSuppressFunc: suppress.CaseDifference, + }, + + "email_account_admins": { + Type: schema.TypeString, + Optional: true, + DiffSuppressFunc: suppress.CaseDifference, + Default: string(sql.SecurityAlertPolicyEmailAccountAdminsDisabled), + ValidateFunc: validation.StringInSlice([]string{ + string(sql.SecurityAlertPolicyEmailAccountAdminsDisabled), + string(sql.SecurityAlertPolicyEmailAccountAdminsEnabled), + }, true), + }, + + "email_addresses": { + Type: schema.TypeString, + Optional: true, + }, + + "retention_days": { + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntAtLeast(0), + }, + + "state": { + Type: schema.TypeString, + Optional: true, + DiffSuppressFunc: suppress.CaseDifference, + Default: string(sql.SecurityAlertPolicyStateDisabled), + ValidateFunc: validation.StringInSlice([]string{ + string(sql.SecurityAlertPolicyStateDisabled), + string(sql.SecurityAlertPolicyStateEnabled), + string(sql.SecurityAlertPolicyStateNew), + }, true), + }, + + "storage_account_access_key": { + Type: schema.TypeString, + Optional: true, + Sensitive: true, + }, + + "storage_endpoint": { + Type: schema.TypeString, + Optional: true, + }, + + "use_server_default": { + Type: schema.TypeString, + Optional: true, + DiffSuppressFunc: suppress.CaseDifference, + Default: string(sql.SecurityAlertPolicyUseServerDefaultDisabled), + ValidateFunc: validation.StringInSlice([]string{ + string(sql.SecurityAlertPolicyUseServerDefaultDisabled), + string(sql.SecurityAlertPolicyUseServerDefaultEnabled), + }, true), + }, + }, + }, + }, + "tags": tagsSchema(), }, + + CustomizeDiff: func(diff *schema.ResourceDiff, v interface{}) error { + + threatDetection, hasThreatDetection := diff.GetOk("threat_detection_policy") + if hasThreatDetection { + if tl := threatDetection.([]interface{}); len(tl) > 0 && tl[0] != nil { + t := tl[0].(map[string]interface{}) + + state := strings.ToLower(t["state"].(string)) + _, hasStorageEndpoint := t["storage_endpoint"] + _, hasStorageAccountAccessKey := t["storage_account_access_key"] + if state == "enabled" && !hasStorageEndpoint && !hasStorageAccountAccessKey { + return fmt.Errorf("`storage_endpoint` and `storage_account_access_key` are required when `state` is `Enabled`") + } + } + } + + return nil + }, } } @@ -212,6 +303,11 @@ func resourceArmSqlDatabaseCreateUpdate(d *schema.ResourceData, meta interface{} createMode := d.Get("create_mode").(string) tags := d.Get("tags").(map[string]interface{}) + threatDetection, err := expandArmSqlServerThreatDetectionPolicy(d, location) + if err != nil { + return fmt.Errorf("Error parsing the database threat detection policy: %+v", err) + } + properties := sql.Database{ Location: utils.String(location), DatabaseProperties: &sql.DatabaseProperties{ @@ -327,6 +423,14 @@ func resourceArmSqlDatabaseCreateUpdate(d *schema.ResourceData, meta interface{} d.SetId(*resp.ID) + if threatDetection != nil { + threatDetectionClient := meta.(*ArmClient).sqlDatabaseThreatDetectionPoliciesClient + _, err = threatDetectionClient.CreateOrUpdate(ctx, resourceGroup, serverName, name, *threatDetection) + if err != nil { + return fmt.Errorf("Error setting database threat detection policy: %+v", err) + } + } + return resourceArmSqlDatabaseRead(d, meta) } @@ -354,6 +458,19 @@ func resourceArmSqlDatabaseRead(d *schema.ResourceData, meta interface{}) error return fmt.Errorf("Error making Read request on Sql Database %s: %+v", name, err) } + oldThreatDetection, hasOldThreatDetection := d.GetOk("threat_detection_policy") + if hasOldThreatDetection { + threatDetectionClient := meta.(*ArmClient).sqlDatabaseThreatDetectionPoliciesClient + + threatDetection, err := threatDetectionClient.Get(ctx, resourceGroup, serverName, name) + if err == nil { + flattenedThreatDetection := flattenArmSqlServerThreatDetectionPolicy(threatDetection, oldThreatDetection.([]interface{})) + if err := d.Set("threat_detection_policy", flattenedThreatDetection); err != nil { + return fmt.Errorf("Error setting `threat_detection_policy`: %+v", err) + } + } + } + d.Set("name", resp.Name) d.Set("resource_group_name", resourceGroup) if location := resp.Location; location != nil { @@ -439,6 +556,36 @@ func flattenEncryptionStatus(encryption *[]sql.TransparentDataEncryption) string return "" } +func flattenArmSqlServerThreatDetectionPolicy(policy sql.DatabaseSecurityAlertPolicy, oldThreatDetection []interface{}) []interface{} { + + properties := policy.DatabaseSecurityAlertPolicyProperties + threatDetectionPolicy := make(map[string]interface{}) + + threatDetectionPolicy["state"] = string(properties.State) + threatDetectionPolicy["email_account_admins"] = string(properties.EmailAccountAdmins) + threatDetectionPolicy["use_server_default"] = string(properties.UseServerDefault) + + if properties.DisabledAlerts != nil { + threatDetectionPolicy["disabled_alerts"] = *properties.DisabledAlerts + } + if properties.EmailAddresses != nil { + threatDetectionPolicy["email_addresses"] = *properties.EmailAddresses + } + if properties.StorageEndpoint != nil { + threatDetectionPolicy["storage_endpoint"] = *properties.StorageEndpoint + } + if properties.RetentionDays != nil { + threatDetectionPolicy["retention_days"] = int(*properties.RetentionDays) + } + + // If storage account access key is in state readd it to the new state, as the API does not return it for security reasons + if t, ok := oldThreatDetection[0].(map[string]interface{})["storage_account_access_key"]; ok { + threatDetectionPolicy["storage_account_access_key"] = t.(string) + } + + return []interface{}{threatDetectionPolicy} +} + func expandAzureRmSqlDatabaseImport(d *schema.ResourceData) sql.ImportExtensionRequest { v := d.Get("import") dbimportRefs := v.([]interface{}) @@ -456,3 +603,48 @@ func expandAzureRmSqlDatabaseImport(d *schema.ResourceData) sql.ImportExtensionR }, } } + +func expandArmSqlServerThreatDetectionPolicy(d *schema.ResourceData, location string) (*sql.DatabaseSecurityAlertPolicy, error) { + v, ok := d.GetOk("threat_detection_policy") + if !ok { + return nil, nil + } + + if tdl := v.([]interface{}); len(tdl) > 0 && tdl[0] != nil { + threadDetection := tdl[0].(map[string]interface{}) + + state := threadDetection["state"].(string) + emailAccountAdmins := threadDetection["email_account_admins"].(string) + useServerDefault := threadDetection["use_server_default"].(string) + + policy := sql.DatabaseSecurityAlertPolicy{ + Location: utils.String(location), + DatabaseSecurityAlertPolicyProperties: &sql.DatabaseSecurityAlertPolicyProperties{ + State: sql.SecurityAlertPolicyState(state), + EmailAccountAdmins: sql.SecurityAlertPolicyEmailAccountAdmins(emailAccountAdmins), + UseServerDefault: sql.SecurityAlertPolicyUseServerDefault(useServerDefault), + }, + } + properties := policy.DatabaseSecurityAlertPolicyProperties + + if v, ok := threadDetection["disabled_alerts"]; ok { + properties.DisabledAlerts = utils.String(v.(string)) + } + if v, ok := threadDetection["email_addresses"]; ok { + properties.EmailAddresses = utils.String(v.(string)) + } + if v, ok := threadDetection["retention_days"]; ok { + properties.RetentionDays = utils.Int32(int32(v.(int))) + } + if v, ok := threadDetection["storage_account_access_key"]; ok { + properties.StorageAccountAccessKey = utils.String(v.(string)) + } + if v, ok := threadDetection["storage_endpoint"]; ok { + properties.StorageEndpoint = utils.String(v.(string)) + } + + return &policy, nil + } + + return nil, nil +} diff --git a/azurerm/resource_arm_sql_database_test.go b/azurerm/resource_arm_sql_database_test.go index 43644d3f6a06..e15c10e5fdfd 100644 --- a/azurerm/resource_arm_sql_database_test.go +++ b/azurerm/resource_arm_sql_database_test.go @@ -215,6 +215,44 @@ func TestAccAzureRMSqlDatabase_requestedServiceObjectiveName(t *testing.T) { }) } +func TestAccAzureRMSqlDatabase_threatDetectionPolicy(t *testing.T) { + resourceName := "azurerm_sql_database.test" + ri := acctest.RandInt() + location := testLocation() + preConfig := testAccAzureRMSqlDatabase_threatDetectionPolicy(ri, location, "Enabled", "Sql_Injection", "Enabled", "", "Disabled", 15) + postConfig := testAccAzureRMSqlDatabase_threatDetectionPolicy(ri, location, "Enabled", "Sql_Injection", "Enabled", "", "Disabled", 15) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMSqlDatabaseDestroy, + Steps: []resource.TestStep{ + { + Config: preConfig, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMSqlDatabaseExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "threat_detection_policy.#", "1"), + resource.TestCheckResourceAttr(resourceName, "threat_detection_policy.0.state", "Enabled"), + resource.TestCheckResourceAttr(resourceName, "threat_detection_policy.0.retention_days", "15"), + resource.TestCheckResourceAttr(resourceName, "threat_detection_policy.0.disabled_alerts", "Sql_Injection"), + resource.TestCheckResourceAttr(resourceName, "threat_detection_policy.0.email_account_admins", "Enabled"), + ), + }, + { + Config: postConfig, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMSqlDatabaseExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "threat_detection_policy.#", "1"), + resource.TestCheckResourceAttr(resourceName, "threat_detection_policy.0.state", "Enabled"), + resource.TestCheckResourceAttr(resourceName, "threat_detection_policy.0.retention_days", "15"), + resource.TestCheckResourceAttr(resourceName, "threat_detection_policy.0.disabled_alerts", "Sql_Injection"), + resource.TestCheckResourceAttr(resourceName, "threat_detection_policy.0.email_account_admins", "Enabled"), + ), + }, + }, + }) +} + func testCheckAzureRMSqlDatabaseExists(name string) resource.TestCheckFunc { return func(s *terraform.State) error { @@ -644,3 +682,51 @@ resource "azurerm_sql_database" "test" { } `, rInt, location, rInt, rInt, requestedServiceObjectiveName) } + +func testAccAzureRMSqlDatabase_threatDetectionPolicy(rInt int, location, state, disabledAlerts, emailAccountAdmins, emailAddresses, + useServerDefault string, retentionDays int) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_storage_account" "test" { + name = "test%d" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + account_tier = "Standard" + account_replication_type = "GRS" + } + +resource "azurerm_sql_server" "test" { + name = "acctestsqlserver%d" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + version = "12.0" + administrator_login = "mradministrator" + administrator_login_password = "thisIsDog11" +} + +resource "azurerm_sql_database" "test" { + name = "acctestdb%d" + resource_group_name = "${azurerm_resource_group.test.name}" + server_name = "${azurerm_sql_server.test.name}" + location = "${azurerm_resource_group.test.location}" + edition = "Standard" + collation = "SQL_Latin1_General_CP1_CI_AS" + max_size_bytes = "1073741824" + + threat_detection_policy { + retention_days = %d + state = "%s" + disabled_alerts = "%s" + email_account_admins = "%s" + email_addresses = "%s" + storage_account_access_key = "${azurerm_storage_account.test.primary_access_key}" + storage_endpoint = "${azurerm_storage_account.test.primary_blob_endpoint}" + use_server_default = "%s" + } +} +`, rInt, location, rInt, rInt, rInt, retentionDays, state, disabledAlerts, emailAccountAdmins, emailAddresses, useServerDefault) +} diff --git a/website/docs/r/sql_database.html.markdown b/website/docs/r/sql_database.html.markdown index cd0387dc4f8c..2e7dc5a4d0c7 100644 --- a/website/docs/r/sql_database.html.markdown +++ b/website/docs/r/sql_database.html.markdown @@ -73,6 +73,8 @@ The following arguments are supported: * `elastic_pool_name` - (Optional) The name of the elastic database pool. +* `threat_detection_policy` - (Optional) Threat detection policy configuration. The `threat_detection_policy` block supports fields documented below. + * `tags` - (Optional) A mapping of tags to assign to the resource. `import` supports the following: @@ -85,6 +87,17 @@ The following arguments are supported: * `authentication_type` - (Required) Specifies the type of authentication used to access the server. Valid values are `SQL` or `ADPassword`. * `operation_mode` - (Optional) Specifies the type of import operation being performed. The only allowable value is `Import`. +`threat_detection_policy` supports the following: + +* `state` - (Required) Specifies the state of the policy. If state is Enabled, storageEndpoint and storageAccountAccessKey are required. +* `disabled_alerts` - (Optional) Specifies the semicolon-separated list of alerts that are disabled, or empty string to disable no alerts. Possible values: Sql_Injection; Sql_Injection_Vulnerability; Access_Anomaly; Usage_Anomaly. +* `email_account_admins` - (Optional) Specifies that the alert is sent to the account administrators. +* `email_addresses` - (Optional) Specifies the semicolon-separated list of e-mail addresses to which the alert is sent. +* `retention_days` - (Optional) Specifies the number of days to keep in the Threat Detection audit logs. +* `storage_account_access_key` - (Optional) Specifies the identifier key of the Threat Detection audit storage account. If state is Enabled, storageAccountAccessKey is required. +* `storage_endpoint` - (Optional) Specifies the blob storage endpoint (e.g. https://MyAccount.blob.core.windows.net). This blob storage will hold all Threat Detection audit logs. If state is Enabled, storageEndpoint is required. +* `use_server_default` - (Optional) Specifies whether to use the default server policy. + ## Attributes Reference The following attributes are exported: From 60c6ccd4f72ccc9ee78ddc2ef4fad4cc444da2f3 Mon Sep 17 00:00:00 2001 From: Tilen Faganel Date: Mon, 23 Jul 2018 15:10:36 +0100 Subject: [PATCH 2/8] Minor cleanup of unnecessary conditions in the sql threat detection configuration of the `azurerm_sql_database` resource --- azurerm/resource_arm_sql_database.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/azurerm/resource_arm_sql_database.go b/azurerm/resource_arm_sql_database.go index bcc6ae56d2e1..481f106a444c 100644 --- a/azurerm/resource_arm_sql_database.go +++ b/azurerm/resource_arm_sql_database.go @@ -275,7 +275,7 @@ func resourceArmSqlDatabase() *schema.Resource { threatDetection, hasThreatDetection := diff.GetOk("threat_detection_policy") if hasThreatDetection { - if tl := threatDetection.([]interface{}); len(tl) > 0 && tl[0] != nil { + if tl := threatDetection.([]interface{}); len(tl) > 0 { t := tl[0].(map[string]interface{}) state := strings.ToLower(t["state"].(string)) @@ -610,7 +610,7 @@ func expandArmSqlServerThreatDetectionPolicy(d *schema.ResourceData, location st return nil, nil } - if tdl := v.([]interface{}); len(tdl) > 0 && tdl[0] != nil { + if tdl := v.([]interface{}); len(tdl) > 0 { threadDetection := tdl[0].(map[string]interface{}) state := threadDetection["state"].(string) From 2e2d854922214ad9d608d3760bbd0b9e8bd1bab8 Mon Sep 17 00:00:00 2001 From: Tilen Faganel Date: Wed, 25 Jul 2018 09:42:47 +0100 Subject: [PATCH 3/8] Updated schema type of string lists to a type set with some minor fixes in the sql threat detection configuration of the `azurerm_sql_database` resource --- azurerm/resource_arm_sql_database.go | 90 +++++++++++++++-------- azurerm/resource_arm_sql_database_test.go | 30 +++----- website/docs/r/sql_database.html.markdown | 16 ++-- 3 files changed, 80 insertions(+), 56 deletions(-) diff --git a/azurerm/resource_arm_sql_database.go b/azurerm/resource_arm_sql_database.go index 481f106a444c..433a8c3b574c 100644 --- a/azurerm/resource_arm_sql_database.go +++ b/azurerm/resource_arm_sql_database.go @@ -204,9 +204,17 @@ func resourceArmSqlDatabase() *schema.Resource { Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "disabled_alerts": { - Type: schema.TypeString, - Optional: true, - DiffSuppressFunc: suppress.CaseDifference, + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validation.StringInSlice([]string{ + "Sql_Injection", + "Sql_Injection_Vulnerability", + "Access_Anomaly", + }, true), + }, + Set: schema.HashString, }, "email_account_admins": { @@ -221,8 +229,12 @@ func resourceArmSqlDatabase() *schema.Resource { }, "email_addresses": { - Type: schema.TypeString, + Type: schema.TypeSet, Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Set: schema.HashString, }, "retention_days": { @@ -423,12 +435,10 @@ func resourceArmSqlDatabaseCreateUpdate(d *schema.ResourceData, meta interface{} d.SetId(*resp.ID) - if threatDetection != nil { - threatDetectionClient := meta.(*ArmClient).sqlDatabaseThreatDetectionPoliciesClient - _, err = threatDetectionClient.CreateOrUpdate(ctx, resourceGroup, serverName, name, *threatDetection) - if err != nil { - return fmt.Errorf("Error setting database threat detection policy: %+v", err) - } + threatDetectionClient := meta.(*ArmClient).sqlDatabaseThreatDetectionPoliciesClient + _, err = threatDetectionClient.CreateOrUpdate(ctx, resourceGroup, serverName, name, *threatDetection) + if err != nil { + return fmt.Errorf("Error setting database threat detection policy: %+v", err) } return resourceArmSqlDatabaseRead(d, meta) @@ -565,11 +575,21 @@ func flattenArmSqlServerThreatDetectionPolicy(policy sql.DatabaseSecurityAlertPo threatDetectionPolicy["email_account_admins"] = string(properties.EmailAccountAdmins) threatDetectionPolicy["use_server_default"] = string(properties.UseServerDefault) - if properties.DisabledAlerts != nil { - threatDetectionPolicy["disabled_alerts"] = *properties.DisabledAlerts + if properties.DisabledAlerts != nil && *properties.DisabledAlerts != "" { + alerts := strings.Split(*properties.DisabledAlerts, ";") + flattenedAlerts := make([]interface{}, len(alerts)) + for i := range alerts { + flattenedAlerts[i] = alerts[i] + } + threatDetectionPolicy["disabled_alerts"] = schema.NewSet(schema.HashString, flattenedAlerts) } - if properties.EmailAddresses != nil { - threatDetectionPolicy["email_addresses"] = *properties.EmailAddresses + if properties.EmailAddresses != nil && *properties.EmailAddresses != "" { + emails := strings.Split(*properties.EmailAddresses, ";") + flattenedEmails := make([]interface{}, len(emails)) + for i := range emails { + flattenedEmails[i] = emails[i] + } + threatDetectionPolicy["email_addresses"] = schema.NewSet(schema.HashString, flattenedEmails) } if properties.StorageEndpoint != nil { threatDetectionPolicy["storage_endpoint"] = *properties.StorageEndpoint @@ -605,33 +625,41 @@ func expandAzureRmSqlDatabaseImport(d *schema.ResourceData) sql.ImportExtensionR } func expandArmSqlServerThreatDetectionPolicy(d *schema.ResourceData, location string) (*sql.DatabaseSecurityAlertPolicy, error) { + policy := sql.DatabaseSecurityAlertPolicy{ + Location: utils.String(location), + DatabaseSecurityAlertPolicyProperties: &sql.DatabaseSecurityAlertPolicyProperties{ + State: sql.SecurityAlertPolicyStateDisabled, + }, + } + properties := policy.DatabaseSecurityAlertPolicyProperties + v, ok := d.GetOk("threat_detection_policy") if !ok { - return nil, nil + return &policy, nil } if tdl := v.([]interface{}); len(tdl) > 0 { threadDetection := tdl[0].(map[string]interface{}) - state := threadDetection["state"].(string) - emailAccountAdmins := threadDetection["email_account_admins"].(string) - useServerDefault := threadDetection["use_server_default"].(string) - - policy := sql.DatabaseSecurityAlertPolicy{ - Location: utils.String(location), - DatabaseSecurityAlertPolicyProperties: &sql.DatabaseSecurityAlertPolicyProperties{ - State: sql.SecurityAlertPolicyState(state), - EmailAccountAdmins: sql.SecurityAlertPolicyEmailAccountAdmins(emailAccountAdmins), - UseServerDefault: sql.SecurityAlertPolicyUseServerDefault(useServerDefault), - }, - } - properties := policy.DatabaseSecurityAlertPolicyProperties + properties.State = sql.SecurityAlertPolicyState(threadDetection["state"].(string)) + properties.EmailAccountAdmins = sql.SecurityAlertPolicyEmailAccountAdmins(threadDetection["email_account_admins"].(string)) + properties.UseServerDefault = sql.SecurityAlertPolicyUseServerDefault(threadDetection["use_server_default"].(string)) if v, ok := threadDetection["disabled_alerts"]; ok { - properties.DisabledAlerts = utils.String(v.(string)) + alerts := v.(*schema.Set).List() + expandedAlerts := make([]string, len(alerts)) + for i := range alerts { + expandedAlerts[i] = alerts[i].(string) + } + properties.DisabledAlerts = utils.String(strings.Join(expandedAlerts, ";")) } if v, ok := threadDetection["email_addresses"]; ok { - properties.EmailAddresses = utils.String(v.(string)) + emails := v.(*schema.Set).List() + expandedEmails := make([]string, len(emails)) + for i := range emails { + expandedEmails[i] = emails[i].(string) + } + properties.EmailAddresses = utils.String(strings.Join(expandedEmails, ";")) } if v, ok := threadDetection["retention_days"]; ok { properties.RetentionDays = utils.Int32(int32(v.(int))) @@ -646,5 +674,5 @@ func expandArmSqlServerThreatDetectionPolicy(d *schema.ResourceData, location st return &policy, nil } - return nil, nil + return &policy, nil } diff --git a/azurerm/resource_arm_sql_database_test.go b/azurerm/resource_arm_sql_database_test.go index e15c10e5fdfd..701a19c2a490 100644 --- a/azurerm/resource_arm_sql_database_test.go +++ b/azurerm/resource_arm_sql_database_test.go @@ -219,8 +219,8 @@ func TestAccAzureRMSqlDatabase_threatDetectionPolicy(t *testing.T) { resourceName := "azurerm_sql_database.test" ri := acctest.RandInt() location := testLocation() - preConfig := testAccAzureRMSqlDatabase_threatDetectionPolicy(ri, location, "Enabled", "Sql_Injection", "Enabled", "", "Disabled", 15) - postConfig := testAccAzureRMSqlDatabase_threatDetectionPolicy(ri, location, "Enabled", "Sql_Injection", "Enabled", "", "Disabled", 15) + preConfig := testAccAzureRMSqlDatabase_threatDetectionPolicy(ri, location) + postConfig := testAccAzureRMSqlDatabase_basic(ri, location) resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -234,7 +234,7 @@ func TestAccAzureRMSqlDatabase_threatDetectionPolicy(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "threat_detection_policy.#", "1"), resource.TestCheckResourceAttr(resourceName, "threat_detection_policy.0.state", "Enabled"), resource.TestCheckResourceAttr(resourceName, "threat_detection_policy.0.retention_days", "15"), - resource.TestCheckResourceAttr(resourceName, "threat_detection_policy.0.disabled_alerts", "Sql_Injection"), + resource.TestCheckResourceAttr(resourceName, "threat_detection_policy.0.disabled_alerts.#", "1"), resource.TestCheckResourceAttr(resourceName, "threat_detection_policy.0.email_account_admins", "Enabled"), ), }, @@ -242,11 +242,7 @@ func TestAccAzureRMSqlDatabase_threatDetectionPolicy(t *testing.T) { Config: postConfig, Check: resource.ComposeTestCheckFunc( testCheckAzureRMSqlDatabaseExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "threat_detection_policy.#", "1"), - resource.TestCheckResourceAttr(resourceName, "threat_detection_policy.0.state", "Enabled"), - resource.TestCheckResourceAttr(resourceName, "threat_detection_policy.0.retention_days", "15"), - resource.TestCheckResourceAttr(resourceName, "threat_detection_policy.0.disabled_alerts", "Sql_Injection"), - resource.TestCheckResourceAttr(resourceName, "threat_detection_policy.0.email_account_admins", "Enabled"), + resource.TestCheckResourceAttr(resourceName, "threat_detection_policy.#", "0"), ), }, }, @@ -683,8 +679,7 @@ resource "azurerm_sql_database" "test" { `, rInt, location, rInt, rInt, requestedServiceObjectiveName) } -func testAccAzureRMSqlDatabase_threatDetectionPolicy(rInt int, location, state, disabledAlerts, emailAccountAdmins, emailAddresses, - useServerDefault string, retentionDays int) string { +func testAccAzureRMSqlDatabase_threatDetectionPolicy(rInt int, location string) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { name = "acctestRG-%d" @@ -718,15 +713,14 @@ resource "azurerm_sql_database" "test" { max_size_bytes = "1073741824" threat_detection_policy { - retention_days = %d - state = "%s" - disabled_alerts = "%s" - email_account_admins = "%s" - email_addresses = "%s" + retention_days = 15 + state = "Enabled" + disabled_alerts = ["Sql_Injection"] + email_account_admins = "Enabled" storage_account_access_key = "${azurerm_storage_account.test.primary_access_key}" - storage_endpoint = "${azurerm_storage_account.test.primary_blob_endpoint}" - use_server_default = "%s" + storage_endpoint = "${azurerm_storage_account.test.primary_blob_endpoint}" + use_server_default = "Disabled" } } -`, rInt, location, rInt, rInt, rInt, retentionDays, state, disabledAlerts, emailAccountAdmins, emailAddresses, useServerDefault) +`, rInt, location, rInt, rInt, rInt) } diff --git a/website/docs/r/sql_database.html.markdown b/website/docs/r/sql_database.html.markdown index 2e7dc5a4d0c7..4f5a08422247 100644 --- a/website/docs/r/sql_database.html.markdown +++ b/website/docs/r/sql_database.html.markdown @@ -87,16 +87,18 @@ The following arguments are supported: * `authentication_type` - (Required) Specifies the type of authentication used to access the server. Valid values are `SQL` or `ADPassword`. * `operation_mode` - (Optional) Specifies the type of import operation being performed. The only allowable value is `Import`. -`threat_detection_policy` supports the following: +--- + +`threat_detection_policy` supports the following: -* `state` - (Required) Specifies the state of the policy. If state is Enabled, storageEndpoint and storageAccountAccessKey are required. -* `disabled_alerts` - (Optional) Specifies the semicolon-separated list of alerts that are disabled, or empty string to disable no alerts. Possible values: Sql_Injection; Sql_Injection_Vulnerability; Access_Anomaly; Usage_Anomaly. -* `email_account_admins` - (Optional) Specifies that the alert is sent to the account administrators. -* `email_addresses` - (Optional) Specifies the semicolon-separated list of e-mail addresses to which the alert is sent. +* `state` - (Required) The State of the Policy. Possible values are `Enabled`, `Disabled` or `New`. +* `disabled_alerts` - (Optional) Specifies a list of alerts which should be disabled. Possible values include `Access_Anomaly`, `Sql_Injection` and `Sql_Injection_Vulnerability`. +* `email_account_admins` - (Optional) Should the account administrators be emailed when this alert is triggered? +* `email_addresses` - (Optional) A list of email addresses which alerts should be sent to. * `retention_days` - (Optional) Specifies the number of days to keep in the Threat Detection audit logs. * `storage_account_access_key` - (Optional) Specifies the identifier key of the Threat Detection audit storage account. If state is Enabled, storageAccountAccessKey is required. -* `storage_endpoint` - (Optional) Specifies the blob storage endpoint (e.g. https://MyAccount.blob.core.windows.net). This blob storage will hold all Threat Detection audit logs. If state is Enabled, storageEndpoint is required. -* `use_server_default` - (Optional) Specifies whether to use the default server policy. +* `storage_endpoint` - (Optional) Specifies the blob storage endpoint (e.g. https://MyAccount.blob.core.windows.net). This blob storage will hold all Threat Detection audit logs. Required if `state` is `Enabled`. +* `use_server_default` - (Optional) Should the default server policy be used? Defaults to `Disabled`. ## Attributes Reference From 68222d26a915df2f155a5a6cf8ff5c9dd95c866c Mon Sep 17 00:00:00 2001 From: Tilen Faganel Date: Sat, 18 Aug 2018 17:59:22 +0100 Subject: [PATCH 4/8] Minor fixes in the sql threat detection list configuration and reading of the remote state of the `azurerm_sql_database` resource --- azurerm/resource_arm_sql_database.go | 76 ++++++++++++----------- azurerm/resource_arm_sql_database_test.go | 19 ++++-- website/docs/r/sql_database.html.markdown | 2 +- 3 files changed, 55 insertions(+), 42 deletions(-) diff --git a/azurerm/resource_arm_sql_database.go b/azurerm/resource_arm_sql_database.go index 433a8c3b574c..75d54a7ba3a7 100644 --- a/azurerm/resource_arm_sql_database.go +++ b/azurerm/resource_arm_sql_database.go @@ -200,6 +200,7 @@ func resourceArmSqlDatabase() *schema.Resource { "threat_detection_policy": { Type: schema.TypeList, Optional: true, + Computed: true, MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ @@ -436,8 +437,7 @@ func resourceArmSqlDatabaseCreateUpdate(d *schema.ResourceData, meta interface{} d.SetId(*resp.ID) threatDetectionClient := meta.(*ArmClient).sqlDatabaseThreatDetectionPoliciesClient - _, err = threatDetectionClient.CreateOrUpdate(ctx, resourceGroup, serverName, name, *threatDetection) - if err != nil { + if _, err = threatDetectionClient.CreateOrUpdate(ctx, resourceGroup, serverName, name, *threatDetection); err != nil { return fmt.Errorf("Error setting database threat detection policy: %+v", err) } @@ -468,16 +468,12 @@ func resourceArmSqlDatabaseRead(d *schema.ResourceData, meta interface{}) error return fmt.Errorf("Error making Read request on Sql Database %s: %+v", name, err) } - oldThreatDetection, hasOldThreatDetection := d.GetOk("threat_detection_policy") - if hasOldThreatDetection { - threatDetectionClient := meta.(*ArmClient).sqlDatabaseThreatDetectionPoliciesClient - - threatDetection, err := threatDetectionClient.Get(ctx, resourceGroup, serverName, name) - if err == nil { - flattenedThreatDetection := flattenArmSqlServerThreatDetectionPolicy(threatDetection, oldThreatDetection.([]interface{})) - if err := d.Set("threat_detection_policy", flattenedThreatDetection); err != nil { - return fmt.Errorf("Error setting `threat_detection_policy`: %+v", err) - } + threatDetectionClient := meta.(*ArmClient).sqlDatabaseThreatDetectionPoliciesClient + threatDetection, err := threatDetectionClient.Get(ctx, resourceGroup, serverName, name) + if err == nil { + flattenedThreatDetection := flattenArmSqlServerThreatDetectionPolicy(d, threatDetection) + if err := d.Set("threat_detection_policy", flattenedThreatDetection); err != nil { + return fmt.Errorf("Error setting `threat_detection_policy`: %+v", err) } } @@ -566,30 +562,40 @@ func flattenEncryptionStatus(encryption *[]sql.TransparentDataEncryption) string return "" } -func flattenArmSqlServerThreatDetectionPolicy(policy sql.DatabaseSecurityAlertPolicy, oldThreatDetection []interface{}) []interface{} { +func flattenArmSqlServerThreatDetectionPolicy(d *schema.ResourceData, policy sql.DatabaseSecurityAlertPolicy) []interface{} { + // The SQL database threat detection API always returns the default value even if never set. + // If the values are on their default one, threat it as not set. properties := policy.DatabaseSecurityAlertPolicyProperties + if properties == nil { + return []interface{}{} + } + threatDetectionPolicy := make(map[string]interface{}) threatDetectionPolicy["state"] = string(properties.State) threatDetectionPolicy["email_account_admins"] = string(properties.EmailAccountAdmins) threatDetectionPolicy["use_server_default"] = string(properties.UseServerDefault) - if properties.DisabledAlerts != nil && *properties.DisabledAlerts != "" { - alerts := strings.Split(*properties.DisabledAlerts, ";") - flattenedAlerts := make([]interface{}, len(alerts)) - for i := range alerts { - flattenedAlerts[i] = alerts[i] + if disabledAlerts := properties.DisabledAlerts; disabledAlerts != nil { + flattenedAlerts := schema.NewSet(schema.HashString, []interface{}{}) + if v := *disabledAlerts; v != "" { + parsedAlerts := strings.Split(v, ";") + for _, a := range parsedAlerts { + flattenedAlerts.Add(a) + } } - threatDetectionPolicy["disabled_alerts"] = schema.NewSet(schema.HashString, flattenedAlerts) - } - if properties.EmailAddresses != nil && *properties.EmailAddresses != "" { - emails := strings.Split(*properties.EmailAddresses, ";") - flattenedEmails := make([]interface{}, len(emails)) - for i := range emails { - flattenedEmails[i] = emails[i] + threatDetectionPolicy["disabled_alerts"] = flattenedAlerts + } + if emailAddresses := properties.EmailAddresses; emailAddresses != nil { + flattenedEmails := schema.NewSet(schema.HashString, []interface{}{}) + if v := *emailAddresses; v != "" { + parsedEmails := strings.Split(*emailAddresses, ";") + for _, e := range parsedEmails { + flattenedEmails.Add(e) + } } - threatDetectionPolicy["email_addresses"] = schema.NewSet(schema.HashString, flattenedEmails) + threatDetectionPolicy["email_addresses"] = flattenedEmails } if properties.StorageEndpoint != nil { threatDetectionPolicy["storage_endpoint"] = *properties.StorageEndpoint @@ -598,9 +604,9 @@ func flattenArmSqlServerThreatDetectionPolicy(policy sql.DatabaseSecurityAlertPo threatDetectionPolicy["retention_days"] = int(*properties.RetentionDays) } - // If storage account access key is in state readd it to the new state, as the API does not return it for security reasons - if t, ok := oldThreatDetection[0].(map[string]interface{})["storage_account_access_key"]; ok { - threatDetectionPolicy["storage_account_access_key"] = t.(string) + // If storage account access key is in state read it to the new state, as the API does not return it for security reasons + if v, ok := d.GetOk("threat_detection_policy.0.storage_account_access_key"); ok { + threatDetectionPolicy["storage_account_access_key"] = v.(string) } return []interface{}{threatDetectionPolicy} @@ -633,12 +639,12 @@ func expandArmSqlServerThreatDetectionPolicy(d *schema.ResourceData, location st } properties := policy.DatabaseSecurityAlertPolicyProperties - v, ok := d.GetOk("threat_detection_policy") + td, ok := d.GetOk("threat_detection_policy") if !ok { return &policy, nil } - if tdl := v.([]interface{}); len(tdl) > 0 { + if tdl := td.([]interface{}); len(tdl) > 0 { threadDetection := tdl[0].(map[string]interface{}) properties.State = sql.SecurityAlertPolicyState(threadDetection["state"].(string)) @@ -648,16 +654,16 @@ func expandArmSqlServerThreatDetectionPolicy(d *schema.ResourceData, location st if v, ok := threadDetection["disabled_alerts"]; ok { alerts := v.(*schema.Set).List() expandedAlerts := make([]string, len(alerts)) - for i := range alerts { - expandedAlerts[i] = alerts[i].(string) + for i, a := range alerts { + expandedAlerts[i] = a.(string) } properties.DisabledAlerts = utils.String(strings.Join(expandedAlerts, ";")) } if v, ok := threadDetection["email_addresses"]; ok { emails := v.(*schema.Set).List() expandedEmails := make([]string, len(emails)) - for i := range emails { - expandedEmails[i] = emails[i].(string) + for i, e := range emails { + expandedEmails[i] = e.(string) } properties.EmailAddresses = utils.String(strings.Join(expandedEmails, ";")) } diff --git a/azurerm/resource_arm_sql_database_test.go b/azurerm/resource_arm_sql_database_test.go index 701a19c2a490..9f6fab40f3c5 100644 --- a/azurerm/resource_arm_sql_database_test.go +++ b/azurerm/resource_arm_sql_database_test.go @@ -219,8 +219,8 @@ func TestAccAzureRMSqlDatabase_threatDetectionPolicy(t *testing.T) { resourceName := "azurerm_sql_database.test" ri := acctest.RandInt() location := testLocation() - preConfig := testAccAzureRMSqlDatabase_threatDetectionPolicy(ri, location) - postConfig := testAccAzureRMSqlDatabase_basic(ri, location) + preConfig := testAccAzureRMSqlDatabase_threatDetectionPolicy(ri, location, "Enabled") + postConfig := testAccAzureRMSqlDatabase_threatDetectionPolicy(ri, location, "Disabled") resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -238,11 +238,18 @@ func TestAccAzureRMSqlDatabase_threatDetectionPolicy(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "threat_detection_policy.0.email_account_admins", "Enabled"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"create_mode", "threat_detection_policy.0.storage_account_access_key"}, + }, { Config: postConfig, Check: resource.ComposeTestCheckFunc( testCheckAzureRMSqlDatabaseExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "threat_detection_policy.#", "0"), + resource.TestCheckResourceAttr(resourceName, "threat_detection_policy.#", "1"), + resource.TestCheckResourceAttr(resourceName, "threat_detection_policy.0.state", "Disabled"), ), }, }, @@ -679,7 +686,7 @@ resource "azurerm_sql_database" "test" { `, rInt, location, rInt, rInt, requestedServiceObjectiveName) } -func testAccAzureRMSqlDatabase_threatDetectionPolicy(rInt int, location string) string { +func testAccAzureRMSqlDatabase_threatDetectionPolicy(rInt int, location, state string) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { name = "acctestRG-%d" @@ -714,7 +721,7 @@ resource "azurerm_sql_database" "test" { threat_detection_policy { retention_days = 15 - state = "Enabled" + state = "%s" disabled_alerts = ["Sql_Injection"] email_account_admins = "Enabled" storage_account_access_key = "${azurerm_storage_account.test.primary_access_key}" @@ -722,5 +729,5 @@ resource "azurerm_sql_database" "test" { use_server_default = "Disabled" } } -`, rInt, location, rInt, rInt, rInt) +`, rInt, location, rInt, rInt, rInt, state) } diff --git a/website/docs/r/sql_database.html.markdown b/website/docs/r/sql_database.html.markdown index 4f5a08422247..2c1c41a5ebd6 100644 --- a/website/docs/r/sql_database.html.markdown +++ b/website/docs/r/sql_database.html.markdown @@ -96,7 +96,7 @@ The following arguments are supported: * `email_account_admins` - (Optional) Should the account administrators be emailed when this alert is triggered? * `email_addresses` - (Optional) A list of email addresses which alerts should be sent to. * `retention_days` - (Optional) Specifies the number of days to keep in the Threat Detection audit logs. -* `storage_account_access_key` - (Optional) Specifies the identifier key of the Threat Detection audit storage account. If state is Enabled, storageAccountAccessKey is required. +* `storage_account_access_key` - (Optional) Specifies the identifier key of the Threat Detection audit storage account. Required if `state` is `Enabled`. * `storage_endpoint` - (Optional) Specifies the blob storage endpoint (e.g. https://MyAccount.blob.core.windows.net). This blob storage will hold all Threat Detection audit logs. Required if `state` is `Enabled`. * `use_server_default` - (Optional) Should the default server policy be used? Defaults to `Disabled`. From 8672d73a3b4c8139047a2897c39c691b5634ae76 Mon Sep 17 00:00:00 2001 From: Tilen Faganel Date: Tue, 21 Aug 2018 07:42:28 +0100 Subject: [PATCH 5/8] Added missing validations to the `storage_endpoint` and the `storage_account_access_key` property of the `azurerm_sql_database` resource --- azurerm/resource_arm_sql_database.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/azurerm/resource_arm_sql_database.go b/azurerm/resource_arm_sql_database.go index 75d54a7ba3a7..7fca80d50bee 100644 --- a/azurerm/resource_arm_sql_database.go +++ b/azurerm/resource_arm_sql_database.go @@ -260,11 +260,13 @@ func resourceArmSqlDatabase() *schema.Resource { Type: schema.TypeString, Optional: true, Sensitive: true, + ValidateFunc: validation.NoZeroValues, }, "storage_endpoint": { Type: schema.TypeString, Optional: true, + ValidateFunc: validation.NoZeroValues, }, "use_server_default": { From 63be1f86186f5174cc2dc5a5e5d80da6186c7482 Mon Sep 17 00:00:00 2001 From: Tilen Faganel Date: Tue, 21 Aug 2018 07:54:16 +0100 Subject: [PATCH 6/8] Fixed formating of the schema of the the `azurerm_sql_database` resource --- azurerm/resource_arm_sql_database.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/azurerm/resource_arm_sql_database.go b/azurerm/resource_arm_sql_database.go index 7fca80d50bee..e9240ab48431 100644 --- a/azurerm/resource_arm_sql_database.go +++ b/azurerm/resource_arm_sql_database.go @@ -257,15 +257,15 @@ func resourceArmSqlDatabase() *schema.Resource { }, "storage_account_access_key": { - Type: schema.TypeString, - Optional: true, - Sensitive: true, + Type: schema.TypeString, + Optional: true, + Sensitive: true, ValidateFunc: validation.NoZeroValues, }, "storage_endpoint": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, ValidateFunc: validation.NoZeroValues, }, From 0eab4deec3da40674994225bb75f20d2164ab6a4 Mon Sep 17 00:00:00 2001 From: kt Date: Sun, 9 Sep 2018 09:50:03 -0700 Subject: [PATCH 7/8] Update resource_arm_sql_database.go --- azurerm/resource_arm_sql_database.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/azurerm/resource_arm_sql_database.go b/azurerm/resource_arm_sql_database.go index e9240ab48431..2e9458fa2414 100644 --- a/azurerm/resource_arm_sql_database.go +++ b/azurerm/resource_arm_sql_database.go @@ -647,13 +647,13 @@ func expandArmSqlServerThreatDetectionPolicy(d *schema.ResourceData, location st } if tdl := td.([]interface{}); len(tdl) > 0 { - threadDetection := tdl[0].(map[string]interface{}) + threatDetection := tdl[0].(map[string]interface{}) - properties.State = sql.SecurityAlertPolicyState(threadDetection["state"].(string)) - properties.EmailAccountAdmins = sql.SecurityAlertPolicyEmailAccountAdmins(threadDetection["email_account_admins"].(string)) - properties.UseServerDefault = sql.SecurityAlertPolicyUseServerDefault(threadDetection["use_server_default"].(string)) + properties.State = sql.SecurityAlertPolicyState(threatDetection["state"].(string)) + properties.EmailAccountAdmins = sql.SecurityAlertPolicyEmailAccountAdmins(threatDetection["email_account_admins"].(string)) + properties.UseServerDefault = sql.SecurityAlertPolicyUseServerDefault(threatDetection["use_server_default"].(string)) - if v, ok := threadDetection["disabled_alerts"]; ok { + if v, ok := threatDetection["disabled_alerts"]; ok { alerts := v.(*schema.Set).List() expandedAlerts := make([]string, len(alerts)) for i, a := range alerts { @@ -661,7 +661,7 @@ func expandArmSqlServerThreatDetectionPolicy(d *schema.ResourceData, location st } properties.DisabledAlerts = utils.String(strings.Join(expandedAlerts, ";")) } - if v, ok := threadDetection["email_addresses"]; ok { + if v, ok := threatDetection["email_addresses"]; ok { emails := v.(*schema.Set).List() expandedEmails := make([]string, len(emails)) for i, e := range emails { @@ -669,13 +669,13 @@ func expandArmSqlServerThreatDetectionPolicy(d *schema.ResourceData, location st } properties.EmailAddresses = utils.String(strings.Join(expandedEmails, ";")) } - if v, ok := threadDetection["retention_days"]; ok { + if v, ok := threatDetection["retention_days"]; ok { properties.RetentionDays = utils.Int32(int32(v.(int))) } - if v, ok := threadDetection["storage_account_access_key"]; ok { + if v, ok := threatDetection["storage_account_access_key"]; ok { properties.StorageAccountAccessKey = utils.String(v.(string)) } - if v, ok := threadDetection["storage_endpoint"]; ok { + if v, ok := threatDetection["storage_endpoint"]; ok { properties.StorageEndpoint = utils.String(v.(string)) } From 6ba227a9c53f5df1efe448275f2e71f8c3a1b157 Mon Sep 17 00:00:00 2001 From: kt Date: Sun, 9 Sep 2018 10:21:36 -0700 Subject: [PATCH 8/8] go fmt --- azurerm/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azurerm/config.go b/azurerm/config.go index 25de01a76522..f3d36f56992e 100644 --- a/azurerm/config.go +++ b/azurerm/config.go @@ -147,7 +147,7 @@ type ArmClient struct { postgresqlServersClient postgresql.ServersClient postgresqlVirtualNetworkRulesClient postgresql.VirtualNetworkRulesClient sqlDatabasesClient sql.DatabasesClient - sqlDatabaseThreatDetectionPoliciesClient sql.DatabaseThreatDetectionPoliciesClient + sqlDatabaseThreatDetectionPoliciesClient sql.DatabaseThreatDetectionPoliciesClient sqlElasticPoolsClient sql.ElasticPoolsClient sqlFirewallRulesClient sql.FirewallRulesClient sqlServersClient sql.ServersClient