(小ネタ)CloudTrail が全リージョンで有効か無効か確認するスクリプトを CloudShell で実行する

(小ネタ)CloudTrail が全リージョンで有効か無効か確認するスクリプトを CloudShell で実行する

CloudTrail が全リージョンで有効か無効かを確認するスクリプトを CloudShell で実行してみました。
Clock Icon2025.03.22

コーヒーが好きな emi です。

スタンドアロンの AWS アカウントを Control Tower に参加させる前に Config の有効化状況を確認するスクリプトを以下のブログで作成し実行しました。

https://dev.classmethod.jp/articles/check-config-status-cloudshell/

次は、CloudTrail 証跡が全リージョンで有効化どうか確認するスクリプトを作成して CloudShell で実行してみます。

CloudTrail 証跡で料金が発生するケース

CloudTrail 証跡は 1 つ目は無料ですが、2 つ目以降は有料になります。

https://aws.amazon.com/jp/cloudtrail/pricing/

よくあるミスとして、Control Tower を有効化した際、既存で設定されていた CloudTrail 証跡に追加で Coltrol Tower の組織レベルの CloudTrail 証跡が有効化されてしまい、課金が発生するケースがあります。

https://dev.classmethod.jp/articles/costs-cloudtrail-after-update-ct-landing-zone/

Config とは違い、CloudTrail 証跡があっても Control Tower への登録は成功します。CloudTrail でのデータイベントの取得など、別の用途で取得する場合もあるためです。

しかし、特に用途がないのに二重に証跡を取得してコスト増になっては無駄なので、生成 AI の力も借り、CloudTrail 証跡が有効になっているかどうか確認するスクリプトを作成し CloudShell で実行してみました。

過去何回も擦られたネタかもしれませんが、読むのと自分でやるのとでは理解に差があると思うので改めて記事に残しておきます。

作成したスクリプト

check-trail-status.sh
#!/bin/bash

# Get all available AWS regions
regionAry=($(aws ec2 describe-regions --all-regions --query "Regions[].RegionName" --output text))

# Print header
printf "| %-18s | %-30s | %-14s | %-12s |\n" "Region" "Trail Name" "Multi-Region?" "Org Trail?"
printf "|--------------------|--------------------------------|----------------|--------------|\n"

for region in "${regionAry[@]}"; do
    # Get trail list with name and isMultiRegion info
    trails=$(aws cloudtrail describe-trails \
        --region "$region" \
        --query "trailList[*].[Name,IsMultiRegionTrail]" \
        --output text 2>/dev/null)

    if [ -z "$trails" ]; then
        # No trail found in this region
        printf "| %-18s | %-30s | %-14s | %-12s |\n" "$region" "-" "-" "-"
    else
        # Process each trail
        while IFS=$'\t' read -r trailName isMulti; do
            if [ "$trailName" != "None" ] && [ -n "$trailName" ]; then
                # Check if this trail is an organization trail
                isOrg=$(aws cloudtrail get-trail \
                    --name "$trailName" \
                    --region "$region" \
                    --query "Trail.IsOrganizationTrail" \
                    --output text 2>/dev/null)
            else
                isOrg="-"
            fi

            printf "| %-18s | %-30s | %-14s | %-12s |\n" "$region" "$trailName" "$isMulti" "$isOrg"
        done <<< "$trails"
    fi
done

スクリプトの説明

このスクリプトは、各リージョンにおける CloudTrail の証跡が存在するかどうかを確認し、表形式で一覧表示するものです。CloudTrail には以下 3 種類の証跡が存在し、それぞれ有効か無効か判定します。

  • 単一リージョンの証跡
  • マルチリージョンの証跡
  • 組織レベルの証跡

1. 全リージョンを取得して配列に格納

regionAry=($(aws ec2 describe-regions --all-regions --query "Regions[].RegionName" --output text))
  • aws ec2 describe-regions で全リージョンのリージョン名を取得
  • regionAry はリージョン名の配列
  • --all-regions を指定すると全リージョンを取得できる

2. 表のヘッダーを表示

printf "| %-18s | %-30s | %-14s | %-12s |\n" "Region" "Trail Name" "Multi-Region?" "Org Trail?"
printf "|--------------------|--------------------------------|----------------|--------------|\n"
  • 出力結果をテーブル形式にするために、ヘッダー(見出し)と罫線を表示
    • --output table だとリージョンの数だけテーブルが出力されるようになってしまったためこのように人力で成形
  • Region:リージョン名
  • Trail Name:CloudTrail の証跡名
  • Multi-Region?:マルチリージョン証跡かどうか(true / false
  • Org Trail?:組織トレイルであるか(true/false)

https://docs.aws.amazon.com/ja_jp/awscloudtrail/latest/userguide/receive-cloudtrail-log-files-from-multiple-regions.html

3. 各リージョンで CloudTrail を確認

for region in "${regionAry[@]}"; do
  • 配列 regionAry に入っているすべてのリージョンに対してループ処理

4. describe-trails 実行

trails=$(aws cloudtrail describe-trails \
    --region "$region" \
    --query "trailList[*].[Name,IsMultiRegionTrail]" \
    --output text 2>/dev/null)
  • 各リージョンで CloudTrail の情報を取得
  • --querytrailList の中から NameIsMultiRegionTrail だけを取り出し
  • --output text でタブ区切りのテキスト形式に変換
  • 2>/dev/null でエラー出力を無視

5. CloudTrail 証跡が存在しない場合の出力

if [ -z "$trails" ]; then
    printf "| %-18s | %-30s | %-14s | %-12s |\n" "$region" "-" "-" "-"
  • result が空(=トレイルが存在しない)場合は「-」で表示

6. CloudTrail 証跡がある場合の出力

while IFS=$'\t' read -r trailName isMulti; do
  • 複数トレイルがある場合、1 つずつ処理
  • --output text を使うと出力が タブ区切り(\t)になるため IFS=$'\t' を設定
    • IFS(Internal Field Separator(内部フィールド区切り文字):Bash が「文字列をどこで区切って単語に分けるかを決めるための変数
  • trailNameisMulti に分割して変数へ代入

7. 各 CloudTrail 証跡について組織レベルか確認

if [ "$trailName" != "None" ] && [ -n "$trailName" ]; then
    isOrg=$(aws cloudtrail get-trail \
        --name "$trailName" \
        --region "$region" \
        --query "Trail.IsOrganizationTrail" \
        --output text 2>/dev/null)
else
    isOrg="-"
fi
  • get-trail コマンドを使ってその証証跡組織レベルかどうか判定
  • Trail.IsOrganizationTrailtrue / false を取得
  • 証跡名が "None" や空なら "-" を表示

8. 結果をテーブルに出力

printf "| %-18s | %-30s | %-14s | %-12s |\n" "$region" "$trailName" "$isMulti" "$isOrg"
  • 4 列の表形式で整形して表示

CloudShell で実行

CloudShell で check-trail-status.sh を保存します。

  • vim check-trail-status.sh と入力し vim エディタを開く
  • :set paste + Enter で貼り付けモードにする
  • i を押下し編集モードにする
  • スクリプトの中身を貼り付ける
  • esc を押下し編集モードを抜ける
  • :wq + Enter で保存し閉じる
  • 保存できたか cat check-trail-status.sh で確認する
  • chmod +x check-trail-status.sh で実行権限を付与

では、CloudShell でスクリプトを実行します。

./check-trail-status.sh

▼実行結果

~ $ ./check-trail-status.sh 
| Region             | Trail Name                     | Multi-Region?  | Org Trail?   |
|--------------------|--------------------------------|----------------|--------------|
| ap-south-2         | -                              | -              | -            |
| ap-south-1         | -                              | -              | -            |
| eu-south-1         | -                              | -              | -            |
| eu-south-2         | -                              | -              | -            |
| me-central-1       | -                              | -              | -            |
| il-central-1       | -                              | -              | -            |
| ca-central-1       | -                              | -              | -            |
| mx-central-1       | -                              | -              | -            |
| eu-central-1       | -                              | -              | -            |
| eu-central-2       | -                              | -              | -            |
| us-west-1          | -                              | -              | -            |
| us-west-2          | -                              | -              | -            |
| af-south-1         | -                              | -              | -            |
| eu-north-1         | -                              | -              | -            |
| eu-west-3          | -                              | -              | -            |
| eu-west-2          | -                              | -              | -            |
| eu-west-1          | -                              | -              | -            |
| ap-northeast-3     | -                              | -              | -            |
| ap-northeast-2     | -                              | -              | -            |
| me-south-1         | -                              | -              | -            |
| ap-northeast-1     | -                              | -              | -            |
| sa-east-1          | -                              | -              | -            |
| ap-east-1          | -                              | -              | -            |
| ca-west-1          | -                              | -              | -            |
| ap-southeast-1     | -                              | -              | -            |
| ap-southeast-2     | -                              | -              | -            |
| ap-southeast-3     | -                              | -              | -            |
| ap-southeast-4     | -                              | -              | -            |
| us-east-1          | -                              | -              | -            |
| ap-southeast-5     | -                              | -              | -            |
| us-east-2          | -                              | -              | -            |
| ap-southeast-7     | -                              | -              | -            |
~ $ 

いいですね。CloudTrail 証跡が無いことが分かりました。

さて、ちゃんとスクリプトが発動するか確認するため、バージニア北部リージョン(us-east-1)で組織レベルの証跡有効化をおこない、再度スクリプトを CloudShell で実行してみます。

~ $ ./check-trail-status.sh 
| Region             | Trail Name                     | Multi-Region?  | Org Trail?   |
|--------------------|--------------------------------|----------------|--------------|
| ap-south-2         | -                              | -              | -            |
| ap-south-1         | management-events              | True           |              |
| eu-south-1         | -                              | -              | -            |
| eu-south-2         | -                              | -              | -            |
| me-central-1       | -                              | -              | -            |
| il-central-1       | -                              | -              | -            |
| ca-central-1       | management-events              | True           |              |
| mx-central-1       | -                              | -              | -            |
| eu-central-1       | management-events              | True           |              |
| eu-central-2       | -                              | -              | -            |
| us-west-1          | management-events              | True           |              |
| us-west-2          | management-events              | True           |              |
| af-south-1         | -                              | -              | -            |
| eu-north-1         | management-events              | True           |              |
| eu-west-3          | management-events              | True           |              |
| eu-west-2          | management-events              | True           |              |
| eu-west-1          | management-events              | True           |              |
| ap-northeast-3     | management-events              | True           |              |
| ap-northeast-2     | management-events              | True           |              |
| me-south-1         | -                              | -              | -            |
| ap-northeast-1     | management-events              | True           |              |
| sa-east-1          | management-events              | True           |              |
| ap-east-1          | -                              | -              | -            |
| ca-west-1          | -                              | -              | -            |
| ap-southeast-1     | management-events              | True           |              |
| ap-southeast-2     | management-events              | True           |              |
| ap-southeast-3     | -                              | -              | -            |
| ap-southeast-4     | -                              | -              | -            |
| us-east-1          | management-events              | True           | True         |
| ap-southeast-5     | -                              | -              | -            |
| us-east-2          | management-events              | True           |              |
| ap-southeast-7     | -                              | -              | -            |
~ $ 

いいですね!バージニア北部リージョン(us-east-1)で組織レベルの証跡が有効になっていて、オプトインリージョンに証跡が存在することが確認できました。
この場合、バージニア北部リージョン(us-east-1)で組織レベルの証跡を削除すれば、全リージョンで証跡が無効になります。

おわりに

本記事への質問やご要望については画面下部のお問い合わせ「DevelopersIO について」からご連絡ください。記事に関してお問い合わせいただけます。

参考

https://dev.classmethod.jp/articles/registering-an-existing-account-in-control-tower/

https://dev.classmethod.jp/articles/costs-cloudtrail-after-update-ct-landing-zone/

https://dev.classmethod.jp/articles/get-aws-cloudtrail-trail-status-etc-from-all-regions/

https://dev.classmethod.jp/articles/cloudtrail-multiregiontrail/

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.