@@ -15,6 +15,8 @@ limitations under the License.
15
15
package tests
16
16
17
17
import (
18
+ "context"
19
+ "fmt"
18
20
"strings"
19
21
"time"
20
22
@@ -26,6 +28,10 @@ import (
26
28
csi "github.com/container-storage-interface/spec/lib/go/csi"
27
29
. "github.com/onsi/ginkgo"
28
30
. "github.com/onsi/gomega"
31
+
32
+ "google.golang.org/api/iterator"
33
+ kmspb "google.golang.org/genproto/googleapis/cloud/kms/v1"
34
+ fieldmask "google.golang.org/genproto/protobuf/field_mask"
29
35
)
30
36
31
37
const (
@@ -78,7 +84,8 @@ var _ = Describe("GCE PD CSI Driver", func() {
78
84
}()
79
85
80
86
// Attach Disk
81
- testAttachWriteReadDetach (volID , volName , instance , client , false /* readOnly */ )
87
+ err = testAttachWriteReadDetach (volID , volName , instance , client , false /* readOnly */ )
88
+ Expect (err ).To (BeNil (), "Failed to go through volume lifecycle" )
82
89
83
90
})
84
91
@@ -152,7 +159,8 @@ var _ = Describe("GCE PD CSI Driver", func() {
152
159
}()
153
160
154
161
// Attach Disk
155
- testAttachWriteReadDetach (underSpecifiedID , volName , instance , client , false /* readOnly */ )
162
+ err = testAttachWriteReadDetach (underSpecifiedID , volName , instance , client , false /* readOnly */ )
163
+ Expect (err ).To (BeNil (), "Failed to go through volume lifecycle" )
156
164
157
165
})
158
166
@@ -295,6 +303,160 @@ var _ = Describe("GCE PD CSI Driver", func() {
295
303
}()
296
304
})
297
305
306
+ It ("Should create CMEK key, go through volume lifecycle, validate behavior on key revoke and restore" , func () {
307
+ ctx := context .Background ()
308
+ Expect (testContexts ).ToNot (BeEmpty ())
309
+ testContext := getRandomTestContext ()
310
+
311
+ controllerInstance := testContext .Instance
312
+ controllerClient := testContext .Client
313
+
314
+ p , z , _ := controllerInstance .GetIdentity ()
315
+ locationID := "global"
316
+
317
+ // The resource name of the key rings.
318
+ parentName := fmt .Sprintf ("projects/%s/locations/%s" , p , locationID )
319
+ keyRingId := "gce-pd-csi-test-ring"
320
+
321
+ // Create KeyRing
322
+ ringReq := & kmspb.CreateKeyRingRequest {
323
+ Parent : parentName ,
324
+ KeyRingId : keyRingId ,
325
+ }
326
+ keyRing , err := kmsClient .CreateKeyRing (ctx , ringReq )
327
+ if ! gce .IsGCEError (err , "alreadyExists" ) {
328
+ getKeyRingReq := & kmspb.GetKeyRingRequest {
329
+ Name : fmt .Sprintf ("%s/keyRings/%s" , parentName , keyRingId ),
330
+ }
331
+ keyRing , err = kmsClient .GetKeyRing (ctx , getKeyRingReq )
332
+
333
+ }
334
+ Expect (err ).To (BeNil (), "Failed to create or get key ring %v" , keyRingId )
335
+
336
+ // Create CryptoKey in KeyRing
337
+ keyId := "test-key-" + string (uuid .NewUUID ())
338
+ keyReq := & kmspb.CreateCryptoKeyRequest {
339
+ Parent : keyRing .Name ,
340
+ CryptoKeyId : keyId ,
341
+ CryptoKey : & kmspb.CryptoKey {
342
+ Purpose : kmspb .CryptoKey_ENCRYPT_DECRYPT ,
343
+ VersionTemplate : & kmspb.CryptoKeyVersionTemplate {
344
+ Algorithm : kmspb .CryptoKeyVersion_GOOGLE_SYMMETRIC_ENCRYPTION ,
345
+ },
346
+ },
347
+ }
348
+ key , err := kmsClient .CreateCryptoKey (ctx , keyReq )
349
+ Expect (err ).To (BeNil (), "Failed to create crypto key %v in key ring %v" , keyId , keyRing .Name )
350
+
351
+ keyVersions := []string {}
352
+ keyVersionReq := & kmspb.ListCryptoKeyVersionsRequest {
353
+ Parent : key .Name ,
354
+ }
355
+
356
+ it := kmsClient .ListCryptoKeyVersions (ctx , keyVersionReq )
357
+
358
+ for {
359
+ keyVersion , err := it .Next ()
360
+ if err == iterator .Done {
361
+ break
362
+ }
363
+ Expect (err ).To (BeNil (), "Failed to list crypto key versions" )
364
+
365
+ keyVersions = append (keyVersions , keyVersion .Name )
366
+ }
367
+
368
+ // Defer deletion of all key versions
369
+ // https://cloud.google.com/kms/docs/destroy-restore
370
+ defer func () {
371
+
372
+ for _ , keyVersion := range keyVersions {
373
+ destroyKeyReq := & kmspb.DestroyCryptoKeyVersionRequest {
374
+ Name : keyVersion ,
375
+ }
376
+ _ , err = kmsClient .DestroyCryptoKeyVersion (ctx , destroyKeyReq )
377
+ Expect (err ).To (BeNil (), "Failed to destroy crypto key version: %v" , keyVersion )
378
+ }
379
+
380
+ }()
381
+
382
+ // Go through volume lifecycle using CMEK-ed PD
383
+ // Create Disk
384
+ volName := testNamePrefix + string (uuid .NewUUID ())
385
+ volID , err := controllerClient .CreateVolume (volName , map [string ]string {
386
+ common .ParameterKeyDiskEncryptionKmsKey : key .Name ,
387
+ }, defaultSizeGb ,
388
+ & csi.TopologyRequirement {
389
+ Requisite : []* csi.Topology {
390
+ {
391
+ Segments : map [string ]string {common .TopologyKeyZone : z },
392
+ },
393
+ },
394
+ })
395
+ Expect (err ).To (BeNil (), "CreateVolume failed with error: %v" , err )
396
+
397
+ // Validate Disk Created
398
+ cloudDisk , err := computeService .Disks .Get (p , z , volName ).Do ()
399
+ Expect (err ).To (BeNil (), "Could not get disk from cloud directly" )
400
+ Expect (cloudDisk .Type ).To (ContainSubstring (standardDiskType ))
401
+ Expect (cloudDisk .Status ).To (Equal (readyState ))
402
+ Expect (cloudDisk .SizeGb ).To (Equal (defaultSizeGb ))
403
+ Expect (cloudDisk .Name ).To (Equal (volName ))
404
+
405
+ defer func () {
406
+ // Delete Disk
407
+ err = controllerClient .DeleteVolume (volID )
408
+ Expect (err ).To (BeNil (), "DeleteVolume failed" )
409
+
410
+ // Validate Disk Deleted
411
+ _ , err = computeService .Disks .Get (p , z , volName ).Do ()
412
+ Expect (gce .IsGCEError (err , "notFound" )).To (BeTrue (), "Expected disk to not be found" )
413
+ }()
414
+
415
+ // Test disk works
416
+ err = testAttachWriteReadDetach (volID , volName , controllerInstance , controllerClient , false /* readOnly */ )
417
+ Expect (err ).To (BeNil (), "Failed to go through volume lifecycle before revoking CMEK key" )
418
+
419
+ // Revoke CMEK key
420
+ // https://cloud.google.com/kms/docs/enable-disable
421
+
422
+ for _ , keyVersion := range keyVersions {
423
+ disableReq := & kmspb.UpdateCryptoKeyVersionRequest {
424
+ CryptoKeyVersion : & kmspb.CryptoKeyVersion {
425
+ Name : keyVersion ,
426
+ State : kmspb .CryptoKeyVersion_DISABLED ,
427
+ },
428
+ UpdateMask : & fieldmask.FieldMask {
429
+ Paths : []string {"state" },
430
+ },
431
+ }
432
+ _ , err = kmsClient .UpdateCryptoKeyVersion (ctx , disableReq )
433
+ Expect (err ).To (BeNil (), "Failed to disable crypto key" )
434
+ }
435
+
436
+ // Make sure attach of PD fails
437
+ err = testAttachWriteReadDetach (volID , volName , controllerInstance , controllerClient , false /* readOnly */ )
438
+ Expect (err ).ToNot (BeNil (), "Volume lifecycle should have failed, but succeeded" )
439
+
440
+ // Restore CMEK key
441
+ for _ , keyVersion := range keyVersions {
442
+ enableReq := & kmspb.UpdateCryptoKeyVersionRequest {
443
+ CryptoKeyVersion : & kmspb.CryptoKeyVersion {
444
+ Name : keyVersion ,
445
+ State : kmspb .CryptoKeyVersion_ENABLED ,
446
+ },
447
+ UpdateMask : & fieldmask.FieldMask {
448
+ Paths : []string {"state" },
449
+ },
450
+ }
451
+ _ , err = kmsClient .UpdateCryptoKeyVersion (ctx , enableReq )
452
+ Expect (err ).To (BeNil (), "Failed to enable crypto key" )
453
+ }
454
+
455
+ // Make sure attach of PD succeeds
456
+ err = testAttachWriteReadDetach (volID , volName , controllerInstance , controllerClient , false /* readOnly */ )
457
+ Expect (err ).To (BeNil (), "Failed to go through volume lifecycle after restoring CMEK key" )
458
+ })
459
+
298
460
It ("Should create and delete snapshot for RePD in two zones " , func () {
299
461
Expect (testContexts ).ToNot (BeEmpty ())
300
462
testContext := getRandomTestContext ()
0 commit comments