Merge pull request #8970 from szamfirov/shielded_vm_support

Adding custom shielded images support (GCP)
This commit is contained in:
Megan Marsh 2020-04-16 16:32:04 -07:00 committed by GitHub
commit 855808ec6f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 99 additions and 12 deletions

View File

@ -57,6 +57,21 @@ type Config struct {
// Type of disk used to back your instance, like pd-ssd or pd-standard.
// Defaults to pd-standard.
DiskType string `mapstructure:"disk_type" required:"false"`
// Create a Shielded VM image with Secure Boot enabled. It helps ensure that
// the system only runs authentic software by verifying the digital signature
// of all boot components, and halting the boot process if signature verification
// fails. [Details](https://cloud.google.com/security/shielded-cloud/shielded-vm)
EnableSecureBoot bool `mapstructure:"enable_secure_boot" required:"false"`
// Create a Shielded VM image with virtual trusted platform module
// Measured Boot enabled. A vTPM is a virtualized trusted platform module,
// which is a specialized computer chip you can use to protect objects,
// like keys and certificates, that you use to authenticate access to your
// system. [Details](https://cloud.google.com/security/shielded-cloud/shielded-vm)
EnableVtpm bool `mapstructure:"enable_vtpm" required:"false"`
// Integrity monitoring helps you understand and make decisions about the
// state of your VM instances. Note: integrity monitoring relies on having
// vTPM enabled. [Details](https://cloud.google.com/security/shielded-cloud/shielded-vm)
EnableIntegrityMonitoring bool `mapstructure:"enable_integrity_monitoring" required:"false"`
// The unique name of the resulting image. Defaults to
// `packer-{{timestamp}}`.
ImageName string `mapstructure:"image_name" required:"false"`
@ -222,6 +237,15 @@ func (c *Config) Prepare(raws ...interface{}) ([]string, error) {
c.DiskType = "pd-standard"
}
// Disabling the vTPM also disables integrity monitoring, because integrity
// monitoring relies on data gathered by Measured Boot.
if !c.EnableVtpm {
if c.EnableIntegrityMonitoring {
errs = packer.MultiErrorAppend(errs,
errors.New("You cannot enable Integrity Monitoring when vTPM is disabled."))
}
}
if c.ImageDescription == "" {
c.ImageDescription = "Created by Packer"
}

View File

@ -66,6 +66,9 @@ type FlatConfig struct {
DiskName *string `mapstructure:"disk_name" required:"false" cty:"disk_name"`
DiskSizeGb *int64 `mapstructure:"disk_size" required:"false" cty:"disk_size"`
DiskType *string `mapstructure:"disk_type" required:"false" cty:"disk_type"`
EnableSecureBoot *bool `mapstructure:"enable_secure_boot" required:"false" cty:"enable_secure_boot"`
EnableVtpm *bool `mapstructure:"enable_vtpm" required:"false" cty:"enable_vtpm"`
EnableIntegrityMonitoring *bool `mapstructure:"enable_integrity_monitoring" required:"false" cty:"enable_integrity_monitoring"`
ImageName *string `mapstructure:"image_name" required:"false" cty:"image_name"`
ImageDescription *string `mapstructure:"image_description" required:"false" cty:"image_description"`
ImageEncryptionKey *FlatCustomerEncryptionKey `mapstructure:"image_encryption_key" required:"false" cty:"image_encryption_key"`
@ -167,6 +170,9 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"disk_name": &hcldec.AttrSpec{Name: "disk_name", Type: cty.String, Required: false},
"disk_size": &hcldec.AttrSpec{Name: "disk_size", Type: cty.Number, Required: false},
"disk_type": &hcldec.AttrSpec{Name: "disk_type", Type: cty.String, Required: false},
"enable_secure_boot": &hcldec.AttrSpec{Name: "enable_secure_boot", Type: cty.Bool, Required: false},
"enable_vtpm": &hcldec.AttrSpec{Name: "enable_vtpm", Type: cty.Bool, Required: false},
"enable_integrity_monitoring": &hcldec.AttrSpec{Name: "enable_integrity_monitoring", Type: cty.Bool, Required: false},
"image_name": &hcldec.AttrSpec{Name: "image_name", Type: cty.String, Required: false},
"image_description": &hcldec.AttrSpec{Name: "image_description", Type: cty.String, Required: false},
"image_encryption_key": &hcldec.BlockSpec{TypeName: "image_encryption_key", Nested: hcldec.ObjectSpec((*FlatCustomerEncryptionKey)(nil).HCL2Spec())},

View File

@ -72,6 +72,9 @@ type InstanceConfig struct {
DisableDefaultServiceAccount bool
DiskSizeGb int64
DiskType string
EnableSecureBoot bool
EnableVtpm bool
EnableIntegrityMonitoring bool
Image *Image
Labels map[string]string
MachineType string

View File

@ -271,11 +271,12 @@ func (d *driverGCE) GetImageFromProject(project, name string, fromFamily bool) (
return nil, fmt.Errorf("Image, %s, could not be found in project: %s", name, project)
} else {
return &Image{
Licenses: image.Licenses,
Name: image.Name,
ProjectId: project,
SelfLink: image.SelfLink,
SizeGb: image.DiskSizeGb,
GuestOsFeatures: image.GuestOsFeatures,
Licenses: image.Licenses,
Name: image.Name,
ProjectId: project,
SelfLink: image.SelfLink,
SizeGb: image.DiskSizeGb,
}, nil
}
}
@ -466,7 +467,23 @@ func (d *driverGCE) RunInstance(c *InstanceConfig) (<-chan error, error) {
},
}
d.ui.Message("Requesting instance creation...")
// Shielded VMs configuration. If the user has set at least one of the
// options, the shielded VM configuration will reflect that. If they
// don't set any of the options the settings will default to the ones
// of the source compute image which is used for creating the virtual
// machine.
shieldedInstanceConfig := &compute.ShieldedInstanceConfig{
EnableSecureBoot: c.EnableSecureBoot,
EnableVtpm: c.EnableVtpm,
EnableIntegrityMonitoring: c.EnableIntegrityMonitoring,
}
shieldedUiMessage := ""
if c.EnableSecureBoot || c.EnableVtpm || c.EnableIntegrityMonitoring {
instance.ShieldedInstanceConfig = shieldedInstanceConfig
shieldedUiMessage = " Shielded VM"
}
d.ui.Message(fmt.Sprintf("Requesting%s instance creation...", shieldedUiMessage))
op, err := d.service.Instances.Insert(d.projectId, zone.Name, &instance).Do()
if err != nil {
return nil, err

View File

@ -2,15 +2,18 @@ package googlecompute
import (
"strings"
compute "google.golang.org/api/compute/v1"
)
type Image struct {
Labels map[string]string
Licenses []string
Name string
ProjectId string
SelfLink string
SizeGb int64
GuestOsFeatures []*compute.GuestOsFeature
Labels map[string]string
Licenses []string
Name string
ProjectId string
SelfLink string
SizeGb int64
}
func (i *Image) IsWindows() bool {
@ -21,3 +24,12 @@ func (i *Image) IsWindows() bool {
}
return false
}
func (i *Image) IsSecureBootCompatible() bool {
for _, osFeature := range i.GuestOsFeatures {
if osFeature.Type == "SECURE_BOOT" {
return true
}
}
return false
}

View File

@ -107,6 +107,13 @@ func (s *StepCreateInstance) Run(ctx context.Context, state multistep.StateBag)
return multistep.ActionHalt
}
if c.EnableSecureBoot && !sourceImage.IsSecureBootCompatible() {
err := fmt.Errorf("Image: %s is not secure boot compatible. Please set 'enable_secure_boot' to false or choose another source image.", sourceImage.Name)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
ui.Say(fmt.Sprintf("Using image: %s", sourceImage.Name))
if sourceImage.IsWindows() && c.Comm.Type == "winrm" && c.Comm.WinRMPassword == "" {
@ -133,6 +140,9 @@ func (s *StepCreateInstance) Run(ctx context.Context, state multistep.StateBag)
DisableDefaultServiceAccount: c.DisableDefaultServiceAccount,
DiskSizeGb: c.DiskSizeGb,
DiskType: c.DiskType,
EnableSecureBoot: c.EnableSecureBoot,
EnableVtpm: c.EnableVtpm,
EnableIntegrityMonitoring: c.EnableIntegrityMonitoring,
Image: sourceImage,
Labels: c.Labels,
MachineType: c.MachineType,

View File

@ -25,6 +25,21 @@
- `disk_type` (string) - Type of disk used to back your instance, like pd-ssd or pd-standard.
Defaults to pd-standard.
- `enable_secure_boot` (bool) - Create a Shielded VM image with Secure Boot enabled. It helps ensure that
the system only runs authentic software by verifying the digital signature
of all boot components, and halting the boot process if signature verification
fails. [Details](https://cloud.google.com/security/shielded-cloud/shielded-vm)
- `enable_vtpm` (bool) - Create a Shielded VM image with virtual trusted platform module
Measured Boot enabled. A vTPM is a virtualized trusted platform module,
which is a specialized computer chip you can use to protect objects,
like keys and certificates, that you use to authenticate access to your
system. [Details](https://cloud.google.com/security/shielded-cloud/shielded-vm)
- `enable_integrity_monitoring` (bool) - Integrity monitoring helps you understand and make decisions about the
state of your VM instances. Note: integrity monitoring relies on having
vTPM enabled. [Details](https://cloud.google.com/security/shielded-cloud/shielded-vm)
- `image_name` (string) - The unique name of the resulting image. Defaults to
`packer-{{timestamp}}`.