GuardDutyが有効化されているリージョンを一発で把握できるCLIを作ってみた

全国のシェル職人から愛情たっぷりのマサカリ募集中です!
2022.02.09

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは!コンサル部のinomaso(@inomasosan)です。

GuardDutyはリージョン毎の有効化のため、AWSマネジメントコンソールで、どのリージョンを有効化したか確認しようとすると中々大変ですよね。

そこで、今回は一発でGuardDuty有効化の状況がわかるコマンドを、AWS CLIで作成してみました!

招待によるマルチアカウントのGurdDutyの通知を一つにまとめている場合についても、コマンドを用意してみましたので、まとめて共有していきます。

とりあえずコマンド

GuardDutyの有効化を確認したいAWSアカウントに対して、以下のコマンドどちらかを実行願います。
コマンドの実行結果や解説に興味のある方は、後続の内容をご一読願います。

AWSアカウント単体のGuardDuty有効化チェック

for REGION in `aws ec2 describe-regions \
    --query "sort(Regions[].RegionName)"  \
    --output text`
do
 DETECTOR_ID=$( \
    aws guardduty list-detectors \
        --region "${REGION}" \
        --query DetectorIds  \
        --output text \
    )
 if [ "${#DETECTOR_ID}" -ne "0" ] ; then
  echo "${REGION}:True:${DETECTOR_ID}"
 else
  echo "${REGION}:False:-"
 fi
done

招待によるマルチアカウントのGuardDuty有効化チェック

for REGION in `aws ec2 describe-regions \
    --query "sort(Regions[].RegionName)" \
    --output text`
do
 DETECTOR_ID=$( \
    aws guardduty list-detectors \
        --region "${REGION}" \
        --query DetectorIds \
        --output text \
    )
 echo "${REGION}"
 if [ "${#DETECTOR_ID}" -ne "0" ] ; then
  MEMBERS_RESULT=$( \
    aws guardduty list-members \
        --detector-id "${DETECTOR_ID}" \
        --query 'sort_by(Members[].{MemberaccountId:AccountId,DetectorId:DetectorId,Status:RelationshipStatus},&MemberaccountId)' \
        --region "${REGION}" \
        --output table \
    )
  if [ "${#MEMBERS_RESULT}" -ne "0" ] ; then
    echo "${MEMBERS_RESULT}"
  else
    echo "No Members"
  fi
 else
  echo "Disabled"
 fi
done

コマンド実行方法

コマンドを実行するためにはAWS CLIがインストールされた環境が必要です。

ローカル環境で用意すると、実行するためにIAMアクセスキー等も追加で必要となるため、管理を誤るとセキュリティリスクにつながってしまいます。

そこで今回はAWS CloudShellという、AWSマネジメントコンソール上でCLIを実行できるサービスをお勧めします! このサービスを利用すると、特にユーザ側の設定なしで最初からAWS CLIを実行することができます。

使い方等については、以下の再入門ブログをご参照願います。

GuardDutyの探知機ID(Detector ID)について

コマンドの内容を理解するために、GuardDutyの探知機ID(Detector ID)について解説していきます。

探知機ID(Detector ID)は、GuardDutyを有効化した各リージョンで作成される一意のIDとなります。 GuardDutyの全ての結果は探知機IDに関連付けられます。

また今回のようなGuardDutyのAPI操作のほとんどに探知機IDが必要となります。

GuardDutyコンソールの設定からも確認することができます。

コマンドの実行結果例と解説

AWSアカウント単体のGuardDuty有効化チェック

実行結果例

出力内容はリージョンGuardDuty有効の有無探知機IDとなります。

ap-northeast-1:True:123456789abcdefghijklmn
ap-northeast-2:False:-
ap-northeast-3:False:-
ap-south-1:False:-
ap-southeast-1:False:-
ap-southeast-2:False:-
ca-central-1:False:-
eu-central-1:False:-
eu-north-1:False:-
eu-west-1:False:-
eu-west-2:False:-
eu-west-3:False:-
sa-east-1:False:-
us-east-1:True:987654321nmlkjihgfedcba
us-east-2:False:-
us-west-1:False:-
us-west-2:False:-

コマンド解説

for REGION in `aws ec2 describe-regions \
    --query "sort(Regions[].RegionName)"  \
    --output text`

1~3行目はAWSアカウントで有効なリージョンを昇順で出力し、forでリージョンの数だけGuardDuty有効化チェックを繰り返すようにしています。
無効なリージョン含めて実行したい場合は--all-regionsオプションを追加して実行できますが、以下のようなエラーが返ってきます。

An error occurred (UnrecognizedClientException) when calling the ListDetectors operation: The security token included in the request is invalid


  DETECTOR_ID=$( \
    aws guardduty list-detectors \
        --region "${REGION}" \
        --query DetectorIds  \
        --output text \
    )

5~10行目はGuardDutyが有効化チェックとして、探知機ID(Detector ID)を出力します。

 if [ "${#DETECTOR_ID}" -ne "0" ] ; then
  echo "${REGION}:True:${DETECTOR_ID}"
 else
  echo "${REGION}:False:-"
 fi

11~15行目は、探知機ID(Detector ID)が存在すれば、${REGION}:True:${DETECTOR_ID}を、それ以外の場合は${REGION}:False:-をコンソールに出力します。

招待によるマルチアカウントのGuardDuty有効化チェック

実行結果例

各リージョン毎に以下のパターンに分けて出力しています。

パターン 出力内容
・管理アカウントでGuardDuty有効
・メンバーアカウントでGuardDutyが有効かつ、管理アカウントからの招待を承諾
メンバーアカウントの一覧を出力
・管理アカウントでGuardDuty有効
・全てのメンバーアカウントが管理アカウントからの招待を未承諾か、退会している
No Members
・管理アカウントでGuardDuty無効 Disabled
ap-northeast-1
--------------------------------------------------------------------
|                            ListMembers                           |
+-----------------------------------+-------------------+----------+
|            DetectorId             |  MemberaccountId  | Status   |
+-----------------------------------+-------------------+----------+
|  123456789010abcdefghijklmnopqrft |  123456789010     |  Enabled |
|  234567890123bcdefghijklmnopqrftu |  234567890123     |  Enabled |
+-----------------------------------+-------------------+----------+
ap-northeast-2
Disabled
ap-northeast-3
Disabled
ap-south-1
Disabled
ap-southeast-1
Disabled
ap-southeast-2
Disabled
ca-central-1
Disabled
eu-central-1
Disabled
eu-north-1
Disabled
eu-west-1
Disabled
eu-west-2
Disabled
eu-west-3
Disabled
sa-east-1
Disabled
us-east-1
No Members
us-east-2
Disabled
us-west-1
Disabled
us-west-2
Disabled


招待によるメンバーアカウント管理の場合、アカウントのステータス有効以外だとアカウント管理ができていない状態となります。

その場合、AWS CLIのaws guardduty list-detectorsで、メンバーアカウントの一覧を出力することができません。
原因については、以下のパターンが考えられるので、管理アカウントにて確認する必要があります。

ステータス 状態
招待 メンバーアカウント追加のみで、「招待」リンクから対象アカウントへ通知していない
招待済み メンバーアカウントを追加・招待したが、承諾されていない
メンバー退会済み メンバーアカウントで承諾されたが、その後解除された

コマンド解説

AWSアカウント単体のGuardDuty有効化チェックと重複する部分は、省略していきます。

    MEMBERS_RESULT=$( \
    aws guardduty list-members \
        --detector-id "${DETECTOR_ID}" \
        --query 'sort_by(Members[].{MemberaccountId:AccountId,DetectorId:DetectorId,Status:RelationshipStatus},&MemberaccountId)' \
        --region "${REGION}" \
        --output table \
    )

13~19行目は、管理アカウントから招待が承諾された全てのメンバーアカウントを、それぞれアカウントID探知機IDステータスについてアカウントIDをキーにして昇順で出力します。

  if [ "${#MEMBERS_RESULT}" -ne "0" ] ; then
    echo "${MEMBERS_RESULT}"
  else
    echo "No Members"
  fi

20~24行目は、有効なメンバーアカウントが存在する場合はコンソールに出力します。 管理アカウントのGuardDutyは有効でも、有効なメンバーアカウントが存在しない場合はNo Membersとコンソールに出力します。

 else
  echo "Disabled"
done

25~26行目は、管理アカウントのGuardDutyが無効な場合はDisabledとコンソールに出力します。

参考

併せて読みたい

まとめ

AWSリソースの構築はIaCをメインに利用してきたのですが、今回のような運用が目的の場合はAWS CLIは便利だと感じました。

この記事が、どなたかのお役に立てば幸いです。それでは!