Skip to content

Commit

Permalink
Enable cross account sharing of private AMIs
Browse files Browse the repository at this point in the history
For private AMIs like FIPS stemcells one has to explicitly configure
the accounts that can launch instances of such private AMIs.
  • Loading branch information
mvach committed Nov 16, 2023
1 parent fed3ae5 commit 24fc007
Show file tree
Hide file tree
Showing 7 changed files with 59 additions and 2 deletions.
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
.idea
config.json
.idea/
local/
light-stemcell-builder
1 change: 1 addition & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ type AmiConfiguration struct {
KmsKeyAliasName string `json:"kms_key_alias_name"`
Visibility string `json:"visibility"`
Tags map[string]string `json:"tags,omitempty"`
SharedWithAccounts []string `json:"shared_with_accounts"`
}

type AmiRegion struct {
Expand Down
18 changes: 18 additions & 0 deletions driver/create_ami_driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,24 @@ func (d *SDKCreateAmiDriver) Create(driverConfig resources.AmiDriverConfig) (res
d.logger.Printf("Error tagging Snapshot: %s, Error: %s ", driverConfig.SnapshotID, err.Error())
}

for i := range driverConfig.SharedWithAccounts {
account := driverConfig.SharedWithAccounts[i]

_, err := d.ec2Client.ModifyImageAttribute(&ec2.ModifyImageAttributeInput{
ImageId: amiIDptr,
LaunchPermission: &ec2.LaunchPermissionModifications{
Add: []*ec2.LaunchPermission{
{
UserId: &account,
},
},
},
})
if err != nil {
return resources.Ami{}, fmt.Errorf("failed to share AMI '%s' with account '%s': %w", *amiIDptr, account, err)
}
}

d.logger.Printf("waiting for AMI: %s to be available\n", *amiIDptr)
err = d.ec2Client.WaitUntilImageAvailable(&ec2.DescribeImagesInput{
ImageIds: []*string{amiIDptr},
Expand Down
30 changes: 30 additions & 0 deletions driver/create_ami_driver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,34 @@ var _ = Describe("CreateAmiDriver", func() {
_, err = ec2Client.DeregisterImage(&ec2.DeregisterImageInput{ImageId: &ami.ID}) // Ignore DeregisterImageOutput
Expect(err).ToNot(HaveOccurred())
})

It("shares the AMI with other accounts", func() {
amiDriverConfig := resources.AmiDriverConfig{
SnapshotID: ebsSnapshotID,
AmiProperties: resources.AmiProperties{
Name: fmt.Sprintf("BOSH-%s", strings.ToUpper(uuid.NewV4().String())),
VirtualizationType: resources.HvmAmiVirtualization,
Accessibility: resources.PublicAmiAccessibility,
SharedWithAccounts: []string{awsAccount},
},
}

ds := driverset.NewStandardRegionDriverSet(GinkgoWriter, creds)

amiDriver := ds.CreateAmiDriver()
ami, err := amiDriver.Create(amiDriverConfig)
Expect(err).ToNot(HaveOccurred())

awsSession, err := session.NewSession(creds.GetAwsConfig())
Expect(err).ToNot(HaveOccurred())
ec2Client := ec2.New(awsSession)

attribute := "launchPermission"
output, err := ec2Client.DescribeImageAttribute(&ec2.DescribeImageAttributeInput{
ImageId: &ami.ID,
Attribute: &attribute,
})
Expect(err).ToNot(HaveOccurred())
Expect(*output.LaunchPermissions[0].UserId).To(Equal(awsAccount))
})
})
5 changes: 5 additions & 0 deletions driver/driver_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ var s3MachineImageUrl, s3MachineImageFormat string

var kmsKeyId string

var awsAccount string

var amiFixtureID string

func TestDrivers(t *testing.T) {
Expand Down Expand Up @@ -71,6 +73,9 @@ var _ = SynchronizedBeforeSuite(
// KMS Key info
kmsKeyId = os.Getenv("AWS_KMS_KEY_ID")
Expect(kmsKeyId).ToNot(BeEmpty(), "AWS_KMS_KEY_ID must be set")

awsAccount = os.Getenv("AWS_ACCOUNT")
Expect(awsAccount).ToNot(BeEmpty(), "AWS_ACCOUNT must be set")
},
)

Expand Down
1 change: 1 addition & 0 deletions publisher/standard_region.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ func NewStandardRegionPublisher(logDest io.Writer, c Config) *StandardRegionPubl
KmsKeyId: c.KmsKeyId,
KmsKeyAliasName: c.KmsKeyAliasName,
Tags: c.Tags,
SharedWithAccounts: c.SharedWithAccounts,
},
logger: log.New(logDest, "StandardRegionPublisher ", log.LstdFlags),
}
Expand Down
1 change: 1 addition & 0 deletions resources/ami.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type AmiProperties struct {
KmsKeyAliasName string
KmsKeyAlias string
Tags map[string]string
SharedWithAccounts []string
}

// AmiDriverConfig allows an AmiDriver to create an AMI from either a snapshot ID or an existing AMI (copy)
Expand Down

0 comments on commit 24fc007

Please sign in to comment.