You share a custom EC2 AMI with a second AWS account. They can see the image, but every launch from it fails. What are the usual causes, and how do you share an AMI so it actually launches?
answer
- two halves, not one
- the manifest and the snapshots
- the default EBS key cannot be shared
- CreateGrant is the forgotten permission
- opaque client error, not AccessDenied
basics
~20 sLaunch permission on the AMI is not enough when its snapshots are encrypted: the consuming account also needs access to the KMS key. Images encrypted with the AWS-managed EBS key cannot be shared at all — re-encrypt under a customer-managed key first.
solid answer
~50 sSharing an AMI has two halves, and teams usually do only the first. Adding a launch permission with `ModifyImageAttribute` makes the image visible and launchable — but only if its backing snapshots are unencrypted. If they are encrypted, the target account must also be able to use the KMS key: you cannot share the AWS-managed `aws/ebs` key at all, so the image has to be re-created or copied encrypted under a **customer-managed** key whose key policy grants the other account `kms:Decrypt`, `kms:DescribeKey`, `kms:ReEncrypt*` and `kms:CreateGrant`. Miss that and launches fail with an opaque client error rather than an access-denied message. Two other causes worth naming: images carrying Marketplace billing product codes cannot be shared or copied, and a shared AMI stays in **your** account, so if you deregister it the consumer breaks. The robust pattern is to have the consumer `CopyImage` into their own account and region.
code
bash · 5 linesaws ec2 modify-image-attribute \
--image-id ami-0123456789abcdef0 \
--launch-permission "Add=[{UserId=111122223333}]"
aws ec2 describe-images --owners 444455556666 --image-ids ami-0123456789abcdef0go deeper
Know that an AMI is private by default and that sharing means adding a launch permission for another account, and that a shared image is still owned by whoever built it.
Explain that the snapshots behind the AMI carry their own access control, that encryption pulls KMS into the picture, and that the consumer must query DescribeImages with the owner filter to see a privately shared image.
Demonstrate having debugged this: the opaque launch failure, the AWS-managed key that cannot be shared, the CreateGrant permission everyone forgets, and the habit of copying the image into the consuming account rather than depending on the producer.
Own the distribution model — organization-scoped grants over account lists, a key policy scoped by organization, images distributed by the build pipeline into every account and region, and a deprecation policy so no consumer is broken by an image being retired.
## The two halves of sharing An AMI is a manifest plus the EBS snapshots it points at. Sharing it therefore requires granting access to **both**, and the fact that only one of them has an obvious API call is why this question comes up in interviews. ### 1. The image: launch permission `ModifyImageAttribute` adds a launch permission for an account ID: ```bash aws ec2 modify-image-attribute \ --image-id ami-0123456789abcdef0 \ --launch-permission "Add=[{UserId=111122223333}]" ``` You can also grant to an entire AWS Organization or organizational unit rather than enumerating accounts, which is what you want for a shared golden-image pipeline. Once granted, the consumer sees the image in `DescribeImages` when they query with the owner filter — private shared AMIs do not show up in a bare listing, which is itself a frequent "I can't see it" complaint. ### 2. The data: the KMS key If the AMI's snapshots are encrypted, EC2 must decrypt them on the consumer's behalf to create volumes. That requires the consumer's principal to be able to use the key, and here the trap: - **The AWS-managed key `aws/ebs` cannot be shared.** Its key policy is not editable. An AMI built on an account with default EBS encryption pointed at the AWS-managed key is therefore fundamentally unshareable. - The fix is a **customer-managed key (CMK)**. Copy or rebuild the image with `--encrypted --kms-key-id <your CMK>`, and put a statement in the key policy granting the target account `kms:Decrypt`, `kms:DescribeKey`, `kms:ReEncrypt*` and `kms:CreateGrant`. `CreateGrant` is the one people omit; EC2 needs it to mint a grant for the volumes it creates. - The consuming account must **also** allow those actions in its own IAM policies. Cross-account access needs both sides. The symptom when the key is missing is the memorable part: the launch is accepted, the instance goes to `pending` and then straight to `terminated`, with a state transition reason along the lines of `Client.InternalError: Client error on launch`. It reads like an AWS fault. It is almost always a KMS permission gap. ## Other real causes of "visible but won't launch" - **Marketplace or licensed images.** AMIs carrying `billingProducts` codes cannot be shared with or copied by other accounts. If your golden image was built by launching a paid Marketplace AMI and calling `CreateImage`, it inherits the codes and is stuck. - **Region mismatch.** The consumer is looking in a different region from the one the AMI is registered in; nothing was shared into their region at all. - **Instance-type incompatibility.** The AMI's architecture (`arm64` vs `x86_64`), boot mode or ENA/NVMe support does not match the instance type the consumer chose. - **Organization policy.** A service control policy or a `RequireImdsV2`-style guardrail in the consuming account can block the launch for reasons that have nothing to do with the share. ## Why sharing is not the end state A shared AMI is still owned by the producing account. Two consequences: 1. If the producer deregisters or deletes it, every consumer's future launches — including Auto Scaling replacements — break, with no warning. 2. Consumers pay nothing for the snapshots but also cannot control their lifecycle or apply their own tags and backup policies. The production-grade pattern is therefore **share, then copy**: the consuming account runs `CopyImage` to create its own AMI in its own account and region. That copy re-encrypts under a key the consumer owns, which cuts the ongoing dependency on the producer's key policy entirely — but note the copy itself needs `kms:CreateGrant` and `kms:ReEncrypt*` on the **source** key, so the share must be permissive enough to allow the copy before it can be dropped. A mature setup automates this: the image pipeline distributes copies into every target account and region as part of the build, and each account references only images it owns. ## How to answer this in an interview Name the two halves — launch permission and key access — say plainly that the AWS-managed EBS key cannot be shared, and mention that the failure mode is an opaque client error rather than AccessDenied. Then close with the copy-into-the-consumer-account pattern; that is the part that shows you have run this at scale rather than done it once by hand.
- Why does the failure surface as an internal client error instead of an access-denied message?The API call that launches the instance succeeds — permissions on `ec2:RunInstances` are fine. The failure happens afterwards, when the EC2 service tries to create encrypted volumes on your behalf and cannot use the key. That asynchronous step reports through the instance's state transition reason, and AWS deliberately keeps the text generic rather than leaking details about another account's key policy.
- The consuming account wants to stop depending on your account entirely. What do they do?They run `CopyImage` into their own account and region with `--encrypted --kms-key-id` pointing at a key they own. The result is an AMI they own outright, with their own snapshots, tags, lifecycle and key policy. The catch is sequencing: the copy needs `kms:ReEncrypt*` and `kms:CreateGrant` on your source key, so the share must remain in place until the copy completes.
- How would you share golden images across fifty accounts in an AWS Organization?Do not enumerate accounts. Grant launch permission to the organization or the relevant organizational units so new accounts inherit access, encrypt under a customer-managed key whose policy is scoped with `aws:PrincipalOrgID`, and have the build pipeline distribute copies into each target region. Then publish the current image ID through a well-known SSM parameter so consumers resolve it rather than hardcoding.
saying these in an interview costs you the question
- Thinking launch permission alone is sufficient for encrypted AMIs
- Trying to share the AWS-managed aws/ebs key
- Granting Decrypt but omitting kms:CreateGrant
- Reading Client.InternalError as an AWS-side outage
- Assuming a shared AMI is safe from the owner deregistering it