From b9b6867ad9fc93c1850b8503830daf5282f7dec5 Mon Sep 17 00:00:00 2001 From: yupwei Date: Wed, 8 Apr 2020 15:56:49 +0800 Subject: [PATCH 1/5] update --- .../services/sql/resource_arm_sql_database.go | 20 +++-- .../tests/resource_arm_sql_database_test.go | 75 +++++++++++++++++++ 2 files changed, 89 insertions(+), 6 deletions(-) diff --git a/azurerm/internal/services/sql/resource_arm_sql_database.go b/azurerm/internal/services/sql/resource_arm_sql_database.go index 321431ea6e91..87374099bc93 100644 --- a/azurerm/internal/services/sql/resource_arm_sql_database.go +++ b/azurerm/internal/services/sql/resource_arm_sql_database.go @@ -364,6 +364,12 @@ func resourceArmSqlDatabaseCreateUpdate(d *schema.ResourceData, meta interface{} resourceGroup := d.Get("resource_group_name").(string) location := azure.NormalizeLocation(d.Get("location").(string)) createMode := d.Get("create_mode").(string) + auditingPolicies := d.Get("extended_auditing_policy").([]interface{}) + + if createMode == string(sql.CreateModeOnlineSecondary) && len(auditingPolicies) > 0 { + return fmt.Errorf("could not configure auditing policies on SQL Database %q (Resource Group %q, Server %q) in online secondary create mode", name, resourceGroup, serverName) + } + zoneRedundant := d.Get("zone_redundant").(bool) t := d.Get("tags").(map[string]interface{}) @@ -505,12 +511,14 @@ func resourceArmSqlDatabaseCreateUpdate(d *schema.ResourceData, meta interface{} return fmt.Errorf("Error setting database threat detection policy: %+v", err) } - auditingClient := meta.(*clients.Client).Sql.ExtendedDatabaseBlobAuditingPoliciesClient - auditingProps := sql.ExtendedDatabaseBlobAuditingPolicy{ - ExtendedDatabaseBlobAuditingPolicyProperties: helper.ExpandAzureRmSqlDBBlobAuditingPolicies(d.Get("extended_auditing_policy").([]interface{})), - } - if _, err = auditingClient.CreateOrUpdate(ctx, resourceGroup, serverName, name, auditingProps); err != nil { - return fmt.Errorf("Error issuing create/update request for SQL Database %q Blob Auditing Policies(SQL Server %q/ Resource Group %q): %+v", name, serverName, resourceGroup, err) + if createMode != string(sql.CreateModeOnlineSecondary) { + auditingClient := meta.(*clients.Client).Sql.ExtendedDatabaseBlobAuditingPoliciesClient + auditingProps := sql.ExtendedDatabaseBlobAuditingPolicy{ + ExtendedDatabaseBlobAuditingPolicyProperties: helper.ExpandAzureRmSqlDBBlobAuditingPolicies(auditingPolicies), + } + if _, err = auditingClient.CreateOrUpdate(ctx, resourceGroup, serverName, name, auditingProps); err != nil { + return fmt.Errorf("Error issuing create/update request for SQL Database %q Blob Auditing Policies(SQL Server %q/ Resource Group %q): %+v", name, serverName, resourceGroup, err) + } } return resourceArmSqlDatabaseRead(d, meta) diff --git a/azurerm/internal/services/sql/tests/resource_arm_sql_database_test.go b/azurerm/internal/services/sql/tests/resource_arm_sql_database_test.go index 3ba62ef2bde3..5d4ebf38eaee 100644 --- a/azurerm/internal/services/sql/tests/resource_arm_sql_database_test.go +++ b/azurerm/internal/services/sql/tests/resource_arm_sql_database_test.go @@ -488,6 +488,25 @@ func TestAccAzureRMSqlDatabase_withBlobAuditingPolicesUpdate(t *testing.T) { }) } +func TestAccAzureRMSqlDatabase_onlineSecondaryMode(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_sql_database", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMSqlDatabaseDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMSqlDatabase_onlineSecondaryMode(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMSqlDatabaseExists(data.ResourceName), + ), + }, + data.ImportStep("administrator_login_password", "create_mode"), + }, + }) +} + func testAccAzureRMSqlDatabase_basic(data acceptance.TestData) string { return fmt.Sprintf(` provider "azurerm" { @@ -1097,3 +1116,59 @@ resource "azurerm_sql_database" "test" { } `, data.RandomInteger, data.Locations.Primary, data.RandomIntOfLength(15)) } + +func testAccAzureRMSqlDatabase_onlineSecondaryMode(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%[1]d" + location = "%[2]s" +} + +resource "azurerm_sql_server" "test" { + name = "acctestsqlserver%[1]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%[1]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" + requested_service_objective_name = "S0" +} + +resource "azurerm_resource_group" "test2" { + name = "acctestRG2-%[1]d" + location = "%[3]s" +} + +resource "azurerm_sql_server" "test2" { + name = "acctestsqlserver2%[1]d" + resource_group_name = azurerm_resource_group.test2.name + location = azurerm_resource_group.test2.location + version = "12.0" + administrator_login = "mradministrator" + administrator_login_password = "thisIsDog11" +} + +resource "azurerm_sql_database" "test2" { + name = "acctestdb2%[1]d" + resource_group_name = azurerm_resource_group.test2.name + server_name = azurerm_sql_server.test2.name + location = azurerm_resource_group.test2.location + create_mode = "OnlineSecondary" + source_database_id = azurerm_sql_database.test.id +} +`, data.RandomInteger, data.Locations.Primary, data.Locations.Secondary) +} From ec57d9a99807650620a392613b8a4c022caf509e Mon Sep 17 00:00:00 2001 From: yupwei Date: Wed, 15 Apr 2020 14:37:53 +0800 Subject: [PATCH 2/5] remove useless --- .../d/data_share_invitation.html.markdown | 50 ----------- .../r/data_share_invitation.html.markdown | 82 ------------------- 2 files changed, 132 deletions(-) delete mode 100644 website/docs/d/data_share_invitation.html.markdown delete mode 100644 website/docs/r/data_share_invitation.html.markdown diff --git a/website/docs/d/data_share_invitation.html.markdown b/website/docs/d/data_share_invitation.html.markdown deleted file mode 100644 index 0aa2f33ee051..000000000000 --- a/website/docs/d/data_share_invitation.html.markdown +++ /dev/null @@ -1,50 +0,0 @@ ---- -subcategory: "Data Share" -layout: "azurerm" -page_title: "Azure Resource Manager: Data Source: azurerm_data_share_invitation" -description: |- - Gets information about an existing Data Share Invitation. ---- - -# Data Source: azurerm_data_share_invitation - -Use this data source to access information about an existing Data Share Invitation. - -## Example Usage - -```hcl -data "azurerm_data_share_invitation" "example" { - name = "existing" - share_id = "TODO" -} - -output "id" { - value = data.azurerm_data_share_invitation.example.id -} -``` - -## Arguments Reference - -The following arguments are supported: - -* `name` - (Required) The name of this Data Share Invitation. Changing this forces a new Data Share Invitation to be created. - -* `share_id` - (Required) The ID of the TODO. Changing this forces a new Data Share Invitation to be created. - -## Attributes Reference - -In addition to the Arguments listed above - the following Attributes are exported: - -* `id` - The ID of the Data Share Invitation. - -* `invitation_id` - The ID of the TODO. - -* `invitation_status` - TODO. - -* `target_email` - TODO. - -## Timeouts - -The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions: - -* `read` - (Defaults to 5 minutes) Used when retrieving the Data Share Invitation. \ No newline at end of file diff --git a/website/docs/r/data_share_invitation.html.markdown b/website/docs/r/data_share_invitation.html.markdown deleted file mode 100644 index 6a15c93cb7e9..000000000000 --- a/website/docs/r/data_share_invitation.html.markdown +++ /dev/null @@ -1,82 +0,0 @@ ---- -subcategory: "Data Share" -layout: "azurerm" -page_title: "Azure Resource Manager: azurerm_data_share_invitation" -description: |- - Manages a Data Share Invitation. ---- - -# azurerm_data_share_invitation - -Manages a Data Share Invitation. - -## Example Usage - -```hcl -provider "azurerm" { - features {} -} - -resource "azurerm_resource_group" "example" { - name = "example-resources" - location = "West Europe" -} - -resource "azurerm_data_share_account" "example" { - name = "example-dsa" -resource_group_name = azurerm_resource_group.example.name - location = azurerm_resource_group.example.location - - tags = { - foo = "bar" - } -} - -resource "azurerm_data_share_share" "example" { - name = "example_dss" - account_id = azurerm_data_share_account.example.id -share_kind = "CopyBased" -} - -resource "azurerm_data_share_invitation" "example" { - name = "example" - share_id = azurerm_data_share_share.example.id -target_email = "123456@microsoft.com" -} -``` - -## Arguments Reference - -The following arguments are supported: - -* `name` - (Required) The name which should be used for this Data Share Invitation. Changing this forces a new Data Share Invitation to be created. - -* `share_id` - (Required) The ID of the TODO. Changing this forces a new Data Share Invitation to be created. - -* `target_email` - (Required) TODO. Changing this forces a new Data Share Invitation to be created. - -## Attributes Reference - -In addition to the Arguments listed above - the following Attributes are exported: - -* `id` - The ID of the Data Share Invitation. - -* `invitation_id` - The ID of the TODO. - -* `invitation_status` - TODO. - -## Timeouts - -The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions: - -* `create` - (Defaults to 30 minutes) Used when creating the Data Share Invitation. -* `read` - (Defaults to 5 minutes) Used when retrieving the Data Share Invitation. -* `delete` - (Defaults to 30 minutes) Used when deleting the Data Share Invitation. - -## Import - -Data Share Invitations can be imported using the `resource id`, e.g. - -```shell -terraform import azurerm_data_share_invitation.example C:/Program Files/Git/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/group1/providers/Microsoft.DataShare/accounts/account1/shares/share1/invitations/invitation1 -``` \ No newline at end of file From 055fd69324fff97ca9e2fdb865e76e1dded1f977 Mon Sep 17 00:00:00 2001 From: yupwei Date: Thu, 16 Apr 2020 16:02:59 +0800 Subject: [PATCH 3/5] mssql db add blob auditing policies --- .../internal/services/mssql/client/client.go | 7 +- .../mssql/helper/sql_extended_auditing.go | 98 ++++++++++++++++ .../mssql/resource_arm_mssql_database.go | 39 ++++++- .../tests/resource_arm_mssql_database_test.go | 108 ++++++++++++++++++ .../services/sql/resource_arm_sql_database.go | 6 +- website/docs/r/mssql_database.html.markdown | 27 +++++ 6 files changed, 275 insertions(+), 10 deletions(-) create mode 100644 azurerm/internal/services/mssql/helper/sql_extended_auditing.go diff --git a/azurerm/internal/services/mssql/client/client.go b/azurerm/internal/services/mssql/client/client.go index 8818b8364104..b7334e2ea491 100644 --- a/azurerm/internal/services/mssql/client/client.go +++ b/azurerm/internal/services/mssql/client/client.go @@ -8,6 +8,7 @@ import ( type Client struct { DatabasesClient *sql.DatabasesClient + DatabaseExtendedBlobAuditingPoliciesClient *sql.ExtendedDatabaseBlobAuditingPoliciesClient DatabaseThreatDetectionPoliciesClient *sql.DatabaseThreatDetectionPoliciesClient ElasticPoolsClient *sql.ElasticPoolsClient DatabaseVulnerabilityAssessmentRuleBaselinesClient *sql.DatabaseVulnerabilityAssessmentRuleBaselinesClient @@ -21,6 +22,9 @@ func NewClient(o *common.ClientOptions) *Client { databasesClient := sql.NewDatabasesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) o.ConfigureClient(&databasesClient.Client, o.ResourceManagerAuthorizer) + databaseExtendedBlobAuditingPoliciesClient := sql.NewExtendedDatabaseBlobAuditingPoliciesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) + o.ConfigureClient(&databaseExtendedBlobAuditingPoliciesClient.Client, o.ResourceManagerAuthorizer) + databaseThreatDetectionPoliciesClient := sql.NewDatabaseThreatDetectionPoliciesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) o.ConfigureClient(&databaseThreatDetectionPoliciesClient.Client, o.ResourceManagerAuthorizer) @@ -43,7 +47,8 @@ func NewClient(o *common.ClientOptions) *Client { o.ConfigureClient(&sqlVirtualMachinesClient.Client, o.ResourceManagerAuthorizer) return &Client{ - DatabasesClient: &databasesClient, + DatabasesClient: &databasesClient, + DatabaseExtendedBlobAuditingPoliciesClient: &databaseExtendedBlobAuditingPoliciesClient, DatabaseThreatDetectionPoliciesClient: &databaseThreatDetectionPoliciesClient, DatabaseVulnerabilityAssessmentRuleBaselinesClient: &databaseVulnerabilityAssessmentRuleBaselinesClient, ElasticPoolsClient: &elasticPoolsClient, diff --git a/azurerm/internal/services/mssql/helper/sql_extended_auditing.go b/azurerm/internal/services/mssql/helper/sql_extended_auditing.go new file mode 100644 index 000000000000..2127993fd584 --- /dev/null +++ b/azurerm/internal/services/mssql/helper/sql_extended_auditing.go @@ -0,0 +1,98 @@ +package helper + +import ( + "github.com/Azure/azure-sdk-for-go/services/preview/sql/mgmt/v3.0/sql" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func ExtendedAuditingSchema() *schema.Schema { + return &schema.Schema{ + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "storage_account_access_key": { + Type: schema.TypeString, + Required: true, + Sensitive: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "storage_endpoint": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.IsURLWithHTTPS, + }, + + "storage_account_access_key_is_secondary": { + Type: schema.TypeBool, + Optional: true, + }, + + "retention_in_days": { + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntBetween(0, 3285), + }, + }, + }, + } +} + +func ExpandAzureRmMsSqlDBBlobAuditingPolicies(input []interface{}) *sql.ExtendedDatabaseBlobAuditingPolicyProperties { + if len(input) == 0 { + return &sql.ExtendedDatabaseBlobAuditingPolicyProperties{ + State: sql.BlobAuditingPolicyStateDisabled, + } + } + dbBlobAuditingPolicies := input[0].(map[string]interface{}) + + ExtendedDatabaseBlobAuditingPolicyProperties := sql.ExtendedDatabaseBlobAuditingPolicyProperties{ + State: sql.BlobAuditingPolicyStateEnabled, + StorageAccountAccessKey: utils.String(dbBlobAuditingPolicies["storage_account_access_key"].(string)), + StorageEndpoint: utils.String(dbBlobAuditingPolicies["storage_endpoint"].(string)), + } + if v, ok := dbBlobAuditingPolicies["storage_account_access_key_is_secondary"]; ok { + ExtendedDatabaseBlobAuditingPolicyProperties.IsStorageSecondaryKeyInUse = utils.Bool(v.(bool)) + } + if v, ok := dbBlobAuditingPolicies["retention_in_days"]; ok { + ExtendedDatabaseBlobAuditingPolicyProperties.RetentionDays = utils.Int32(int32(v.(int))) + } + + return &ExtendedDatabaseBlobAuditingPolicyProperties +} + +func FlattenAzureRmMsSqlDBBlobAuditingPolicies(extendedDatabaseBlobAuditingPolicy *sql.ExtendedDatabaseBlobAuditingPolicy, d *schema.ResourceData) []interface{} { + if extendedDatabaseBlobAuditingPolicy == nil || extendedDatabaseBlobAuditingPolicy.State == sql.BlobAuditingPolicyStateDisabled { + return []interface{}{} + } + var storageAccessKey, storageEndpoint string + // storage_account_access_key will not be returned, so we transfer the schema value + if v, ok := d.GetOk("extended_auditing_policy.0.storage_account_access_key"); ok { + storageAccessKey = v.(string) + } + + if extendedDatabaseBlobAuditingPolicy.StorageEndpoint != nil { + storageEndpoint = *extendedDatabaseBlobAuditingPolicy.StorageEndpoint + } + var secondKeyInUse bool + if extendedDatabaseBlobAuditingPolicy.IsStorageSecondaryKeyInUse != nil { + secondKeyInUse = *extendedDatabaseBlobAuditingPolicy.IsStorageSecondaryKeyInUse + } + var retentionDays int32 + if extendedDatabaseBlobAuditingPolicy.RetentionDays != nil { + retentionDays = *extendedDatabaseBlobAuditingPolicy.RetentionDays + } + + return []interface{}{ + map[string]interface{}{ + "storage_account_access_key": storageAccessKey, + "storage_endpoint": storageEndpoint, + "storage_account_access_key_is_secondary": secondKeyInUse, + "retention_in_days": retentionDays, + }, + } +} diff --git a/azurerm/internal/services/mssql/resource_arm_mssql_database.go b/azurerm/internal/services/mssql/resource_arm_mssql_database.go index 8f7e8cd92f12..51f034e20a8c 100644 --- a/azurerm/internal/services/mssql/resource_arm_mssql_database.go +++ b/azurerm/internal/services/mssql/resource_arm_mssql_database.go @@ -2,10 +2,10 @@ package mssql import ( "fmt" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/mssql/helper" "log" "strings" "time" - "github.com/Azure/azure-sdk-for-go/services/preview/sql/mgmt/v3.0/sql" "github.com/Azure/go-autorest/autorest/date" "github.com/hashicorp/go-azure-helpers/response" @@ -99,6 +99,8 @@ func resourceArmMsSqlDatabase() *schema.Resource { ValidateFunc: validate.MsSqlElasticPoolID, }, + "extended_auditing_policy": helper.ExtendedAuditingSchema(), + "license_type": { Type: schema.TypeString, Optional: true, @@ -270,6 +272,7 @@ func resourceArmMsSqlDatabase() *schema.Resource { func resourceArmMsSqlDatabaseCreateUpdate(d *schema.ResourceData, meta interface{}) error { client := meta.(*clients.Client).MSSQL.DatabasesClient + auditingClient := meta.(*clients.Client).MSSQL.DatabaseExtendedBlobAuditingPoliciesClient serverClient := meta.(*clients.Client).MSSQL.ServersClient threatClient := meta.(*clients.Client).MSSQL.DatabaseThreatDetectionPoliciesClient ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) @@ -321,11 +324,15 @@ func resourceArmMsSqlDatabaseCreateUpdate(d *schema.ResourceData, meta interface Tags: tags.Expand(d.Get("tags").(map[string]interface{})), } - if v, ok := d.GetOk("create_mode"); ok { - if _, ok := d.GetOk("creation_source_database_id"); (v.(string) == string(sql.CreateModeCopy) || v.(string) == string(sql.CreateModePointInTimeRestore) || v.(string) == string(sql.CreateModeRestore) || v.(string) == string(sql.CreateModeSecondary)) && !ok { - return fmt.Errorf("'creation_source_database_id' is required for create_mode %s", v.(string)) - } - params.DatabaseProperties.CreateMode = sql.CreateMode(v.(string)) + createMode, ok := d.GetOk("create_mode") + if _, dbok := d.GetOk("creation_source_database_id"); ok && (createMode.(string) == string(sql.CreateModeCopy) || createMode.(string) == string(sql.CreateModePointInTimeRestore) || createMode.(string) == string(sql.CreateModeRestore) || createMode.(string) == string(sql.CreateModeSecondary)) && !dbok { + return fmt.Errorf("'creation_source_database_id' is required for create_mode %s", createMode.(string)) + params.DatabaseProperties.CreateMode = sql.CreateMode(createMode.(string)) + } + + auditingPolicies := d.Get("extended_auditing_policy").([]interface{}) + if (createMode == string(sql.CreateModeOnlineSecondary) || createMode == string(sql.Secondary)) && len(auditingPolicies) > 0 { + return fmt.Errorf("could not configure auditing policies on SQL Database %q (Resource Group %q, Server %q) in secondary create mode", name, serverId.ResourceGroup, serverId.Name) } if v, ok := d.GetOk("max_size_gb"); ok { @@ -382,12 +389,22 @@ func resourceArmMsSqlDatabaseCreateUpdate(d *schema.ResourceData, meta interface return fmt.Errorf("setting database threat detection policy: %+v", err) } + if createMode != string(sql.CreateModeOnlineSecondary) && createMode != string(sql.CreateModeSecondary) { + auditingProps := sql.ExtendedDatabaseBlobAuditingPolicy{ + ExtendedDatabaseBlobAuditingPolicyProperties: helper.ExpandAzureRmMsSqlDBBlobAuditingPolicies(auditingPolicies), + } + if _, err = auditingClient.CreateOrUpdate(ctx, serverId.ResourceGroup, serverId.Name, name, auditingProps); err != nil { + return fmt.Errorf("failure in issuing create/update request for SQL Database %q Blob Auditing Policies(SQL Server %q/ Resource Group %q): %+v", name, serverId.Name, serverId.ResourceGroup, err) + } + } + return resourceArmMsSqlDatabaseRead(d, meta) } func resourceArmMsSqlDatabaseRead(d *schema.ResourceData, meta interface{}) error { client := meta.(*clients.Client).MSSQL.DatabasesClient threatClient := meta.(*clients.Client).MSSQL.DatabaseThreatDetectionPoliciesClient + auditingClient := meta.(*clients.Client).MSSQL.DatabaseExtendedBlobAuditingPoliciesClient ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) defer cancel() @@ -441,6 +458,16 @@ func resourceArmMsSqlDatabaseRead(d *schema.ResourceData, meta interface{}) erro } } + auditingResp, err := auditingClient.Get(ctx, id.ResourceGroup, id.MsSqlServer, id.Name) + if err != nil { + return fmt.Errorf("failure in reading SQL Database %q: %v Blob Auditing Policies", id.Name, err) + } + + flattenBlobAuditing := helper.FlattenAzureRmMsSqlDBBlobAuditingPolicies(&auditingResp, d) + if err := d.Set("extended_auditing_policy", flattenBlobAuditing); err != nil { + return fmt.Errorf("failure in setting `extended_auditing_policy`: %+v", err) + } + return tags.FlattenAndSet(d, resp.Tags) } diff --git a/azurerm/internal/services/mssql/tests/resource_arm_mssql_database_test.go b/azurerm/internal/services/mssql/tests/resource_arm_mssql_database_test.go index c714384e5165..487f74ef0530 100644 --- a/azurerm/internal/services/mssql/tests/resource_arm_mssql_database_test.go +++ b/azurerm/internal/services/mssql/tests/resource_arm_mssql_database_test.go @@ -333,6 +333,46 @@ func TestAccAzureRMMsSqlDatabase_threatDetectionPolicy(t *testing.T) { }) } +func TestAccAzureRMSqlDatabase_withBlobAuditingPolices(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_mssql_database", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMMsSqlDatabaseDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMMsSqlDatabase_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMMsSqlDatabaseExists(data.ResourceName), + ), + }, + data.ImportStep(), + { + Config: testAccAzureRMMsSqlDatabase_withBlobAuditingPolices(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMMsSqlDatabaseExists(data.ResourceName), + ), + }, + data.ImportStep("extended_auditing_policy.0.storage_account_access_key"), + { + Config: testAccAzureRMMsSqlDatabase_withBlobAuditingPolicesUpdated(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMMsSqlDatabaseExists(data.ResourceName), + ), + }, + data.ImportStep("extended_auditing_policy.0.storage_account_access_key"), + { + Config: testAccAzureRMMsSqlDatabase_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMMsSqlDatabaseExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + func testCheckAzureRMMsSqlDatabaseExists(resourceName string) resource.TestCheckFunc { return func(s *terraform.State) error { client := acceptance.AzureProvider.Meta().(*clients.Client).MSSQL.DatabasesClient @@ -704,3 +744,71 @@ resource "azurerm_mssql_database" "test" { } `, template, data.RandomInteger, state) } + +func testAccAzureRMMsSqlDatabase_withBlobAuditingPolices(data acceptance.TestData) string { + template := testAccAzureRMMsSqlDatabase_template(data) + return fmt.Sprintf(` +%s + +resource "azurerm_storage_account" "test" { + name = "acctest%[2]d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + account_tier = "Standard" + account_replication_type = "LRS" +} + +resource "azurerm_storage_account" "test2" { + name = "acctest2%[2]d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + account_tier = "Standard" + account_replication_type = "LRS" +} + +resource "azurerm_mssql_database" "test" { + name = "acctest-db-%[3]d" + server_id = azurerm_sql_server.test.id + extended_auditing_policy { + storage_endpoint = azurerm_storage_account.test.primary_blob_endpoint + storage_account_access_key = azurerm_storage_account.test.primary_access_key + storage_account_access_key_is_secondary = true + retention_in_days = 6 + } +} +`, template, data.RandomIntOfLength(15), data.RandomInteger) +} + +func testAccAzureRMMsSqlDatabase_withBlobAuditingPolicesUpdated(data acceptance.TestData) string { + template := testAccAzureRMMsSqlDatabase_template(data) + return fmt.Sprintf(` +%s + +resource "azurerm_storage_account" "test" { + name = "acctest%[2]d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + account_tier = "Standard" + account_replication_type = "LRS" +} + +resource "azurerm_storage_account" "test2" { + name = "acctest2%[2]d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + account_tier = "Standard" + account_replication_type = "LRS" +} + +resource "azurerm_mssql_database" "test" { + name = "acctest-db-%[3]d" + server_id = azurerm_sql_server.test.id + extended_auditing_policy { + storage_endpoint = azurerm_storage_account.test2.primary_blob_endpoint + storage_account_access_key = azurerm_storage_account.test2.primary_access_key + storage_account_access_key_is_secondary = false + retention_in_days = 3 + } +} +`, template, data.RandomIntOfLength(15), data.RandomInteger) +} diff --git a/azurerm/internal/services/sql/resource_arm_sql_database.go b/azurerm/internal/services/sql/resource_arm_sql_database.go index 244bcca88581..2f848614d4bb 100644 --- a/azurerm/internal/services/sql/resource_arm_sql_database.go +++ b/azurerm/internal/services/sql/resource_arm_sql_database.go @@ -512,7 +512,7 @@ func resourceArmSqlDatabaseCreateUpdate(d *schema.ResourceData, meta interface{} ExtendedDatabaseBlobAuditingPolicyProperties: helper.ExpandAzureRmSqlDBBlobAuditingPolicies(auditingPolicies), } if _, err = auditingClient.CreateOrUpdate(ctx, resourceGroup, serverName, name, auditingProps); err != nil { - return fmt.Errorf("Error issuing create/update request for SQL Database %q Blob Auditing Policies(SQL Server %q/ Resource Group %q): %+v", name, serverName, resourceGroup, err) + return fmt.Errorf("failure in issuing create/update request for SQL Database %q Blob Auditing Policies(SQL Server %q/ Resource Group %q): %+v", name, serverName, resourceGroup, err) } } @@ -602,12 +602,12 @@ func resourceArmSqlDatabaseRead(d *schema.ResourceData, meta interface{}) error auditingClient := meta.(*clients.Client).Sql.DatabaseExtendedBlobAuditingPoliciesClient auditingResp, err := auditingClient.Get(ctx, resourceGroup, serverName, name) if err != nil { - return fmt.Errorf("Error reading SQL Database %q: %v Blob Auditing Policies", name, err) + return fmt.Errorf("failure in reading SQL Database %q: %v Blob Auditing Policies", name, err) } flattenBlobAuditing := helper.FlattenAzureRmSqlDBBlobAuditingPolicies(&auditingResp, d) if err := d.Set("extended_auditing_policy", flattenBlobAuditing); err != nil { - return fmt.Errorf("Error setting `extended_auditing_policy`: %+v", err) + return fmt.Errorf("failure in setting `extended_auditing_policy`: %+v", err) } return tags.FlattenAndSet(d, resp.Tags) diff --git a/website/docs/r/mssql_database.html.markdown b/website/docs/r/mssql_database.html.markdown index ad27f10f3605..ed226c2d1f58 100644 --- a/website/docs/r/mssql_database.html.markdown +++ b/website/docs/r/mssql_database.html.markdown @@ -22,6 +22,14 @@ resource "azurerm_resource_group" "example" { location = "West Europe" } +resource "azurerm_storage_account" "example" { + name = "examplesa" + resource_group_name = azurerm_resource_group.example.name + location = azurerm_resource_group.example.location + account_tier = "Standard" + account_replication_type = "LRS" +} + resource "azurerm_sql_server" "example" { name = "example-sqlserver" resource_group_name = azurerm_resource_group.example.name @@ -40,6 +48,14 @@ resource "azurerm_mssql_database" "test" { sku_name = "BC_Gen5_2" zone_redundant = true + extended_auditing_policy { + storage_endpoint = azurerm_storage_account.example.primary_blob_endpoint + storage_account_access_key = azurerm_storage_account.example.primary_access_key + storage_account_access_key_is_secondary = true + retention_in_days = 6 + } + + tags = { foo = "bar" } @@ -67,6 +83,8 @@ The following arguments are supported: * `elastic_pool_id` - (Optional) Specifies the ID of the elastic pool containing this database. Changing this forces a new resource to be created. +* `extended_auditing_policy` - (Optional) A `extended_auditing_policy` block as defined below. + * `license_type` - (Optional) Specifies the license type applied to this database. Possible values are `LicenseIncluded` and `BasePrice`. * `max_size_gb` - (Optional) The max size of the database in gigabytes. @@ -91,6 +109,7 @@ The following arguments are supported: * `tags` - (Optional) A mapping of tags to assign to the resource. +--- a `threat_detection_policy` block supports the following: * `state` - (Required) The State of the Policy. Possible values are `Enabled`, `Disabled` or `New`. @@ -102,6 +121,14 @@ a `threat_detection_policy` block supports the following: * `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`. +--- + +A `extended_auditing_policy` block supports the following: + +* `storage_account_access_key` - (Required) Specifies the access key to use for the auditing storage account. +* `storage_endpoint` - (Required) Specifies the blob storage endpoint (e.g. https://MyAccount.blob.core.windows.net). +* `storage_account_access_key_is_secondary` - (Optional) Specifies whether `storage_account_access_key` value is the storage's secondary key. +* `retention_in_days` - (Optional) Specifies the number of days to retain logs for in the storage account. ## Attributes Reference From 9bd3d65ae7a470be6bc4a4cd0b36edf204471667 Mon Sep 17 00:00:00 2001 From: yupwei Date: Fri, 17 Apr 2020 10:37:40 +0800 Subject: [PATCH 4/5] ci --- azurerm/internal/services/mssql/resource_arm_mssql_database.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/azurerm/internal/services/mssql/resource_arm_mssql_database.go b/azurerm/internal/services/mssql/resource_arm_mssql_database.go index 51f034e20a8c..5fff608e42f7 100644 --- a/azurerm/internal/services/mssql/resource_arm_mssql_database.go +++ b/azurerm/internal/services/mssql/resource_arm_mssql_database.go @@ -2,10 +2,10 @@ package mssql import ( "fmt" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/mssql/helper" "log" "strings" "time" + "github.com/Azure/azure-sdk-for-go/services/preview/sql/mgmt/v3.0/sql" "github.com/Azure/go-autorest/autorest/date" "github.com/hashicorp/go-azure-helpers/response" @@ -17,6 +17,7 @@ import ( azValidate "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/mssql/helper" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/mssql/parse" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/mssql/validate" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" From cfafc4bcf9f38ed0313053ae2667581f9c6a269c Mon Sep 17 00:00:00 2001 From: yupwei Date: Fri, 17 Apr 2020 13:07:55 +0800 Subject: [PATCH 5/5] ci --- azurerm/internal/services/mssql/resource_arm_mssql_database.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azurerm/internal/services/mssql/resource_arm_mssql_database.go b/azurerm/internal/services/mssql/resource_arm_mssql_database.go index 5fff608e42f7..e679b45fae0b 100644 --- a/azurerm/internal/services/mssql/resource_arm_mssql_database.go +++ b/azurerm/internal/services/mssql/resource_arm_mssql_database.go @@ -328,8 +328,8 @@ func resourceArmMsSqlDatabaseCreateUpdate(d *schema.ResourceData, meta interface createMode, ok := d.GetOk("create_mode") if _, dbok := d.GetOk("creation_source_database_id"); ok && (createMode.(string) == string(sql.CreateModeCopy) || createMode.(string) == string(sql.CreateModePointInTimeRestore) || createMode.(string) == string(sql.CreateModeRestore) || createMode.(string) == string(sql.CreateModeSecondary)) && !dbok { return fmt.Errorf("'creation_source_database_id' is required for create_mode %s", createMode.(string)) - params.DatabaseProperties.CreateMode = sql.CreateMode(createMode.(string)) } + params.DatabaseProperties.CreateMode = sql.CreateMode(createMode.(string)) auditingPolicies := d.Get("extended_auditing_policy").([]interface{}) if (createMode == string(sql.CreateModeOnlineSecondary) || createMode == string(sql.Secondary)) && len(auditingPolicies) > 0 {