Skip to content

Commit

Permalink
Rekey disks for encrypted VMs
Browse files Browse the repository at this point in the history
This patch supports rekeying disks when an encrypted VM is rekeyed.
  • Loading branch information
akutz committed Oct 24, 2024
1 parent 38b38ba commit f52b1ee
Show file tree
Hide file tree
Showing 19 changed files with 715 additions and 86 deletions.
21 changes: 21 additions & 0 deletions api/v1alpha3/virtualmachine_storage_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,22 @@ const (
VirtualMachineStorageDiskTypeManaged VirtualMachineVolumeType = "Managed"
)

type VirtualMachineVolumeCryptoStatus struct {
// +optional

// ProviderID describes the provider ID used to encrypt the volume.
// Please note, this field will be empty if the volume is not
// encrypted.
ProviderID string `json:"providerID,omitempty"`

// +optional

// KeyID describes the key ID used to encrypt the volume.
// Please note, this field will be empty if the volume is not
// encrypted.
KeyID string `json:"keyID,omitempty"`
}

// VirtualMachineVolumeStatus defines the observed state of a
// VirtualMachineVolume instance.
type VirtualMachineVolumeStatus struct {
Expand All @@ -97,6 +113,11 @@ type VirtualMachineVolumeStatus struct {

// +optional

// Crypto describes the volume's encryption status.
Crypto *VirtualMachineVolumeCryptoStatus `json:"crypto,omitempty"`

// +optional

// Limit describes the storage limit for the volume.
Limit *resource.Quantity `json:"limit,omitempty"`

Expand Down
8 changes: 3 additions & 5 deletions api/v1alpha3/virtualmachine_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -745,11 +745,9 @@ type VirtualMachineCryptoStatus struct {
//
// - Config -- This refers to all of the files related to a VM except any
// virtual disks.
// - Disk -- This refers to all of the VM's virtual disks that are *not*
// PVCs.
//
// To determine whether or not a PVC is encrypted, please refer to the PVC
// resource.
// - Disks -- This refers to at least one of the VM's attached disks. To
// determine the encryption state of the individual disks,
// please refer to status.volumes[].crypto.
Encrypted []VirtualMachineEncryptionType `json:"encrypted,omitempty"`

// +optional
Expand Down
20 changes: 20 additions & 0 deletions api/v1alpha3/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 19 additions & 5 deletions config/crd/bases/vmoperator.vmware.com_virtualmachines.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4688,11 +4688,9 @@ spec:
- Config -- This refers to all of the files related to a VM except any
virtual disks.
- Disk -- This refers to all of the VM's virtual disks that are *not*
PVCs.
To determine whether or not a PVC is encrypted, please refer to the PVC
resource.
- Disks -- This refers to at least one of the VM's attached disks. To
determine the encryption state of the individual disks,
please refer to status.volumes[].crypto.
items:
type: string
type: array
Expand Down Expand Up @@ -5403,6 +5401,22 @@ spec:
Attached represents whether a volume has been successfully attached to
the VirtualMachine or not.
type: boolean
crypto:
description: Crypto describes the volume's encryption status.
properties:
keyID:
description: |-
KeyID describes the key ID used to encrypt the volume.
Please note, this field will be empty if the volume is not
encrypted.
type: string
providerID:
description: |-
ProviderID describes the provider ID used to encrypt the volume.
Please note, this field will be empty if the volume is not
encrypted.
type: string
type: object
diskUUID:
description: |-
DiskUUID represents the underlying virtual disk UUID and is present when
Expand Down
4 changes: 2 additions & 2 deletions controllers/storageclass/storageclass_controller_intg_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func intgTestsReconcile() {
})
It("should eventually mark the storage class as encrypted in the context", func() {
Eventually(func(g Gomega) {
ok, err := kubeutil.IsEncryptedStorageClass(ctx, ctx.Client, obj.Name)
ok, _, err := kubeutil.IsEncryptedStorageClass(ctx, ctx.Client, obj.Name)
Expect(err).ToNot(HaveOccurred())
Expect(ok).To(BeTrue())
})
Expand All @@ -69,7 +69,7 @@ func intgTestsReconcile() {
Context("reconciling a plain storage class", func() {
It("should never mark the storage class as encrypted in the context", func() {
Consistently(func(g Gomega) {
ok, err := kubeutil.IsEncryptedStorageClass(ctx, ctx.Client, obj.Name)
ok, _, err := kubeutil.IsEncryptedStorageClass(ctx, ctx.Client, obj.Name)
Expect(err).ToNot(HaveOccurred())
Expect(ok).To(BeFalse())
})
Expand Down
4 changes: 2 additions & 2 deletions controllers/storageclass/storageclass_controller_unit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ func unitTestsReconcile() {
})
It("marks item as encrypted and returns success", func() {
Expect(err).ToNot(HaveOccurred())
ok, err := kubeutil.IsEncryptedStorageClass(ctx, ctx.Client, obj.Name)
ok, _, err := kubeutil.IsEncryptedStorageClass(ctx, ctx.Client, obj.Name)
Expect(err).ToNot(HaveOccurred())
Expect(ok).To(BeFalse())
})
Expand All @@ -136,7 +136,7 @@ func unitTestsReconcile() {
})
It("marks item as encrypted and returns success", func() {
Expect(err).ToNot(HaveOccurred())
ok, err := kubeutil.IsEncryptedStorageClass(ctx, ctx.Client, obj.Name)
ok, _, err := kubeutil.IsEncryptedStorageClass(ctx, ctx.Client, obj.Name)
Expect(err).ToNot(HaveOccurred())
Expect(ok).To(BeTrue())
})
Expand Down
4 changes: 2 additions & 2 deletions docs/concepts/workloads/vm.md
Original file line number Diff line number Diff line change
Expand Up @@ -476,14 +476,14 @@ The field `spec.crypto` may be used in conjunction with a VM's storage class and

#### Encryption type

The type of encryption depends on the storage class and hardware present in the VM as the chart below illustrates:
The type of encryption used by the VM is reported in the list `status.crypto.encrypted`. The list may contain the values `Config` and/or `Disks`, depending on the storage class and hardware present in the VM as the chart below illustrates:

| | Config | Disks |
|--------------------------|:------:|:-----:|
| Encryption storage class | ✓ | ✓ |
| vTPM | ✓ | |

The `Config` type refers to all files related to a VM except for virtual disks. The `Disks` type refers to a VM's virtual disks except for PVCs. To ascertain the encryption status of a PVC, please refer directly to the PVC resource.
The `Config` type refers to all files related to a VM except for virtual disks. The `Disks` type indicates at least one of a VM's virtual disks is encrypted. To determine which of the VM's disks are encrypted, please refer to `status.volumes[].crypto`.

#### Default Key Provider

Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ replace (
github.com/vmware-tanzu/vm-operator/external/tanzu-topology => ./external/tanzu-topology
github.com/vmware-tanzu/vm-operator/pkg/backup/api => ./pkg/backup/api
github.com/vmware-tanzu/vm-operator/pkg/constants/testlabels => ./pkg/constants/testlabels
github.com/vmware/govmomi => github.com/akutz/govmomi v0.28.1-0.20241024134239-6e84b72c9034
)

require (
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbt
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/akutz/govmomi v0.28.1-0.20241024134239-6e84b72c9034 h1:k7sNrb+byle2w7gR/XaeMixngZPTHOYARW4iLJ33rgA=
github.com/akutz/govmomi v0.28.1-0.20241024134239-6e84b72c9034/go.mod h1:uoLVU9zlXC4p4GmLVG+ZJmBC0Gn3Q7mytOJvi39OhxA=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
Expand Down Expand Up @@ -459,8 +461,6 @@ github.com/vmware-tanzu/net-operator-api v0.0.0-20240523152550-862e2c4eb0e0 h1:y
github.com/vmware-tanzu/net-operator-api v0.0.0-20240523152550-862e2c4eb0e0/go.mod h1:w6QJGm3crIA16ZIz1FVQXD2NVeJhOgGXxW05RbVTSTo=
github.com/vmware-tanzu/nsx-operator/pkg/apis v0.0.0-20240902045731-00a14868c72d h1:6pMXrQmTYpu5FipoQ9fT4FJG3VPMMbBoIi6h3KvdQc8=
github.com/vmware-tanzu/nsx-operator/pkg/apis v0.0.0-20240902045731-00a14868c72d/go.mod h1:Q4JzNkNMvjo7pXtlB5/R3oME4Nhah7fAObWgghVmtxk=
github.com/vmware/govmomi v0.31.1-0.20241015181712-cd4331eda367 h1:4gP1VC+N9onypUJh52dSrAKsnpyhQLHc/g3tH9qd4vM=
github.com/vmware/govmomi v0.31.1-0.20241015181712-cd4331eda367/go.mod h1:uoLVU9zlXC4p4GmLVG+ZJmBC0Gn3Q7mytOJvi39OhxA=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
Expand Down
31 changes: 21 additions & 10 deletions pkg/providers/vsphere/vmlifecycle/update_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -827,21 +827,32 @@ func updateVolumeStatus(vm *vmopv1.VirtualMachine, moVM mo.VirtualMachine) {
// existing status with the usage information.
di, _ := vmdk.GetVirtualDiskInfoByUUID(ctx, nil, moVM, false, diskUUID)
vm.Status.Volumes[diskIndex].Used = BytesToResourceGiB(di.UniqueSize)
if di.CryptoKey.ProviderID != "" || di.CryptoKey.KeyID != "" {
vm.Status.Volumes[diskIndex].Crypto = &vmopv1.VirtualMachineVolumeCryptoStatus{
ProviderID: di.CryptoKey.ProviderID,
KeyID: di.CryptoKey.KeyID,
}
}
} else if !isFCD {
// The disk is a classic, non-FCD that must be added to the list of
// volume statuses.
di, _ := vmdk.GetVirtualDiskInfoByUUID(ctx, nil, moVM, false, diskUUID)
dp := diskPath.Path
vm.Status.Volumes = append(
vm.Status.Volumes,
vmopv1.VirtualMachineVolumeStatus{
Name: strings.TrimSuffix(path.Base(dp), path.Ext(dp)),
Type: vmopv1.VirtualMachineStorageDiskTypeClassic,
Attached: true,
DiskUUID: diskUUID,
Limit: BytesToResourceGiB(di.CapacityInBytes),
Used: BytesToResourceGiB(di.UniqueSize),
})
volStatus := vmopv1.VirtualMachineVolumeStatus{
Name: strings.TrimSuffix(path.Base(dp), path.Ext(dp)),
Type: vmopv1.VirtualMachineStorageDiskTypeClassic,
Attached: true,
DiskUUID: diskUUID,
Limit: BytesToResourceGiB(di.CapacityInBytes),
Used: BytesToResourceGiB(di.UniqueSize),
}
if di.CryptoKey.ProviderID != "" || di.CryptoKey.KeyID != "" {
volStatus.Crypto = &vmopv1.VirtualMachineVolumeCryptoStatus{
ProviderID: di.CryptoKey.ProviderID,
KeyID: di.CryptoKey.KeyID,
}
}
vm.Status.Volumes = append(vm.Status.Volumes, volStatus)
}
}

Expand Down
24 changes: 24 additions & 0 deletions pkg/providers/vsphere/vmlifecycle/update_status_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,12 @@ var _ = Describe("UpdateStatus", func() {
FileName: "[datastore] vm/my-disk-100.vmdk",
},
Uuid: "100",
KeyId: &vimtypes.CryptoKeyId{
KeyId: "my-key-id",
ProviderId: &vimtypes.KeyProviderId{
Id: "my-provider-id",
},
},
},
Key: 100,
},
Expand Down Expand Up @@ -610,6 +616,12 @@ var _ = Describe("UpdateStatus", func() {
FileName: "[datastore] vm/my-disk-105.vmdk",
},
Uuid: "105",
KeyId: &vimtypes.CryptoKeyId{
KeyId: "my-key-id",
ProviderId: &vimtypes.KeyProviderId{
Id: "my-provider-id",
},
},
},
Key: 105,
},
Expand Down Expand Up @@ -788,6 +800,10 @@ var _ = Describe("UpdateStatus", func() {
Name: "my-disk-100",
DiskUUID: "100",
Type: vmopv1.VirtualMachineStorageDiskTypeClassic,
Crypto: &vmopv1.VirtualMachineVolumeCryptoStatus{
KeyID: "my-key-id",
ProviderID: "my-provider-id",
},
Attached: true,
Limit: vmlifecycle.BytesToResourceGiB(10 * oneGiBInBytes),
Used: vmlifecycle.BytesToResourceGiB(500 + (1 * oneGiBInBytes)),
Expand Down Expand Up @@ -846,6 +862,10 @@ var _ = Describe("UpdateStatus", func() {
Name: "my-disk-100",
DiskUUID: "100",
Type: vmopv1.VirtualMachineStorageDiskTypeClassic,
Crypto: &vmopv1.VirtualMachineVolumeCryptoStatus{
KeyID: "my-key-id",
ProviderID: "my-provider-id",
},
Attached: true,
Limit: vmlifecycle.BytesToResourceGiB(10 * oneGiBInBytes),
Used: vmlifecycle.BytesToResourceGiB(500 + (1 * oneGiBInBytes)),
Expand Down Expand Up @@ -886,6 +906,10 @@ var _ = Describe("UpdateStatus", func() {
Name: "my-disk-105",
DiskUUID: "105",
Type: vmopv1.VirtualMachineStorageDiskTypeManaged,
Crypto: &vmopv1.VirtualMachineVolumeCryptoStatus{
KeyID: "my-key-id",
ProviderID: "my-provider-id",
},
Attached: false,
Limit: vmlifecycle.BytesToResourceGiB(100 * oneGiBInBytes),
Used: vmlifecycle.BytesToResourceGiB(500 + (50 * oneGiBInBytes)),
Expand Down
Loading

0 comments on commit f52b1ee

Please sign in to comment.