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 23, 2024
1 parent 38b38ba commit e454d7b
Show file tree
Hide file tree
Showing 7 changed files with 161 additions and 33 deletions.
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
28 changes: 19 additions & 9 deletions pkg/util/kube/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,20 +211,21 @@ func MarkEncryptedStorageClass(
return k8sClient.Patch(ctx, &obj, objPatch)
}

// IsEncryptedStorageClass returns true if the provided StorageClass was marked
// as encrypted.
// IsEncryptedStorageClass returns true if the provided StorageClass name was
// marked as encrypted. If encryption is supported, the StorageClass's profile
// ID is also returned.
func IsEncryptedStorageClass(
ctx context.Context,
k8sClient ctrlclient.Client,
storageClassName string) (bool, error) {
name string) (bool, string, error) {

var obj storagev1.StorageClass
if err := k8sClient.Get(
ctx,
ctrlclient.ObjectKey{Name: storageClassName},
ctrlclient.ObjectKey{Name: name},
&obj); err != nil {

return false, ctrlclient.IgnoreNotFound(err)
return false, "", ctrlclient.IgnoreNotFound(err)
}

return isEncryptedStorageClass(ctx, k8sClient, obj)
Expand All @@ -244,7 +245,11 @@ func IsEncryptedStorageProfile(

for i := range obj.Items {
if pid, _ := GetStoragePolicyID(obj.Items[i]); pid == profileID {
return isEncryptedStorageClass(ctx, k8sClient, obj.Items[i])
ok, _, err := isEncryptedStorageClass(
ctx,
k8sClient,
obj.Items[i])
return ok, err
}
}

Expand All @@ -254,7 +259,7 @@ func IsEncryptedStorageProfile(
func isEncryptedStorageClass(
ctx context.Context,
k8sClient ctrlclient.Client,
storageClass storagev1.StorageClass) (bool, error) {
storageClass storagev1.StorageClass) (bool, string, error) {

var (
obj corev1.ConfigMap
Expand All @@ -266,8 +271,13 @@ func isEncryptedStorageClass(
)

if err := k8sClient.Get(ctx, objKey, &obj); err != nil {
return false, ctrlclient.IgnoreNotFound(err)
return false, "", ctrlclient.IgnoreNotFound(err)
}

return slices.Contains(obj.OwnerReferences, ownerRef), nil
if slices.Contains(obj.OwnerReferences, ownerRef) {
profileID, err := GetStoragePolicyID(storageClass)
return true, profileID, err
}

return false, "", nil
}
40 changes: 28 additions & 12 deletions pkg/util/kube/storage_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ var _ = Describe("IsEncryptedStorageClass", func() {
WithInterceptorFuncs(funcs).
Build()

ok, err = kubeutil.IsEncryptedStorageClass(
ok, _, err = kubeutil.IsEncryptedStorageClass(
ctx, client, storageClass.Name)
})

Expand Down Expand Up @@ -480,6 +480,9 @@ var _ = Describe("EncryptedStorageClass", func() {
Name: fakeString,
UID: types.UID(uuid.NewString()),
},
Parameters: map[string]string{
internal.StoragePolicyIDParameter: fakeString,
},
}
})

Expand All @@ -495,38 +498,43 @@ var _ = Describe("EncryptedStorageClass", func() {
Expect(kubeutil.MarkEncryptedStorageClass(ctx, client, storageClass, true)).To(Succeed())
})
It("should return true", func() {
ok, err := kubeutil.IsEncryptedStorageClass(ctx, client, storageClass.Name)
ok, pid, err := kubeutil.IsEncryptedStorageClass(ctx, client, storageClass.Name)
Expect(err).ToNot(HaveOccurred())
Expect(ok).To(BeTrue())
Expect(pid).To(Equal(fakeString))
})
When("the storage class is marked as encrypted again", func() {
JustBeforeEach(func() {
Expect(kubeutil.MarkEncryptedStorageClass(ctx, client, storageClass, true)).To(Succeed())
})
It("should return true", func() {
ok, err := kubeutil.IsEncryptedStorageClass(ctx, client, storageClass.Name)
ok, pid, err := kubeutil.IsEncryptedStorageClass(ctx, client, storageClass.Name)
Expect(err).ToNot(HaveOccurred())
Expect(ok).To(BeTrue())
Expect(pid).To(Equal(fakeString))
})
})
When("the storage class is marked as unencrypted", func() {
JustBeforeEach(func() {
Expect(kubeutil.MarkEncryptedStorageClass(ctx, client, storageClass, false)).To(Succeed())
})
It("should return false", func() {
ok, err := kubeutil.IsEncryptedStorageClass(ctx, client, storageClass.Name)
ok, pid, err := kubeutil.IsEncryptedStorageClass(ctx, client, storageClass.Name)
Expect(err).ToNot(HaveOccurred())
Expect(ok).To(BeFalse())
Expect(pid).To(BeEmpty())

})

When("the storage class is marked as encrypted again", func() {
JustBeforeEach(func() {
Expect(kubeutil.MarkEncryptedStorageClass(ctx, client, storageClass, true)).To(Succeed())
})
It("should return true", func() {
ok, err := kubeutil.IsEncryptedStorageClass(ctx, client, storageClass.Name)
ok, pid, err := kubeutil.IsEncryptedStorageClass(ctx, client, storageClass.Name)
Expect(err).ToNot(HaveOccurred())
Expect(ok).To(BeTrue())
Expect(pid).To(Equal(fakeString))
})
})
})
Expand All @@ -537,9 +545,10 @@ var _ = Describe("EncryptedStorageClass", func() {
Expect(kubeutil.MarkEncryptedStorageClass(ctx, client, storageClass, false)).To(Succeed())
})
It("should return false for the second storage class", func() {
ok, err := kubeutil.IsEncryptedStorageClass(ctx, client, storageClass.Name)
ok, pid, err := kubeutil.IsEncryptedStorageClass(ctx, client, storageClass.Name)
Expect(err).ToNot(HaveOccurred())
Expect(ok).To(BeFalse())
Expect(pid).To(BeEmpty())
})
})
})
Expand All @@ -549,17 +558,19 @@ var _ = Describe("EncryptedStorageClass", func() {
Expect(kubeutil.MarkEncryptedStorageClass(ctx, client, storageClass, false)).To(Succeed())
})
It("should return false", func() {
ok, err := kubeutil.IsEncryptedStorageClass(ctx, client, storageClass.Name)
ok, pid, err := kubeutil.IsEncryptedStorageClass(ctx, client, storageClass.Name)
Expect(err).ToNot(HaveOccurred())
Expect(ok).To(BeFalse())
Expect(pid).To(BeEmpty())
})
})

When("the storage class is not marked at all", func() {
It("should return false", func() {
ok, err := kubeutil.IsEncryptedStorageClass(ctx, client, storageClass.Name)
ok, pid, err := kubeutil.IsEncryptedStorageClass(ctx, client, storageClass.Name)
Expect(err).ToNot(HaveOccurred())
Expect(ok).To(BeFalse())
Expect(pid).To(BeEmpty())
})
})

Expand All @@ -580,9 +591,10 @@ var _ = Describe("EncryptedStorageClass", func() {
}
})
It("should return an error for IsEncryptedStorageClass", func() {
ok, err := kubeutil.IsEncryptedStorageClass(ctx, client, storageClass.Name)
ok, pid, err := kubeutil.IsEncryptedStorageClass(ctx, client, storageClass.Name)
Expect(err).To(MatchError(apierrors.NewInternalError(errors.New(fakeString)).Error()))
Expect(ok).To(BeFalse())
Expect(pid).To(BeEmpty())
})
It("should return an error for MarkEncryptedStorageClass", func() {
err := kubeutil.MarkEncryptedStorageClass(ctx, client, storageClass, false)
Expand Down Expand Up @@ -683,10 +695,11 @@ var _ = Describe("EncryptedStorageClass", func() {
Expect(refs).To(ContainElements(expRefs...))

for i := range storageClasses {
ok, err := kubeutil.IsEncryptedStorageClass(
ok, pid, err := kubeutil.IsEncryptedStorageClass(
ctx, client, storageClasses[i].Name)
Expect(err).ToNot(HaveOccurred())
Expect(ok).To(BeTrue())
Expect(pid).To(Equal(fakeString))
}
})
})
Expand Down Expand Up @@ -733,10 +746,11 @@ var _ = Describe("EncryptedStorageClass", func() {
Expect(refs).To(BeEmpty())

for i := range storageClasses {
ok, err := kubeutil.IsEncryptedStorageClass(
ok, pid, err := kubeutil.IsEncryptedStorageClass(
ctx, client, storageClasses[i].Name)
Expect(err).ToNot(HaveOccurred())
Expect(ok).To(BeFalse())
Expect(pid).To(BeEmpty())
}
})
})
Expand Down Expand Up @@ -801,13 +815,15 @@ var _ = Describe("EncryptedStorageClass", func() {
Expect(refs).To(ContainElements(expRefs...))

for i := range storageClasses {
ok, err := kubeutil.IsEncryptedStorageClass(
ok, pid, err := kubeutil.IsEncryptedStorageClass(
ctx, client, storageClasses[i].Name)
Expect(err).ToNot(HaveOccurred())
if i%2 == 0 {
Expect(ok).To(BeFalse())
Expect(pid).To(BeEmpty())
} else {
Expect(ok).To(BeTrue())
Expect(pid).To(Equal(fakeString))
}
}
})
Expand Down
Loading

0 comments on commit e454d7b

Please sign in to comment.