Root Access Management で AWS におけるメンバーアカウントのルートユーザーの認証情報を削除してみた
こんにちは、CSC の平木です!
今回は、昨年 11 月頃に登場した Root Access Management を用いてルートユーザーの認証情報を削除する手順を確認してみたいと思います。
早速やってみた
Root Access Management の有効化
まずは機能の有効化を実施します。
Organizations の管理アカウントにログインします。
権限があればルートユーザーではなく IAM ユーザーで問題ないです。
必要な権限は下記ドキュメントの前提条件をご確認ください。
ログイン後、 IAM へ遷移し、ナビゲーションペインからルートアクセス管理を押し、「有効化」を押します。
機能欄の「ルート認証情報管理」と「メンバーアカウントでの特権ルートアクション」にチェックを入れます。
また、必要に応じて委任管理アカウントに指定したいアカウント ID を入力し「有効化」を押します。
成功のログが出たら機能の有効化は完了です。
ルートユーザーの認証情報の削除
続いて認証情報を削除します。
削除したい対象のアカウントを選択し、「特権的なアクションを実行する」を押します。
特権的なアクションにて「ルートユーザー認証情報を削除」を押し、橙の「ルートユーザー認証情報を削除」を押します。
内容を確認し、問題なければ「削除」をクリックします。
成功のメッセージが出れば完了です。
ルートユーザーのパスワードの再設定を許可したい場合
なんらかの理由でやはりルートユーザーのログインを許可したいケースもあるかと思います。
その場合、次の設定を行うことでパスワードの再設定ができるようになります。
再設定したいアカウントを選択し、「特権的なアクションを実行する」を押します。
特権的なアクションにて「パスワード許可を回復」を押し、橙の「パスワード許可を回復」を押します。
以上で完了です。
AWS CLI で一括でルートユーザーの認証情報を削除したい場合
AWS CLI でも実行可能です。
account_id.list
に対象のアカウント ID をリストで記載し、同じディレクトリでスクリプトを実行してください。
こちらは、既に機能有効化済みかつ管理アカウントまたは委任管理アカウントの CloudShell での実行を想定しています。
削除を実行したいアカウント ID をまずaccount_id.list
に記載してください。
111122223333
222233334444
333344445555
下記が実際のスクリプトです。
削除実行時には必ず確認プロンプトが表示されます。実行に問題がなければ「Y」を、問題がある場合は「n」または「Y以外」のキーを押してください。
#!/bin/bash
# ==============================================================================
# 設定変数
# ==============================================================================
# 対象アカウント ID リストファイル
ACCOUNT_LIST_FILE="account_id.list"
# assume-root を実行するリージョン
AWS_REGION="us-east-1"
# アクセスキーのリストと削除、MFA/パスワードの削除をカバーするポリシー
TASK_POLICY_ARN="arn:aws:iam::aws:policy/root-task/IAMDeleteRootUserCredentials"
# ==============================================================================
# ヘルパー関数: 削除確認
# ==============================================================================
# ユーザーに y/n で確認を求め、n が入力されたら処理をスキップする
confirm_deletion() {
local prompt_message="$1"
local response
read -r -p "${prompt_message} (y/n): " response </dev/tty
if [[ "$response" =~ ^[Yy]$ ]]; then
return 0 # 0 は成功(削除実行)
else
echo " -> スキップしました。"
return 1 # 1 は失敗(削除スキップ)
fi
}
# ==============================================================================
# メイン処理: ファイルからアカウント ID を読み込みループ実行
# ==============================================================================
if [ ! -f "${ACCOUNT_LIST_FILE}" ]; then
echo "❌ ERROR: アカウントリストファイル (${ACCOUNT_LIST_FILE}) が見つかりません。"
exit 1
fi
# ファイルからアカウント ID を読み込み、ループ処理
while IFS= read -r MEMBER_ACCOUNT_ID || [ -n "$MEMBER_ACCOUNT_ID" ]; do
# 空行またはコメント行をスキップ
if [[ -z "$MEMBER_ACCOUNT_ID" || "$MEMBER_ACCOUNT_ID" =~ ^# ]]; then
continue
fi
echo "===================================================="
echo "▶️ 【アカウント ID: ${MEMBER_ACCOUNT_ID}】の処理を開始します。"
echo "===================================================="
# ----------------------------------------------------
# 1. assume-root コマンドを実行し、一時認証情報を取得
# ----------------------------------------------------
echo " ▶️ ルートセッションを確立します..."
ASSUME_ROOT_OUTPUT=$(aws sts assume-root \
--target-principal "arn:aws:iam::${MEMBER_ACCOUNT_ID}:root" \
--task-policy-arn "arn=${TASK_POLICY_ARN}" \
--region "${AWS_REGION}" \
--output json)
if [ $? -ne 0 ]; then
echo " ❌ ERROR: assume-root の実行に失敗しました。このアカウントはスキップします。"
# 環境変数が設定されるのを防ぐため、次のループへ
continue
fi
# 一時認証情報を環境変数にエクスポート
export AWS_ACCESS_KEY_ID=$(echo "${ASSUME_ROOT_OUTPUT}" | jq -r '.Credentials.AccessKeyId')
export AWS_SECRET_ACCESS_KEY=$(echo "${ASSUME_ROOT_OUTPUT}" | jq -r '.Credentials.SecretAccessKey')
export AWS_SESSION_TOKEN=$(echo "${ASSUME_ROOT_OUTPUT}" | jq -r '.Credentials.SessionToken')
echo " ✅ ルートセッション認証情報を取得しました。"
echo "----------------------------------------------------"
# ==============================================================================
# 2. 認証情報の参照と削除 (ルートユーザー特権として操作)
# ==============================================================================
# ----------------------------------
# 2-1. 署名証明書の削除 (1 番目)
# ----------------------------------
echo "--- 2-1. 署名証明書の削除 ---"
CERTIFICATES=$(aws iam list-signing-certificates --output json)
CERTIFICATE_IDS=$(echo "${CERTIFICATES}" | jq -r '.Certificates[].CertificateId')
if [ -z "${CERTIFICATE_IDS}" ]; then
echo " ☑️ 削除対象の署名証明書はありません。"
else
for CERT_ID in ${CERTIFICATE_IDS}; do
if confirm_deletion " - 証明書 ID: ${CERT_ID} を削除します。よろしいですか?"; then
aws iam delete-signing-certificate --certificate-id "${CERT_ID}"
if [ $? -eq 0 ]; then
echo " ✅ 署名証明書 ${CERT_ID} を削除しました。"
else
echo " ❌ 署名証明書 ${CERT_ID} の削除に失敗しました。"
fi
fi
done
fi
echo "----------------------------------------------------"
# ----------------------------------
# 2-2. アクセスキーの削除 (2 番目)
# ----------------------------------
echo "--- 2-2. アクセスキーの削除 ---"
ACCESS_KEYS=$(aws iam list-access-keys --output json)
KEY_IDS=$(echo "${ACCESS_KEYS}" | jq -r '.AccessKeyMetadata[].AccessKeyId')
if [ -z "${KEY_IDS}" ]; then
echo " ☑️ 削除対象のアクセスキーはありません。"
else
for KEY_ID in ${KEY_IDS}; do
if confirm_deletion " - アクセスキー ID: ${KEY_ID} を削除します。よろしいですか?"; then
aws iam delete-access-key --access-key-id "${KEY_ID}"
if [ $? -eq 0 ]; then
echo " ✅ アクセスキー ${KEY_ID} を削除しました。"
else
echo " ❌ アクセスキー ${KEY_ID} の削除に失敗しました。"
fi
fi
done
fi
echo "----------------------------------------------------"
# ----------------------------------
# 2-3. MFA デバイスの非アクティブ化 (3 番目)
# ----------------------------------
echo "--- 2-3. MFA デバイスの非アクティブ化 ---"
MFA_DEVICES=$(aws iam list-mfa-devices --output json)
MFA_SERIAL_NUMBERS=$(echo "${MFA_DEVICES}" | jq -r '.MFADevices[].SerialNumber')
if [ -z "${MFA_SERIAL_NUMBERS}" ]; then
echo " ☑️ 削除対象の MFA デバイスはありません。"
else
for SERIAL in ${MFA_SERIAL_NUMBERS}; do
if confirm_deletion " - MFA シリアル: ${SERIAL} を非アクティブ化します。よろしいですか?"; then
aws iam deactivate-mfa-device --serial-number "${SERIAL}"
if [ $? -eq 0 ]; then
echo " ✅ MFA デバイス ${SERIAL} を非アクティブ化しました。"
else
echo " ❌ MFA デバイス ${SERIAL} の非アクティブ化に失敗しました。"
fi
fi
done
fi
echo "----------------------------------------------------"
# ----------------------------------
# 2-4. ログインプロファイルの削除 (パスワードの削除) (4 番目)
# ----------------------------------
echo "--- 2-4. ログインプロファイルの削除 (パスワード) ---"
if confirm_deletion " - ルートユーザーのログインプロファイル(パスワード)を削除します。よろしいですか?"; then
aws iam delete-login-profile
if [ $? -eq 0 ]; then
echo " ✅ ログインプロファイル (パスワード) を削除しました。"
else
echo " ⚠️ ログインプロファイルの削除は失敗したか、最初から設定されていませんでした。"
fi
fi
echo "----------------------------------------------------"
# ----------------------------------
# 3. 環境変数のクリーンアップ
# ----------------------------------
unset AWS_ACCESS_KEY_ID
unset AWS_SECRET_ACCESS_KEY
unset AWS_SESSION_TOKEN
echo "✅ アカウント ${MEMBER_ACCOUNT_ID} の処理を完了しました。"
echo "===================================================="
done < "${ACCOUNT_LIST_FILE}"
echo "✅ すべてのアカウントに対する処理が完了しました。"
おわりに
今回は、Root Access Management によるメンバーアカウントのルートユーザーの認証情報の削除をやってみました。
Security Hubのコントロール「IAM.6」で頻繁に検出される仮想MFAに関する問題を、認証情報自体を持たないことで根本的に解決できます。
この記事がどなたかの役に立つと嬉しいです。
Discussion