一覧に戻る
    「誰が作ったかわからない」IAMユーザーを調査する──CloudTrailの保持期限という壁にぶつかった話
    開発ラボ
    PRこの記事には広告が含まれています

    「誰が作ったかわからない」IAMユーザーを調査する──CloudTrailの保持期限という壁にぶつかった話

    14 分で読める

    ある日、社内の AWS アカウントに「誰がいつ何のために作ったかわからない」IAM ユーザーが存在していることに気づきました。

    こういうの、ありますよね。気づいたら存在しているやつ。タグもない、ドキュメントもない、Slack を検索しても該当する会話が出てこない。

    「放置するのは怖い、でも消すのも怖い」という板挟み状態で、まずは調査することにしました。Claude Code に相談しながらの作業ログをもとに、調査の経緯と学びを整理します。

    状況

    • ある IAM ユーザー(以下 external-service-user)が存在している
    • タグ情報なし
    • 作成者不明
    • アクセスキーが2本ある(どちらも有効)
    • 発行者も不明

    まずは「誰が作ったのか」を調べることにしました。

    調査1:まず CloudTrail を見に行く

    IAM ユーザーの作成者を調べるなら、CloudTrail の CreateUser イベントを見るのが定石です。

    # ユーザー情報の確認
    aws iam get-user --user-name external-service-user
    
    # CloudTrailでユーザー名を検索
    aws cloudtrail lookup-events \
      --lookup-attributes AttributeKey=ResourceName,AttributeValue=external-service-user \
      --max-results 50

    結果は "Events": []。空でした。

    タグも確認しましたが、こちらも空。「作成者を示す情報が何もない」状態です。

    調査2:CloudTrail のログ保持期限という壁

    なぜイベントが取れないのかを調べました。

    # CloudTrailのログ設定確認
    aws cloudtrail list-trails --region ap-northeast-1
    
    # CloudWatch Logsへの連携確認
    aws cloudtrail get-trail --name <trail-arn>

    ここで判明したのが、ログ保持期限の壁です。

    ログの保管場所保持期間状態
    CloudTrail イベント履歴90日期限切れ
    CloudWatch Logs設定次第(今回は77日)期限切れ
    S3 アーカイブ(Log Archive アカウント)長期権限なしでアクセス不可

    このユーザーの作成日は約7ヶ月前。90日保持の CloudTrail イベント履歴は当然期限切れ。CloudWatch Logs も77日設定で期限切れ。

    S3 にはアーカイブされているはずですが、今回は Log Archive アカウントという AWS Organizations 管理下の別アカウントに保存されており、現在の IAM ロールからはアクセス権限がありませんでした。

    AccessDenied: User is not authorized to perform s3:ListBucket

    グサッと刺さるエラーです。「ログはある、でも見えない」という状況。

    ここで気づいた重要な設計の話

    CloudTrail を使っていても、保持期間の設計を甘く見ると詰む、というのが今回の教訓の一つです。

    • CloudTrail イベント履歴(90日)は無料で自動有効。ただし90日で消える
    • S3 に長期保存するには CloudTrail を有効化して S3 バケットに出力する設定が必要
    • その S3 にアクセスできる権限設計も別途必要

    今回の構成では、Control Tower による集中ログ管理(Log Archive アカウント)がされていましたが、調査する側のアカウントからその S3 を見る権限がなかったというのが詰まったポイントです。

    調査3:アクセスキーの使用履歴から逆引きする

    作成者は特定できませんでした。しかし調査はまだ続きます。

    「誰が作ったか」はわからなくても、「今このキーがどこから使われているか」は調べられます。

    aws iam get-access-key-last-used --access-key-id <アクセスキーID>

    返ってきた情報:

    • 最終使用日時: 直近
    • サービス: S3
    • リージョン: ap-northeast-1(東京)

    動いてる。しかも最近。

    さらに CloudTrail でアクセスキー ID を軸に検索:

    aws cloudtrail lookup-events \
      --lookup-attributes AttributeKey=AccessKeyId,AttributeValue=<アクセスキーID>

    ここで面白い情報が出てきました。

    呼び出し元の情報:

    • 送信元 IP: 特定の IP レンジ(複数)
    • User-Agent: aws-sdk-dotnet-coreclr/3.7.304.5 (.NET_Core#8.0.24, Windows 10.0.20348.0)

    User-Agent があるとこんなことがわかります:

    • .NET アプリケーションから呼ばれている
    • Windows 10.0.20348 = Windows Server 2022
    • つまり Windows Server 2022 上で動く .NET アプリが実行している

    送信元 IP を IPinfo で調べたところ、特定のクラウドプロバイダーの東京リージョンの IP でした。

    呼び出しパターンも見えた

    CloudTrail を全件見ていくと、呼び出しパターンがはっきりしていました:

    • 毎週月曜 09:00 JST 頃に2回実行
    • 操作: s3:GetBucketAcl を特定の S3 バケットに対して
    • 結果: すべて AccessDenied

    90日分の履歴がすべてこのパターン。定期バッチが毎週月曜に動いていて、ずっと AccessDenied で失敗し続けている状態でした。

    権限がないため実際のデータアクセスは発生していない、でも使われ続けているキーです。

    アクセスキーの全体像

    調査で判明した内容を整理するとこうなりました。

    キー作成日最終使用状態
    1本目ユーザー作成と同日作成直後のみ7ヶ月未使用
    2本目2ヶ月後に追加発行直近(毎週月曜)定期使用中

    2本目のキーが追加発行されている点も気になります。「1本目でうまくいかなかったから追加した」という可能性が高いですが、その発行者も90日を超えているため特定できず。

    推奨対応:いきなり消さない

    ここで判断が難しかったのは、「消したい気持ちはあるが、動いているバッチがあるから消せない」という状況です。

    正直、このキーが何の目的で作られたかが最後までわからないまま調査を終えました。でも「すぐ消す」ではなく「段階的に対処する」という判断になりました。

    推奨した手順

    Step 1: 7ヶ月未使用の1本目のキーを Inactive 化
             → 低リスクで即実行可能
    
    Step 2: 外部サービスの担当者に連絡・確認
             → どのシステムが使っているか
             → GetBucketAcl が失敗しているのは想定内か
    
    Step 3: 新しいキーを発行して安全な方法(パスワードマネージャー等)で共有
    
    Step 4: 切り替え確認後、2本目を Inactive → 様子見 → Delete

    「すぐ困っていないなら最低限やるべきこと」として、未使用キーの Inactive 化と担当者への確認連絡だけでも先に動かすことを提案しました。

    キー管理に使える AWS のサービス

    調査の過程で整理した、IAM キー管理のための AWS サービスをまとめます。

    IAM Credential Report(全ユーザーの棚卸しに便利)

    # レポート生成
    aws iam generate-credential-report
    
    # 取得してデコード
    aws iam get-credential-report \
      --output text --query Content | base64 -d > credential_report.csv

    アカウント全体の IAM ユーザーとキーの状態を CSV で一覧出力できます。各ユーザーのキー作成日・最終使用日・MFA 有無が一度に見えるので、棚卸しにはこれが一番手軽です。

    4時間キャッシュされる点だけ注意です。

    IAM Access Analyzer - Unused Access

    • 指定日数以上未使用のアクセスキー・IAM ユーザー・ロールを自動検出
    • 今回の「7ヶ月未使用キー」のようなものをダッシュボードで可視化してくれる
    • 定期的な棚卸しを自動化したいならこれ

    AWS Config ルール

    マネージドルールを有効にするだけで検知できます:

    • access-keys-rotated: N日以上ローテーションされていないキーを検知
    • iam-user-unused-credentials-check: 未使用認証情報を検知

    SNS 通知や自動修復と組み合わせることも可能です。

    長期的には: IAM ロール + AssumeRole

    今回のような「外部サービスからの AWS アクセス」には、長期アクセスキーより IAM ロール + AssumeRole の構成が適しています。

    シークレットキーを相手に渡す必要がなくなり、「紛失したらどうするか」という問題自体がなくなります。外部 ID を使えばクロスアカウントでも制御できます。

    今回の学び

    調査してみて、あらためて整理できたことをまとめます。

    CloudTrail の保持期限を設計に組み込む

    90日で消える CloudTrail イベント履歴に頼るだけでは、半年後の調査には対応できません。S3 への長期保存設定と、その保存先へのアクセス権限設計が必要です。

    User-Agent は意外と情報量が多い

    .NET のバージョン、OS のビルド番号まで入っていることがあります。呼び出し元のシステムを推定する手がかりになります。

    「誰が作ったかわからないキー」を放置しない

    作成者・発行先・目的が不明な IAM キーは、漏洩リスクの観点でも管理上の観点でも好ましくないです。定期的な Credential Report による棚卸しと、IAM Access Analyzer の活用で、こういう「気づかない状態」を減らすことができます。

    「消す前に確認する」の重要性

    今回は「毎週月曜に使われているバッチがある」とわかってから止まりました。いきなり削除していたら外部サービス側のジョブに影響が出ていた可能性があります。影響範囲の確認を先にやる、というのはあたりまえに聞こえて、焦っているときに飛ばしがちです。

    最終的に「誰が作ったか」はわからないままでした。CloudTrail の壁は越えられませんでした。

    でも、「何が起きているか」「次に何をすべきか」は見えました。「わからない」を「わからないなりに整理する」作業は、地味ですが SRE っぽい仕事だと思います。

    参考

    AWS の運用設計や IAM・CloudTrail の実務的な使い方を体系的に学びたい方には、以下の書籍が参考になります。

    この記事は役に立ちましたか?

    Coffee cup

    この記事が、何かの整理につながったら

    コーヒー1杯分の応援をもらえると嬉しいです。

    ※ これは応援とは別の話ですが、

    同じようなテーマを自分の文脈で整理したい場合は、 (文章だけだと詰まりやすい人向けに) 思考整理の壁打ちという形で対話の時間も取っています。

    対話の時間について