Skip to content

[release-1.10] Added support for confidential storage to disk parametrs and metric #1315

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

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions pkg/common/parameters.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const (
ParameterKeyProvisionedIOPSOnCreate = "provisioned-iops-on-create"
ParameterKeyProvisionedThroughputOnCreate = "provisioned-throughput-on-create"
ParameterAvailabilityClass = "availability-class"
ParameterKeyEnableConfidentialCompute = "enable-confidential-storage"

// Parameters for VolumeSnapshotClass
ParameterKeyStorageLocations = "storage-locations"
Expand Down Expand Up @@ -88,6 +89,9 @@ type DiskParameters struct {
// Values: {int64}
// Default: none
ProvisionedThroughputOnCreate int64
// Values: {bool}
// Default: false
EnableConfidentialCompute bool
// Default: false
ForceAttach bool
}
Expand Down Expand Up @@ -170,6 +174,21 @@ func ExtractAndDefaultParameters(parameters map[string]string, driverName string
if paramAvailabilityClass == ParameterRegionalHardFailoverClass {
p.ForceAttach = true
}
case ParameterKeyEnableConfidentialCompute:
paramEnableConfidentialCompute, err := ConvertStringToBool(v)
if err != nil {
return p, fmt.Errorf("parameters contain invalid value for enable-confidential-storage parameter: %w", err)
}

if paramEnableConfidentialCompute {
// DiskEncryptionKmsKey is needed to enable confidentialStorage
if val, ok := parameters[ParameterKeyDiskEncryptionKmsKey]; !ok || !isValidDiskEncryptionKmsKey(val) {
return p, fmt.Errorf("Valid %v is required to enbale ConfidentialStorage", ParameterKeyDiskEncryptionKmsKey)
}
}

p.EnableConfidentialCompute = paramEnableConfidentialCompute

default:
return p, fmt.Errorf("parameters contains invalid option %q", k)
}
Expand Down
6 changes: 6 additions & 0 deletions pkg/common/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -386,3 +386,9 @@ func LoggedError(msg string, err error) error {
klog.Errorf(msg+"%v", err.Error())
return status.Errorf(CodeForError(err), msg+"%v", err.Error())
}

func isValidDiskEncryptionKmsKey(DiskEncryptionKmsKey string) bool {
// Validate key against default kmskey pattern
kmsKeyPattern := regexp.MustCompile("projects/[^/]+/locations/([^/]+)/keyRings/[^/]+/cryptoKeys/[^/]+")
return kmsKeyPattern.MatchString(DiskEncryptionKmsKey)
}
26 changes: 26 additions & 0 deletions pkg/common/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1075,3 +1075,29 @@ func TestIsContextError(t *testing.T) {
}
}
}

func TestIsValidDiskEncryptionKmsKey(t *testing.T) {
cases := []struct {
diskEncryptionKmsKey string
expectedIsValid bool
}{
{
diskEncryptionKmsKey: "projects/my-project/locations/us-central1/keyRings/TestKeyRing/cryptoKeys/test-key",
expectedIsValid: true,
},
{
diskEncryptionKmsKey: "projects/my-project/locations/global/keyRings/TestKeyRing/cryptoKeys/test-key",
expectedIsValid: true,
},
{
diskEncryptionKmsKey: "projects/my-project/locations/keyRings/TestKeyRing/cryptoKeys/test-key",
expectedIsValid: false,
},
}
for _, tc := range cases {
isValid := isValidDiskEncryptionKmsKey(tc.diskEncryptionKmsKey)
if tc.expectedIsValid != isValid {
t.Errorf("test failed: the provided key %s expected to be %v bu tgot %v", tc.diskEncryptionKmsKey, tc.expectedIsValid, isValid)
}
}
}
11 changes: 11 additions & 0 deletions pkg/gce-cloud-provider/compute/cloud-disk.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,3 +223,14 @@ func (d *CloudDisk) GetMultiWriter() bool {
return false
}
}

func (d *CloudDisk) GetEnableConfidentialCompute() bool {
switch {
case d.disk != nil:
return false
case d.betaDisk != nil:
return d.betaDisk.EnableConfidentialCompute
default:
return false
}
}
79 changes: 79 additions & 0 deletions pkg/gce-cloud-provider/compute/cloud-disk_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
Copyright 2023 The Kubernetes Authors.


Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package gcecloudprovider

import (
"testing"

computebeta "google.golang.org/api/compute/v0.beta"
computev1 "google.golang.org/api/compute/v1"
)

func CreateDiskWithConfidentialCompute(betaDisk bool, confidentialCompute bool, diskType string) *CloudDisk {
if betaDisk {
return &CloudDisk{
betaDisk: &computebeta.Disk{
EnableConfidentialCompute: confidentialCompute,
Type: diskType,
},
}
}
return &CloudDisk{
disk: &computev1.Disk{},
}
}

func TestGetEnableConfidentialCompute(t *testing.T) {
testCases := []struct {
name string
diskVersion *CloudDisk
expectedEnableConfidentialCompute bool
}{
{
name: "test betaDisk with enableConfidentialCompute=false",
diskVersion: CreateDiskWithConfidentialCompute(true, false, "hyperdisk-balanced"),
expectedEnableConfidentialCompute: false,
},
{
name: "test betaDisk with enableConfidentialCompute=true",
diskVersion: CreateDiskWithConfidentialCompute(true, true, "hyperdisk-balanced"),
expectedEnableConfidentialCompute: true,
},
{
name: "test disk withpit enableConfidentialCompute",
diskVersion: CreateDiskWithConfidentialCompute(false, false, "hyperdisk-balanced"),
expectedEnableConfidentialCompute: false,
},
{
name: "test disk withpit enableConfidentialCompute",
diskVersion: CreateDiskWithConfidentialCompute(false, false, "pd-standard"),
expectedEnableConfidentialCompute: false,
},
}

for _, tc := range testCases {
t.Logf("Running test: %v", tc.name)
confidentialCompute := tc.diskVersion.GetEnableConfidentialCompute()
if confidentialCompute != tc.expectedEnableConfidentialCompute {
t.Fatalf("Got confidentialCompute value %t expected %t", confidentialCompute, tc.expectedEnableConfidentialCompute)
}
if confidentialCompute != tc.expectedEnableConfidentialCompute {
t.Fatalf("Got confidentialCompute value %t expected %t", confidentialCompute, tc.expectedEnableConfidentialCompute)
}
}
}
8 changes: 7 additions & 1 deletion pkg/gce-cloud-provider/compute/fake-gce.go
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,13 @@ func (cloud *FakeCloudProvider) InsertDisk(ctx context.Context, project string,
return fmt.Errorf("could not create disk, key was neither zonal nor regional, instead got: %v", volKey.String())
}

cloud.disks[volKey.Name] = CloudDiskFromV1(computeDisk)
if containsBetaDiskType(hyperdiskTypes, params.DiskType) {
betaDisk := convertV1DiskToBetaDisk(computeDisk, params.ProvisionedThroughputOnCreate)
betaDisk.EnableConfidentialCompute = params.EnableConfidentialCompute
cloud.disks[volKey.Name] = CloudDiskFromBeta(betaDisk)
} else {
cloud.disks[volKey.Name] = CloudDiskFromV1(computeDisk)
}
return nil
}

Expand Down
15 changes: 13 additions & 2 deletions pkg/gce-cloud-provider/compute/gce-compute.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const (
pdDiskTypeUnsupportedPattern = `\[([a-z-]+)\] features are not compatible for creating instance`
)

var hyperdiskTypes = []string{"hyperdisk-extreme", "hyperdisk-throughput"}
var hyperdiskTypes = []string{"hyperdisk-extreme", "hyperdisk-throughput", "hyperdisk-balanced"}
var pdDiskTypeUnsupportedRegex = regexp.MustCompile(pdDiskTypeUnsupportedPattern)

type GCEAPIVersion string
Expand Down Expand Up @@ -258,6 +258,9 @@ func (cloud *CloudProvider) ListSnapshots(ctx context.Context, filter string) ([

func (cloud *CloudProvider) GetDisk(ctx context.Context, project string, key *meta.Key, gceAPIVersion GCEAPIVersion) (*CloudDisk, error) {
klog.V(5).Infof("Getting disk %v", key)

// Override GCEAPIVersion as hyperdisk is only available in beta and we cannot get the disk-type with get disk call.
gceAPIVersion = GCEAPIVersionBeta
switch key.Type() {
case meta.Zonal:
if gceAPIVersion == GCEAPIVersionBeta {
Expand Down Expand Up @@ -416,8 +419,16 @@ func convertV1DiskToBetaDisk(v1Disk *computev1.Disk, provisionedThroughputOnCrea
Description: v1Disk.Description,
Type: v1Disk.Type,
SourceSnapshot: v1Disk.SourceSnapshot,
SourceImage: v1Disk.SourceImage,
SourceImageId: v1Disk.SourceImageId,
SourceSnapshotId: v1Disk.SourceSnapshotId,
SourceDisk: v1Disk.SourceDisk,
ReplicaZones: v1Disk.ReplicaZones,
DiskEncryptionKey: dek,
Zone: v1Disk.Zone,
Region: v1Disk.Region,
Status: v1Disk.Status,
SelfLink: v1Disk.SelfLink,
}
if v1Disk.ProvisionedIops > 0 {
betaDisk.ProvisionedIops = v1Disk.ProvisionedIops
Expand Down Expand Up @@ -558,7 +569,6 @@ func (cloud *CloudProvider) insertZonalDisk(
opName string
gceAPIVersion = GCEAPIVersionV1
)

if multiWriter || containsBetaDiskType(hyperdiskTypes, params.DiskType) {
gceAPIVersion = GCEAPIVersionBeta
}
Expand Down Expand Up @@ -600,6 +610,7 @@ func (cloud *CloudProvider) insertZonalDisk(
var insertOp *computebeta.Operation
betaDiskToCreate := convertV1DiskToBetaDisk(diskToCreate, params.ProvisionedThroughputOnCreate)
betaDiskToCreate.MultiWriter = multiWriter
betaDiskToCreate.EnableConfidentialCompute = params.EnableConfidentialCompute
insertOp, err = cloud.betaService.Disks.Insert(project, volKey.Zone, betaDiskToCreate).Context(ctx).Do()
if insertOp != nil {
opName = insertOp.Name
Expand Down
Loading