builder/amazon regional KMS keys

This commit is contained in:
Megan Marsh 2017-05-26 12:21:07 -07:00
parent 7174a7a3d5
commit f9d7292566
4 changed files with 39 additions and 13 deletions

View File

@ -67,6 +67,17 @@ func TestAMIConfigPrepare_regions(t *testing.T) {
t.Fatal("shouldn't have error") t.Fatal("shouldn't have error")
} }
c.SnapshotUsers = []string{"user-foo", "user-bar"}
c.AMIRegions = []string{"us-east-1", "us-east-2", "us-west-1"}
c.AMIRegionKmsKeyIds = map[string]string{
"us-east-1": "123-456-7890",
"us-west-1": "789-012-3456",
"us-east-2": "",
}
if err := c.Prepare(nil); err == nil {
t.Fatal("should have an error b/c can't use default KMS key if sharing")
}
c.AMIRegions = []string{"us-east-1", "us-west-1"} c.AMIRegions = []string{"us-east-1", "us-west-1"}
c.AMIRegionKmsKeyIds = map[string]string{ c.AMIRegionKmsKeyIds = map[string]string{
"us-east-1": "123-456-7890", "us-east-1": "123-456-7890",

View File

@ -13,9 +13,11 @@ import (
) )
type StepAMIRegionCopy struct { type StepAMIRegionCopy struct {
AccessConfig *AccessConfig AccessConfig *AccessConfig
Regions []string Regions []string
Name string RegionKeyIds map[string]string
EncryptBootVolume bool
Name string
} }
func (s *StepAMIRegionCopy) Run(state multistep.StateBag) multistep.StepAction { func (s *StepAMIRegionCopy) Run(state multistep.StateBag) multistep.StepAction {
@ -33,6 +35,7 @@ func (s *StepAMIRegionCopy) Run(state multistep.StateBag) multistep.StepAction {
var lock sync.Mutex var lock sync.Mutex
var wg sync.WaitGroup var wg sync.WaitGroup
var reg_key_id string
errs := new(packer.MultiError) errs := new(packer.MultiError)
for _, region := range s.Regions { for _, region := range s.Regions {
if region == *ec2conn.Config.Region { if region == *ec2conn.Config.Region {
@ -44,10 +47,14 @@ func (s *StepAMIRegionCopy) Run(state multistep.StateBag) multistep.StepAction {
wg.Add(1) wg.Add(1)
ui.Message(fmt.Sprintf("Copying to: %s", region)) ui.Message(fmt.Sprintf("Copying to: %s", region))
reg_key_id = s.RegionKeyIds[region]
if !s.EncryptBootVolume {
reg_key_id = ""
}
go func(region string) { go func(region string) {
defer wg.Done() defer wg.Done()
id, snapshotIds, err := amiRegionCopy(state, s.AccessConfig, s.Name, ami, region, *ec2conn.Config.Region) id, snapshotIds, err := amiRegionCopy(state, s.AccessConfig, s.Name, ami, region, *ec2conn.Config.Region, reg_key_id)
lock.Lock() lock.Lock()
defer lock.Unlock() defer lock.Unlock()
amis[region] = id amis[region] = id
@ -80,8 +87,9 @@ func (s *StepAMIRegionCopy) Cleanup(state multistep.StateBag) {
// amiRegionCopy does a copy for the given AMI to the target region and // amiRegionCopy does a copy for the given AMI to the target region and
// returns the resulting ID and snapshot IDs, or error. // returns the resulting ID and snapshot IDs, or error.
func amiRegionCopy(state multistep.StateBag, config *AccessConfig, name string, imageId string, func amiRegionCopy(state multistep.StateBag, config *AccessConfig, name string, imageId string,
target string, source string) (string, []string, error) { target string, source string, key_id string) (string, []string, error) {
snapshotIds := []string{} snapshotIds := []string{}
is_encrypted := false
// Connect to the region where the AMI will be copied to // Connect to the region where the AMI will be copied to
awsConfig, err := config.Config() awsConfig, err := config.Config()
@ -95,11 +103,16 @@ func amiRegionCopy(state multistep.StateBag, config *AccessConfig, name string,
return "", snapshotIds, err return "", snapshotIds, err
} }
regionconn := ec2.New(session) regionconn := ec2.New(session)
// if we've provided a map of key ids to regions, use those keys.
if len(key_id) > 0 {
is_encrypted = true
}
resp, err := regionconn.CopyImage(&ec2.CopyImageInput{ resp, err := regionconn.CopyImage(&ec2.CopyImageInput{
SourceRegion: &source, SourceRegion: &source,
SourceImageId: &imageId, SourceImageId: &imageId,
Name: &name, Name: &name,
Encrypted: aws.Bool(is_encrypted),
KmsKeyId: aws.String(key_id),
}) })
if err != nil { if err != nil {

View File

@ -25,7 +25,7 @@ func (s *StepCreateEncryptedAMICopy) Run(state multistep.StateBag) multistep.Ste
// Encrypt boot not set, so skip step // Encrypt boot not set, so skip step
if !s.EncryptBootVolume { if !s.EncryptBootVolume {
if kmsKeyId != "" { if kmsKeyId != "" {
log.Printf("Ignoring KMS Key ID: %s, encrypted_boot=false", kmsKeyId) log.Printf("Ignoring KMS Key ID: %s, encrypted=false", kmsKeyId)
} }
return multistep.ActionContinue return multistep.ActionContinue
} }
@ -36,14 +36,14 @@ func (s *StepCreateEncryptedAMICopy) Run(state multistep.StateBag) multistep.Ste
var region, id string var region, id string
if amis != nil { if amis != nil {
for region, id = range amis { for region, id = range amis {
break // Only get the first break // There is only ever one region:ami pair in this map
} }
} }
ui.Say(fmt.Sprintf("Copying AMI: %s(%s)", region, id)) ui.Say(fmt.Sprintf("Copying AMI: %s(%s)", region, id))
if kmsKeyId != "" { if kmsKeyId != "" {
ui.Say(fmt.Sprintf("Encrypting with KMS Key ID: %s", kmsKeyId)) ui.Say(fmt.Sprintf("Encypting with KMS Key ID: %s", kmsKeyId))
} }
copyOpts := &ec2.CopyImageInput{ copyOpts := &ec2.CopyImageInput{

View File

@ -198,9 +198,11 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
Name: b.config.AMIName, Name: b.config.AMIName,
}, },
&awscommon.StepAMIRegionCopy{ &awscommon.StepAMIRegionCopy{
AccessConfig: &b.config.AccessConfig, AccessConfig: &b.config.AccessConfig,
Regions: b.config.AMIRegions, Regions: b.config.AMIRegions,
Name: b.config.AMIName, RegionKeyIds: b.config.AMIRegionKmsKeyIds,
EncryptBootVolume: b.config.AMIEncryptBootVolume,
Name: b.config.AMIName,
}, },
&awscommon.StepModifyAMIAttributes{ &awscommon.StepModifyAMIAttributes{
Description: b.config.AMIDescription, Description: b.config.AMIDescription,