Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support EncryptionAtRestWithPlatformAndCustomerKeys in disk encryption #14218

Merged
merged 4 commits into from
Nov 18, 2021

Conversation

myc2h6o
Copy link
Contributor

@myc2h6o myc2h6o commented Nov 17, 2021

Fix #10588

  • r\disk_encrytpion_set: Add new property encryption_type
    • By default the value is EncryptionAtRestWithCustomerKey, and user can specify EncryptionAtRestWithPlatformAndCustomerKeys to enable double encryption, which uses both customer key and platform key.
    • This property cannot be updated although it is an settable in update api, thus setting ForceNew
  • r\managed_disk, r\linux_virtual_machine, r\windows_virtual_machine: Auto-detect encryptionType from disk_encryption_set_id
    • Earlier encryptionType is always EncryptionAtRestWithCustomerKey, which throws an error when the encryption type of the corresponding encryption set is EncryptionAtRestWithPlatformAndCustomerKeys. In this change, when disk_encryption_set_id is specified, the encryptionType will be retrieved from the encryption set so that it can support both encryption types.
  • r\managed_disk: Update ValidateFunc from azure.ValidateResourceID to validate.DiskEncryptionSetID
  • Test result
    Tested with TestAccDiskEncryptionSet_|TestAccManagedDisk_|TestAccLinuxVirtualMachine_|TestAccWindowsVirtualMachine_. 196/200 tests pass, failed tests fail at main as well
    image

Copy link
Member

@stephybun stephybun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @myc2h6o, thanks for this PR! Overall this look goods, I have a few suggestions though.

@@ -344,8 +344,19 @@ func resourceManagedDiskCreate(d *pluginsdk.ResourceData, meta interface{}) erro
}

if diskEncryptionSetId := d.Get("disk_encryption_set_id").(string); diskEncryptionSetId != "" {
diskEncryptionSet, err := parse.DiskEncryptionSetID(diskEncryptionSetId)
if err != nil {
return fmt.Errorf("`disk_encryption_set_id` is not a valid disk encryption set id")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error returned from parse.DiskEncryptionSetID contains some really useful information on why the id couldn't be parsed so I think it would be more helpful to return that in addition/instead of an error message

Suggested change
return fmt.Errorf("`disk_encryption_set_id` is not a valid disk encryption set id")
return err

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated and moved to new method retrieveDiskEncryptionSetEncryptionType in disk_encryption_set.go

diskEncryptionSetClient := meta.(*clients.Client).Compute.DiskEncryptionSetsClient
resp, err := diskEncryptionSetClient.Get(ctx, diskEncryptionSet.ResourceGroup, diskEncryptionSet.Name)
if err != nil {
return fmt.Errorf("reading Disk Encryption Set %q (Resource Group %q): %+v", diskEncryptionSet.Name, diskEncryptionSet.ResourceGroup, err)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could shorten the error message here since that info is contained within the parsed resource ID

Suggested change
return fmt.Errorf("reading Disk Encryption Set %q (Resource Group %q): %+v", diskEncryptionSet.Name, diskEncryptionSet.ResourceGroup, err)
return fmt.Errorf("reading %s: %+v", *diskEncryptionSet, err)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated in the new method

@@ -537,8 +548,19 @@ func resourceManagedDiskUpdate(d *pluginsdk.ResourceData, meta interface{}) erro
if d.HasChange("disk_encryption_set_id") {
shouldShutDown = true
if diskEncryptionSetId := d.Get("disk_encryption_set_id").(string); diskEncryptionSetId != "" {
diskEncryptionSet, err := parse.DiskEncryptionSetID(diskEncryptionSetId)
if err != nil {
return fmt.Errorf("`disk_encryption_set_id` is not a valid disk encryption set id")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment here as above

diskEncryptionSetClient := meta.(*clients.Client).Compute.DiskEncryptionSetsClient
resp, err := diskEncryptionSetClient.Get(ctx, diskEncryptionSet.ResourceGroup, diskEncryptionSet.Name)
if err != nil {
return fmt.Errorf("reading Disk Encryption Set %q (Resource Group %q): %+v", diskEncryptionSet.Name, diskEncryptionSet.ResourceGroup, err)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here as above

@@ -107,6 +107,8 @@ The following arguments are supported:

* `auto_key_rotation_enabled` - (Optional) Boolean flag to specify whether Azure Disk Encryption Set automatically rotates encryption Key to latest version. Defaults to `false`.

* `encryption_type` - (Optional) The type of key used to encrypt the data of the disk. Allowed values are `EncryptionAtRestWithCustomerKey` and `EncryptionAtRestWithPlatformAndCustomerKeys`. Defaults to `EncryptionAtRestWithCustomerKey`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* `encryption_type` - (Optional) The type of key used to encrypt the data of the disk. Allowed values are `EncryptionAtRestWithCustomerKey` and `EncryptionAtRestWithPlatformAndCustomerKeys`. Defaults to `EncryptionAtRestWithCustomerKey`.
* `encryption_type` - (Optional) The type of key used to encrypt the data of the disk. Accepted values are `EncryptionAtRestWithCustomerKey` and `EncryptionAtRestWithPlatformAndCustomerKeys`. Defaults to `EncryptionAtRestWithCustomerKey`.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've been using Possible in most cases fwiw:

Suggested change
* `encryption_type` - (Optional) The type of key used to encrypt the data of the disk. Allowed values are `EncryptionAtRestWithCustomerKey` and `EncryptionAtRestWithPlatformAndCustomerKeys`. Defaults to `EncryptionAtRestWithCustomerKey`.
* `encryption_type` - (Optional) The type of key used to encrypt the data of the disk. Possible values are `EncryptionAtRestWithCustomerKey` and `EncryptionAtRestWithPlatformAndCustomerKeys`. Defaults to `EncryptionAtRestWithCustomerKey`.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated


resp, err := client.Get(ctx, diskEncryptionSet.ResourceGroup, diskEncryptionSet.Name)
if err != nil {
return nil, err
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it makes sense to specify an error occurred while attempting to retrieve a disk encryption set

Suggested change
return nil, err
return nil, fmt.Errorf("retrieving %s: %+v", *diskEncryptionSet, err)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes make sense, adding retrieving %s to the error message

@@ -1089,12 +1089,17 @@ func resourceLinuxVirtualMachineUpdate(d *pluginsdk.ResourceData, meta interface
diskName := d.Get("os_disk.0.name").(string)
log.Printf("[DEBUG] Updating encryption settings of OS Disk %q for Linux Virtual Machine %q (Resource Group %q) to %q..", diskName, id.Name, id.ResourceGroup, diskEncryptionSetId)

encryptionType, err := retrieveDiskEncryptionSetEncryptionType(ctx, meta.(*clients.Client).Compute.DiskEncryptionSetsClient, diskEncryptionSetId)
if err != nil {
return fmt.Errorf("retrieving encryption type from disk encryption set %q: %+v", diskEncryptionSetId, err)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And then here to just return the error

Suggested change
return fmt.Errorf("retrieving encryption type from disk encryption set %q: %+v", diskEncryptionSetId, err)
return err

@@ -344,8 +344,13 @@ func resourceManagedDiskCreate(d *pluginsdk.ResourceData, meta interface{}) erro
}

if diskEncryptionSetId := d.Get("disk_encryption_set_id").(string); diskEncryptionSetId != "" {
encryptionType, err := retrieveDiskEncryptionSetEncryptionType(ctx, meta.(*clients.Client).Compute.DiskEncryptionSetsClient, diskEncryptionSetId)
if err != nil {
return fmt.Errorf("retrieving encryption type from disk encryption set %q: %+v", diskEncryptionSetId, err)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here

@@ -537,8 +542,13 @@ func resourceManagedDiskUpdate(d *pluginsdk.ResourceData, meta interface{}) erro
if d.HasChange("disk_encryption_set_id") {
shouldShutDown = true
if diskEncryptionSetId := d.Get("disk_encryption_set_id").(string); diskEncryptionSetId != "" {
encryptionType, err := retrieveDiskEncryptionSetEncryptionType(ctx, meta.(*clients.Client).Compute.DiskEncryptionSetsClient, diskEncryptionSetId)
if err != nil {
return fmt.Errorf("retrieving encryption type from disk encryption set %q: %+v", diskEncryptionSetId, err)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here

@@ -1126,12 +1126,17 @@ func resourceWindowsVirtualMachineUpdate(d *pluginsdk.ResourceData, meta interfa
diskName := d.Get("os_disk.0.name").(string)
log.Printf("[DEBUG] Updating encryption settings of OS Disk %q for Windows Virtual Machine %q (Resource Group %q) to %q..", diskName, id.Name, id.ResourceGroup, diskEncryptionSetId)

encryptionType, err := retrieveDiskEncryptionSetEncryptionType(ctx, meta.(*clients.Client).Compute.DiskEncryptionSetsClient, diskEncryptionSetId)
if err != nil {
return fmt.Errorf("retrieving encryption type from disk encryption set %q: %+v", diskEncryptionSetId, err)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here

Copy link
Contributor

@tombuildsstuff tombuildsstuff left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hi @myc2h6o

Thanks for this PR.

I've taken a look through and left some comments line in addition to @stephybun's review - if we can fix up both sets of comments then we should be able to take another look.

Thanks!

ValidateFunc: validation.StringInSlice([]string{
string(compute.DiskEncryptionSetTypeEncryptionAtRestWithCustomerKey),
string(compute.DiskEncryptionSetTypeEncryptionAtRestWithPlatformAndCustomerKeys),
}, true),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be case-sensitive:

Suggested change
}, true),
}, false),

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated

@@ -203,6 +216,7 @@ func resourceDiskEncryptionSetRead(d *pluginsdk.ResourceData, meta interface{})
}
d.Set("key_vault_key_id", keyVaultKeyId)
d.Set("auto_key_rotation_enabled", props.RotationToLatestKeyVersionEnabled)
d.Set("encryption_type", props.EncryptionType)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this won't be returned from the API for older resources - so we'll need to default that in code:

Suggested change
d.Set("encryption_type", props.EncryptionType)
encryptionType := string(compute.DiskEncryptionSetTypeEncryptionAtRestWithCustomerKey)
if props.EncryptionType != "" {
encryptionType = string(props.EncryptionType)
}
d.Set("encryption_type", encryptionType)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to set default value

Type: pluginsdk.TypeString,
Optional: true,
ForceNew: true,
Default: compute.DiskEncryptionSetTypeEncryptionAtRestWithCustomerKey,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be a string:

Suggested change
Default: compute.DiskEncryptionSetTypeEncryptionAtRestWithCustomerKey,
Default: string(compute.DiskEncryptionSetTypeEncryptionAtRestWithCustomerKey),

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for pointing out, updated

Comment on lines 112 to 121
{
Config: r.withEncryptionTypeDefault(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
check.That(data.ResourceName).Key("encryption_type").HasValue("EncryptionAtRestWithCustomerKey"),
),
},
data.ImportStep(),
{
Config: r.withEncryptionTypeUpdated(data),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this field is ForceNew, so this won't update - it'll destroy and recreate the resource. Since the first step is the same as Basic we can remove this, and move the assertion up into the Basic test

Suggested change
{
Config: r.withEncryptionTypeDefault(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
check.That(data.ResourceName).Key("encryption_type").HasValue("EncryptionAtRestWithCustomerKey"),
),
},
data.ImportStep(),
{
Config: r.withEncryptionTypeUpdated(data),
{
Config: r.customerAndPlatformKey(data),

Copy link
Contributor Author

@myc2h6o myc2h6o Nov 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes make sense, removed the update part in the test and add the default value check to the basic test

`, r.dependencies(data), data.RandomInteger)
}

func (r DiskEncryptionSetResource) withEncryptionTypeUpdated(data acceptance.TestData) string {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
func (r DiskEncryptionSetResource) withEncryptionTypeUpdated(data acceptance.TestData) string {
func (r DiskEncryptionSetResource) customerAndPlatformKey(data acceptance.TestData) string {

disksClient := meta.(*clients.Client).Compute.DisksClient

update := compute.DiskUpdate{
DiskUpdateProperties: &compute.DiskUpdateProperties{
Encryption: &compute.Encryption{
Type: compute.EncryptionTypeEncryptionAtRestWithCustomerKey,
Type: compute.EncryptionType(*encryptionType),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here:

Suggested change
Type: compute.EncryptionType(*encryptionType),
Type: *encryptionType,

@@ -107,6 +107,8 @@ The following arguments are supported:

* `auto_key_rotation_enabled` - (Optional) Boolean flag to specify whether Azure Disk Encryption Set automatically rotates encryption Key to latest version. Defaults to `false`.

* `encryption_type` - (Optional) The type of key used to encrypt the data of the disk. Allowed values are `EncryptionAtRestWithCustomerKey` and `EncryptionAtRestWithPlatformAndCustomerKeys`. Defaults to `EncryptionAtRestWithCustomerKey`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've been using Possible in most cases fwiw:

Suggested change
* `encryption_type` - (Optional) The type of key used to encrypt the data of the disk. Allowed values are `EncryptionAtRestWithCustomerKey` and `EncryptionAtRestWithPlatformAndCustomerKeys`. Defaults to `EncryptionAtRestWithCustomerKey`.
* `encryption_type` - (Optional) The type of key used to encrypt the data of the disk. Possible values are `EncryptionAtRestWithCustomerKey` and `EncryptionAtRestWithPlatformAndCustomerKeys`. Defaults to `EncryptionAtRestWithCustomerKey`.

@@ -248,6 +248,8 @@ A `os_disk` block supports the following:

-> **NOTE:** The Disk Encryption Set must have the `Reader` Role Assignment scoped on the Key Vault - in addition to an Access Policy to the Key Vault

-> **NOTE:** Encryption type of the key will be decided by the disk encryption set. [More info on encryption type](https://docs.microsoft.com/en-us/azure/virtual-machines/disk-encryption)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this fields configured on the Disk Encryption Set rather than the VM, so this comment isn't really necessary:

Suggested change
-> **NOTE:** Encryption type of the key will be decided by the disk encryption set. [More info on encryption type](https://docs.microsoft.com/en-us/azure/virtual-machines/disk-encryption)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed.

@@ -97,6 +97,8 @@ The following arguments are supported:

~> **NOTE:** Disk Encryption Sets are in Public Preview in a limited set of regions

-> **NOTE:** Encryption type of the key will be decided by the disk encryption set. [More info on encryption type](https://docs.microsoft.com/en-us/azure/virtual-machines/disk-encryption)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this fields configured on the Disk Encryption Set rather than the VM, so this comment isn't really necessary:

Suggested change
-> **NOTE:** Encryption type of the key will be decided by the disk encryption set. [More info on encryption type](https://docs.microsoft.com/en-us/azure/virtual-machines/disk-encryption)

@@ -241,6 +241,8 @@ A `os_disk` block supports the following:

-> **NOTE:** The Disk Encryption Set must have the `Reader` Role Assignment scoped on the Key Vault - in addition to an Access Policy to the Key Vault

-> **NOTE:** Encryption type of the key will be decided by the disk encryption set. [More info on encryption type](https://docs.microsoft.com/en-us/azure/virtual-machines/disk-encryption)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this fields configured on the Disk Encryption Set rather than the VM, so this comment isn't really necessary:

Suggested change
-> **NOTE:** Encryption type of the key will be decided by the disk encryption set. [More info on encryption type](https://docs.microsoft.com/en-us/azure/virtual-machines/disk-encryption)

Copy link
Member

@stephybun stephybun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for adopting those changes @myc2h6o. The tests are passing too so this LGTM 🚀

@stephybun stephybun merged commit 6cdd818 into hashicorp:main Nov 18, 2021
@github-actions github-actions bot added this to the v2.86.0 milestone Nov 18, 2021
stephybun added a commit that referenced this pull request Nov 18, 2021
@myc2h6o myc2h6o deleted the double_encryption branch November 19, 2021 01:51
@github-actions
Copy link

This functionality has been released in v2.86.0 of the Terraform Provider. Please see the Terraform documentation on provider versioning or reach out if you need any assistance upgrading.

For further feature requests or bug reports with this functionality, please create a new GitHub issue following the template. Thank you!

@github-actions
Copy link

I'm going to lock this pull request because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active contributions.
If you have found a problem that seems related to this change, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Dec 21, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
3 participants