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