AWS Organizations管理下の各EC2インスタンスで使用されているAmazon提供以外のAMIの一覧を出してみた

AWS Organizations管理下の各EC2インスタンスで使用されているAmazon提供以外のAMIの一覧を出してみた

AWS Organizations管理下の各EC2インスタンスで使用されているAmazon提供以外のAMIの一覧を出してみた
Clock Icon2025.05.02

お疲れさまです。とーちです。

今回は、AWS Organizations環境下で、Amazon提供以外のAMIを使用しているEC2インスタンスを一覧化する方法について解説したいと思います。

なぜAmazon提供以外のAMIを探したいのか

AMIの中には、Amazonが提供しているものとほぼ同様と思われるAMIを別の会社がマーケットプレイスで提供しているケースがあります。詳しくは以下の記事でも紹介されています。

https://dev.classmethod.jp/articles/procomputers-windows-server-ami/

こういったAMIの使用が妥当かどうかはここでは言及しませんが、少なくともEC2の1時間あたりの単価はマーケットプレイス料金が上乗せされることもあり、Amazon提供のAMIを使う場合と比較して高くなります。もし組織内でAmazon公式提供のものと勘違いして使用しているという場合は、それを洗い出して適切に対応したいですよね。

そこで今回は、AWS Organizations内でAmazon提供のAMI以外のAMIを使用しているEC2の一覧を出す方法を紹介します。

前提条件

先に今回紹介する方法を実行するための前提条件を記載しておきます。

方法の検討

Amazon提供以外のAMIを探し出したいというときにうってつけの機能が昨年のre:Invent 2024前後でリリースされています。それがEC2 Allowed AMI機能です。

EC2 Allowed AMI機能はそれ単体ではAWS Organizations単位で展開することは出来ないので、この機能を組織単位で有効化するために宣言型ポリシーを使います。これによって簡単にEC2 Allowed AMI機能をAWS Organizationsに展開することができます。

上記によりAmazon提供以外のAMIを洗い出すベースが整うので、洗い出した情報をどのようにAWS Organizations単位で一覧で見れるかを検討してみました。私が考えうる限りでは以下の方法を思いつきました。

  1. AWS CLIで1アカウントずつ確認する
  2. AWS Configのマネージドルールを有効化し非準拠のリソースの一覧を取得する

それぞれの方法を実際に試してみましょう。

やってみる

宣言型ポリシーを有効にする

それではやってみましょう。

まずはAWS Organizationsの宣言型ポリシーを使って、EC2 Allowed AMI機能を組織単位で有効化します。

EC2 Allowed AMI機能には、有効・無効・監査モードの3つのモードがありますが、有効にすると現在の環境への影響が大きいので監査モードで有効化します。

まずはAWS Organizationsで宣言型ポリシーを使用可能にするために、管理アカウントのAWS Organizations画面から、以下のように宣言型ポリシーを有効化します。

alt text

有効化できたら、ポリシーを作成ボタンを押して、以下のポリシーを設定します。

{
  "ec2_attributes": {
    "allowed_images_settings": {
      "state": {
        "@@assign": "audit_mode"
      },
      "image_criteria": {
        "criteria_1": {
          "allowed_image_providers": {
            "@@assign": [
              "amazon"
            ]
          }
        }
      }
    }
  }
}

設定内容としては、監査モードで、Amazonが提供するAMIのみを許可されたAMIとするというものになります。

続いて作成したポリシーをアタッチします。今回は組織のルート(Root)にアタッチすることで組織全体で上記のポリシーを有効にしました。

alt text

これで全アカウントで設定したポリシーが有効となります。

AWS Organizations全体で許可されていないAMIを使用するEC2インスタンスを確認する(AWS CLIで1アカウントずつ確認)

まずはAWS CLIを使って許可されていないAMIを使うEC2を確認します。

この場合はアカウントごとにコマンドを発行して確認していきます。

コマンドは以下の通りです。許可されていないAMIを確認するにはaws ec2 describe-instance-image-metadataというコマンドを使うのが便利です。

for region in $(aws ec2 describe-regions --query "Regions[].RegionName" --output text); do
  echo "=== リージョン: $region ==="
  aws ec2 describe-instance-image-metadata --region $region \
    --query "InstanceImageMetadata[?ImageMetadata.ImageAllowed==\`false\`].{InstanceId:InstanceId,Name:Tags[?Key=='Name'].Value|[0],AMI:ImageMetadata.ImageId,AMI_Name:ImageMetadata.Name}" \
    --output table 2>/dev/null || echo "データなし"
  echo
done

以下のように出力されます。データなしとなっているのはSCPでリージョン制限しているためにデータ自体が取れないからですね。ap-northeast-3については起動しているEC2インスタンスがないので何も出力されていません。

=== リージョン: ap-northeast-3 ===

=== リージョン: ap-northeast-2 ===
データなし

=== リージョン: ap-northeast-1 ===
----------------------------------------------------------------------------------------------------------------------------------------------
|                                                        DescribeInstanceImageMetadata                                                       |
+-----------------------+------------------------------------------------------------------------------------+----------------------+--------+
|          AMI          |                                     AMI_Name                                       |     InstanceId       | Name   |
+-----------------------+------------------------------------------------------------------------------------+----------------------+--------+
|  ami-XXXXXXXXXXXX     |  openSUSE-Leap-15-6-vXXXXXXXX-hvm-ssd-x86_64-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX  |  i-XXXXXXXXXXXX      |  test  |
+-----------------------+------------------------------------------------------------------------------------+----------------------+--------+

AWS Organizations全体で許可されていないAMIを使用するEC2インスタンスを確認する(AWS Configのマネージドルールを有効化し非準拠のリソースの一覧を取得)

続いてAWS Configを使って許可されていないAMIを使用するEC2インスタンスを洗い出してみます。

こちらの方法は1アカウントから組織全体のEC2インスタンスについて洗い出せるのがメリットです。

まずは管理アカウントまたはconfig-multiaccountsetupサービスを委任された委任アカウントAWS Organizations全体許可されていないAMIで起動したEC2インスタンスを検出するマネージドルール(ec2-instance-launched-with-allowed-ami)を有効化します。

cat > ec2-ami-rule.json << 'EOF'
{
  "OrganizationConfigRuleName": "ec2-instance-launched-with-allowed-ami",
  "OrganizationManagedRuleMetadata": {
    "Description": "Checks if running or stopped EC2 instances were launched with Amazon Machine Images (AMIs) that meet your Allowed AMIs criteria. The rule is NON_COMPLIANT if an AMI doesn't meet the Allowed AMIs criteria and the Allowed AMIs settings isn't disabled.",
    "RuleIdentifier": "EC2_INSTANCE_LAUNCHED_WITH_ALLOWED_AMI",
    "ResourceTypesScope": [
      "AWS::EC2::Instance"
    ]
  }
}
EOF
aws configservice put-organization-config-rule --cli-input-json file://ec2-ami-rule.json

組織全体でAWS Configのマネージドルールを有効化できたら、以下のスクリプトで組織全体でルールに違反しているリソースを洗いだすことができます(こちらも管理アカウントまたは委任アカウントで実施)。

#!/bin/bash

# 変数設定
AGGREGATOR_NAME="<組織単位で有効化されているアグリゲータ名を指定>"
CONFIG_RULE_NAME="<AWS Config ルール名>"

# クエリ実行
aws configservice select-aggregate-resource-config \
  --expression "SELECT configuration.targetResourceId, configuration.targetResourceType, configuration.complianceType, configuration.configRuleList, awsRegion, accountId WHERE resourceType = 'AWS::Config::ResourceCompliance' AND configuration.complianceType = 'NON_COMPLIANT'" \
  --configuration-aggregator-name $AGGREGATOR_NAME \
  --output json > all_noncompliant.json

# 特定のルールに対して非準拠のリソースだけをフィルタリング
echo "フィルタリング結果:"
cat all_noncompliant.json | jq -r '.Results[] | 
  fromjson | 
  select(.configuration.configRuleList | map(select(.configRuleName == "'$CONFIG_RULE_NAME'" and .complianceType == "NON_COMPLIANT")) | length > 0) | 
  "リソースID: " + .configuration.targetResourceId + ", リソースタイプ: " + .configuration.targetResourceType + ", アカウント: " + .accountId + ", リージョン: " + .awsRegion'

AWS Config ルール名は以下のコマンドで確認できます。

aws configservice describe-organization-config-rules --query  OrganizationConfigRules[*].OrganizationConfigRuleArn | grep 'allowed-ami'

# 以下のようにARNが表示されるので、`ec2-instance-launched-with-allowed-ami-***` の部分をAWS Config ルール名として指定
    "arn:aws:config:ap-northeast-1:***:organization-config-rule/ec2-instance-launched-with-allowed-ami-***"

上記のスクリプトを実行すると、以下のような出力結果が出ます。

フィルタリング結果:
リソースID: i-XXXXXXXXXXXX, リソースタイプ: AWS::EC2::Instance, アカウント: XXXXXXXXXXXX, リージョン: ap-northeast-1

またはAWS Security Hubが組織全体で有効となっている場合、AWS Security Hubの委任アカウントから以下の方法で確認するのも良いかもしれません。

https://dev.classmethod.jp/articles/view-config-on-security-hub/

まとめ

今回は、AWS Organizations管理下の各EC2で使用されているAmazon提供以外のAMIの一覧を出す方法を紹介しました。

思ったよりもAWS Configで組織全体の非準拠状況を確認するのが難しいなという印象を受けました。おそらく上記のAWS Security Hubで非準拠状況を確認するのが一番楽だと思うので、AWS Configを使うときはAWS Security Hubとセットで運用したいですね。

以上、とーちでした。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.