Skip to content

Commit

Permalink
data_protection_backup_instance_postgresql: support database_credenti…
Browse files Browse the repository at this point in the history
…al_key_vault_secret_id (#13183)

* enhancement for postgresql backup instance

* update

* update
  • Loading branch information
ms-henglu authored Sep 2, 2021
1 parent 349389a commit 25adf41
Show file tree
Hide file tree
Showing 3 changed files with 209 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/hashicorp/terraform-provider-azurerm/internal/services/dataprotection/legacysdk/dataprotection"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/dataprotection/parse"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/dataprotection/validate"
keyVaultValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/keyvault/validate"
postgresParse "github.com/hashicorp/terraform-provider-azurerm/internal/services/postgres/parse"
postgresValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/postgres/validate"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
Expand Down Expand Up @@ -68,6 +69,12 @@ func resourceDataProtectionBackupInstancePostgreSQL() *pluginsdk.Resource {
Required: true,
ValidateFunc: validate.BackupPolicyID,
},

"database_credential_key_vault_secret_id": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: keyVaultValidate.NestedItemIdWithOptionalVersion,
},
},
}
}
Expand Down Expand Up @@ -125,6 +132,17 @@ func resourceDataProtectionBackupInstancePostgreSQLCreateUpdate(d *schema.Resour
},
},
}

if v, ok := d.GetOk("database_credential_key_vault_secret_id"); ok {
parameters.Properties.DatasourceAuthCredentials = &dataprotection.SecretStoreBasedAuthCredentials{
SecretStoreResource: &dataprotection.SecretStoreResource{
URI: utils.String(v.(string)),
SecretStoreType: dataprotection.SecretStoreTypeAzureKeyVault,
},
ObjectType: dataprotection.ObjectTypeSecretStoreBasedAuthCredentials,
}
}

future, err := client.CreateOrUpdate(ctx, id.BackupVaultName, id.ResourceGroup, id.Name, parameters)
if err != nil {
return fmt.Errorf("creating/updating DataProtection BackupInstance (%q): %+v", id, err)
Expand All @@ -139,7 +157,7 @@ func resourceDataProtectionBackupInstancePostgreSQLCreateUpdate(d *schema.Resour
return fmt.Errorf("context had no deadline")
}
stateConf := &pluginsdk.StateChangeConf{
Pending: []string{string(dataprotection.StatusConfiguringProtection)},
Pending: []string{string(dataprotection.StatusConfiguringProtection), "UpdatingProtection"},
Target: []string{string(dataprotection.StatusProtectionConfigured)},
Refresh: policyProtectionStateRefreshFunc(ctx, client, id),
MinTimeout: 1 * time.Minute,
Expand Down Expand Up @@ -184,6 +202,15 @@ func resourceDataProtectionBackupInstancePostgreSQLRead(d *schema.ResourceData,
if props.PolicyInfo != nil {
d.Set("backup_policy_id", props.PolicyInfo.PolicyID)
}
if props.DatasourceAuthCredentials != nil {
if credential, ok := props.DatasourceAuthCredentials.AsSecretStoreBasedAuthCredentials(); ok {
if credential.SecretStoreResource != nil {
d.Set("database_credential_key_vault_secret_id", credential.SecretStoreResource.URI)
}
} else {
log.Printf("[DEBUG] Skipping setting database_credential_key_vault_secret_id since this DatasourceAuthCredentials is not supported")
}
}
}
return nil
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,20 @@ func TestAccDataProtectionBackupInstancePostgreSQL_complete(t *testing.T) {
})
}

func TestAccDataProtectionBackupInstancePostgreSQL_keyVaultAuth(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_data_protection_backup_instance_postgresql", "test")
r := DataProtectionBackupInstancePostgreSQLResource{}
data.ResourceTest(t, r, []resource.TestStep{
{
Config: r.keyVaultAuth(data),
Check: resource.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
})
}

func TestAccDataProtectionBackupInstancePostgreSQL_update(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_data_protection_backup_instance_postgresql", "test")
r := DataProtectionBackupInstancePostgreSQLResource{}
Expand Down Expand Up @@ -107,13 +121,15 @@ provider "azurerm" {
features {}
}
data "azurerm_client_config" "current" {}
resource "azurerm_resource_group" "test" {
name = "acctest-dataprotection-%d"
location = "%s"
name = "acctest-dataprotection-%[1]d"
location = "%[2]s"
}
resource "azurerm_postgresql_server" "test" {
name = "acctest-postgresql-server-%d"
name = "acctest-postgresql-server-%[1]d"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
Expand All @@ -130,16 +146,24 @@ resource "azurerm_postgresql_server" "test" {
ssl_enforcement_enabled = true
}
resource "azurerm_postgresql_firewall_rule" "test" {
name = "AllowAllWindowsAzureIps"
resource_group_name = azurerm_resource_group.test.name
server_name = azurerm_postgresql_server.test.name
start_ip_address = "0.0.0.0"
end_ip_address = "0.0.0.0"
}
resource "azurerm_postgresql_database" "test" {
name = "acctest-postgresql-database-%d"
name = "acctest-postgresql-database-%[1]d"
resource_group_name = azurerm_resource_group.test.name
server_name = azurerm_postgresql_server.test.name
charset = "UTF8"
collation = "English_United States.1252"
}
resource "azurerm_data_protection_backup_vault" "test" {
name = "acctest-dataprotection-vault-%d"
name = "acctest-dataprotection-vault-%[1]d"
resource_group_name = azurerm_resource_group.test.name
location = azurerm_resource_group.test.location
datastore_type = "VaultStore"
Expand All @@ -150,22 +174,73 @@ resource "azurerm_data_protection_backup_vault" "test" {
}
}
resource "azurerm_key_vault" "test" {
name = "acctest%[3]s"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
tenant_id = data.azurerm_client_config.current.tenant_id
sku_name = "premium"
soft_delete_retention_days = 7
access_policy {
tenant_id = data.azurerm_client_config.current.tenant_id
object_id = data.azurerm_client_config.current.object_id
key_permissions = ["create", "get"]
secret_permissions = [
"set",
"get",
"delete",
"purge",
"recover"
]
}
access_policy {
tenant_id = azurerm_data_protection_backup_vault.test.identity.0.tenant_id
object_id = azurerm_data_protection_backup_vault.test.identity.0.principal_id
key_permissions = ["create", "get"]
secret_permissions = [
"set",
"get",
"delete",
"purge",
"recover"
]
}
}
resource "azurerm_key_vault_secret" "test" {
name = "acctestsecret%[1]d"
value = "Server=${azurerm_postgresql_server.test.name}.postgres.database.azure.com;Database=${azurerm_postgresql_database.test.name};Port=5432;User Id=psqladminun@${azurerm_postgresql_server.test.name};Password=H@Sh1CoR3!;Ssl Mode=Require;"
key_vault_id = azurerm_key_vault.test.id
}
resource "azurerm_role_assignment" "test" {
scope = azurerm_postgresql_server.test.id
role_definition_name = "Reader"
principal_id = azurerm_data_protection_backup_vault.test.identity.0.principal_id
}
resource "azurerm_data_protection_backup_policy_postgresql" "test" {
name = "acctest-dp-%d"
name = "acctest-dp-%[1]d"
resource_group_name = azurerm_resource_group.test.name
vault_name = azurerm_data_protection_backup_vault.test.name
backup_repeating_time_intervals = ["R/2021-05-23T02:30:00+00:00/P1W"]
default_retention_duration = "P4M"
}
resource "azurerm_data_protection_backup_policy_postgresql" "another" {
name = "acctest-dp-second-%d"
name = "acctest-dp-second-%[1]d"
resource_group_name = azurerm_resource_group.test.name
vault_name = azurerm_data_protection_backup_vault.test.name
backup_repeating_time_intervals = ["R/2021-05-23T02:30:00+00:00/P1W"]
default_retention_duration = "P3M"
}
`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger)
`, data.RandomInteger, data.Locations.Primary, data.RandomStringOfLength(16))
}

func (r DataProtectionBackupInstancePostgreSQLResource) basic(data acceptance.TestData) string {
Expand Down Expand Up @@ -212,3 +287,19 @@ resource "azurerm_data_protection_backup_instance_postgresql" "test" {
}
`, template, data.RandomInteger)
}

func (r DataProtectionBackupInstancePostgreSQLResource) keyVaultAuth(data acceptance.TestData) string {
template := r.template(data)
return fmt.Sprintf(`
%s
resource "azurerm_data_protection_backup_instance_postgresql" "test" {
name = "acctest-dbi-%d"
location = azurerm_resource_group.test.location
vault_id = azurerm_data_protection_backup_vault.test.id
database_id = azurerm_postgresql_database.test.id
backup_policy_id = azurerm_data_protection_backup_policy_postgresql.another.id
database_credential_key_vault_secret_id = azurerm_key_vault_secret.test.versionless_id
}
`, template, data.RandomInteger)
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@ Manages a Backup Instance to back up PostgreSQL.
## Example Usage

```hcl
resource "azurerm_resource_group" "rg" {
name = "example-resources"
data "azurerm_client_config" "current" {}
resource "azurerm_resource_group" "example" {
name = "example"
location = "West Europe"
}
resource "azurerm_postgresql_server" "example" {
name = "example-postgresql-server"
name = "example"
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
Expand All @@ -38,37 +40,100 @@ resource "azurerm_postgresql_server" "example" {
ssl_enforcement_enabled = true
}
resource "azurerm_postgresql_firewall_rule" "example" {
name = "AllowAllWindowsAzureIps"
resource_group_name = azurerm_resource_group.example.name
server_name = azurerm_postgresql_server.example.name
start_ip_address = "0.0.0.0"
end_ip_address = "0.0.0.0"
}
resource "azurerm_postgresql_database" "example" {
name = "example-postgresql-database"
name = "example"
resource_group_name = azurerm_resource_group.example.name
server_name = azurerm_postgresql_server.example.name
charset = "UTF8"
collation = "English_United States.1252"
}
resource "azurerm_data_protection_backup_vault" "example" {
name = "example-backup-vault"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
name = "example"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
datastore_type = "VaultStore"
redundancy = "LocallyRedundant"
identity {
type = "SystemAssigned"
}
}
resource "azurerm_key_vault" "example" {
name = "example"
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
tenant_id = data.azurerm_client_config.current.tenant_id
sku_name = "premium"
soft_delete_retention_days = 7
access_policy {
tenant_id = data.azurerm_client_config.current.tenant_id
object_id = data.azurerm_client_config.current.object_id
key_permissions = ["create", "get"]
secret_permissions = [
"set",
"get",
"delete",
"purge",
"recover"
]
}
access_policy {
tenant_id = azurerm_data_protection_backup_vault.example.identity.0.tenant_id
object_id = azurerm_data_protection_backup_vault.example.identity.0.principal_id
key_permissions = ["create", "get"]
secret_permissions = [
"set",
"get",
"delete",
"purge",
"recover"
]
}
}
resource "azurerm_key_vault_secret" "example" {
name = "example"
value = "Server=${azurerm_postgresql_server.example.name}.postgres.database.azure.com;Database=${azurerm_postgresql_database.example.name};Port=5432;User Id=psqladminun@${azurerm_postgresql_server.example.name};Password=H@Sh1CoR3!;Ssl Mode=Require;"
key_vault_id = azurerm_key_vault.example.id
}
resource "azurerm_data_protection_backup_policy_postgresql" "example" {
name = "example-backup-policy"
resource_group_name = azurerm_resource_group.rg.name
name = "example"
resource_group_name = azurerm_resource_group.example.name
vault_name = azurerm_data_protection_backup_vault.example.name
backup_repeating_time_intervals = ["R/2021-05-23T02:30:00+00:00/P1W"]
default_retention_duration = "P4M"
}
resource "azurerm_data_protection_backup_instance_postgresql" "example" {
name = "example-backup-instance"
location = azurerm_resource_group.rg.location
vault_id = azurerm_data_protection_backup_vault.example.id
resource "azurerm_role_assignment" "example" {
scope = azurerm_postgresql_server.example.id
role_definition_name = "Reader"
principal_id = azurerm_data_protection_backup_vault.example.identity.0.principal_id
}
database_id = azurerm_postgresql_database.example.id
backup_policy_id = azurerm_data_protection_backup_policy_postgresql.example.id
resource "azurerm_data_protection_backup_instance_postgresql" "example" {
name = "example"
location = azurerm_resource_group.example.location
vault_id = azurerm_data_protection_backup_vault.example.id
database_id = azurerm_postgresql_database.example.id
backup_policy_id = azurerm_data_protection_backup_policy_postgresql.example.id
database_credential_key_vault_secret_id = azurerm_key_vault_secret.example.versionless_id
}
```

Expand All @@ -86,6 +151,8 @@ The following arguments are supported:

* `backup_policy_id` - (Required) The ID of the Backup Policy.

* `database_credential_key_vault_secret_id` - (Optional) The ID or versionless ID of the key vault secret which stores the connection string of the database.

## Attributes Reference

In addition to the Arguments listed above - the following Attributes are exported:
Expand Down

0 comments on commit 25adf41

Please sign in to comment.