{"id":15152101,"url":"https://github.com/elastic/aws-ami-share","last_synced_at":"2025-10-19T21:30:24.087Z","repository":{"id":65978180,"uuid":"243643600","full_name":"elastic/aws-ami-share","owner":"elastic","description":"Tool for sharing AWS AMIs across accounts","archived":false,"fork":false,"pushed_at":"2024-08-08T19:27:55.000Z","size":158,"stargazers_count":12,"open_issues_count":1,"forks_count":4,"subscribers_count":7,"default_branch":"master","last_synced_at":"2024-09-27T15:42:08.212Z","etag":null,"topics":["ami","aws","golang"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/elastic.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-02-28T00:15:55.000Z","updated_at":"2024-03-11T15:47:52.000Z","dependencies_parsed_at":"2023-02-19T18:55:15.457Z","dependency_job_id":null,"html_url":"https://github.com/elastic/aws-ami-share","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elastic%2Faws-ami-share","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elastic%2Faws-ami-share/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elastic%2Faws-ami-share/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elastic%2Faws-ami-share/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/elastic","download_url":"https://codeload.github.com/elastic/aws-ami-share/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":219869272,"owners_count":16555575,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ami","aws","golang"],"created_at":"2024-09-26T15:42:07.540Z","updated_at":"2025-10-19T21:30:23.693Z","avatar_url":"https://github.com/elastic.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"## AWS AMI Share\n\n![Go](https://github.com/elastic/aws-ami-share/workflows/Go/badge.svg)\n\n* [Configure IAM permission on \"source\" (owner of AMIs) account](#iam-permissions-on-source-account)\n* [Configure IAM permission on target account](#iam-permissions-on-target-account)\n* [Encrypted AMIs](#encrypted-amis)\n* [Utility usage](#usage)\n* [Configuring a manifest](#configure-manifest)\n\n## Overview\n\nUtility for sharing AMIs from a AWS source account to one or more target account(s). This utility works best in a ecosystem of accounts where the source account acts like a central registry of AMIs.\n![AMI accounts layout](img/ami_accounts.png)\n\nDuring a run, the following actions happen:\n* Share AMIs to target account(s)\n* Give target account access to EBS snapshots (for EBS-backed AMIs)\n* Copy AMI tags to AMI in target account\n* Mark shared AMI with marker tags. Marker tags include:\n    * Static user-supplied tags in config property `post-share-tags`: e.g. `\"Shared=true, UnDeletable=true\"`\n    * Meta tags added by this utility:`\"SharedWith-\u003cTARGET_ACCOUNT_ALIAS\u003e=true\"` after successfully sharing with a target account in the config.\n\n**Cross Account Access**:\nThe user that is running this CLI MUST have permissions to assume the roles specified in the target accounts. The specific role to assume is `AMIShareConsumer` role. \n\n### IAM Permissions\n\nThe `aws-ami-share` tool requires IAM permission on both source and target account. The setup is described below.\n\n#### IAM Permissions on source account\n\nThe permissions required on the source account are described in the policy below.\n\n```yaml\nPolicy: AMIShareSourcePolicy\n    {\n      \"Version\": \"2012-10-17\",\n      \"Statement\": [\n        {\n          \"Sid\": \"TagResources\",\n          \"Effect\": \"Allow\",\n          \"Action\": [\n            \"ec2:CreateTags\"\n          ],\n          \"Resource\": [\n            \"arn:aws:ec2:*::image/*\",\n            \"arn:aws:ec2:*::snapshot/*\"\n          ]\n        },\n        {\n          \"Sid\": \"GetAccountAlias\",\n          \"Effect\": \"Allow\",\n          \"Action\": [\n            \"iam:ListAccountAliases\"\n          ],\n          \"Resource\": \"*\"\n        },\n        {\n          \"Sid\": \"ShareImageOperations\",\n          \"Effect\": \"Allow\",\n          \"Action\": [\n            \"ec2:DescribeImages\",\n            \"ec2:DescribeTags\",\n            \"ec2:ModifyImageAttribute\",\n            \"ec2:ModifySnapshotAttribute\"\n          ],\n          \"Resource\": \"*\"\n        }\n      ]\n    }\n```\n\nThe above policy should be attached to a role created in the source account. In addition the IAM principal that will be running this CLI should be given permissions to assume the role with this policy.\n\n```yaml\nRole: AMIShareProvider\nAssumeRolePolicy:\n    {\n      \"Version\": \"2012-10-17\",\n      \"Statement\": [\n        {\n          \"Effect\": \"Allow\",\n          \"Principal\": {\n            \"AWS\": \"arn:aws:iam::\u003cSOURCE_ACCOUNT\u003e:root\"\n          },\n          \"Action\": \"sts:AssumeRole\",\n          \"Condition\": {}\n        }\n      ]\n    }\nPolicies:\n- AMIShareSourcePolicy (see policy above)\n\n```\n\n#### IAM Permissions on target account\n\nThe permissions required on the target account(s) for sharing an AMI are described in the policy below.\n\n```yaml\nPolicy: AMIShareConsumerPolicy\n    {\n      \"Version\": \"2012-10-17\",\n      \"Statement\": [\n        {\n          \"Sid\": \"TagResources\",\n          \"Effect\": \"Allow\",\n          \"Action\": [\n            \"ec2:CreateTags\"\n          ],\n          \"Resource\": [\n            \"arn:aws:ec2:*::image/*\",\n            \"arn:aws:ec2:*::snapshot/*\"\n          ]\n        },\n        {\n          \"Sid\": \"GetAccountAlias\",\n          \"Effect\": \"Allow\",\n          \"Action\": [\n            \"iam:ListAccountAliases\"\n          ],\n          \"Resource\": \"*\"\n        }\n      ]\n    }\n```\n\nThe above policy should be attached to a role created in the target account(s). In addition IAM principal that will be running this CLI should be given permissions to assume the role with this policy.\n\n```yaml\nRole: AMIShareConsumer\nAssumeRolePolicy:\n    {\n      \"Version\": \"2012-10-17\",\n      \"Statement\": [\n        {\n          \"Effect\": \"Allow\",\n          \"Principal\": {\n            \"AWS\": \"arn:aws:iam::\u003cSOURCE_ACCOUNT\u003e:root\"\n          },\n          \"Action\": \"sts:AssumeRole\",\n          \"Condition\": {}\n        }\n      ]\n    }\nPolicies:\n- AMIShareConsumerPolicy (see policy above)\n```\n\nThe setup should look like the diagram below:\n\n![AMI IAM layout](img/accounts_iam.png)\n\n### Encrypted AMIs\n\nThis tool does not interact with/manage KMS key sharing. For encrypted AMIs, the target account(s) must have access to the encryption KMS used to encrypt the AMI. THIS UTILITY DOES NOT SETTING UP KMS KEY ACCESS. \n\nSome useful AWS resources related to encrypted AMIs/instances:\n* [Sharing AMI KMS keys](https://aws.amazon.com/blogs/security/share-custom-encryption-keys-more-securely-between-accounts-by-using-aws-key-management-service/)\n* [Launching Encrytped Instance from Unencrypted AMIs](https://aws.amazon.com/blogs/security/how-to-quickly-launch-encrypted-ebs-backed-ec2-instances-from-unencrypted-amis/)\n\n## Usage\n\n```bash\nAWS AMI Share is a utility for sharing AMIs across accounts.\nVersion=v2.6.15.g69a00990.dirty, Build=69a00990f45b3f9ea861484064e91c9b496ffcb2, Date=Sat May 18 23:07:38 EDT 2019\n\nUsage:\n ami-share [flags]\n\nExamples:\nAWS AMI Share is a utility for sharing AMIs across accounts.\nVersion=v2.6.15.g69a00990.dirty, Build=69a00990f45b3f9ea861484064e91c9b496ffcb2, Date=Sat May 18 23:13:16 EDT 2019\n\nUsage:\n  ami-share [flags]\n\nExamples:\nAWS_SDK_LOAD_CONFIG=true AWS_PROFILE=staging-ami ./ami-share -v -c example.yaml -p plan.yaml\n\nFlags:\n  -c, --config string     (required) Path to the config file.\n  -h, --help              help for ami-share\n      --no-dry-run        If specified, it shares AMIs. Otherwise it just list target candidates in plan file.\n  -p, --plan string       (required) Path to output file for plan.\n      --share-snapshots   (optional) Whether to share snapshots attached to AMIs.\n  -v, --verbose           Enables debug output.\n      --version           version for ami-share\n```\n\nThis utility uses standard AWS credentials. Since it uses the GO SDK, you should set the environment variable `AWS_SDK_LOAD_CONFIG=true` which the AWS GO SDK requires if using a custom credentials file.\nThis [article](https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/guide_credentials_profiles.html) contains more information about AWS credentials file.\n\n## Configure manifest\nThe configuration has the following format:\n\n```yaml\nsource-account:\n  id: '************'\n  alias: registry-account\n  assume-role: \"AMIShareProvider\"\n  post-share-tags:\n    Shared: 1\n\ntarget-accounts:\n  - id: '************'\n    alias: integration-account\n    assume-role: \"AMIShareConsumer\"\n    regions:\n      - us-east-1\n    amis:\n      web:\n        filters:\n          - property: tag:Name\n            value: WebApp\n```\n\nThe manifest has these fields:\n\n| Field  | Explanation |\n| ------------- | ------------- |\n| **id**  | Account ID in AWS |\n| **alias**  | Account alias must match the IAM account alias in AWS - will also be used in the meta tag `\"ShareWith-\"`. |\n| **post-share-tags**  | (Optional) Only applicable to source account. The set of tags to add after sharing an AMI to mark it as such. |\n| **regions**  | Set of regions to share AMIs for this account. Can be overridden per AMI entry in `amis` property. |\n| **amis**  | A map of AMI alias to filters to find this AMI and (optional) regions to share it in (override account regions). |\n\n### Filters\nFilters section in config yaml should provide \"property\" and \"value\" as shown in the example above. If value contains white spaces, it should be surrounded by double quotes. The possible property are as following.\n\n| Property | Description | Example of value |\n| -------- | ----------- | ------- |\n| tag:[tag name] | Any tag property such as `tag:Name` | smp |\n| AMIName | AMI Name | \"smp 1557419569\" |\n| ID | AMI ID | ami-07f067a1643a549f3 |\n\nMultiple property/value pair can be provided and they will be \"AND\"-joined.\n\n\n### Variables in Config\n\nVariables from the environment can be injected into the config using the syntax `{{ .VarName }}`. These variable are read from the environment.\n\nFor example, if the config has contents and environment variable `GitHash=934JDOJF`:\n```yaml\n    amis:\n      proxy:\n        filters:\n          - property: tag:GitHash\n            value: {{ .GitHash }}\n```\n\nThis will be resolved to:\n```yaml\n    amis:\n      proxy:\n        filters:\n          - property: tag:GitHash\n            value: 934JDOJF\n```\n\n## Plan\n\nThis utility can be run in a plan mode. This is similar to a dry run mode, the output will be written to a YAML file. The output file format is similar to the config - it gives a summary of processed AMIs. \n\n```yaml\nsource-account:\n  id: '************'\n  alias: registry-account\n  assume-role: arn:aws:iam::************:role/AMIShareProvider\n  amis:\n    all:\n      us-east-1:\n      - ID=ami-0042e12a118e0e666, Name=centos-base 1557402212, Date=2019-05-09T11:47:23.000Z\n      - ID=ami-01627485c1afecab3, Name=salt-master 1556800156, Date=2019-05-02T12:32:42.000Z\n      - ID=ami-01ae7ef67904f53aa, Name=web 1557163383, Date=2019-05-06T17:26:04.000Z\n      - ID=ami-01cdfe13b893c918e, Name=web 1555343610, Date=2019-04-15T15:56:13.000Z\n      - ID=ami-026c267e0f55acb47, Name=centos-base 1556197455, Date=2019-04-25T13:08:15.000Z\n      - ID=ami-033639f6dabc7fe3d, Name=web 1557173915, Date=2019-05-06T20:21:36.000Z\n      - ID=ami-03d7d5c301b7c4214, Name=salt-master 1557922320, Date=2019-05-15T12:15:08.000Z\n      - ID=ami-0624083c2a7a25b0f, Name=salt-master 1557414503, Date=2019-05-09T15:12:18.000Z\n      - ID=ami-0652b6884ced0d9aa, Name=web 1557922631, Date=2019-05-15T12:19:11.000Z\n      - ID=ami-0655afaf61c633388, Name=web 1556198786, Date=2019-04-25T13:30:59.000Z\n      - ID=ami-06e97c608a2bc870e, Name=centos-base 1555342382, Date=2019-04-15T15:41:34.000Z      \n      - ID=ami-074de3342df5942f8, Name=salt-master 1556198013, Date=2019-04-25T13:18:38.000Z\n      - ID=ami-07d09200b9a34ed9d, Name=salt-master 1555343346, Date=2019-04-15T15:51:56.000Z      \n      - ID=ami-0884bc88383252b5a, Name=web 1557402995, Date=2019-05-09T11:59:04.000Z\n      - ID=ami-08d081224234e970c, Name=centos-base 1557921767, Date=2019-05-15T12:07:04.000Z\n      - ID=ami-0bb2e9c091228a8ea, Name=centos-base 1556799610, Date=2019-05-02T12:24:25.000Z      \n      - ID=ami-0f510098b2f5c1c4c, Name=web 1556800454, Date=2019-05-02T12:36:55.000Z\ntarget-accounts:\n- id: '************'\n  alias: integration-account\n  assume-role: arn:aws:iam::************:role/AMIShareConsumer\n  amis:\n    proxy:\n      us-east-1:\n      - ID=ami-0652b6884ced0d9aa, Name=web 1557922631, Date=2019-05-15T12:19:11.000Z\n```\n\n## Sample Run\n\n#### Dry Run\n\n```\nINFO[0000] Validating config                             context=share-command operation=validation\nINFO[0000] Initializing                                  context=share-command operation=validation\nDEBU[0000] Creating master session with: ************ in global as [arn:aws:iam::************:role/AMIShareProvider]  context=aws-session-factory operation=session\nINFO[0000] Validating accounts                           context=share-command operation=validation\nINFO[0000] Validating source account                     context=aws-share-ami operation=share\nDEBU[0000] Generating session: ************ in us-east-1 as [arn:aws:iam::************:role/AMIShareProvider]  context=aws-session-factory operation=session\nDEBU[0000] Generating session: ************ in global as [arn:aws:iam::************:role/AMIShareProvider]  context=aws-session-factory operation=session\nINFO[0000] Validating account: ************              context=aws-share-ami operation=share\nDEBU[0000] Generating session: ************ in us-east-1 as [arn:aws:iam::************:role/AMIShareConsumer]  context=aws-session-factory operation=session\nDEBU[0000] Generating session: ************ in global as [arn:aws:iam::************:role/AMIShareConsumer]  context=aws-session-factory operation=session\nINFO[0000] Generating plan for sharing AMIs              context=aws-share-ami operation=share\nDEBU[0001] AMIs in source account: map[us-east-1:[ami-0042e12a118e0e666 ami-01627485c1afecab3 ami-01ae7ef67904f53aa ami-01cdfe13b893c918e ami-026c267e0f55acb47 ami-033639f6dabc7fe3d ami-03d7d5c301b7c4214 ami-0624083c2a7a25b0f ami-0652b6884ced0d9aa ami-0655afaf61c633388 ami-06e97c608a2bc870e ami-0735224a86fcbf1b5 ami-074de3342df5942f8 ami-07d09200b9a34ed9d ami-07f067a1643a549f3 ami-0884bc88383252b5a ami-08d081224234e970c ami-0bb2e9c091228a8ea ami-0dd6d0bdabb5734f4 ami-0f510098b2f5c1c4c]]  context=aws-share-ami operation=share\nINFO[0001] Processing proxy AMIs                         context=aws-share-ami operation=share\nINFO[0001] Found 1 proxy AMIs in [us-east-1]             context=aws-share-ami operation=share\nDEBU[0001] Filtered proxy AMIs in [us-east-1] =\u003e [ami-0652b6884ced0d9aa]  context=aws-share-ami operation=share\nINFO[0001] Account: map[proxy:map[us-east-1:[ami-0652b6884ced0d9aa]]]  context=aws-share-ami operation=share\nDEBU[0001] Plan for sharing: \u0026{{************ saas-staging arn:aws:iam::************:role/AMIShareProvider map[all:map[us-east-1:[ami-0042e12a118e0e666 ami-01627485c1afecab3 ami-01ae7ef67904f53aa ami-01cdfe13b893c918e ami-026c267e0f55acb47 ami-033639f6dabc7fe3d ami-03d7d5c301b7c4214 ami-0624083c2a7a25b0f ami-0652b6884ced0d9aa ami-0655afaf61c633388 ami-06e97c608a2bc870e ami-0735224a86fcbf1b5 ami-074de3342df5942f8 ami-07d09200b9a34ed9d ami-07f067a1643a549f3 ami-0884bc88383252b5a ami-08d081224234e970c ami-0bb2e9c091228a8ea ami-0dd6d0bdabb5734f4 ami-0f510098b2f5c1c4c]]]} [{************ saas-integration arn:aws:iam::************:role/AMIShareConsumer map[proxy:map[us-east-1:[ami-0652b6884ced0d9aa]]]}]}  context=aws-share-ami operation=share\nINFO[0001] Wrote plan to: test.yaml                      context=aws-share-ami operation=share\nINFO[0001] Would share AMIs in plan: test.yaml           context=aws-share-ami operation=share\n```\n\n#### Real Run\n```\nINFO[0000] Validating config                             context=share-command operation=validation\nINFO[0000] Initializing                                  context=share-command operation=validation\nDEBU[0000] Creating master session with: ************ in global as [arn:aws:iam::************:role/AMIShareProvider]  context=aws-session-factory operation=session\nINFO[0000] Validating accounts                           context=share-command operation=validation\nINFO[0000] Validating source account                     context=aws-share-ami operation=share\nDEBU[0000] Generating session: ************ in us-east-1 as [arn:aws:iam::************:role/AMIShareProvider]  context=aws-session-factory operation=session\nDEBU[0000] Generating session: ************ in global as [arn:aws:iam::************:role/AMIShareProvider]  context=aws-session-factory operation=session\nINFO[0000] Validating account: ************              context=aws-share-ami operation=share\nDEBU[0000] Generating session: ************ in us-east-1 as [arn:aws:iam::************:role/AMIShareConsumer]  context=aws-session-factory operation=session\nDEBU[0000] Generating session: ************ in global as [arn:aws:iam::************:role/AMIShareConsumer]  context=aws-session-factory operation=session\nINFO[0000] Generating plan for sharing AMIs              context=aws-share-ami operation=share\nDEBU[0001] AMIs in source account: map[us-east-1:[ami-0042e12a118e0e666 ami-01627485c1afecab3 ami-01ae7ef67904f53aa ami-01cdfe13b893c918e ami-026c267e0f55acb47 ami-033639f6dabc7fe3d ami-03d7d5c301b7c4214 ami-0624083c2a7a25b0f ami-0652b6884ced0d9aa ami-0655afaf61c633388 ami-06e97c608a2bc870e ami-0735224a86fcbf1b5 ami-074de3342df5942f8 ami-07d09200b9a34ed9d ami-07f067a1643a549f3 ami-0884bc88383252b5a ami-08d081224234e970c ami-0bb2e9c091228a8ea ami-0dd6d0bdabb5734f4 ami-0f510098b2f5c1c4c]]  context=aws-share-ami operation=share\nINFO[0001] Processing proxy AMIs                         context=aws-share-ami operation=share\nINFO[0001] Found 1 proxy AMIs in [us-east-1]             context=aws-share-ami operation=share\nDEBU[0001] Filtered proxy AMIs in [us-east-1] =\u003e [ami-0652b6884ced0d9aa]  context=aws-share-ami operation=share\nINFO[0001] Account: map[proxy:map[us-east-1:[ami-0652b6884ced0d9aa]]]  context=aws-share-ami operation=share\nDEBU[0001] Plan for sharing: \u0026{{************ saas-staging arn:aws:iam::************:role/AMIShareProvider map[all:map[us-east-1:[ami-0042e12a118e0e666 ami-01627485c1afecab3 ami-01ae7ef67904f53aa ami-01cdfe13b893c918e ami-026c267e0f55acb47 ami-033639f6dabc7fe3d ami-03d7d5c301b7c4214 ami-0624083c2a7a25b0f ami-0652b6884ced0d9aa ami-0655afaf61c633388 ami-06e97c608a2bc870e ami-0735224a86fcbf1b5 ami-074de3342df5942f8 ami-07d09200b9a34ed9d ami-07f067a1643a549f3 ami-0884bc88383252b5a ami-08d081224234e970c ami-0bb2e9c091228a8ea ami-0dd6d0bdabb5734f4 ami-0f510098b2f5c1c4c]]]} [{************ saas-integration arn:aws:iam::************:role/AMIShareConsumer map[proxy:map[us-east-1:[ami-0652b6884ced0d9aa]]]}]}  context=aws-share-ami operation=share\nINFO[0001] Wrote plan to: test.yaml                      context=aws-share-ami operation=share\nINFO[0001] Running plan for sharing AMIs                 context=aws-share-ami operation=share\nINFO[0001] Sharing AMI proxy[ami-0652b6884ced0d9aa] with account [************] in region [us-east-1]  context=aws-share-ami operation=share```\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felastic%2Faws-ami-share","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Felastic%2Faws-ami-share","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felastic%2Faws-ami-share/lists"}