セキュリティ基本 — 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) | 標準 — ほぼすべての場合 |
| ハードウェア MFA | YubiKey のような USB キー | ルート / 高特権 — 最強 |
| U2F / WebAuthn | ブラウザ + ハードウェアキー | 運用認証情報の格上げ |
| SMS | テキストメッセージ | 使用禁止 (SIM swap 攻撃) |
ルートはハードウェア MFA が理想的で、一般ユーザーは virtual 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 がオンのセッションでなければほぼすべてのアクションを拒否」です。
{
"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-OLDIAM Credential Report — ローテーションの点検 #
CSV 一枚ですべてのユーザーのキー / MFA / 活動状態を見ます。
aws iam generate-credential-report
aws iam get-credential-report --query Content --output text | base64 -d > report.csvuser
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_used90日を超えたキー、MFA をオンにしていないユーザー、1ヶ月未使用のユーザーがひと目で分かります。
漏洩したキーを発見したとき #
コードにキーを push したなら、ボットが発見するまで通常は分単位です。
即座にすべきこと (時間順) #
aws iam update-access-key --user-name <user> --access-key-id <キーID> --status Inactiveaws iam create-access-key --user-name <user># コンソール → CloudTrail → Event history
# AccessKeyId で検索 → 意図しない使用があるかaws iam delete-access-key --user-name <user> --access-key-id <キーID># 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日未使用の権限は絞る候補です。
aws iam generate-service-last-accessed-details --arn arn:aws:iam::123:role/MyRole
# (しばらく後)
aws iam get-service-last-accessed-details --job-id ...最小権限 — 通用するパターン #
「必要なだけ、必要なところにだけ。」理想は簡単ですが、運用でどう実践するかが問題です。
パターン1: 広く始める → 絞る #
最初から完璧な権限を組むのは難しいです。次の流れが現実的です。
- 始まりは
PowerUserAccess/ サービスの*FullAccess。 - 一週間運用した後、Access Analyzer の Action Last Accessed を確認。
- 使っていないサービス / アクションを削除。
- ワイルドカードを ARN に絞る。
- 条件(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: 環境分離 #
- アカウント分離(Organizations) — 最も強い防御策であり、第29章 セキュリティガバナンス で扱います。
- VPC 分離 — 同じアカウントでも prod VPC と dev VPC を分離します(第8章 EC2 と VPC)。
- タグ分離 —
env=prodタグで権限とコストを分離します(第3章 コスト管理 のタグ戦略)。
パターン5: Break-glass ロール #
普段は ReadOnly だけ、事故時に一時的に Admin へ格上げします。SSO Permission Set を2つに分離します。
| 項目 | 普段 | 事故時 |
|---|---|---|
| 使用 | ReadOnly | Break-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 events | API 呼び出し (RunInstances、DeleteBucket など) | 無料 (一度) |
| Data events | S3 オブジェクトアクセス、Lambda 呼び出しなど | 有料 (量が多い) |
ほとんどの Trail は management だけオンにします。data events は特定のバケット / 関数にだけオンにします。
よく使うクエリ #
コンソールの Event history で検索します。
- AccessKeyId — 漏洩キーの使用痕跡
- UserName — 一人のユーザーがしたこと
- EventName —
ConsoleLogin、DeleteBucket、RunInstances - 時間範囲
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(gitleaks、truffleHog)、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 通知を送ります。
練習問題 #
- §「MFA — 最も重要なもの」の表を根拠に、ルートと一般ユーザーにそれぞれどの MFA の種類を使い、なぜ SMS を禁止するかを一段落で書いてみましょう。
- §「アクセスキーのローテーション」の5段階の手順を見ずに書いてみましょう。4段階で古いキーをすぐに削除せず無効化だけする理由を 第4章 の認証情報チェーンと結びつけて説明しておきましょう。
- §「最小権限 — 通用するパターン」の5つのパターンのうち一つを選び、それが §「よく出会う事故事例」のどの事例を防いでくれるかを対にしてみましょう。
一行まとめ: AWS のセキュリティ事故のほぼすべては MFA の不在 · キーの漏洩 · 過度な権限 · ロギングの不在から出る。すべてのユーザーに MFA を強制し、アクセスキーは90日ごとにローテーションし、IAM Access Analyzer で広い権限を絞り、人は SSO · マシンは Role で永続キーを減らす。CloudTrail · GuardDuty をオンにしておけば事故を遅れずに発見する。
次の章 #
ここまでが登録直後のセットアップです。次の 第7章 CloudWatch 入門 では、すべての運用の目である CloudWatch を整理します。Logs / Metrics / Alarms / Dashboards の構成、ロググループと retention、Metric Filter、Logs Insights クエリの基礎まで扱います。