diff --git a/azurerm/internal/services/recoveryservices/site_recovery_replicated_vm_resource.go b/azurerm/internal/services/recoveryservices/site_recovery_replicated_vm_resource.go index ff1be8e2e1b7..800d8ea44fac 100644 --- a/azurerm/internal/services/recoveryservices/site_recovery_replicated_vm_resource.go +++ b/azurerm/internal/services/recoveryservices/site_recovery_replicated_vm_resource.go @@ -164,6 +164,13 @@ func resourceSiteRecoveryReplicatedVM() *pluginsdk.Resource { }, true), DiffSuppressFunc: suppress.CaseDifference, }, + "target_disk_encryption_set_id": { + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: azure.ValidateResourceID, + DiffSuppressFunc: suppress.CaseDifference, + }, }, }, }, @@ -253,6 +260,7 @@ func resourceSiteRecoveryReplicatedItemCreate(d *pluginsdk.ResourceData, meta in recoveryResourceGroupId := diskInput["target_resource_group_id"].(string) targetReplicaDiskType := diskInput["target_replica_disk_type"].(string) targetDiskType := diskInput["target_disk_type"].(string) + targetEncryptionDiskSetID := diskInput["target_disk_encryption_set_id"].(string) managedDisks = append(managedDisks, siterecovery.A2AVMManagedDiskInputDetails{ DiskID: &diskId, @@ -260,6 +268,7 @@ func resourceSiteRecoveryReplicatedItemCreate(d *pluginsdk.ResourceData, meta in RecoveryResourceGroupID: &recoveryResourceGroupId, RecoveryReplicaDiskAccountType: &targetReplicaDiskType, RecoveryTargetDiskAccountType: &targetDiskType, + RecoveryDiskEncryptionSetID: &targetEncryptionDiskSetID, }) } @@ -453,6 +462,7 @@ func resourceSiteRecoveryReplicatedItemRead(d *pluginsdk.ResourceData, meta inte diskOutput["target_resource_group_id"] = *disk.RecoveryResourceGroupID diskOutput["target_replica_disk_type"] = *disk.RecoveryReplicaDiskAccountType diskOutput["target_disk_type"] = *disk.RecoveryTargetDiskAccountType + diskOutput["target_disk_encryption_set_id"] = *disk.RecoveryDiskEncryptionSetID disksOutput = append(disksOutput, diskOutput) } diff --git a/azurerm/internal/services/recoveryservices/site_recovery_replicated_vm_resource_test.go b/azurerm/internal/services/recoveryservices/site_recovery_replicated_vm_resource_test.go index 09c6e30ecc7c..706cb2fe151b 100644 --- a/azurerm/internal/services/recoveryservices/site_recovery_replicated_vm_resource_test.go +++ b/azurerm/internal/services/recoveryservices/site_recovery_replicated_vm_resource_test.go @@ -31,6 +31,21 @@ func TestAccSiteRecoveryReplicatedVm_basic(t *testing.T) { }) } +func TestAccSiteRecoveryReplicatedVm_des(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_site_recovery_replicated_vm", "test") + r := SiteRecoveryReplicatedVmResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.des(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + func (SiteRecoveryReplicatedVmResource) basic(data acceptance.TestData) string { return fmt.Sprintf(` provider "azurerm" { @@ -254,6 +269,409 @@ resource "azurerm_site_recovery_replicated_vm" "test" { `, data.RandomInteger, data.Locations.Primary, data.Locations.Secondary) } +func (SiteRecoveryReplicatedVmResource) des(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features { + key_vault { + purge_soft_delete_on_destroy = false + } + } +} + +data "azurerm_client_config" "current" {} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-recovery-%[1]d-1" + location = "%[2]s" +} + +resource "azurerm_resource_group" "test2" { + name = "acctestRG-recovery-%[1]d-2" + location = "%[3]s" +} + + +resource "azurerm_key_vault" "test" { + name = "kv%[1]d" + 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 = "standard" + enabled_for_disk_encryption = true + purge_protection_enabled = true +} + + +resource "azurerm_key_vault_access_policy" "service-principal" { + key_vault_id = azurerm_key_vault.test.id + tenant_id = data.azurerm_client_config.current.tenant_id + object_id = data.azurerm_client_config.current.object_id + + key_permissions = [ + "create", + "delete", + "get", + "purge", + "update", + ] + + secret_permissions = [ + "get", + "delete", + "set", + ] +} + +resource "azurerm_key_vault_key" "test" { + name = "examplekey" + key_vault_id = azurerm_key_vault.test.id + key_type = "RSA" + key_size = 2048 + + key_opts = [ + "decrypt", + "encrypt", + "sign", + "unwrapKey", + "verify", + "wrapKey", + ] + + depends_on = ["azurerm_key_vault_access_policy.service-principal"] +} + +resource "azurerm_disk_encryption_set" "test" { + name = "acctestdes-%[1]d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + key_vault_key_id = azurerm_key_vault_key.test.id + + identity { + type = "SystemAssigned" + } +} + +resource "azurerm_key_vault_access_policy" "disk-encryption" { + key_vault_id = azurerm_key_vault.test.id + + key_permissions = [ + "get", + "wrapkey", + "unwrapkey", + ] + + tenant_id = azurerm_disk_encryption_set.test.identity.0.tenant_id + object_id = azurerm_disk_encryption_set.test.identity.0.principal_id +} + +resource "azurerm_role_assignment" "disk-encryption-read-keyvault" { + scope = azurerm_key_vault.test.id + role_definition_name = "Reader" + principal_id = azurerm_disk_encryption_set.test.identity.0.principal_id +} + +resource "azurerm_managed_disk" "test" { + name = "acctestd-%[1]d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + storage_account_type = "Standard_LRS" + create_option = "Empty" + disk_size_gb = 1 + disk_encryption_set_id = azurerm_disk_encryption_set.test.id + + depends_on = [ + "azurerm_role_assignment.disk-encryption-read-keyvault", + "azurerm_key_vault_access_policy.disk-encryption", + ] +} + +resource "azurerm_virtual_network" "test" { + name = "acctvn-%[1]d" + address_space = ["10.0.0.0/16"] + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name +} + +resource "azurerm_subnet" "test" { + name = "acctsub-%[1]d" + resource_group_name = azurerm_resource_group.test.name + virtual_network_name = azurerm_virtual_network.test.name + address_prefix = "10.0.2.0/24" +} + +resource "azurerm_network_interface" "test" { + name = "acctni-%[1]d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + + ip_configuration { + name = "testconfiguration1" + subnet_id = azurerm_subnet.test.id + private_ip_address_allocation = "Dynamic" + } +} + + +resource "azurerm_virtual_machine" "test" { + name = "acctvm-%[1]d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + network_interface_ids = [azurerm_network_interface.test.id] + vm_size = "Standard_D1_v2" + + storage_image_reference { + publisher = "Canonical" + offer = "UbuntuServer" + sku = "16.04-LTS" + version = "latest" + } + + storage_os_disk { + name = "osd-%[1]d" + caching = "ReadWrite" + create_option = "FromImage" + disk_size_gb = "50" + managed_disk_type = "Standard_LRS" + } + + storage_data_disk { + name = "acctmd-%[1]d" + create_option = "Empty" + disk_size_gb = "1" + lun = 0 + managed_disk_type = "Standard_LRS" + } + + storage_data_disk { + name = azurerm_managed_disk.test.name + create_option = "Attach" + disk_size_gb = "1" + lun = 1 + managed_disk_id = azurerm_managed_disk.test.id + } + + os_profile { + computer_name = "hn%[1]d" + admin_username = "testadmin" + admin_password = "Password1234!" + } + + os_profile_linux_config { + disable_password_authentication = false + } + + tags = { + environment = "Production" + cost-center = "Ops" + } +} + +resource "azurerm_recovery_services_vault" "test" { + name = "acctest-vault-%[1]d" + location = azurerm_resource_group.test2.location + resource_group_name = azurerm_resource_group.test2.name + sku = "Standard" + + soft_delete_enabled = false +} + +resource "azurerm_site_recovery_fabric" "test1" { + resource_group_name = azurerm_resource_group.test2.name + recovery_vault_name = azurerm_recovery_services_vault.test.name + name = "acctest-fabric1-%[1]d" + location = azurerm_resource_group.test.location +} + +resource "azurerm_site_recovery_fabric" "test2" { + resource_group_name = azurerm_resource_group.test2.name + recovery_vault_name = azurerm_recovery_services_vault.test.name + name = "acctest-fabric2-%[1]d" + location = azurerm_resource_group.test2.location + depends_on = [azurerm_site_recovery_fabric.test1] +} + +resource "azurerm_site_recovery_protection_container" "test1" { + resource_group_name = azurerm_resource_group.test2.name + recovery_vault_name = azurerm_recovery_services_vault.test.name + recovery_fabric_name = azurerm_site_recovery_fabric.test1.name + name = "acctest-protection-cont1-%[1]d" +} + +resource "azurerm_site_recovery_protection_container" "test2" { + resource_group_name = azurerm_resource_group.test2.name + recovery_vault_name = azurerm_recovery_services_vault.test.name + recovery_fabric_name = azurerm_site_recovery_fabric.test2.name + name = "acctest-protection-cont2-%[1]d" +} + +resource "azurerm_site_recovery_replication_policy" "test" { + resource_group_name = azurerm_resource_group.test2.name + recovery_vault_name = azurerm_recovery_services_vault.test.name + name = "acctest-policy-%[1]d" + recovery_point_retention_in_minutes = 24 * 60 + application_consistent_snapshot_frequency_in_minutes = 4 * 60 +} + +resource "azurerm_site_recovery_protection_container_mapping" "test" { + resource_group_name = azurerm_resource_group.test2.name + recovery_vault_name = azurerm_recovery_services_vault.test.name + recovery_fabric_name = azurerm_site_recovery_fabric.test1.name + recovery_source_protection_container_name = azurerm_site_recovery_protection_container.test1.name + recovery_target_protection_container_id = azurerm_site_recovery_protection_container.test2.id + recovery_replication_policy_id = azurerm_site_recovery_replication_policy.test.id + name = "mapping-%[1]d" +} + +resource "azurerm_virtual_network" "test2" { + name = "net-%[1]d-2" + resource_group_name = azurerm_resource_group.test2.name + address_space = ["192.168.2.0/24"] + location = azurerm_site_recovery_fabric.test2.location +} + +resource "azurerm_subnet" "test2_1" { + name = "acctest-snet-%[1]d-2" + resource_group_name = "${azurerm_resource_group.test2.name}" + virtual_network_name = "${azurerm_virtual_network.test2.name}" + address_prefixes = ["192.168.2.0/27"] +} + +resource "azurerm_subnet" "test2_2" { + name = "snet-%[1]d-3" + resource_group_name = "${azurerm_resource_group.test2.name}" + virtual_network_name = "${azurerm_virtual_network.test2.name}" + address_prefixes = ["192.168.2.32/27"] +} + +resource "azurerm_site_recovery_network_mapping" "test" { + resource_group_name = azurerm_resource_group.test2.name + recovery_vault_name = azurerm_recovery_services_vault.test.name + name = "mapping-%[1]d" + source_recovery_fabric_name = azurerm_site_recovery_fabric.test1.name + target_recovery_fabric_name = azurerm_site_recovery_fabric.test2.name + source_network_id = azurerm_virtual_network.test.id + target_network_id = azurerm_virtual_network.test2.id +} + +resource "azurerm_public_ip" "test-recovery" { + name = "pubip%[1]d-recovery" + allocation_method = "Static" + location = azurerm_resource_group.test2.location + resource_group_name = azurerm_resource_group.test2.name + sku = "Basic" +} + +resource "azurerm_key_vault" "test2" { + name = "kv%[1]d2" + 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" + enabled_for_disk_encryption = true + purge_protection_enabled = true +} + +resource "azurerm_key_vault_access_policy" "service-principal2" { + 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 = [ + "create", + "delete", + "get", + "purge", + "update", + ] + + secret_permissions = [ + "get", + "delete", + "set", + ] +} + +resource "azurerm_key_vault_key" "test2" { + name = "examplekey" + 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.service-principal2"] +} + +resource "azurerm_disk_encryption_set" "test2" { + name = "acctestdes-%[1]d2" + resource_group_name = azurerm_resource_group.test2.name + location = azurerm_resource_group.test2.location + key_vault_key_id = azurerm_key_vault_key.test2.id + + identity { + type = "SystemAssigned" + } +} + +resource "azurerm_key_vault_access_policy" "disk-encryption2" { + key_vault_id = azurerm_key_vault.test2.id + + key_permissions = [ + "get", + "wrapkey", + "unwrapkey", + ] + + tenant_id = azurerm_disk_encryption_set.test2.identity.0.tenant_id + object_id = azurerm_disk_encryption_set.test2.identity.0.principal_id +} + +resource "azurerm_storage_account" "test" { + name = "acct%[1]d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + account_tier = "Standard" + account_replication_type = "LRS" +} + +resource "azurerm_site_recovery_replicated_vm" "test" { + name = "repl-%[1]d" + resource_group_name = azurerm_resource_group.test2.name + recovery_vault_name = azurerm_recovery_services_vault.test.name + source_vm_id = azurerm_virtual_machine.test.id + source_recovery_fabric_name = azurerm_site_recovery_fabric.test1.name + recovery_replication_policy_id = azurerm_site_recovery_replication_policy.test.id + source_recovery_protection_container_name = azurerm_site_recovery_protection_container.test1.name + + target_resource_group_id = azurerm_resource_group.test2.id + target_recovery_fabric_id = azurerm_site_recovery_fabric.test2.id + target_recovery_protection_container_id = azurerm_site_recovery_protection_container.test2.id + + managed_disk { + disk_id = azurerm_virtual_machine.test.storage_os_disk[0].managed_disk_id + staging_storage_account_id = azurerm_storage_account.test.id + target_resource_group_id = azurerm_resource_group.test2.id + target_disk_type = "Premium_LRS" + target_replica_disk_type = "Premium_LRS" + target_disk_encryption_set_id = azurerm_disk_encryption_set.test2.id + } + + depends_on = [ + azurerm_site_recovery_protection_container_mapping.test, + azurerm_site_recovery_network_mapping.test, + ] +} +`, data.RandomInteger, data.Locations.Primary, data.Locations.Secondary) +} + func (t SiteRecoveryReplicatedVmResource) Exists(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { id, err := azure.ParseAzureResourceID(state.ID) if err != nil { diff --git a/website/docs/r/site_recovery_replicated_vm.html.markdown b/website/docs/r/site_recovery_replicated_vm.html.markdown index 32800a4b4d8c..ef039f50b53a 100644 --- a/website/docs/r/site_recovery_replicated_vm.html.markdown +++ b/website/docs/r/site_recovery_replicated_vm.html.markdown @@ -247,6 +247,8 @@ A `managed_disk` block supports the following: * `target_replica_disk_type` - (Required) What type should the disk be that holds the replication data. +* `target_disk_encryption_set_id` - (Optional) The Disk Encryption Set that the Managed Disk will be associated with. + --- A `network_interface` block supports the following: