Merge pull request #7551 from krzyszko/gcp_encryption_key
Googlecompute builder image encryption support
This commit is contained in:
commit
fdae14bc18
|
@ -13,6 +13,7 @@ import (
|
||||||
"github.com/hashicorp/packer/helper/config"
|
"github.com/hashicorp/packer/helper/config"
|
||||||
"github.com/hashicorp/packer/packer"
|
"github.com/hashicorp/packer/packer"
|
||||||
"github.com/hashicorp/packer/template/interpolate"
|
"github.com/hashicorp/packer/template/interpolate"
|
||||||
|
compute "google.golang.org/api/compute/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
var reImageFamily = regexp.MustCompile(`^[a-z]([-a-z0-9]{0,61}[a-z0-9])?$`)
|
var reImageFamily = regexp.MustCompile(`^[a-z]([-a-z0-9]{0,61}[a-z0-9])?$`)
|
||||||
|
@ -27,40 +28,41 @@ type Config struct {
|
||||||
AccountFile string `mapstructure:"account_file"`
|
AccountFile string `mapstructure:"account_file"`
|
||||||
ProjectId string `mapstructure:"project_id"`
|
ProjectId string `mapstructure:"project_id"`
|
||||||
|
|
||||||
AcceleratorType string `mapstructure:"accelerator_type"`
|
AcceleratorType string `mapstructure:"accelerator_type"`
|
||||||
AcceleratorCount int64 `mapstructure:"accelerator_count"`
|
AcceleratorCount int64 `mapstructure:"accelerator_count"`
|
||||||
Address string `mapstructure:"address"`
|
Address string `mapstructure:"address"`
|
||||||
DisableDefaultServiceAccount bool `mapstructure:"disable_default_service_account"`
|
DisableDefaultServiceAccount bool `mapstructure:"disable_default_service_account"`
|
||||||
DiskName string `mapstructure:"disk_name"`
|
DiskName string `mapstructure:"disk_name"`
|
||||||
DiskSizeGb int64 `mapstructure:"disk_size"`
|
DiskSizeGb int64 `mapstructure:"disk_size"`
|
||||||
DiskType string `mapstructure:"disk_type"`
|
DiskType string `mapstructure:"disk_type"`
|
||||||
ImageName string `mapstructure:"image_name"`
|
ImageName string `mapstructure:"image_name"`
|
||||||
ImageDescription string `mapstructure:"image_description"`
|
ImageDescription string `mapstructure:"image_description"`
|
||||||
ImageFamily string `mapstructure:"image_family"`
|
ImageEncryptionKey *compute.CustomerEncryptionKey `mapstructure:"image_encryption_key"`
|
||||||
ImageLabels map[string]string `mapstructure:"image_labels"`
|
ImageFamily string `mapstructure:"image_family"`
|
||||||
ImageLicenses []string `mapstructure:"image_licenses"`
|
ImageLabels map[string]string `mapstructure:"image_labels"`
|
||||||
InstanceName string `mapstructure:"instance_name"`
|
ImageLicenses []string `mapstructure:"image_licenses"`
|
||||||
Labels map[string]string `mapstructure:"labels"`
|
InstanceName string `mapstructure:"instance_name"`
|
||||||
MachineType string `mapstructure:"machine_type"`
|
Labels map[string]string `mapstructure:"labels"`
|
||||||
Metadata map[string]string `mapstructure:"metadata"`
|
MachineType string `mapstructure:"machine_type"`
|
||||||
MinCpuPlatform string `mapstructure:"min_cpu_platform"`
|
Metadata map[string]string `mapstructure:"metadata"`
|
||||||
Network string `mapstructure:"network"`
|
MinCpuPlatform string `mapstructure:"min_cpu_platform"`
|
||||||
NetworkProjectId string `mapstructure:"network_project_id"`
|
Network string `mapstructure:"network"`
|
||||||
OmitExternalIP bool `mapstructure:"omit_external_ip"`
|
NetworkProjectId string `mapstructure:"network_project_id"`
|
||||||
OnHostMaintenance string `mapstructure:"on_host_maintenance"`
|
OmitExternalIP bool `mapstructure:"omit_external_ip"`
|
||||||
Preemptible bool `mapstructure:"preemptible"`
|
OnHostMaintenance string `mapstructure:"on_host_maintenance"`
|
||||||
RawStateTimeout string `mapstructure:"state_timeout"`
|
Preemptible bool `mapstructure:"preemptible"`
|
||||||
Region string `mapstructure:"region"`
|
RawStateTimeout string `mapstructure:"state_timeout"`
|
||||||
Scopes []string `mapstructure:"scopes"`
|
Region string `mapstructure:"region"`
|
||||||
ServiceAccountEmail string `mapstructure:"service_account_email"`
|
Scopes []string `mapstructure:"scopes"`
|
||||||
SourceImage string `mapstructure:"source_image"`
|
ServiceAccountEmail string `mapstructure:"service_account_email"`
|
||||||
SourceImageFamily string `mapstructure:"source_image_family"`
|
SourceImage string `mapstructure:"source_image"`
|
||||||
SourceImageProjectId string `mapstructure:"source_image_project_id"`
|
SourceImageFamily string `mapstructure:"source_image_family"`
|
||||||
StartupScriptFile string `mapstructure:"startup_script_file"`
|
SourceImageProjectId string `mapstructure:"source_image_project_id"`
|
||||||
Subnetwork string `mapstructure:"subnetwork"`
|
StartupScriptFile string `mapstructure:"startup_script_file"`
|
||||||
Tags []string `mapstructure:"tags"`
|
Subnetwork string `mapstructure:"subnetwork"`
|
||||||
UseInternalIP bool `mapstructure:"use_internal_ip"`
|
Tags []string `mapstructure:"tags"`
|
||||||
Zone string `mapstructure:"zone"`
|
UseInternalIP bool `mapstructure:"use_internal_ip"`
|
||||||
|
Zone string `mapstructure:"zone"`
|
||||||
|
|
||||||
Account AccountFile
|
Account AccountFile
|
||||||
stateTimeout time.Duration
|
stateTimeout time.Duration
|
||||||
|
|
|
@ -156,6 +156,21 @@ func TestConfigPrepare(t *testing.T) {
|
||||||
"foo bar",
|
"foo bar",
|
||||||
true,
|
true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"image_encryption_key",
|
||||||
|
map[string]string{"kmsKeyName": "foo"},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"image_encryption_key",
|
||||||
|
map[string]string{"No such key": "foo"},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"image_encryption_key",
|
||||||
|
map[string]string{"kmsKeyName": "foo", "RawKey": "foo"},
|
||||||
|
false,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"scopes",
|
"scopes",
|
||||||
[]string{},
|
[]string{},
|
||||||
|
|
|
@ -3,6 +3,8 @@ package googlecompute
|
||||||
import (
|
import (
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
compute "google.golang.org/api/compute/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Driver is the interface that has to be implemented to communicate
|
// Driver is the interface that has to be implemented to communicate
|
||||||
|
@ -11,7 +13,7 @@ import (
|
||||||
type Driver interface {
|
type Driver interface {
|
||||||
// CreateImage creates an image from the given disk in Google Compute
|
// CreateImage creates an image from the given disk in Google Compute
|
||||||
// Engine.
|
// Engine.
|
||||||
CreateImage(name, description, family, zone, disk string, image_labels map[string]string, image_licenses []string) (<-chan *Image, <-chan error)
|
CreateImage(name, description, family, zone, disk string, image_labels map[string]string, image_licenses []string, image_encryption_key *compute.CustomerEncryptionKey) (<-chan *Image, <-chan error)
|
||||||
|
|
||||||
// DeleteImage deletes the image with the given name.
|
// DeleteImage deletes the image with the given name.
|
||||||
DeleteImage(name string) <-chan error
|
DeleteImage(name string) <-chan error
|
||||||
|
|
|
@ -104,15 +104,16 @@ func NewDriverGCE(ui packer.Ui, p string, a *AccountFile) (Driver, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *driverGCE) CreateImage(name, description, family, zone, disk string, image_labels map[string]string, image_licenses []string) (<-chan *Image, <-chan error) {
|
func (d *driverGCE) CreateImage(name, description, family, zone, disk string, image_labels map[string]string, image_licenses []string, image_encryption_key *compute.CustomerEncryptionKey) (<-chan *Image, <-chan error) {
|
||||||
gce_image := &compute.Image{
|
gce_image := &compute.Image{
|
||||||
Description: description,
|
Description: description,
|
||||||
Name: name,
|
Name: name,
|
||||||
Family: family,
|
Family: family,
|
||||||
Labels: image_labels,
|
Labels: image_labels,
|
||||||
Licenses: image_licenses,
|
Licenses: image_licenses,
|
||||||
SourceDisk: fmt.Sprintf("%s%s/zones/%s/disks/%s", d.service.BasePath, d.projectId, zone, disk),
|
ImageEncryptionKey: image_encryption_key,
|
||||||
SourceType: "RAW",
|
SourceDisk: fmt.Sprintf("%s%s/zones/%s/disks/%s", d.service.BasePath, d.projectId, zone, disk),
|
||||||
|
SourceType: "RAW",
|
||||||
}
|
}
|
||||||
|
|
||||||
imageCh := make(chan *Image, 1)
|
imageCh := make(chan *Image, 1)
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
package googlecompute
|
package googlecompute
|
||||||
|
|
||||||
import "fmt"
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
compute "google.golang.org/api/compute/v1"
|
||||||
|
)
|
||||||
|
|
||||||
// DriverMock is a Driver implementation that is a mocked out so that
|
// DriverMock is a Driver implementation that is a mocked out so that
|
||||||
// it can be used for tests.
|
// it can be used for tests.
|
||||||
|
@ -8,6 +12,7 @@ type DriverMock struct {
|
||||||
CreateImageName string
|
CreateImageName string
|
||||||
CreateImageDesc string
|
CreateImageDesc string
|
||||||
CreateImageFamily string
|
CreateImageFamily string
|
||||||
|
CreateImageEncryptionKey *compute.CustomerEncryptionKey
|
||||||
CreateImageLabels map[string]string
|
CreateImageLabels map[string]string
|
||||||
CreateImageLicenses []string
|
CreateImageLicenses []string
|
||||||
CreateImageZone string
|
CreateImageZone string
|
||||||
|
@ -82,7 +87,7 @@ type DriverMock struct {
|
||||||
WaitForInstanceErrCh <-chan error
|
WaitForInstanceErrCh <-chan error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DriverMock) CreateImage(name, description, family, zone, disk string, image_labels map[string]string, image_licenses []string) (<-chan *Image, <-chan error) {
|
func (d *DriverMock) CreateImage(name, description, family, zone, disk string, image_labels map[string]string, image_licenses []string, image_encryption_key *compute.CustomerEncryptionKey) (<-chan *Image, <-chan error) {
|
||||||
d.CreateImageName = name
|
d.CreateImageName = name
|
||||||
d.CreateImageDesc = description
|
d.CreateImageDesc = description
|
||||||
d.CreateImageFamily = family
|
d.CreateImageFamily = family
|
||||||
|
@ -90,6 +95,7 @@ func (d *DriverMock) CreateImage(name, description, family, zone, disk string, i
|
||||||
d.CreateImageLicenses = image_licenses
|
d.CreateImageLicenses = image_licenses
|
||||||
d.CreateImageZone = zone
|
d.CreateImageZone = zone
|
||||||
d.CreateImageDisk = disk
|
d.CreateImageDisk = disk
|
||||||
|
d.CreateImageEncryptionKey = image_encryption_key
|
||||||
if d.CreateImageResultProjectId == "" {
|
if d.CreateImageResultProjectId == "" {
|
||||||
d.CreateImageResultProjectId = "test"
|
d.CreateImageResultProjectId = "test"
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ func (s *StepCreateImage) Run(ctx context.Context, state multistep.StateBag) mul
|
||||||
|
|
||||||
imageCh, errCh := driver.CreateImage(
|
imageCh, errCh := driver.CreateImage(
|
||||||
config.ImageName, config.ImageDescription, config.ImageFamily, config.Zone,
|
config.ImageName, config.ImageDescription, config.ImageFamily, config.Zone,
|
||||||
config.DiskName, config.ImageLabels, config.ImageLicenses)
|
config.DiskName, config.ImageLabels, config.ImageLicenses, config.ImageEncryptionKey)
|
||||||
var err error
|
var err error
|
||||||
select {
|
select {
|
||||||
case err = <-errCh:
|
case err = <-errCh:
|
||||||
|
|
|
@ -47,6 +47,7 @@ func TestStepCreateImage(t *testing.T) {
|
||||||
assert.Equal(t, d.CreateImageDisk, c.DiskName, "Incorrect disk passed to driver.")
|
assert.Equal(t, d.CreateImageDisk, c.DiskName, "Incorrect disk passed to driver.")
|
||||||
assert.Equal(t, d.CreateImageLabels, c.ImageLabels, "Incorrect image_labels passed to driver.")
|
assert.Equal(t, d.CreateImageLabels, c.ImageLabels, "Incorrect image_labels passed to driver.")
|
||||||
assert.Equal(t, d.CreateImageLicenses, c.ImageLicenses, "Incorrect image_licenses passed to driver.")
|
assert.Equal(t, d.CreateImageLicenses, c.ImageLicenses, "Incorrect image_licenses passed to driver.")
|
||||||
|
assert.Equal(t, d.CreateImageEncryptionKey, c.ImageEncryptionKey, "Incorrect image_encryption_key passed to driver.")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStepCreateImage_errorOnChannel(t *testing.T) {
|
func TestStepCreateImage_errorOnChannel(t *testing.T) {
|
||||||
|
|
|
@ -270,6 +270,17 @@ builder.
|
||||||
- `image_name` (string) - The unique name of the resulting image. Defaults to
|
- `image_name` (string) - The unique name of the resulting image. Defaults to
|
||||||
`"packer-{{timestamp}}"`.
|
`"packer-{{timestamp}}"`.
|
||||||
|
|
||||||
|
- `image_encryption_key` (object of encryption key) - Image encryption key to apply to the created image. Possible values:
|
||||||
|
* kmsKeyName - The name of the encryption key that is stored in Google Cloud KMS.
|
||||||
|
* RawKey: - A 256-bit customer-supplied encryption key, encodes in RFC 4648 base64.
|
||||||
|
|
||||||
|
example:
|
||||||
|
``` json
|
||||||
|
{
|
||||||
|
"kmsKeyName": "projects/${project}/locations/${region}/keyRings/computeEngine/cryptoKeys/computeEngine/cryptoKeyVersions/4"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
- `instance_name` (string) - A name to give the launched instance. Beware
|
- `instance_name` (string) - A name to give the launched instance. Beware
|
||||||
that this must be unique. Defaults to `"packer-{{uuid}}"`.
|
that this must be unique. Defaults to `"packer-{{uuid}}"`.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue