CloudFront一覧 を抽出する
1. はじめに
こんにちは。クラスメソッドオペレーションズのあのふじたです。
最近、CloudFrontのパスパターンごとのオリジンを含む一覧を出力する必要があったので備忘録として記事を書こうと思います。
2. 利用するAWS CLI と公式リファレンス
-
aws cloudfront list-distributions(一覧取得)
- https://docs.aws.amazon.com/cli/latest/reference/cloudfront/list-distributions.html
- 各アカウントの CloudFront ディストリビューション一覧(ID・ドメイン・ステータス・オリジン・ビヘイビアなど)を取得するために利用します。
-
aws cloudfront list-tags-for-resource(タグ取得)
- https://docs.aws.amazon.com/cli/latest/reference/cloudfront/list-tags-for-resource.html
list-distributionsのレスポンスにはタグ情報が含まれていないため、別途取得する必要があります。- CloudFront のタグは「リソース単位(ARN指定)」でしか取得できない仕様のため、ディストリビューションごとにループして1件ずつ呼び出しています。
3. 実装ステップ
具体的には、以下のステップで進めていきます。
- 取得先のプロファイルをあらかじめ外部ファイル(
profile_list.txt)から読み込み、リストで保持。 - プロファイルごとに
aws sts get-caller-identityでアカウントIDを取得し、あわせて認証の疎通確認を行う。 aws cloudfront list-distributionsでプロファイルを指定し、ディストリビューション一覧(オリジン・ビヘイビア含む)を取得。- ディストリビューション一覧からARNを抜き出し、
aws cloudfront list-tags-for-resourceを利用してディストリビューション別のタグを取得し「ARN→タグ文字列」のJSONマップとして保持。 - 取得したディストリビューション一覧を
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月 アノテーション㈱から社名変更しました。





