目次
6 章

セキュリティ基本 — MFA、キーのローテーション、最小権限

ルートと IAM ユーザーの MFA 強制、アクセスキーのローテーション自動化、IAM Access Analyzer での権限点検、最小権限のパターン、そしてよく出会う事故事例まで — 運用で通用するセキュリティのガードレールを整理します。

第2章 IAM で権限モデルを、第5章 CloudShell と SSO で SSO ログインまで見ました。本章はその上に、運用で通用するセキュリティのガードレールをまとめて整理します。登録直後に必ず通るべき最初のセットアップの最後の軸です。

AWS のセキュリティ事故の大半は次のいずれかです。ルートやユーザーのパスワードが一度のフィッシングで奪取される場合(MFA がなくて)、アクセスキーが git / Slack / ログに漏洩する場合、あまりに広い権限が侵害時に被害を膨らませる場合、そして CloudTrail / GuardDuty がオフになっていて事件を発見できない場合です。

この4つにガードレールを敷けば、事故の確率が一桁に下がります。本章はそのガードレールを順に立てます。

MFA — 最も重要なもの #

パスワードだけで完結する認証は2026年の運用水準ではありません。一度のフィッシングでパスワードは流れます。MFA (Multi-Factor Authentication) は二つ目の要素(通常はスマートフォンアプリ)の6桁コードを追加で要求します。

MFA の種類 #

種類何か推奨
Virtual MFA (TOTP)スマートフォンアプリ (Google Authenticator、1Password、Authy)標準 — ほぼすべての場合
ハードウェア MFAYubiKey のような USB キールート / 高特権 — 最強
U2F / WebAuthnブラウザ + ハードウェアキー運用認証情報の格上げ
SMSテキストメッセージ使用禁止 (SIM swap 攻撃)

ルートはハードウェア MFA が理想的で、一般ユーザーは virtual MFA で十分です。

ルートユーザーの MFA を有効化 #

登録直後の最初の作業として即座に行います。

ルート MFA
コンソール (ルートログイン) → 右上のユーザーメニュー → Security credentials
→ Multi-factor authentication (MFA) → Assign MFA device
→ Virtual MFA / Hardware MFA を選択
→ QR コードをスマートフォンアプリでスキャン
→ 連続2つのコードを入力 (アプリが30秒ごとに新しいコード)

以後、ルートログインのたびにパスワード + 6桁コードを要求します。

IAM ユーザーに MFA を強制 #

ルートだけオンにするのは不足です。すべての IAM ユーザーに強制すべきです。2つの方法があります。

方法1: ポリシーで — 「MFA がオンのセッションでなければほぼすべてのアクションを拒否」です。

IAM ユーザーの MFA 強制ポリシー
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowSelfManageCredentials",
      "Effect": "Allow",
      "Action": [
        "iam:ChangePassword",
        "iam:CreateVirtualMFADevice",
        "iam:EnableMFADevice",
        "iam:GetUser",
        "iam:ListMFADevices",
        "iam:ResyncMFADevice"
      ],
      "Resource": [
        "arn:aws:iam::*:user/${aws:username}",
        "arn:aws:iam::*:mfa/${aws:username}"
      ]
    },
    {
      "Sid": "DenyAllExceptListedIfNoMFA",
      "Effect": "Deny",
      "NotAction": [
        "iam:CreateVirtualMFADevice",
        "iam:EnableMFADevice",
        "iam:GetUser",
        "iam:ListMFADevices",
        "iam:ResyncMFADevice",
        "iam:ChangePassword",
        "sts:GetSessionToken"
      ],
      "Resource": "*",
      "Condition": {
        "BoolIfExists": { "aws:MultiFactorAuthPresent": "false" }
      }
    }
  ]
}

このポリシーをすべてのユーザーが属するグループに付けると、MFA なしでは事実上何もできません。MFA の登録だけが例外です。

方法2: SSO第5章 CloudShell と SSO の IAM Identity Center のユーザーには、コンソール / CLI ログイン時に MFA が自動で強制されます。ポリシーを別に組まなくてよいです。

初回ログイン時の MFA 登録強制の流れ #

新規 IAM ユーザーが初めてログインすると、上のポリシーで MFA の登録以外は何もできません。自分の MFA を登録すれば、その後から正常に使えます。この流れが標準です。

アクセスキーのローテーション — 90日が標準 #

第4章 CLI と SDK で見たアクセスキーは、時間が経つと漏洩リスクが累積します。

ローテーションのポリシー #

項目推奨ローテーション周期
ユーザーのアクセスキー90日
CI / CD キー60日 (または OIDC へ転換)
サービスアカウントのキー30 ~ 60日
一時認証情報 (SSO / Role)ローテーション不要 (自動で短期発行)

ローテーションの手順 #

キーを一度に2つまで持てる IAM の特性を活用します。

安全なローテーションの手順
# 1) 新しいキーを発行 (これでアクティブキーが2個)
aws iam create-access-key --user-name curtis

# 2) すべての環境で新しいキーに交換 (CI 環境変数、~/.aws/credentials など)

# 3) 数日モニタリング — 古いキーの使用があるか
#    CloudTrail または IAM credential report で確認

# 4) 古いキーを無効化 (削除はまだ X — ロールバック用)
aws iam update-access-key --user-name curtis --access-key-id AKIA-OLD --status Inactive

# 5) もう一週間モニタリング → 本当に使わないなら削除
aws iam delete-access-key --user-name curtis --access-key-id AKIA-OLD

IAM Credential Report — ローテーションの点検 #

CSV 一枚ですべてのユーザーのキー / MFA / 活動状態を見ます。

Credential Report を受け取る
aws iam generate-credential-report
aws iam get-credential-report --query Content --output text | base64 -d > report.csv
report.csv の興味深いカラム
user
mfa_active
access_key_1_active
access_key_1_last_rotated
access_key_1_last_used_date
access_key_2_active
access_key_2_last_rotated
password_last_used

90日を超えたキー、MFA をオンにしていないユーザー、1ヶ月未使用のユーザーがひと目で分かります。

漏洩したキーを発見したとき #

コードにキーを push したなら、ボットが発見するまで通常は分単位です。

即座にすべきこと (時間順) #

0 分 — キーの無効化
aws iam update-access-key --user-name <user> --access-key-id <キーID> --status Inactive
5 分 — 新しいキーを発行、古いキーはそのまま無効
aws iam create-access-key --user-name <user>
10 分 — 古いキーの使用痕跡を確認 (CloudTrail)
# コンソール → CloudTrail → Event history
# AccessKeyId で検索 → 意図しない使用があるか
30 分 — 古いキーの削除
aws iam delete-access-key --user-name <user> --access-key-id <キーID>
git history の掃除
# BFG Repo-Cleaner または git filter-repo で history からキーを削除
# (すでに push 済みなら history の掃除だけでは安全 X — キーの削除がより重要)

AWS が自動で助けてくれるツール #

AWS は GitHub などの公開リポジトリをスキャンして漏洩キーを発見すると、ユーザーに即座にメールを送り、一部の場合は自動的にキーを無効化してポリシーをアタッチします。ただしこれは補助的な安全網です。自分で発見する方が速いです。

IAM Access Analyzer — 広すぎる権限を探す #

自分のアカウントのポリシーとリソースポリシー(S3 バケットポリシー、KMS キーポリシーなど)を分析して、外部アクセスが可能な部分を探すツールです。無料です。

有効化 #

有効化
コンソール → IAM → Access Analyzer → Create analyzer
- Type: Account / Organization
- Name: my-account-analyzer

有効化後24時間以内に、外部アクセス可能なリソースのリストが出ます。

何を捕まえてくれるか #

リソースリスク
S3 バケット — public read誰でもオブジェクトを読める
S3 バケット — 他のアカウントに権限意図した設定か確認が必要
KMS キー — 外部使用暗号化キーの漏洩
IAM Role — 外部 trust他のアカウントが借りられる
Lambda — 外部呼び出し権限誰でも呼び出せる
RDS スナップショット / SQS / SNS / Secrets Manager / EBS / ECR — publicデータ / メッセージの漏洩

ポリシーの検証 #

新しいポリシーを作るときに Access Analyzer が推奨事項も見せてくれます。使っていない権限、広すぎるワイルドカード、条件のない場合の追加推奨などです。

Action Last Accessed — 未使用権限を探す #

各 IAM ユーザー / ロールに対して、最後に使用したアクションを見せてくれます。90日未使用の権限は絞る候補です。

CLI から
aws iam generate-service-last-accessed-details --arn arn:aws:iam::123:role/MyRole
# (しばらく後)
aws iam get-service-last-accessed-details --job-id ...

最小権限 — 通用するパターン #

「必要なだけ、必要なところにだけ。」理想は簡単ですが、運用でどう実践するかが問題です。

パターン1: 広く始める → 絞る #

最初から完璧な権限を組むのは難しいです。次の流れが現実的です。

  1. 始まりは PowerUserAccess / サービスの *FullAccess
  2. 一週間運用した後、Access Analyzer の Action Last Accessed を確認。
  3. 使っていないサービス / アクションを削除。
  4. ワイルドカードを ARN に絞る。
  5. 条件(Condition)を追加。

このサイクルを四半期ごとに繰り返します。

パターン2: ユーザー ↔ ロールの分離 #

第2章 IAM のパターンを再確認します。

  • 人は SSO で(第5章 CloudShell と SSO)。
  • マシンは Role で(インスタンスプロファイル、実行ロール、OIDC)。
  • CI/CD は OIDC + Role で(GitHub Actions、GitLab)。

永続的なアクセスキーがほぼなくなる構造です。

パターン3: 権限境界 (Permission Boundary) #

「このユーザーは何をしてもこの限度の中だけで。」新人開発者に IAM 権限を与えつつ、彼が新しいポリシーやユーザーを作って自分の権限を増やす事故を遮断します。

権限境界の形
{
  "Effect": "Allow",
  "Action": [
    "ec2:*",
    "s3:*",
    "rds:*",
    "logs:*"
  ],
  "Resource": "*",
  "Condition": {
    "StringEquals": { "aws:RequestTag/env": "dev" }
  }
}

この境界が付いたユーザーは、自分のポリシーでも dev 環境のリソース以外は作れません。

パターン4: 環境分離 #

パターン5: Break-glass ロール #

普段は ReadOnly だけ、事故時に一時的に Admin へ格上げします。SSO Permission Set を2つに分離します。

項目普段事故時
使用ReadOnlyBreak-glass-Admin (1時間)
通知Slack チャンネルに自動通知
監査CloudTrail ですべてのアクションを記録

CloudTrail — 誰が何をしたか #

CloudTrail はアカウント内のすべての API 呼び出しを記録します。登録直後に自動で有効化され、過去90日のイベントを無料で照会できます。運用用は Trail を作って S3 に永続保存します。

登録直後の点検 #

有効化の確認
コンソール → CloudTrail → Trails
→ Multi-region Trail を1個作る (運用標準)
- 名前: my-trail
- Storage: 新しい S3 バケット
- Log file SSE-KMS encryption: オン
- Log file validation: オン (改ざん検知)

CloudTrail の2種類のイベント #

種類何か費用
Management eventsAPI 呼び出し (RunInstances、DeleteBucket など)無料 (一度)
Data eventsS3 オブジェクトアクセス、Lambda 呼び出しなど有料 (量が多い)

ほとんどの Trail は management だけオンにします。data events は特定のバケット / 関数にだけオンにします。

よく使うクエリ #

コンソールの Event history で検索します。

  • AccessKeyId — 漏洩キーの使用痕跡
  • UserName — 一人のユーザーがしたこと
  • EventName — ConsoleLoginDeleteBucketRunInstances
  • 時間範囲

CloudTrail Lake または Athena で SQL 分析も可能です(大きな組織)。

GuardDuty — 脅威検知の自動化 #

GuardDuty は CloudTrail / VPC Flow Logs / DNS ログを機械学習で分析して、疑わしい活動を捕まえてくれます。

捕まえてくれる例 #

パターン説明
EC2 が異常な地域と通信侵入 / C&C
アクセスキーが異常な地域で使用キー漏洩後の使用
Cryptocurrency マイニングのトラフィック侵入後のマイニング
EC2 の異常なポートスキャン横方向移動
Tor exit node との通信疑わしいトラフィック
IAM ユーザーの異常な行動認証情報の盗用

有効化 #

有効化
コンソール → GuardDuty → Get started → Enable
- 30 日の無料評価
- 無料評価後はデータ量ベースの課金 (通常 \$10~50 / 月 / 小さな運用)

運用段階では必ずオンにします。価格に対して捕まえてくれる事故が大きいです。

Security Hub — セキュリティ状態の統合 #

複数のセキュリティツールの結果を一か所に集めます。CIS Benchmark、AWS Foundational Security Best Practices などの標準点検を自動実行します。

有効化
コンソール → Security Hub → Enable
- 推奨標準をすべてオンに
- GuardDuty / Access Analyzer / Inspector の結果が統合される

登録直後には少し過剰です。3か月後にリソースが一定水準以上になったらオンにします。

よく出会う事故事例 #

事例1: GitHub にアクセスキーを push → 仮想通貨マイニング #

最もよくあるシナリオです。分単位でボットが発見し、時間単位で費用が累積します。

対応 — 即座にキーを無効化 → 新しいキー → CloudTrail で使用痕跡 → 可能ならアカウント自体を隔離。請求の紛争時に AWS サポートへ連絡すれば、ほとんどの無料利用枠の事故は遡及して免除されます(反復はダメ)。

予防 — pre-commit hook(gitleakstruffleHog)、GitHub secret scanning、ローカルにキー自体を置かない(SSO)。

事例2: 広すぎる S3 バケットポリシー #

「うちの会社の人が全員見られるように」しようとして Principal: "*" を追加すると public read になり、検索エンジンにインデックスされます。

対応 — Access Analyzer が捕まえてくれます。S3 Block Public Access がアカウント / バケット単位で強制します。

予防 — S3 Block Public Access を常にオン、本当に public が必要な場合は CloudFront + Origin Access Control のパターン。

事例3: MFA なしのルートパスワードのフィッシング #

「AWS 決済アラート」の偽メール → 偽のログインページ → パスワード入力。ルート MFA がなければそのまま侵害されます。

対応 — パスワードを即座に変更、すべてのリソースを点検、AWS サポートへ連絡。

予防 — ルート MFA 必須(理想的にはハードウェア)、日常作業は IAM / SSO で。

事例4: 退職者のアクセスキーが生きている #

退職処理後にも IAM ユーザー / キーがそのまま残り、数ヶ月後に事故が起こります。

対応 — 即座にユーザーを無効化 / 削除 + Trail 点検。

予防 — 退職チェックリストに IAM の整理を含める。SSO なら IdP で無効化すれば終わりです。

事例5: CloudTrail がオフになっている #

侵害の調査を始めようとしたら、事件の時点のログがありません。誰かが意図的に Trail をオフにしたか、最初からオンにしていなかった場合です。

対応 — もう遅いです。可能な他のログ(CloudWatch、GuardDuty findings)で部分的に復元します。

予防 — Trail の有効化 + Log file validation + S3 オブジェクトロック。SCP(Service Control Policy)で CloudTrail の無効化自体を拒否します。

よく出会う落とし穴 #

  • MFA だけオンにして終わり — MFA がオンになっていても、アクセスキーが漏洩すればキーはそのまま作動します(CLI 呼び出しは MFA と無関係、第4章 の認証情報チェーン)。キーも併せて気にするか、SSO でキー自体を減らします。
  • ローテーションを約束だけして実行しない — Credential Report で定期点検を自動化します。90日を超えたキーは Slack 通知で送ります。
  • iam:PassRole の広範な許可iam:PassRole = * は事実上権限昇格が可能です。ロール ARN で絞ります。
  • 条件を強くしすぎる → 自分がロックアウトaws:SourceIp で会社の IP だけ許可したのに、自分が外出中の場合です。コンソールの IP ガードは最後に置き、迂回路(VPN / 緊急ユーザー)を置きます。
  • GuardDuty をオフにする — 「費用がもったいなくて」オフにする場合、一つの事件が GuardDuty 1年分の費用より大きいです。運用では常にオンにします。
  • Security Hub の findings を見ない — オンにして通知を見なければ意味がありません。週次レビューまたは EventBridge で Slack 通知を送ります。

練習問題 #

  1. §「MFA — 最も重要なもの」の表を根拠に、ルートと一般ユーザーにそれぞれどの MFA の種類を使い、なぜ SMS を禁止するかを一段落で書いてみましょう。
  2. §「アクセスキーのローテーション」の5段階の手順を見ずに書いてみましょう。4段階で古いキーをすぐに削除せず無効化だけする理由を 第4章 の認証情報チェーンと結びつけて説明しておきましょう。
  3. §「最小権限 — 通用するパターン」の5つのパターンのうち一つを選び、それが §「よく出会う事故事例」のどの事例を防いでくれるかを対にしてみましょう。

一行まとめ: AWS のセキュリティ事故のほぼすべては MFA の不在 · キーの漏洩 · 過度な権限 · ロギングの不在から出る。すべてのユーザーに MFA を強制し、アクセスキーは90日ごとにローテーションし、IAM Access Analyzer で広い権限を絞り、人は SSO · マシンは Role で永続キーを減らす。CloudTrail · GuardDuty をオンにしておけば事故を遅れずに発見する。

次の章 #

ここまでが登録直後のセットアップです。次の 第7章 CloudWatch 入門 では、すべての運用の目である CloudWatch を整理します。Logs / Metrics / Alarms / Dashboards の構成、ロググループと retention、Metric Filter、Logs Insights クエリの基礎まで扱います。

X