こんにちは、かつコーチです。
今回は、AWSのIAMポリシーを自分で書きたいという方向けに、基本のJSON構文を解説します。
「コンソールでポチポチ設定はできるけど、JSONで書けと言われると手が止まる」という声をよく聞きます。
この記事を読めば、ポリシーの構造を理解して、自分で最小権限のポリシーを組み立てられるようになります。
IAMポリシーとは?
IAMとポリシーの基本
IAMとは、AWSにおける「誰が」「何に」アクセスできるかを管理する仕組みです。
会社に例えるなら、社員証と入退室権限を管理する仕組みだと考えるとわかりやすいです。
社員証がなければビルに入れないように、IAMの許可がなければAWSのリソースは操作できません。
IAMポリシーとは、この許可の内容を具体的に定義したJSON形式のドキュメントです。
「誰が」の部分はIAMユーザーやロールが担い、「何に」「何を」許可するかをポリシーが記述します。
なぜポリシーの書き方を理解する必要があるのか
コンソールの画面操作だけでも権限設定は可能です。
しかし実務では、複数人での運用やCI/CDパイプラインからのリソース操作など、細かい権限調整が必要な場面が必ず出てきます。
そのときにJSON構文を理解していないと、権限を広げすぎたり、逆に必要な操作ができずエラーになったりします。
最小権限の原則を守るためにも、ポリシーを自分の手で書けることは中級者に欠かせないスキルです。
基本の書き方・実装手順
手順1: ポリシーのJSON構造を理解する
IAMポリシーは以下の要素で構成されます。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowS3ReadOnly",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::my-sample-bucket",
"arn:aws:s3:::my-sample-bucket/*"
]
}
]
}
それぞれの要素の役割は次のとおりです。
- Version: ポリシー言語のバージョンです。基本的に”2012-10-17″を指定します。
- Statement: 許可・拒否のルールを配列で並べる部分です。
- Effect: “Allow”(許可)か”Deny”(拒否)のどちらかを指定します。
- Action: 許可・拒否する操作を指定します。「s3:GetObject」のように「サービス名:操作名」の形式です。
- Resource: 対象となるリソースをARN(Amazon Resource Name、AWSリソースを一意に示す識別子)で指定します。
手順2: S3への読み取り専用アクセスを作る
先ほどのJSON例は、S3の特定バケットに対して読み取り専用アクセスを許可するポリシーです。
「s3:GetObject」がオブジェクトの取得、「s3:ListBucket」がバケット内一覧の取得を意味します。
書き込みや削除の操作(s3:PutObject、s3:DeleteObjectなど)は含まれていないため、閲覧しかできません。
これをIAMユーザーにアタッチするには、AWS CLIで以下のように実行します。
aws iam put-user-policy \
--user-name sample-user \
--policy-name S3ReadOnlyPolicy \
--policy-document file://s3-readonly-policy.json
つまずきやすい設定・注意点
ResourceにバケットのARNだけを書いて、オブジェクトへのARN(末尾に/を付けたもの)を書き忘れるミスが非常に多いです。
バケット自体へのARNは「s3:ListBucket」用、オブジェクトへのARN(/付き)は「s3:GetObject」用と、対象が異なる点に注意してください。
この2つを両方Resourceに含めないと、意図した権限が正しく機能しません。
よくあるつまずきポイント・エラー対処
Resourceの指定漏れでハマった話
私が実際にS3の読み取り専用ポリシーを作ったとき、こんなエラーに遭遇しました。
An error occurred (AccessDenied) when calling the ListObjectsV2 operation: Access Denied
GetObjectは通せているのにListObjectsだけ弾かれるという、原因が絞りにくい状態でした。
ポリシーを見直すと、Resourceにバケット本体のARN(arn:aws:s3:::my-sample-bucket)を書かず、オブジェクト用のARN(/*付き)しか指定していませんでした。
ListBucketはバケット単位の操作なので、オブジェクト用ARNだけでは権限が及ばなかったのです。
- ❌ Before:
"Resource": "arn:aws:s3:::my-sample-bucket/*"のみ指定 - ✅ After:
"Resource": ["arn:aws:s3:::my-sample-bucket", "arn:aws:s3:::my-sample-bucket/*"]の2つを指定
バケット本体とオブジェクトのARNをセットで書く、というルールを体で覚えてからは同じミスをしなくなりました。
応用・一歩先の使い方
条件キーでさらに絞り込む
慣れてきたらCondition(条件、特定の状況下でのみ許可・拒否を発動させる指定)を使うと、より柔軟な制御ができます。
たとえば特定のIPアドレスからのアクセスのみ許可する場合は、以下のように書きます。
{
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-sample-bucket/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": "203.0.113.0/24"
}
}
}
こうした条件を組み合わせることで、社内ネットワークからのみアクセス可能にするなど、実務に近い権限設計ができるようになります。
まとめ
この記事のポイント
- IAMポリシーはVersion、Statement、Effect、Action、Resourceの5要素で構成される
- S3の読み取り専用など、目的に応じてActionとResourceを絞り込むのが基本
- バケット本体とオブジェクトでARNの書き方が異なる点に要注意
- Conditionを使えばさらに細かい権限制御が可能
次に読むべき記事
ポリシーを書いていると、必ずと言っていいほどAccess Deniedエラーに遭遇します。
次は「よくあるAccess Deniedエラーの原因と対処法」を読んで、切り分けの手順を身につけておきましょう。
