Skip to content

Commit

Permalink
azurerm_mysql_flexible_server - support `geo_backup_key_vault_key_i…
Browse files Browse the repository at this point in the history
…d` and `geo_backup_user_assigned_identity_id` (#20796)

Co-authored-by: kt <kt@katbyte.me>
  • Loading branch information
neil-yechenwei and katbyte authored Mar 21, 2023
1 parent 0cd25eb commit 965d723
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 4 deletions.
45 changes: 42 additions & 3 deletions internal/services/mysql/mysql_flexible_server_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,20 @@ func resourceMysqlFlexibleServer() *pluginsdk.Resource {
Optional: true,
ValidateFunc: commonids.ValidateUserAssignedIdentityID,
},
"geo_backup_key_vault_key_id": {
Type: pluginsdk.TypeString,
Optional: true,
ValidateFunc: keyVaultValidate.NestedItemIdWithOptionalVersion,
RequiredWith: []string{
"identity",
"customer_managed_key.0.geo_backup_user_assigned_identity_id",
},
},
"geo_backup_user_assigned_identity_id": {
Type: pluginsdk.TypeString,
Optional: true,
ValidateFunc: commonids.ValidateUserAssignedIdentityID,
},
},
},
},
Expand Down Expand Up @@ -930,9 +944,23 @@ func expandFlexibleServerDataEncryption(input []interface{}) *servers.DataEncryp

det := servers.DataEncryptionTypeAzureKeyVault
dataEncryption := servers.DataEncryption{
Type: &det,
PrimaryKeyURI: utils.String(v["key_vault_key_id"].(string)),
PrimaryUserAssignedIdentityId: utils.String(v["primary_user_assigned_identity_id"].(string)),
Type: &det,
}

if keyVaultKeyId := v["key_vault_key_id"].(string); keyVaultKeyId != "" {
dataEncryption.PrimaryKeyURI = utils.String(keyVaultKeyId)
}

if primaryUserAssignedIdentityId := v["primary_user_assigned_identity_id"].(string); primaryUserAssignedIdentityId != "" {
dataEncryption.PrimaryUserAssignedIdentityId = utils.String(primaryUserAssignedIdentityId)
}

if geoBackupKeyVaultKeyId := v["geo_backup_key_vault_key_id"].(string); geoBackupKeyVaultKeyId != "" {
dataEncryption.GeoBackupKeyURI = utils.String(geoBackupKeyVaultKeyId)
}

if geoBackupUserAssignedIdentityId := v["geo_backup_user_assigned_identity_id"].(string); geoBackupUserAssignedIdentityId != "" {
dataEncryption.GeoBackupUserAssignedIdentityId = utils.String(geoBackupUserAssignedIdentityId)
}

return &dataEncryption
Expand All @@ -955,6 +983,17 @@ func flattenFlexibleServerDataEncryption(de *servers.DataEncryption) ([]interfac
item["primary_user_assigned_identity_id"] = parsed.ID()
}

if de.GeoBackupKeyURI != nil {
item["geo_backup_key_vault_key_id"] = *de.GeoBackupKeyURI
}
if identity := de.GeoBackupUserAssignedIdentityId; identity != nil {
parsed, err := commonids.ParseUserAssignedIdentityIDInsensitively(*identity)
if err != nil {
return nil, fmt.Errorf("parsing %q: %+v", *identity, err)
}
item["geo_backup_user_assigned_identity_id"] = parsed.ID()
}

return []interface{}{item}, nil
}

Expand Down
94 changes: 94 additions & 0 deletions internal/services/mysql/mysql_flexible_server_resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,22 @@ func TestAccMySqlFlexibleServer_updateToCustomerManagedKey(t *testing.T) {
})
}

// this test can fail with a uninformative error, tracked here https://github.com/Azure/azure-rest-api-specs/issues/22980
func TestAccMySqlFlexibleServer_enableGeoRedundantBackup(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_mysql_flexible_server", "test")
r := MySqlFlexibleServerResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.enableGeoRedundantBackup(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep("administrator_password"),
})
}

func (MySqlFlexibleServerResource) Exists(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) (*bool, error) {
id, err := servers.ParseFlexibleServerID(state.ID)
if err != nil {
Expand Down Expand Up @@ -1080,3 +1096,81 @@ resource "azurerm_mysql_flexible_server" "test" {
}
`, r.cmkTemplate(data), data.RandomInteger)
}

func (r MySqlFlexibleServerResource) enableGeoRedundantBackup(data acceptance.TestData) string {
return fmt.Sprintf(`
%s
resource "azurerm_resource_group" "test2" {
name = "acctestRG-mysql2-%d"
location = "%s"
}
resource "azurerm_user_assigned_identity" "test2" {
name = "acctestmi%s"
location = azurerm_resource_group.test2.location
resource_group_name = azurerm_resource_group.test2.name
}
resource "azurerm_key_vault" "test2" {
name = "acctestkv2%s"
location = azurerm_resource_group.test2.location
resource_group_name = azurerm_resource_group.test2.name
tenant_id = data.azurerm_client_config.current.tenant_id
sku_name = "standard"
purge_protection_enabled = true
}
resource "azurerm_key_vault_access_policy" "server2" {
key_vault_id = azurerm_key_vault.test2.id
tenant_id = data.azurerm_client_config.current.tenant_id
object_id = azurerm_user_assigned_identity.test2.principal_id
key_permissions = ["Get", "List", "WrapKey", "UnwrapKey"]
}
resource "azurerm_key_vault_access_policy" "client2" {
key_vault_id = azurerm_key_vault.test2.id
tenant_id = data.azurerm_client_config.current.tenant_id
object_id = data.azurerm_client_config.current.object_id
key_permissions = ["Get", "Create", "Delete", "List", "Restore", "Recover", "UnwrapKey", "WrapKey", "Purge", "Encrypt", "Decrypt", "Sign", "Verify", "GetRotationPolicy"]
}
resource "azurerm_key_vault_key" "test2" {
name = "test2"
key_vault_id = azurerm_key_vault.test2.id
key_type = "RSA"
key_size = 2048
key_opts = ["decrypt", "encrypt", "sign", "unwrapKey", "verify", "wrapKey"]
depends_on = [
azurerm_key_vault_access_policy.client2,
azurerm_key_vault_access_policy.server2,
]
}
resource "azurerm_mysql_flexible_server" "test" {
name = "acctest-fs-%d"
resource_group_name = azurerm_resource_group.test.name
location = azurerm_resource_group.test.location
administrator_login = "_admin_Terraform_892123456789312"
administrator_password = "QAZwsx123"
sku_name = "B_Standard_B1s"
zone = "2"
geo_redundant_backup_enabled = true
identity {
type = "UserAssigned"
identity_ids = [azurerm_user_assigned_identity.test.id, azurerm_user_assigned_identity.test2.id]
}
customer_managed_key {
key_vault_key_id = azurerm_key_vault_key.test.id
primary_user_assigned_identity_id = azurerm_user_assigned_identity.test.id
geo_backup_key_vault_key_id = azurerm_key_vault_key.test2.id
geo_backup_user_assigned_identity_id = azurerm_user_assigned_identity.test2.id
}
}
`, r.cmkTemplate(data), data.RandomInteger, data.Locations.Secondary, data.RandomString, data.RandomString, data.RandomInteger)
}
6 changes: 5 additions & 1 deletion website/docs/r/mysql_flexible_server.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,11 @@ A `customer_managed_key` block supports the following:

* `primary_user_assigned_identity_id` - (Optional) Specifies the primary user managed identity id for a Customer Managed Key. Should be added with `identity_ids`.

~> **NOTE:** This is required when `type` is set to `UserAssigned` or `SystemAssigned, UserAssigned`.
* `geo_backup_key_vault_key_id` - (Optional) The ID of the geo backup Key Vault Key. It can't cross region and need Customer Managed Key in same region as geo backup.

* `geo_backup_user_assigned_identity_id` - (Optional) The geo backup user managed identity id for a Customer Managed Key. Should be added with `identity_ids`. It can't cross region and need identity in same region as geo backup.

~> **NOTE:** `primary_user_assigned_identity_id` or `geo_backup_user_assigned_identity_id` is required when `type` is set to `UserAssigned` or `SystemAssigned, UserAssigned`.

---

Expand Down

0 comments on commit 965d723

Please sign in to comment.