Adding custom shielded images support (GCP)
Adds `enable_secure_boot`, `enable_vtpm` and `enable_integrity_monitoring` config options to enable building of custom Shielded GCP Compute images. Feedback on this is more than welcome as this is my first attempt in contributing to anything Packer related. Packer is great for us to build custom images on top of GCP but we would like to enhance that to support Shielded VM images. This will allow us to have more secure and trusted images which our team(s) will be using.
This commit is contained in:
parent
553b1fb9f8
commit
d827f4f757
@ -57,6 +57,22 @@ 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"`
|
||||
// Shielded VM offers verifiable integrity of your Compute Engine VM instances,
|
||||
// so you can be confident your instances haven't been compromised by boot-
|
||||
// or kernel-level malware or rootkits. Shielded VM's verifiable integrity
|
||||
// is achieved through the use of:
|
||||
// * Secure Boot - 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.
|
||||
EnableSecureBoot bool `mapstructure:"enable_secure_boot" required:"false"`
|
||||
// * virtual trusted platform module (vTPM)-enabled Measured Boot - 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.
|
||||
EnableVtpm bool `mapstructure:"enable_vtpm" required:"false"`
|
||||
// * Integrity monitoring - Integrity monitoring helps you understand and
|
||||
// make decisions about the state of your VM instances.
|
||||
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 +238,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"
|
||||
}
|
||||
|
@ -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())},
|
||||
|
@ -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
|
||||
|
@ -271,6 +271,7 @@ 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{
|
||||
GuestOsFeatures: image.GuestOsFeatures,
|
||||
Licenses: image.Licenses,
|
||||
Name: image.Name,
|
||||
ProjectId: project,
|
||||
@ -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
|
||||
|
@ -2,9 +2,12 @@ package googlecompute
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
)
|
||||
|
||||
type Image struct {
|
||||
GuestOsFeatures []*compute.GuestOsFeature
|
||||
Labels map[string]string
|
||||
Licenses []string
|
||||
Name string
|
||||
@ -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
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -25,6 +25,19 @@
|
||||
- `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) - Enable Secure Boot on a Shielded VM instance. Secure Boot 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#secure-boot)
|
||||
|
||||
- `enable_vtpm` (bool) - Enable virtualized trusted platform module on a Shielded VM instance.
|
||||
[Details](https://cloud.google.com/security/shielded-cloud/shielded-vm#vtpm)
|
||||
|
||||
- `enable_integrity_monitoring` (bool) - Enable integrity monitoring on a Shielded VM instance. Integrity
|
||||
monitoring helps you understand and make decisions about the state of your VM instances. Note: requires
|
||||
enable_vtpm to be set to true.
|
||||
[Details](https://cloud.google.com/security/shielded-cloud/shielded-vm#integrity-monitoring)
|
||||
|
||||
- `image_name` (string) - The unique name of the resulting image. Defaults to
|
||||
`packer-{{timestamp}}`.
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user