2026年8月22日
2026年8月22日
AWS IAMポリシーの書き方と管理方法|JSONの読み方・最小権限の作り方・検証と更新の手順
IAMポリシーは「どの操作を、どのリソースに対して、どんな条件で許可(または拒否)するか」をJSONで書いたものです。書き方の要点は、AWS管理ポリシーの広い権限をそのまま使わず、必要な操作とリソースだけを並べたカスタマー管理ポリシーを作り、検証ツールで確認してから付けることです。この記事では、ポリシーの構造、WordPressの運用でよく使うS3とSESを例にした最小権限の書き方、評価の仕組み、作成後の検証と更新の手順を説明します。
ポリシーを付ける相手(IAMユーザーやロール)の作り方は「IAMユーザーとロールの作成方法」の記事で扱っています。この記事は権限の中身の書き方と管理に絞っています。
ポリシーの基本構造
まず、S3の特定のバケットにだけファイルを置けるようにするポリシーを見てみます。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowObjectReadWrite",
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:DeleteObject"
],
"Resource": "arn:aws:s3:::example-wp-media/*"
},
{
"Sid": "AllowListBucket",
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::example-wp-media"
}
]
}
各要素の意味は次のとおりです。
Version:ポリシー言語のバージョン。日付に見えますが、作成日ではありません。現行の2012-10-17を指定します。古い値を使うとポリシー変数などが使えませんStatement:許可や拒否のルールの配列。複数のルールを並べられますSid:ルールの識別用の名前(任意)。あとで読む人のために付けておくと便利ですEffect:Allow(許可)かDeny(拒否)Action:操作名。サービス名:操作名の形式ですResource:対象のリソースのARNCondition:許可する条件(任意)。後述します
上の例でルールを2つに分けているのには理由があります。s3:ListBucket はバケットそのものに対する操作なので、ResourceはバケットのARN(末尾に /* なし)です。一方、PutObject などはバケットの中のオブジェクトに対する操作なので、バケット/* を指定します。ここを1つにまとめて書くと、どちらかが効かず「Access Denied」になる、というのがS3のポリシーで最も多いつまずきです。
ポリシーの種類と使い分け
ポリシーには、大きく分けて次の種類があります。
- AWS管理ポリシー:AWSが用意しているもの。
AmazonS3FullAccessのように範囲が広いものが多く、AWS側で内容が更新されることがあります - カスタマー管理ポリシー:自分で作って複数のユーザーやロールに付けられるもの。バージョン管理ができます
- インラインポリシー:特定のユーザーやロールに直接埋め込むもの。その主体を削除すると一緒に消えます
さらに、IAMユーザーやロールに付ける「アイデンティティベースのポリシー」と、S3のバケットポリシーのようにリソース側に付ける「リソースベースのポリシー」があります。同じアカウント内なら、どちらかで許可されていればアクセスできるのが基本ですが、どちらかに明示的な拒否があれば拒否されます。
実務では、まずAWS管理ポリシーで動作を確認し、そのあとカスタマー管理ポリシーで必要な権限だけに絞る、という順番で進めると迷いにくくなります。WordPressのプラグイン(たとえばS3を使うバックアップやメディアのプラグイン)の多くは、必要な権限をドキュメントに載せているので、それを出発点にします。プラグインの更新で必要な操作が増えることもあるため、更新後に動作がおかしくなったら権限不足を疑います。
評価の仕組み:拒否が優先される
AWSはリクエストを受けると、関係するポリシーをまとめて評価します。考え方は次の3点です。
- 何も書かれていない操作は拒否される(暗黙的な拒否)
- どこかで
Allowされていれば許可される - どこかに
Denyがあれば、Allowがあっても拒否される(明示的な拒否が優先)
この仕組みを利用すると、「基本は広めに許可しつつ、危険な操作だけは禁止する」書き方ができます。たとえば、バックアップ用のロールがバケットを消せないようにするには、次のような拒否のルールを Statement の配列に加えます。
{
"Sid": "DenyBucketDeletion",
"Effect": "Deny",
"Action": [
"s3:DeleteBucket",
"s3:PutBucketPolicy"
],
"Resource": "arn:aws:s3:::example-wp-backup"
}
組織でAWS Organizationsを使っている場合は、サービスコントロールポリシー(SCP)やアクセス許可の境界(Permissions Boundary)も評価に加わります。自分のポリシーで許可しているのに拒否される場合は、これらで制限されていないかを管理者に確認します。
Conditionで範囲をさらに絞る
Condition を使うと、「この条件のときだけ許可する」という指定ができます。WordPressの運用でよく使うのは、SESで送信元のアドレスを限定する書き方です。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ses:SendEmail",
"ses:SendRawEmail"
],
"Resource": "*",
"Condition": {
"StringLike": {
"ses:FromAddress": "*@example.com"
}
}
}
]
}
これで、キーが漏れても自分のドメイン以外の差出人では送れなくなります。ほかに、aws:SourceIp で呼び出し元のIPアドレスを限定する方法もあります。ただし、VPCエンドポイント経由のリクエストや、AWSのサービスが代わりに呼び出すリクエストではこの条件が期待どおりに働かないことがあります。AWSの外のサーバーからアクセスキーで呼ぶ場合に限って使うのが無難です。条件キーの名前はサービスごとに決まっているので、公式ドキュメントの「サービス認可リファレンス」で確認してから書いてください。
作成・付与・更新の手順
CLIで作成して付ける
# ポリシーを作成(wp-media-s3.json は上で書いたJSON)
aws iam create-policy \
--policy-name wp-media-s3 \
--policy-document file://wp-media-s3.json
# ロールに付ける
aws iam attach-role-policy \
--role-name wp-ec2-role \
--policy-arn arn:aws:iam::123456789012:policy/wp-media-s3
付ける前に検証する
作ったポリシーは、本番の主体に付ける前に確認します。主な道具は2つです。
- IAM Access Analyzerのポリシー検証:コンソールのJSONエディタでは、文法の誤りや、広すぎる権限などの警告が表示されます。警告は内容を読んで、意図したものかを判断します
- IAMポリシーシミュレーター:特定の操作とリソースを指定して、許可されるか拒否されるかを試せます
さらに、Access Analyzerには、CloudTrailに記録された実際の操作履歴から、必要最小限のポリシーの下書きを作る機能もあります。広い権限でしばらく運用してから絞り込みたい場合に役立ちます。機能の名前や場所は変わることがあるため、使う前に公式ドキュメントで確認してください(2026年10月現在)。
更新はバージョンで管理する
カスタマー管理ポリシーは、内容を変えると新しいバージョンとして保存され、どのバージョンを有効にするかを選べます。保存できるバージョン数には上限があるので、古いものは整理します。
# 新しいバージョンを作って有効にする
aws iam create-policy-version \
--policy-arn arn:aws:iam::123456789012:policy/wp-media-s3 \
--policy-document file://wp-media-s3-v2.json \
--set-as-default
# バージョン一覧を確認
aws iam list-policy-versions \
--policy-arn arn:aws:iam::123456789012:policy/wp-media-s3
権限を減らす変更でWordPressのプラグインが動かなくなった場合は、以前のバージョンを既定に戻せばすぐに元に戻せます。権限を減らす変更は、ステージング環境で動作を確認してから本番に反映してください。JSONファイルはGitなどで管理しておくと、誰がいつ何を変えたかを追えます。
Access Deniedが出たときの調べ方
権限不足のエラーには、拒否された操作名と、場合によっては拒否の原因になったポリシーの種類が表示されます。次の順に確認すると原因にたどり着きやすくなります。
- エラーに出た操作名がポリシーの
Actionにあるか(綴りやサービス名の誤りも含む) ResourceのARNが合っているか(S3のバケットとオブジェクトの区別、リージョンやアカウントIDの誤り)- どこかに
Denyが無いか(自分のポリシー、バケットポリシー、SCP、境界) Conditionの条件を満たしているか- 実際に使われている主体が想定どおりか(
aws sts get-caller-identityで確認)
CloudTrailのイベント履歴でも、拒否されたリクエストのエラーコードと操作名を確認できます。
まとめ
- ポリシーは
Effect・Action・Resource・Conditionの組み合わせ。S3はバケットとオブジェクトでResourceの書き方が違う - 評価は「暗黙的に拒否、Allowで許可、Denyが最優先」。危険な操作は明示的なDenyで塞げる
- AWS管理ポリシーで動作確認してから、カスタマー管理ポリシーで必要な権限に絞る
- 付ける前にAccess Analyzerの検証やポリシーシミュレーターで確認し、更新はバージョンで管理する
- Access Deniedは、操作名・ARN・Deny・Condition・実際の主体の順に確認する