CloudFront一覧 を抽出する

CloudFront一覧 を抽出する

2026.06.18

1. はじめに

こんにちは。クラスメソッドオペレーションズのあのふじたです。

最近、CloudFrontのパスパターンごとのオリジンを含む一覧を出力する必要があったので備忘録として記事を書こうと思います。

2. 利用するAWS CLI と公式リファレンス

3. 実装ステップ

具体的には、以下のステップで進めていきます。

  1. 取得先のプロファイルをあらかじめ外部ファイル(profile_list.txt)から読み込み、リストで保持。
  2. プロファイルごとに aws sts get-caller-identity でアカウントIDを取得し、あわせて認証の疎通確認を行う。
  3. aws cloudfront list-distributions でプロファイルを指定し、ディストリビューション一覧(オリジン・ビヘイビア含む)を取得。
  4. ディストリビューション一覧からARNを抜き出し、aws cloudfront list-tags-for-resource を利用してディストリビューション別のタグを取得し「ARN→タグ文字列」のJSONマップとして保持。
  5. 取得したディストリビューション一覧を jq で1回だけ処理し、オリジン(OriginId→DomainName)の逆引き・デフォルト/追加ビヘイビアの展開・タグマップの逆引きをまとめて行い、ビヘイビア単位でcsvファイルに保存。

必要なパッケージのインストール(動作確認した環境のみ)

jq Install
MacOS: brew install jq
Amzn2023: yum install jq

4. ファイル構成

.
├── get-all-cloudfront-list-with-origin.sh      # メインスクリプト
└── profile_list.txt           # プロファイル一覧

以下のような構成で実装しました。
スクリプトの構造設計やエラーハンドリング部分の実装にAIの支援を活用しました。

profile_list.txt

account_a
account_b
account_c
account_d

get-all-cloudfront-list-with-origin.sh

#!/bin/bash

# ==================================================
# CloudFront ディストリビューション一覧取得スクリプト
# (タグ・ビヘイビア・オリジン対応版)
# ==================================================

# ==================================================
# 設定: 外部ファイルパス
# ==================================================
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PROFILE_FILE="${SCRIPT_DIR}/profile_list.txt"
OUTPUT_FILE="${SCRIPT_DIR}/cloudfront_distribution_report.csv"

# ==================================================
# 外部ファイル存在チェック
# ==================================================
if [ ! -f "${PROFILE_FILE}" ]; then
  echo "エラー: ${PROFILE_FILE} が見つかりません" >&2
  exit 1
fi

# ==================================================
# 外部ファイル読み込み(空行・コメント行を除外)
# ==================================================
profile_list=()
while IFS= read -r line; do
  profile_list+=("$line")
done < <(grep -v -e '^\s*$' -e '^\s*#' "${PROFILE_FILE}")

# 読み込み件数チェック
if [ ${#profile_list[@]} -eq 0 ]; then
  echo "エラー: プロファイルが0件です" >&2
  exit 1
fi

echo "プロファイル数: ${#profile_list[@]}" >&2
echo "" >&2

# ==================================================
# AWS SSO ログインを実行する
# ==================================================
# echo "AWS SSO ログインを実行します..." >&2
# if ! aws sso login --sso-session xxx-sso; then
#  echo "エラー: SSO ログインに失敗しました" >&2
#  exit 1
# fi
# echo "" >&2

# ==================================================
# CSVヘッダー出力
# ==================================================
echo "Profile,AccountId,DistributionId,CloudFrontDomain,CustomDomains,PathPattern,ViewerProtocolPolicy,OriginId,OriginDomain,Status,Comment,Tags" > "${OUTPUT_FILE}"

# ==================================================
# 各プロファイルでCloudFront一覧を取得
# ==================================================
total_count=0

for profile in "${profile_list[@]}"; do
  echo "処理中: ${profile}" >&2

  # アカウントID取得
  if ! account_id=$(aws sts get-caller-identity --profile "${profile}" --query "Account" --output text 2>/dev/null) \
     || [ -z "${account_id}" ] || [ "${account_id}" = "None" ]; then
    echo "  警告: ${profile} の認証に失敗しました。スキップします。" >&2
    echo "${profile},ERROR,,,,,,,,,," >> "${OUTPUT_FILE}"
    continue
  fi

  echo "  アカウントID: ${account_id}" >&2

  # CloudFront ディストリビューション一覧取得
  if ! distributions=$(aws cloudfront list-distributions \
    --profile "${profile}" \
    --output json 2>&1); then
    echo "  警告: ${profile} のCloudFront一覧取得に失敗しました。" >&2
    echo "  詳細: ${distributions}" >&2
    echo "${profile},${account_id},ERROR,,,,,,,,," >> "${OUTPUT_FILE}"
    continue
  fi

  # ディストリビューションが存在しない場合
  item_count=$(echo "${distributions}" | jq -r '.DistributionList.Items // [] | length')
  if [ "${item_count}" = "0" ]; then
    echo "  ディストリビューションなし" >&2
    echo "${profile},${account_id},,,,,,,,(ディストリビューションなし),," >> "${OUTPUT_FILE}"
    continue
  fi

  echo "  ディストリビューション数: ${item_count}" >&2
  total_count=$((total_count + item_count))

  # 各ディストリビューションを処理
  echo "${distributions}" | jq -c '.DistributionList.Items[]' | \
  while IFS= read -r dist; do

    # 基本情報抽出
    arn=$(echo "${dist}" | jq -r '.ARN')
    dist_id=$(echo "${dist}" | jq -r '.Id')
    domain=$(echo "${dist}" | jq -r '.DomainName')
    aliases=$(echo "${dist}" | jq -r '(.Aliases.Items // []) | join(";")')
    status=$(echo "${dist}" | jq -r '.Status')
    comment=$(echo "${dist}" | jq -r '.Comment // ""')

    # タグ取得
    if ! tags_json=$(aws cloudfront list-tags-for-resource \
      --resource "${arn}" \
      --profile "${profile}" \
      --output json 2>/dev/null); then
      tags_str="(タグ取得失敗)"
    else
      tags_str=$(echo "${tags_json}" | jq -r '
        (.Tags.Items // [])
        | if length == 0 then ""
          else map(.Key + "=" + .Value) | join(";")
          end
      ')
    fi

    # オリジン一覧をマップとして保持(OriginId -> DomainName)
    origins_map=$(echo "${dist}" | jq -c '[.Origins.Items[] | {(.Id): .DomainName}] | add // {}')

    # デフォルトビヘイビア出力
    default_behavior=$(echo "${dist}" | jq -c '.DefaultCacheBehavior')
    default_origin_id=$(echo "${default_behavior}" | jq -r '.TargetOriginId')
    default_viewer_protocol=$(echo "${default_behavior}" | jq -r '.ViewerProtocolPolicy')
    default_origin_domain=$(echo "${origins_map}" | jq -r --arg oid "${default_origin_id}" '.[$oid] // ""')

    jq -nr --arg profile "${profile}" \
            --arg account_id "${account_id}" \
            --arg dist_id "${dist_id}" \
            --arg domain "${domain}" \
            --arg aliases "${aliases}" \
            --arg path "*(Default)" \
            --arg viewer "${default_viewer_protocol}" \
            --arg origin_id "${default_origin_id}" \
            --arg origin_domain "${default_origin_domain}" \
            --arg status "${status}" \
            --arg comment "${comment}" \
            --arg tags "${tags_str}" \
      '[$profile, $account_id, $dist_id, $domain, $aliases, $path, $viewer, $origin_id, $origin_domain, $status, $comment, $tags] | @csv' >> "${OUTPUT_FILE}"

    # 追加ビヘイビア出力(CacheBehaviors)
    cache_behaviors_count=$(echo "${dist}" | jq -r '.CacheBehaviors.Items // [] | length')
    if [ "${cache_behaviors_count}" != "0" ]; then
      echo "${dist}" | jq -c '.CacheBehaviors.Items[]' | \
      while IFS= read -r behavior; do
        path_pattern=$(echo "${behavior}" | jq -r '.PathPattern')
        viewer_protocol=$(echo "${behavior}" | jq -r '.ViewerProtocolPolicy')
        origin_id=$(echo "${behavior}" | jq -r '.TargetOriginId')
        origin_domain=$(echo "${origins_map}" | jq -r --arg oid "${origin_id}" '.[$oid] // ""')

        jq -nr --arg profile "${profile}" \
                --arg account_id "${account_id}" \
                --arg dist_id "${dist_id}" \
                --arg domain "${domain}" \
                --arg aliases "${aliases}" \
                --arg path "${path_pattern}" \
                --arg viewer "${viewer_protocol}" \
                --arg origin_id "${origin_id}" \
                --arg origin_domain "${origin_domain}" \
                --arg status "${status}" \
                --arg comment "${comment}" \
                --arg tags "${tags_str}" \
          '[$profile, $account_id, $dist_id, $domain, $aliases, $path, $viewer, $origin_id, $origin_domain, $status, $comment, $tags] | @csv' >> "${OUTPUT_FILE}"
      done
    fi

  done

done

# ==================================================
# 完了メッセージ
# ==================================================
echo "" >&2
echo "================================================" >&2
echo "処理完了" >&2
echo "総ディストリビューション数: ${total_count}" >&2
echo "出力ファイル: ${OUTPUT_FILE}" >&2
echo "================================================" >&2

5. 実行イメージ

プロファイル数: 4

処理中: account_a
  アカウントID: 123456789012
  ディストリビューション数: 11
処理中: account_b
  アカウントID: 234567890123
  ディストリビューション数: 12
処理中: account_c
  アカウントID: 345678901234
  ディストリビューション数: 13
処理中: account_d
  アカウントID: 456789012345
  ディストリビューション数: 14

================================================
処理完了
総ディストリビューション数: 50
出力ファイル: /home/ec2-user/cloudfront_distribution_report.csv

出力イメージ

Profile,AccountId,DistributionId,CloudFrontDomain,CustomDomains,PathPattern,ViewerProtocolPolicy,OriginId,OriginDomain,Status,Comment,Tags
"account_a","123456789012","ABCDEFGHIJKLM","abcdefghijklm.cloudfront.net","","*(Default)","redirect-to-https","s3origin-a","example-bucket-a.s3.amazonaws.com","Deployed","Test","Tag Group=AAA-AAA"
"account_a","123456789012","BCDEFGHIJKLMN","bcdefghijklmn.cloudfront.net","","*(Default)","redirect-to-https","s3origin-b","example-bucket-b.s3.amazonaws.com","Deployed","Prod","Tag Group=BBB-BBB"
"account_a","123456789012","BCDEFGHIJKLMN","bcdefghijklmn.cloudfront.net","","/login*","redirect-to-https","s3origin-b","example-bucket-b.s3.amazonaws.com","Deployed","Prod","Tag Group=BBB-BBB"
"account_a","123456789012","CDEFGHIJKLMNO","cdefghijklmno.cloudfront.net","","*(Default)","https-only","Custom-origin-c","api-c.example.com","Deployed","API","Tag Group=CCC-CCC"
"account_a","123456789012","DEFGHIJKLMNOP","defghijklmnop.cloudfront.net","","*(Default)","https-only","Custom-origin-d","api-d.example.com","Deployed","ProdAPI","Tag Group=DDD-DDD"
"account_a","123456789012","EFGHIJKLMNOPQ","efghijklmnopq.cloudfront.net","","*(Default)","redirect-to-https","s3origin-e","example-bucket-e.s3.amazonaws.com","Deployed","s3","Tag Group=EEE-EEE"

6. 最後に

オリジンの脆弱性等が心配な場合は全ての洗い出しを行うこともあるかもしれません。
このブログがどなたかの役に立てば幸いです。

クラスメソッドオペレーションズ株式会社について

クラスメソッドグループのオペレーション企業です。

運用・保守開発・サポート・情シス・バックオフィスの専門チームが、IT・AIをフル活用した「しくみ」を通じて、お客様の業務代行から課題解決や高付加価値サービスまでを提供するエキスパート集団です。

当社は様々な職種でメンバーを募集しています。

「オペレーション・エクセレンス」と「らしく働く、らしく生きる」を共に実現するカルチャー・しくみ・働き方にご興味がある方は、クラスメソッドオペレーションズ株式会社 コーポレートサイト をぜひご覧ください。※2026年1月 アノテーション㈱から社名変更しました。

この記事をシェアする

関連記事