Merge pull request #7396 from c0sco/amazon-import-encryption

Support S3 and AMI encryption in amazon-import post-processor
This commit is contained in:
Megan Marsh 2019-03-25 17:24:49 -06:00 committed by GitHub
commit 2c67cd966b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 64 additions and 16 deletions

View File

@ -25,17 +25,21 @@ type Config struct {
awscommon.AccessConfig `mapstructure:",squash"` awscommon.AccessConfig `mapstructure:",squash"`
// Variables specific to this post processor // Variables specific to this post processor
S3Bucket string `mapstructure:"s3_bucket_name"` S3Bucket string `mapstructure:"s3_bucket_name"`
S3Key string `mapstructure:"s3_key_name"` S3Key string `mapstructure:"s3_key_name"`
SkipClean bool `mapstructure:"skip_clean"` S3Encryption string `mapstructure:"s3_encryption"`
Tags map[string]string `mapstructure:"tags"` S3EncryptionKey string `mapstructure:"s3_encryption_key"`
Name string `mapstructure:"ami_name"` SkipClean bool `mapstructure:"skip_clean"`
Description string `mapstructure:"ami_description"` Tags map[string]string `mapstructure:"tags"`
Users []string `mapstructure:"ami_users"` Name string `mapstructure:"ami_name"`
Groups []string `mapstructure:"ami_groups"` Description string `mapstructure:"ami_description"`
LicenseType string `mapstructure:"license_type"` Users []string `mapstructure:"ami_users"`
RoleName string `mapstructure:"role_name"` Groups []string `mapstructure:"ami_groups"`
Format string `mapstructure:"format"` Encrypt bool `mapstructure:"ami_encrypt"`
KMSKey string `mapstructure:"ami_kms_key"`
LicenseType string `mapstructure:"license_type"`
RoleName string `mapstructure:"role_name"`
Format string `mapstructure:"format"`
ctx interpolate.Context ctx interpolate.Context
} }
@ -99,6 +103,11 @@ func (p *PostProcessor) Configure(raws ...interface{}) error {
errs, fmt.Errorf("invalid format '%s'. Only 'ova', 'raw', 'vhd', 'vhdx', or 'vmdk' are allowed", p.config.Format)) errs, fmt.Errorf("invalid format '%s'. Only 'ova', 'raw', 'vhd', 'vhdx', or 'vmdk' are allowed", p.config.Format))
} }
if p.config.S3Encryption != "" && p.config.S3Encryption != "AES256" && p.config.S3Encryption != "aws:kms" {
errs = packer.MultiErrorAppend(
errs, fmt.Errorf("invalid s3 encryption format '%s'. Only 'AES256' and 'aws:kms' are allowed", p.config.S3Encryption))
}
// Anything which flagged return back up the stack // Anything which flagged return back up the stack
if len(errs.Errors) > 0 { if len(errs.Errors) > 0 {
return errs return errs
@ -141,6 +150,10 @@ func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (pac
return nil, false, fmt.Errorf("No %s image file found in artifact from builder", p.config.Format) return nil, false, fmt.Errorf("No %s image file found in artifact from builder", p.config.Format)
} }
if p.config.S3Encryption == "AES256" && p.config.S3EncryptionKey != "" {
ui.Message(fmt.Sprintf("Ignoring s3_encryption_key because s3_encryption is set to '%s'", p.config.S3Encryption))
}
// open the source file // open the source file
log.Printf("Opening file %s to upload", source) log.Printf("Opening file %s to upload", source)
file, err := os.Open(source) file, err := os.Open(source)
@ -150,14 +163,24 @@ func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (pac
ui.Message(fmt.Sprintf("Uploading %s to s3://%s/%s", source, p.config.S3Bucket, p.config.S3Key)) ui.Message(fmt.Sprintf("Uploading %s to s3://%s/%s", source, p.config.S3Bucket, p.config.S3Key))
// Copy the image file into the S3 bucket specified // Prepare S3 request
uploader := s3manager.NewUploader(session) updata := &s3manager.UploadInput{
_, err = uploader.Upload(&s3manager.UploadInput{
Body: file, Body: file,
Bucket: &p.config.S3Bucket, Bucket: &p.config.S3Bucket,
Key: &p.config.S3Key, Key: &p.config.S3Key,
}) }
if err != nil {
// Add encryption if specified in the config
if p.config.S3Encryption != "" {
updata.ServerSideEncryption = &p.config.S3Encryption
if p.config.S3Encryption == "aws:kms" && p.config.S3EncryptionKey != "" {
updata.SSEKMSKeyId = &p.config.S3EncryptionKey
}
}
// Copy the image file into the S3 bucket specified
uploader := s3manager.NewUploader(session)
if _, err = uploader.Upload(updata); err != nil {
return nil, false, fmt.Errorf("Failed to upload %s: %s", source, err) return nil, false, fmt.Errorf("Failed to upload %s: %s", source, err)
} }
@ -171,6 +194,7 @@ func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (pac
ec2conn := ec2.New(session) ec2conn := ec2.New(session)
params := &ec2.ImportImageInput{ params := &ec2.ImportImageInput{
Encrypted: &p.config.Encrypt,
DiskContainers: []*ec2.ImageDiskContainer{ DiskContainers: []*ec2.ImageDiskContainer{
{ {
Format: &p.config.Format, Format: &p.config.Format,
@ -182,6 +206,10 @@ func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (pac
}, },
} }
if p.config.Encrypt && p.config.KMSKey != "" {
params.KmsKeyId = &p.config.KMSKey
}
if p.config.RoleName != "" { if p.config.RoleName != "" {
params.SetRoleName(p.config.RoleName) params.SetRoleName(p.config.RoleName)
} }

View File

@ -67,11 +67,19 @@ Optional:
imported AMI. By default this description is generated by the AMI import imported AMI. By default this description is generated by the AMI import
process. process.
- `ami_encrypt` (boolean) - Encrypt the resulting AMI using KMS. This defaults
to `false`.
- `ami_groups` (array of strings) - A list of groups that have access to - `ami_groups` (array of strings) - A list of groups that have access to
launch the imported AMI. By default no groups have permission to launch the launch the imported AMI. By default no groups have permission to launch the
AMI. `all` will make the AMI publicly accessible. AWS currently doesn't AMI. `all` will make the AMI publicly accessible. AWS currently doesn't
accept any value other than "all". accept any value other than "all".
- `ami_kms_key` (string) - The ID of the KMS key used to encrypt the AMI
if `ami_encrypt` is true. If set, the role specified in `role_name` must
be granted access to use this key. If not set, the account default KMS key
will be used.
- `ami_name` (string) - The name of the ami within the console. If not - `ami_name` (string) - The name of the ami within the console. If not
specified, this will default to something like `ami-import-sfwerwf`. Please specified, this will default to something like `ami-import-sfwerwf`. Please
note, specifying this option will result in a slightly longer execution note, specifying this option will result in a slightly longer execution
@ -112,6 +120,18 @@ Optional:
- `role_name` (string) - The name of the role to use when not using the - `role_name` (string) - The name of the role to use when not using the
default role, 'vmimport' default role, 'vmimport'
- `s3_encryption` (string) - One of: `aws:kms`, or `AES256`. The algorithm
used to encrypt the artifact in S3. This **does not** encrypt the
resulting AMI, and is only used to encrypt the uploaded artifact before
it becomes an AMI. By default no encryption is used.
- `s3_encryption_key` (string) - The KMS key ID to use when `aws:kms` is
specified in `s3_encryption`. This setting is ignored if AES is used
as Amazon does not currently support custom AES keys when using the VM
import service. If set, the role specified in `role_name` must be granted
access to use this key. If not set, and `s3_encryption` is set to `aws:kms`,
the account default KMS key will be used.
- `s3_key_name` (string) - The name of the key in `s3_bucket_name` where the - `s3_key_name` (string) - The name of the key in `s3_bucket_name` where the
OVA file will be copied to for import. If not specified, this will default OVA file will be copied to for import. If not specified, this will default
to "packer-import-{{timestamp}}.ova". This key (i.e., the uploaded OVA) to "packer-import-{{timestamp}}.ova". This key (i.e., the uploaded OVA)