IAMグループとIAMユーザー設定を視覚化するスクリプトを作ってみた

記事タイトルとURLをコピーする

こんにちは!
エンタープライズクラウド部技術2課の日高です。

今回は「IAMグループとIAMユーザー設定を視覚化するスクリプト」を作成したので、そちらについてブログを記載しようと思います。

はじめに

最近、多くのお客様から以下のようなお悩みをいただいています。

  • AWSで運用を開始してからある程度の時間が経過し、現在はIAMユーザーやIAMポリシーが増えてしまい、これらが散乱している状態。そのため統制が十分に取れておらず、管理が困難になっている。
  • 現状どのような設定になっているかを一括で確認したい。

このような状態はセキュリティインシデントを引き起こす大きなリスクを伴います。
そのため、IAMグループとIAMユーザーの現状の設定を視覚化できるスクリプトを作成してみました。

本ブログで作成したスクリプトについて解説していきます。

前提と作成したスクリプト解説

前提

  • AWS CLIがインストールされている
  • スイッチロールできる設定が済まされている(AWS CLI の設定 (~/.aws/config ファイル) にて、ロールの情報が設定されている)
  • 実行環境のOSがMacOS

※スイッチロールではなく、デフォルトに設定されているアカウントでスクリプトを実行したい場合は、スクリプトの「PROFILE="指定してください"」と「--profile $PROFILE」を削除して利用してください。

また、筆者の実行環境(OSとシェル)は以下です。

% sw_vers
ProductName:        macOS
ProductVersion:     14.0
BuildVersion:       23A344

% bash --version
GNU bash, version 3.2.57(1)-release (arm64-apple-darwin23)
Copyright (C) 2007 Free Software Foundation, Inc.

作成したスクリプト

このスクリプトは、指定したAWSアカウントに関するIAMの詳細をマークダウンの表形式で出力します。

具体的には、IAMグループの情報として、そのグループに関連付けられているIAMユーザー、管理ポリシー(AWS管理ポリシーとカスタムポリシーの両方)、そしてインラインポリシーを把握できます。
さらに、IAMユーザーの詳細に関しても、該当ユーザーが関連しているIAMグループ、管理ポリシー、インラインポリシーの他、マネジメントコンソールやAWS CLIへのアクセス許可、そして多要素認証(MFA)の設定状況も確認できるようになっています。

#!/bin/bash -eu

PROFILES=("指定してください" "指定してください" ....n ) # この配列にプロファイル名を追加してください。

get_group_info() {
    local profile="$1"
    local group="$2"

    users=$(aws iam get-group --profile "$profile" --group-name "$group" --query "Users[].[UserName]" --output text | tr '\n' ',' | sed 's/,$//')
    managed_policies=$(aws iam list-attached-group-policies --profile "$profile" --group-name "$group" --query "AttachedPolicies[].[PolicyName]" --output text | tr '\n' ',' | sed 's/,$//')
    inline_policies=$(aws iam list-group-policies --profile "$profile" --group-name "$group" --query "PolicyNames[]" --output text | tr '\n' ',' | sed 's/,$//')

    echo "| $group | [$users](mailto:$users) | $managed_policies | $inline_policies |"
}

get_user_info() {
    local profile="$1"
    local user="$2"

    groups=$(aws iam list-groups-for-user --profile "$profile" --user-name "$user" --query "Groups[].[GroupName]" --output text | tr '\n' ',' | sed 's/,$//')
    managed_policies=$(aws iam list-attached-user-policies --profile "$profile" --user-name "$user" --query "AttachedPolicies[].[PolicyName]" --output text | tr '\n' ',' | sed 's/,$//')
    inline_policies=$(aws iam list-user-policies --profile "$profile" --user-name "$user" --query "PolicyNames[]" --output text | tr '\n' ',' | sed 's/,$//')

    login_profile=$(aws iam get-login-profile --profile "$profile" --user-name "$user" --query "LoginProfile.UserName" --output text 2>/dev/null)
    if [ "$login_profile" == "$user" ]; then
        console_access="Yes"
    else
        console_access="No"
    fi

    access_keys=$(aws iam list-access-keys --profile "$profile" --user-name "$user" --query "AccessKeyMetadata[?Status=='Active'].[AccessKeyId]" --output text)
    if [ -z "$access_keys" ]; then
        cli_access="No"
    else
        cli_access="Yes"
    fi

    mfa_devices=$(aws iam list-mfa-devices --profile "$profile" --user-name "$user" --query "MFADevices[].[SerialNumber]" --output text)
    if [ -z "$mfa_devices" ]; then
        mfa_status="Not Enabled"
    else
        mfa_status="Enabled"
    fi

    echo "| $user | $groups | $managed_policies | $inline_policies | $console_access | $cli_access | $mfa_status |"
}

export -f get_group_info
export -f get_user_info

for PROFILE in "${PROFILES[@]}"; do

    OUTPUT_FILE="${PROFILE}_iam_assessment.md"

    {
    echo "## IAM Groups for $PROFILE"
    echo "| Group Name | Users | Managed Policy | Inline Policy |"
    echo "| :---: | :---: | :---: | :---: |"
    aws iam list-groups --profile "$PROFILE" --query "Groups[].[GroupName]" --output text | xargs -I {} bash -c 'get_group_info "$0" "$1"' "$PROFILE" "{}"
    
    echo ""
    echo "## IAM Users for $PROFILE"
    echo "| User Name | IAM Groups | Managed Policy | Inline Policy | Management Console Access | CLI Access | MFA Status |"
    echo "| :---: | :---: | :---: | :---: | :---: | :---: | :---: |"
    aws iam list-users --profile "$PROFILE" --query "Users[].[UserName]" --output text | xargs -I {} bash -c 'get_user_info "$0" "$1"' "$PROFILE" "{}"
    } > $OUTPUT_FILE

    echo "IAM assessment for $PROFILE saved to $OUTPUT_FILE"

done

利用方法

準備

  • 上記のスクリプトを実行するフォルダ配下に作成する。

※この際PROFILESはご自身が実行したいものに書き換えてください。

実行コマンド

  • 下記コマンドを実行します。
  • bash <保存時のスクリプト名>
    • 私の場合は「assessment-iam.sh」で保存しているのでbash assessment-iam.shが実行コマンドになります。

スクリプトの実行結果

Typoraというテキストエディタでマークダウン形式からテキスト形式に変換して出力していますが以下のようになります。

上記のように、IAMグループの情報として、そのグループに関連付けられているIAMユーザー、管理ポリシー(AWS管理ポリシーとカスタムポリシーの両方)、そしてインラインポリシーを把握できます。

さらに、IAMユーザーの詳細に関しても、該当ユーザーが関連しているIAMグループ、管理ポリシー、インラインポリシーの他、マネジメントコンソールやAWS CLIへのアクセス許可、そして多要素認証(MFA)の設定状況も確認することができます。

スクリプトの詳細

下記でスクリプトの解説をします。

1. シェバングとオプション

#!/bin/bash -eu

シェルスクリプト: この行はシェバングと呼ばれるもので、スクリプトを実行する際のシェルをbashとして指定しています。-euオプションは、スクリプト内でエラーが発生したり未定義の変数が使われた時にスクリプトを終了させるためのものです。

2. プロファイルの定義

PROFILES=("指定してください" "指定してください" ....n ) 

シェルスクリプト: AWS CLIのプロファイル名を格納する配列を定義しています。ユーザーはこの配列に独自のプロファイル名を追加することが期待されています。

3. IAMグループの情報を取得する関数

get_group_info() {

シェルスクリプト: get_group_info関数の定義を開始しています。この関数はIAMグループに関連する情報を取得します。

4. 引数の受け取り

local profile="$1"
local group="$2"

シェルスクリプト: 関数に渡された2つの引数(AWS CLIのプロファイル名とIAMグループ名)をローカル変数に代入しています。

5. グループに関連付けられたユーザーの取得

users=$(aws iam get-group --profile "$profile" --group-name "$group" --query "Users[].[UserName]" --output text | tr '\n' ',' | sed 's/,$//')

AWS CLI: aws iam get-groupコマンドを使用して、指定されたプロファイルとグループ名でIAMグループに関連付けられたユーザーのリストを取得しています。

シェルスクリプト: 続いて、trsedコマンドを用いて、取得したユーザーのリストをカンマで区切り、末尾のカンマを削除しています。

6. グループにアタッチされた管理ポリシーの取得

managed_policies=$(aws iam list-attached-group-policies --profile "$profile" --group-name "$group" --query "AttachedPolicies[].[PolicyName]" --output text | tr '\n' ',' | sed 's/,$//')

AWS CLI: aws iam list-attached-group-policiesコマンドを使用して、指定されたプロファイルとグループ名でIAMグループにアタッチされている管理ポリシーのリストを取得しています。

シェルスクリプト: ユーザーの取得と同様に、ポリシーのリストをカンマで区切り、末尾のカンマを削除しています。

7. グループのインラインポリシーの取得

inline_policies=$(aws iam list-group-policies --profile "$profile" --group-name "$group" --query "PolicyNames[]" --output text | tr '\n' ',' | sed 's/,$//')

AWS CLI: aws iam list-group-policiesコマンドを使用して、指定されたプロファイルとグループ名でIAMグループに関連するインラインポリシーのリストを取得しています。

シェルスクリプト: これも同様に、ポリシーのリストをカンマで区切り、末尾のカンマを削除しています。

8. 取得した情報の出力

echo "| $group | [$users](mailto:$users) | $managed_policies | $inline_policies |"

シェルスクリプト: 前述の変数を使用して、マークダウン形式のテーブル行を出力しています。ユーザー名はメールリンクとしてフォーマットされています。

9. IAMユーザーの情報を取得する関数

get_user_info() {

シェルスクリプト: get_user_info関数の定義を開始しています。この関数はIAMユーザーに関連する情報を取得します。

10. 引数の受け取り

local profile="$1"
local user="$2"

シェルスクリプト: 関数に渡された2つの引数(AWS CLIのプロファイル名とIAMユーザー名)をローカル変数に代入しています。

11. ユーザーが所属するグループの取得

groups=$(aws iam list-groups-for-user --profile "$profile" --user-name "$user" --query "Groups[].[GroupName]" --output text | tr '\n' ',' | sed 's/,$//')

AWS CLI: aws iam list-groups-for-userコマンドを使用して、指定されたプロファイルとユーザー名でIAMユーザーが所属するグループのリストを取得しています。 シェルスクリプト: これも、グループのリストをカンマで区切り、末尾のカンマを削除しています。

12. ユーザーにアタッチされた管理ポリシーの取得

managed_policies=$(aws iam list-attached-user-policies --profile "$profile" --user-name "$user" --query "AttachedPolicies[].[PolicyName]" --output text | tr '\n' ',' | sed 's/,$//')

AWS CLI: aws iam list-attached-user-policiesコマンドを使用して、指定されたプロファイルとユーザー名でIAMユーザーにアタッチされている管理ポリシーのリストを取得しています。 シェルスクリプト: 同様に、ポリシーのリストをカンマで区切り、末尾のカンマを削除しています。

13. ユーザーのインラインポリシーの取得

inline_policies=$(aws iam list-user-policies --profile "$profile" --user-name "$user" --query "PolicyNames[]" --output text | tr '\n' ',' | sed 's/,$//')

AWS CLI: aws iam list-user-policiesコマンドを使用して、指定されたプロファイルとユーザー名でIAMユーザーに関連するインラインポリシーのリストを取得しています。 シェルスクリプト: これも、ポリシーのリストをカンマで区切り、末尾のカンマを削除しています。

14. ユーザーのマネジメントコンソールへのアクセス許可の確認

login_profile=$(aws iam get-login-profile --profile "$profile" --user-name "$user" --query "LoginProfile.UserName" --output text 2>/dev/null)

AWS CLI: aws iam get-login-profileコマンドを使用して、指定されたプロファイルとユーザー名でIAMユーザーのログインプロファイルを取得しています。この情報を使用して、ユーザーがAWSマネジメントコンソールへのアクセス権を持っているかどうかを確認します。

if [ "$login_profile" == "$user" ]; then
    console_access="Yes"
else
    console_access="No"
fi

シェルスクリプト: get-login-profileコマンドの結果を確認して、ユーザーがマネジメントコンソールにアクセスできるかどうかを判断しています。

15. ユーザーのAWS CLIへのアクセス許可の確認

access_keys=$(aws iam list-access-keys --profile "$profile" --user-name "$user" --query "AccessKeyMetadata[?Status=='Active'].[AccessKeyId]" --output text)

AWS CLI: aws iam list-access-keysコマンドを使用して、指定されたプロファイルとユーザー名でIAMユーザーのアクセスキーを取得しています。

if [ -z "$access_keys" ]; then
    cli_access="No"
else
    cli_access="Yes"
fi

シェルスクリプト: 取得したアクセスキーの有無を確認して、ユーザーがAWS CLIにアクセスできるかどうかを判断しています。

16. ユーザーのMFA (多要素認証) の設定状況の確認

mfa_devices=$(aws iam list-mfa-devices --profile "$profile" --user-name "$user" --query "MFADevices[].[SerialNumber]" --output text)

AWS CLI: aws iam list-mfa-devicesコマンドを使用して、指定されたプロファイルとユーザー名でIAMユーザーのMFAデバイスを取得しています。

if [ -z "$mfa_devices" ]; then
    mfa_status="Not Enabled"
else
    mfa_status="Enabled"
fi

シェルスクリプト: 取得したMFAデバイスの有無を確認して、ユーザーがMFAを有効にしているかどうかを判断しています。

17. 取得した情報の出力

echo "| $user | $groups | $managed_policies | $inline_policies | $console_access | $cli_access | $mfa_status |"

シェルスクリプト: 前述の変数を使用して、マークダウン形式のテーブル行を出力しています。

18. 関数のエクスポート

export -f get_group_info
export -f get_user_info

シェルスクリプト: 現在のシェルセッションに関数をエクスポートしています。これにより、xargs経由でのサブシェルからもこれらの関数を呼び出すことができます。

19. メインの処理部分

for PROFILE in "${PROFILES[@]}"; do

シェルスクリプト: PROFILES配列に格納されている各プロファイルに対してループ処理を開始しています。

20. 出力ファイル名の設定

OUTPUT_FILE="${PROFILE}_iam_assessment.md"

シェルスクリプト: 各プロファイルに対する出力ファイル名を設定しています。

21-30. IAMの情報の取得とファイルへの出力

{
...
} > $OUTPUT_FILE

シェルスクリプト: {...}ブロック内のコマンドの出力を$OUTPUT_FILEにリダイレクトしています。このブロック内では、前述のget_group_infoおよびget_user_info関数を使用してIAMの情報を取得し、マークダウン形式で出力しています。

31. 処理終了の通知

echo "IAM assessment for $PROFILE saved to $OUTPUT_FILE"

シェルスクリプト: 各プロファイルに対するIAMの評価結果がどのファイルに保存されたかを通知しています。

まとめ

権限整理をする際などにご利用いただけると嬉しいです。
本ブログが誰かの助けになっていれば幸いです。

日高 僚太(執筆記事の一覧)

EC部ソリューションアーキテクト2課 / AWS認定資格 12冠

2022年IT未経験で新卒入社しました。
最近はダーツとサウナが気になっています!
記事に関するお問い合わせや修正依頼⇒ hidaka@serverworks.co.jp