providers/google: Add support for encrypting a disk (#11167)

* providers/google: add support for encrypting a disk

* providers/google: Add docs for encrypting disks

* providers/google: CSEK small fixes: sensitive params and mismatched state files
This commit is contained in:
Dana Hoffman 2017-01-18 05:49:48 -08:00 committed by Paul Stack
parent 17af2f69af
commit 5e04661a5a
4 changed files with 187 additions and 0 deletions

View File

@ -28,6 +28,18 @@ func resourceComputeDisk() *schema.Resource {
ForceNew: true,
},
"disk_encryption_key_raw": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Sensitive: true,
},
"disk_encryption_key_sha256": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
"image": &schema.Schema{
Type: schema.TypeString,
Optional: true,
@ -129,6 +141,11 @@ func resourceComputeDiskCreate(d *schema.ResourceData, meta interface{}) error {
disk.SourceSnapshot = snapshotData.SelfLink
}
if v, ok := d.GetOk("disk_encryption_key_raw"); ok {
disk.DiskEncryptionKey = &compute.CustomerEncryptionKey{}
disk.DiskEncryptionKey.RawKey = v.(string)
}
op, err := config.clientCompute.Disks.Insert(
project, d.Get("zone").(string), disk).Do()
if err != nil {
@ -168,6 +185,9 @@ func resourceComputeDiskRead(d *schema.ResourceData, meta interface{}) error {
}
d.Set("self_link", disk.SelfLink)
if disk.DiskEncryptionKey != nil && disk.DiskEncryptionKey.Sha256 != "" {
d.Set("disk_encryption_key_sha256", disk.DiskEncryptionKey.Sha256)
}
return nil
}

View File

@ -30,6 +30,28 @@ func TestAccComputeDisk_basic(t *testing.T) {
})
}
func TestAccComputeDisk_encryption(t *testing.T) {
diskName := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
var disk compute.Disk
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckComputeDiskDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccComputeDisk_encryption(diskName),
Check: resource.ComposeTestCheckFunc(
testAccCheckComputeDiskExists(
"google_compute_disk.foobar", &disk),
testAccCheckEncryptionKey(
"google_compute_disk.foobar", &disk),
),
},
},
})
}
func testAccCheckComputeDiskDestroy(s *terraform.State) error {
config := testAccProvider.Meta().(*Config)
@ -77,6 +99,26 @@ func testAccCheckComputeDiskExists(n string, disk *compute.Disk) resource.TestCh
}
}
func testAccCheckEncryptionKey(n string, disk *compute.Disk) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
if !ok {
return fmt.Errorf("Not found: %s", n)
}
attr := rs.Primary.Attributes["disk_encryption_key_sha256"]
if disk.DiskEncryptionKey == nil && attr != "" {
return fmt.Errorf("Disk %s has mismatched encryption key.\nTF State: %+v\nGCP State: <empty>", n, attr)
}
if attr != disk.DiskEncryptionKey.Sha256 {
return fmt.Errorf("Disk %s has mismatched encryption key.\nTF State: %+v.\nGCP State: %+v",
n, attr, disk.DiskEncryptionKey.Sha256)
}
return nil
}
}
func testAccComputeDisk_basic(diskName string) string {
return fmt.Sprintf(`
resource "google_compute_disk" "foobar" {
@ -87,3 +129,15 @@ resource "google_compute_disk" "foobar" {
zone = "us-central1-a"
}`, diskName)
}
func testAccComputeDisk_encryption(diskName string) string {
return fmt.Sprintf(`
resource "google_compute_disk" "foobar" {
name = "%s"
image = "debian-8-jessie-v20160803"
size = 50
type = "pd-ssd"
zone = "us-central1-a"
disk_encryption_key_raw = "SGVsbG8gZnJvbSBHb29nbGUgQ2xvdWQgUGxhdGZvcm0="
}`, diskName)
}

View File

@ -75,6 +75,18 @@ func resourceComputeInstance() *schema.Resource {
Type: schema.TypeString,
Optional: true,
},
"disk_encryption_key_raw": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Sensitive: true,
},
"disk_encryption_key_sha256": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
},
},
},
@ -437,6 +449,11 @@ func resourceComputeInstanceCreate(d *schema.ResourceData, meta interface{}) err
disk.DeviceName = v.(string)
}
if v, ok := d.GetOk(prefix + ".disk_encryption_key_raw"); ok {
disk.DiskEncryptionKey = &compute.CustomerEncryptionKey{}
disk.DiskEncryptionKey.RawKey = v.(string)
}
disks = append(disks, &disk)
}
@ -770,6 +787,24 @@ func resourceComputeInstanceRead(d *schema.ResourceData, meta interface{}) error
d.Set("tags_fingerprint", instance.Tags.Fingerprint)
}
disks := make([]map[string]interface{}, 0, 1)
for i, disk := range instance.Disks {
di := map[string]interface{}{
"disk": d.Get(fmt.Sprintf("disk.%d.disk", i)),
"image": d.Get(fmt.Sprintf("disk.%d.image", i)),
"type": d.Get(fmt.Sprintf("disk.%d.type", i)),
"scratch": d.Get(fmt.Sprintf("disk.%d.scratch", i)),
"auto_delete": d.Get(fmt.Sprintf("disk.%d.auto_delete", i)),
"size": d.Get(fmt.Sprintf("disk.%d.size", i)),
"device_name": d.Get(fmt.Sprintf("disk.%d.device_name", i)),
}
if disk.DiskEncryptionKey != nil && disk.DiskEncryptionKey.Sha256 != "" {
di["disk_encryption_key_sha256"] = disk.DiskEncryptionKey.Sha256
}
disks = append(disks, di)
}
d.Set("disk", disks)
d.Set("self_link", instance.SelfLink)
d.SetId(instance.Name)

View File

@ -220,6 +220,30 @@ func TestAccComputeInstance_disksWithAutodelete(t *testing.T) {
})
}
func TestAccComputeInstance_diskEncryption(t *testing.T) {
var instance compute.Instance
var instanceName = fmt.Sprintf("instance-test-%s", acctest.RandString(10))
var diskName = fmt.Sprintf("instance-testd-%s", acctest.RandString(10))
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckComputeInstanceDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccComputeInstance_disks_encryption(diskName, instanceName),
Check: resource.ComposeTestCheckFunc(
testAccCheckComputeInstanceExists(
"google_compute_instance.foobar", &instance),
testAccCheckComputeInstanceDisk(&instance, instanceName, true, true),
testAccCheckComputeInstanceDisk(&instance, diskName, true, false),
testAccCheckComputeInstanceDiskEncryptionKey("google_compute_instance.foobar", &instance),
),
},
},
})
}
func TestAccComputeInstance_local_ssd(t *testing.T) {
var instance compute.Instance
var instanceName = fmt.Sprintf("instance-test-%s", acctest.RandString(10))
@ -636,6 +660,27 @@ func testAccCheckComputeInstanceDisk(instance *compute.Instance, source string,
}
}
func testAccCheckComputeInstanceDiskEncryptionKey(n string, instance *compute.Instance) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
if !ok {
return fmt.Errorf("Not found: %s", n)
}
for i, disk := range instance.Disks {
attr := rs.Primary.Attributes[fmt.Sprintf("disk.%d.disk_encryption_key_sha256", i)]
if disk.DiskEncryptionKey == nil && attr != "" {
return fmt.Errorf("Disk %d has mismatched encryption key.\nTF State: %+v\nGCP State: <empty>", i, attr)
}
if disk.DiskEncryptionKey != nil && attr != disk.DiskEncryptionKey.Sha256 {
return fmt.Errorf("Disk %d has mismatched encryption key.\nTF State: %+v\nGCP State: %+v",
i, attr, disk.DiskEncryptionKey.Sha256)
}
}
return nil
}
}
func testAccCheckComputeInstanceTag(instance *compute.Instance, n string) resource.TestCheckFunc {
return func(s *terraform.State) error {
if instance.Tags == nil {
@ -983,6 +1028,39 @@ func testAccComputeInstance_disks(disk, instance string, autodelete bool) string
}`, disk, instance, autodelete)
}
func testAccComputeInstance_disks_encryption(disk, instance string) string {
return fmt.Sprintf(`
resource "google_compute_disk" "foobar" {
name = "%s"
size = 10
type = "pd-ssd"
zone = "us-central1-a"
}
resource "google_compute_instance" "foobar" {
name = "%s"
machine_type = "n1-standard-1"
zone = "us-central1-a"
disk {
image = "debian-8-jessie-v20160803"
disk_encryption_key_raw = "SGVsbG8gZnJvbSBHb29nbGUgQ2xvdWQgUGxhdGZvcm0="
}
disk {
disk = "${google_compute_disk.foobar.name}"
}
network_interface {
network = "default"
}
metadata {
foo = "bar"
}
}`, disk, instance)
}
func testAccComputeInstance_local_ssd(instance string) string {
return fmt.Sprintf(`
resource "google_compute_instance" "local-ssd" {