diff --git a/data/data/gcp/bootstrap/main.tf b/data/data/gcp/bootstrap/main.tf index 9014ca892a3..1144d15010f 100644 --- a/data/data/gcp/bootstrap/main.tf +++ b/data/data/gcp/bootstrap/main.tf @@ -54,6 +54,7 @@ resource "google_compute_instance" "bootstrap" { size = var.root_volume_size image = var.image } + kms_key_self_link = var.root_volume_kms_key_link } network_interface { diff --git a/data/data/gcp/bootstrap/variables.tf b/data/data/gcp/bootstrap/variables.tf index d30ad78053c..95dfeb69b93 100644 --- a/data/data/gcp/bootstrap/variables.tf +++ b/data/data/gcp/bootstrap/variables.tf @@ -59,6 +59,12 @@ variable "root_volume_type" { description = "The volume type for the bootstrap node's root volume." } +variable "root_volume_kms_key_link" { + type = string + description = "The GCP self link of KMS key to encrypt the volume." + default = null +} + variable "zone" { type = string description = "The zone for the bootstrap node." diff --git a/data/data/gcp/main.tf b/data/data/gcp/main.tf index 3e7fc06f820..b0d9ba02f04 100644 --- a/data/data/gcp/main.tf +++ b/data/data/gcp/main.tf @@ -30,8 +30,9 @@ module "bootstrap" { zone = var.gcp_master_availability_zones[0] region = var.gcp_region - root_volume_size = var.gcp_master_root_volume_size - root_volume_type = var.gcp_master_root_volume_type + root_volume_size = var.gcp_master_root_volume_size + root_volume_type = var.gcp_master_root_volume_type + root_volume_kms_key_link = var.gcp_root_volume_kms_key_link labels = local.labels } @@ -47,8 +48,9 @@ module "master" { subnet = module.network.master_subnet zones = distinct(var.gcp_master_availability_zones) - root_volume_size = var.gcp_master_root_volume_size - root_volume_type = var.gcp_master_root_volume_type + root_volume_size = var.gcp_master_root_volume_size + root_volume_type = var.gcp_master_root_volume_type + root_volume_kms_key_link = var.gcp_root_volume_kms_key_link labels = local.labels } diff --git a/data/data/gcp/master/main.tf b/data/data/gcp/master/main.tf index 5bb9a438287..427a63f2901 100644 --- a/data/data/gcp/master/main.tf +++ b/data/data/gcp/master/main.tf @@ -41,6 +41,7 @@ resource "google_compute_instance" "master" { size = var.root_volume_size image = var.image } + kms_key_self_link = var.root_volume_kms_key_link } network_interface { diff --git a/data/data/gcp/master/variables.tf b/data/data/gcp/master/variables.tf index 4b623d7add1..0f898a8376b 100644 --- a/data/data/gcp/master/variables.tf +++ b/data/data/gcp/master/variables.tf @@ -44,6 +44,12 @@ variable "root_volume_type" { description = "The type of volume for the root block device." } +variable "root_volume_kms_key_link" { + type = string + description = "The GCP self link of KMS key to encrypt the volume." + default = null +} + variable "zones" { type = list } diff --git a/data/data/gcp/variables-gcp.tf b/data/data/gcp/variables-gcp.tf index 435f05aa54e..960d5599894 100644 --- a/data/data/gcp/variables-gcp.tf +++ b/data/data/gcp/variables-gcp.tf @@ -115,3 +115,8 @@ variable "gcp_image_licenses" { default = [] } +variable "gcp_root_volume_kms_key_link" { + type = string + description = "The GCP self link of KMS key to encrypt the volume." + default = null +} diff --git a/pkg/asset/machines/gcp/machines.go b/pkg/asset/machines/gcp/machines.go index 201b290dcf6..20f90246fb7 100644 --- a/pkg/asset/machines/gcp/machines.go +++ b/pkg/asset/machines/gcp/machines.go @@ -77,6 +77,20 @@ func provider(clusterID string, platform *gcp.Platform, mpool *gcp.MachinePool, return nil, err } + var encryptionKey *gcpprovider.GCPEncryptionKeyReference + + if mpool.OSDisk.EncryptionKey != nil { + encryptionKey = &gcpprovider.GCPEncryptionKeyReference{ + KMSKey: &gcpprovider.GCPKMSKeyReference{ + Name: mpool.OSDisk.EncryptionKey.KMSKey.Name, + KeyRing: mpool.OSDisk.EncryptionKey.KMSKey.KeyRing, + ProjectID: mpool.OSDisk.EncryptionKey.KMSKey.ProjectID, + Location: mpool.OSDisk.EncryptionKey.KMSKey.Location, + }, + KMSKeyServiceAccount: mpool.OSDisk.EncryptionKey.KMSKeyServiceAccount, + } + } + return &gcpprovider.GCPMachineProviderSpec{ TypeMeta: metav1.TypeMeta{ APIVersion: "gcpprovider.openshift.io/v1beta1", @@ -85,11 +99,12 @@ func provider(clusterID string, platform *gcp.Platform, mpool *gcp.MachinePool, UserDataSecret: &corev1.LocalObjectReference{Name: userDataSecret}, CredentialsSecret: &corev1.LocalObjectReference{Name: "gcp-cloud-credentials"}, Disks: []*gcpprovider.GCPDisk{{ - AutoDelete: true, - Boot: true, - SizeGb: mpool.OSDisk.DiskSizeGB, - Type: mpool.OSDisk.DiskType, - Image: osImage, + AutoDelete: true, + Boot: true, + SizeGb: mpool.OSDisk.DiskSizeGB, + Type: mpool.OSDisk.DiskType, + Image: osImage, + EncryptionKey: encryptionKey, }}, NetworkInterfaces: []*gcpprovider.GCPNetworkInterface{{ Network: network, diff --git a/pkg/tfvars/gcp/gcp.go b/pkg/tfvars/gcp/gcp.go index 876ebb7976a..48edfd68c27 100644 --- a/pkg/tfvars/gcp/gcp.go +++ b/pkg/tfvars/gcp/gcp.go @@ -2,12 +2,17 @@ package gcp import ( "encoding/json" + "fmt" gcpprovider "github.com/openshift/cluster-api-provider-gcp/pkg/apis/gcpprovider/v1beta1" "github.com/openshift/installer/pkg/types" ) +const ( + kmsKeyNameFmt = "projects/%s/locations/%s/keyRings/%s/cryptoKeys/%s" +) + // Auth is the collection of credentials that will be used by terrform. type Auth struct { ProjectID string `json:"gcp_project_id,omitempty"` @@ -26,6 +31,7 @@ type config struct { ImageLicenses []string `json:"gcp_image_licenses,omitempty"` VolumeType string `json:"gcp_master_root_volume_type"` VolumeSize int64 `json:"gcp_master_root_volume_size"` + VolumeKMSKeyLink string `json:"gcp_root_volume_kms_key_link"` PublicZoneName string `json:"gcp_public_dns_zone_name,omitempty"` PublishStrategy string `json:"gcp_publish_strategy,omitempty"` PreexistingNetwork bool `json:"gcp_preexisting_network,omitempty"` @@ -78,5 +84,17 @@ func TFVars(sources TFVarsSources) ([]byte, error) { cfg.PreexistingImage = false } + if masterConfig.Disks[0].EncryptionKey != nil { + cfg.VolumeKMSKeyLink = generateDiskEncryptionKeyLink(masterConfig.Disks[0].EncryptionKey, masterConfig.ProjectID) + } + return json.MarshalIndent(cfg, "", " ") } + +func generateDiskEncryptionKeyLink(keyRef *gcpprovider.GCPEncryptionKeyReference, projectID string) string { + if keyRef.KMSKey.ProjectID != "" { + projectID = keyRef.KMSKey.ProjectID + } + + return fmt.Sprintf(kmsKeyNameFmt, projectID, keyRef.KMSKey.Location, keyRef.KMSKey.KeyRing, keyRef.KMSKey.Name) +}