S3 バケットポリシーとは、バケットに直接付ける JSON 形式のアクセス許可ルールで、「誰が(Principal)・何を(Action)・どこに(Resource)・どんな条件で(Condition)・許可か拒否か(Effect)」を書きます。 IAM ポリシーが「利用者の側」に付くのに対し、バケットポリシーは「バケットの側」に付きます。

この記事では、各要素の意味を表で整理したうえで、よく使う6つのパターンをコピーして使える JSON で並べます。CLI と boto3 での設定・確認・削除、パブリックアクセスブロックの4つの設定、つまずきやすい点(ARN の /*、Allow だけの IP 条件、明示的 Deny の優先)も、実行結果や公式ドキュメントの記載と合わせてまとめました。

確認環境:Ubuntu 24.04、AWS CLI 1.46.1、Python 3.11.15、boto3 1.43.103。AWS の API をローカルで再現するツール(moto 5.2.3)で実行しています。掲載するコマンドは接続先の指定を外してあり、実際の AWS でそのまま使える形です。

S3バケットポリシーの早見表

要素の意味

要素 書くこと 例
Version ポリシー言語の版。"2012-10-17" と書く "Version": "2012-10-17"
Statement ルールの配列。1つ以上のステートメントを並べる "Statement": [ {…}, {…} ]
Sid ステートメントの名前(任意)。あとで見分けるための目印 "Sid": "DenyInsecureTransport"
Effect 許可か拒否か。Allow または Deny "Effect": "Deny"
Principal だれに対するルールか "*"、{"AWS": "arn:aws:iam::111122223333:root"}、{"Service": "cloudfront.amazonaws.com"}
Action どの操作か。s3: で始まる名前 "s3:GetObject"、["s3:GetObject", "s3:PutObject"]、"s3:*"
Resource どのバケット・オブジェクトか(ARN) バケット:arn:aws:s3:::example-policy-demo、オブジェクト:arn:aws:s3:::example-policy-demo/*
Condition 条件(任意)。演算子・条件キー・値の組 {"Bool": {"aws:SecureTransport": "false"}}

やりたいこと別のパターン

やりたいこと Effect Principal Condition
特定の IP 以外を拒否 Deny "*" NotIpAddress + aws:SourceIp
HTTP(暗号化なし)を拒否 Deny "*" Bool + aws:SecureTransport が false
別アカウントに許可 Allow {"AWS": "相手アカウントの ARN"} なし
特定の VPC エンドポイント以外を拒否 Deny "*" StringNotEquals + aws:SourceVpce
CloudFront(OAC)からの読み取りを許可 Allow {"Service": "cloudfront.amazonaws.com"} StringEquals + AWS:SourceArn
だれでも読み取り可(公開) Allow "*" なし

コマンド

操作 CLI boto3
設定 aws s3api put-bucket-policy --bucket 名前 --policy file://policy.json s3.put_bucket_policy(Bucket=…, Policy=json.dumps(…))
確認 aws s3api get-bucket-policy --bucket 名前 s3.get_bucket_policy(Bucket=…)
削除 aws s3api delete-bucket-policy --bucket 名前 s3.delete_bucket_policy(Bucket=…)
公開の防止設定 aws s3api put-public-access-block --bucket 名前 --public-access-block-configuration … s3.put_public_access_block(Bucket=…, PublicAccessBlockConfiguration={…})

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「S3バケットポリシーの書き方と例 IP制限・Condition早見表」

バケットポリシーの基本の形

最小の形は次のとおりです。Statement の中に、ルールを1つずつ書きます。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ルールの名前",
      "Effect": "Allow または Deny",
      "Principal": "だれに",
      "Action": "どの操作を",
      "Resource": "どのバケット・オブジェクトに",
      "Condition": { "演算子": { "条件キー": "値" } }
    }
  ]
}

Principal の書き方

対象 書き方
すべて(匿名を含む) "Principal": "*"
AWS アカウント全体 "Principal": {"AWS": "arn:aws:iam::111122223333:root"} または {"AWS": "111122223333"}
IAM ユーザー "Principal": {"AWS": "arn:aws:iam::111122223333:user/taro"}
IAM ロール "Principal": {"AWS": "arn:aws:iam::111122223333:role/app-role"}
AWS サービス "Principal": {"Service": "cloudfront.amazonaws.com"}
複数 "Principal": {"AWS": ["111122223333", "444455556666"]}

公式ドキュメントでは、"Principal": "*" と "Effect": "Allow" の組み合わせは、公開や匿名アクセスを意図する場合に限って使うよう案内されています。それ以外では、Principal を具体的に書くか、Condition で絞ります。

Resource はバケットとオブジェクトで ARN が違う

操作の種類 例 Resource に書く ARN
バケットに対する操作 s3:ListBucket、s3:PutBucketPolicy arn:aws:s3:::example-policy-demo
オブジェクトに対する操作 s3:GetObject、s3:PutObject、s3:DeleteObject arn:aws:s3:::example-policy-demo/*
特定の接頭辞の下だけ s3:GetObject arn:aws:s3:::example-policy-demo/public/*
両方をまとめて対象にする s3:* 上の2つを配列で並べる

オブジェクトの ARN は、バケット名のあとに / が必要です。この取り違えは MalformedPolicy の代表的な原因なので、後半で詳しく扱います。

Condition の書き方

Condition は「演算子 → 条件キー → 値」の3段で書きます。

演算子 条件キーの例 使いどころ
IpAddress / NotIpAddress aws:SourceIp 接続元の IP アドレス(CIDR)で判定
Bool aws:SecureTransport HTTPS かどうかで判定
StringEquals / StringNotEquals aws:SourceVpce、aws:SourceVpc、AWS:SourceArn VPC エンドポイント、VPC、呼び出し元リソースで判定

値を配列で書くと「どれかに一致」の意味になります("aws:SourceIp": ["192.0.2.0/24", "203.0.113.0/24"] は、どちらかの範囲なら一致)。

コピーして使えるバケットポリシー6例

バケット名 example-policy-demo、アカウント ID、IP アドレスなどは、自分の値に置き換えてください。

1. 特定の IP アドレス以外を拒否する(Deny + NotIpAddress)

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyExceptAllowedIp",
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:*",
      "Resource": [
        "arn:aws:s3:::example-policy-demo",
        "arn:aws:s3:::example-policy-demo/*"
      ],
      "Condition": {
        "NotIpAddress": {
          "aws:SourceIp": ["192.0.2.0/24", "203.0.113.0/24"]
        }
      }
    }
  ]
}

IAM の公式ドキュメントにある「接続元 IP で拒否する」例(Deny + NotIpAddress + aws:SourceIp)を、バケットポリシーの形(Principal と Resource を追加)にしたものです。公式の注意書きを2つ紹介します。

  • このステートメントは何も許可しません。 許可は、IAM ポリシーや別の Allow ステートメントで与えます。
  • Deny と否定形の条件(Not〜)を組み合わせると、条件に当てはまるもの以外がすべて拒否されます。 自分の IP を書き間違えると、自分もバケットを操作できなくなるので、適用前に値をよく確かめます。

2. HTTPS 以外を拒否する(aws:SecureTransport)

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyInsecureTransport",
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:*",
      "Resource": [
        "arn:aws:s3:::example-policy-demo",
        "arn:aws:s3:::example-policy-demo/*"
      ],
      "Condition": {
        "Bool": { "aws:SecureTransport": "false" }
      }
    }
  ]
}

S3 の公式ドキュメントに載っている形です。aws:SecureTransport が false(HTTP でのリクエスト)のときに拒否します。

3. 別アカウントに読み取りと一覧を許可する

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowOtherAccountList",
      "Effect": "Allow",
      "Principal": { "AWS": "arn:aws:iam::111122223333:root" },
      "Action": "s3:ListBucket",
      "Resource": "arn:aws:s3:::example-policy-demo"
    },
    {
      "Sid": "AllowOtherAccountRead",
      "Effect": "Allow",
      "Principal": { "AWS": "arn:aws:iam::111122223333:root" },
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::example-policy-demo/*"
    }
  ]
}

一覧(ListBucket)はバケットの ARN、読み取り(GetObject)はオブジェクトの ARN と、ステートメントを分けています。相手アカウントの中の特定のユーザーやロールだけに絞るときは、Principal にその ARN を書きます。別アカウントからのアクセスでは、相手アカウント側の IAM ポリシーでも同じ操作が許可されている必要があります。

4. 特定の VPC エンドポイント以外を拒否する(aws:SourceVpce)

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AccessToSpecificVpceOnly",
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:*",
      "Resource": [
        "arn:aws:s3:::example-policy-demo",
        "arn:aws:s3:::example-policy-demo/*"
      ],
      "Condition": {
        "StringNotEquals": { "aws:SourceVpce": "vpce-0abcdef1234567890" }
      }
    }
  ]
}

S3 の公式ドキュメントに載っている形です。VPC 全体で絞るときは、条件キーを aws:SourceVpc、値を vpc-1a2b3c4d のような VPC ID にします。公式の注意書きでは、このポリシーを付けるとコンソールからのアクセスも拒否される(コンソールのリクエストは指定した VPC エンドポイントを通らないため)こと、エンドポイント ID を正しい値に置き換えないと自分もアクセスできなくなることが案内されています。このステートメントも許可は与えないので、Allow は別に用意します。

5. CloudFront の OAC からの読み取りを許可する

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowCloudFrontServicePrincipalReadOnly",
      "Effect": "Allow",
      "Principal": { "Service": "cloudfront.amazonaws.com" },
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::example-policy-demo/*",
      "Condition": {
        "StringEquals": {
          "AWS:SourceArn": "arn:aws:cloudfront::123456789012:distribution/EDFDVBD6EXAMPLE"
        }
      }
    }
  ]
}

CloudFront の公式ドキュメントに載っている形です。Principal は CloudFront のサービス、Condition でディストリビューションの ARN(arn:aws:cloudfront::アカウントID:distribution/ディストリビューションID)を指定します。Condition を付けることで、自分のディストリビューション経由のリクエストだけが許可されます。 オブジェクトを SSE-KMS で暗号化している場合は、KMS キーのポリシーにも CloudFront への許可を足します。

6. だれでも読み取れるようにする(公開)

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "PublicReadGetObject",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::example-policy-demo/*"
    }
  ]
}

静的ウェブサイトのホスティング用として、S3 の公式ドキュメントに載っている形です。このポリシーを設定するには、先にパブリックアクセスブロックをバケットとアカウントの両方で外す必要があります。公式ドキュメントは、すべての公開アクセスをブロックしておくことを推奨しています。公開したい場合は、5 の CloudFront + OAC の形にして、バケット自体は非公開のままにする方法も検討できます。

CLI で設定・確認・削除する

HTTPS 強制のポリシー(例2)を policy.json に保存して、設定から削除まで実行します。

設定する(put-bucket-policy)

aws s3api put-bucket-policy --bucket example-policy-demo --policy file://policy.json

成功すると何も表示されません(終了コード 0)。put-bucket-policy は追記ではなく、ポリシー全体の置き換えです。ステートメントを足したいときは、いまのポリシーを取り出して編集し、全体を設定し直します。

確認する(get-bucket-policy)

aws s3api get-bucket-policy --bucket example-policy-demo
{
    "Policy": "{\n  \"Version\": \"2012-10-17\",\n  \"Statement\": [\n    {\n      \"Sid\": \"DenyInsecureTransport\",\n      \"Effect\": \"Deny\",\n …(省略)… }\n  ]\n}\n"
}

Policy は「JSON を文字列にしたもの」で返るので、そのままでは読みにくい形です。--query Policy --output text で文字列を取り出し、jq に渡すと整形できます。

aws s3api get-bucket-policy --bucket example-policy-demo --query Policy --output text | jq .
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyInsecureTransport",
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:*",
      "Resource": [
        "arn:aws:s3:::example-policy-demo",
        "arn:aws:s3:::example-policy-demo/*"
      ],
      "Condition": {
        "Bool": {
          "aws:SecureTransport": "false"
        }
      }
    }
  ]
}

末尾を > policy.json にすれば、編集用のファイルとして保存できます。

削除する(delete-bucket-policy)

aws s3api delete-bucket-policy --bucket example-policy-demo
aws s3api get-bucket-policy --bucket example-policy-demo
An error occurred (NoSuchBucketPolicy) when calling the GetBucketPolicy operation: The bucket policy does not exist

削除も成功時は無表示です。削除後に get-bucket-policy を実行すると、NoSuchBucketPolicy が返ります。ポリシーが1つも設定されていないバケットでも同じエラーになるので、「未設定」の判定に使えます。

boto3 で設定・確認・削除する

import json
import boto3
from botocore.exceptions import ClientError

s3 = boto3.client("s3")
bucket = "example-policy-demo"

policy = {
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "DenyInsecureTransport",
            "Effect": "Deny",
            "Principal": "*",
            "Action": "s3:*",
            "Resource": [f"arn:aws:s3:::{bucket}", f"arn:aws:s3:::{bucket}/*"],
            "Condition": {"Bool": {"aws:SecureTransport": "false"}},
        }
    ],
}

# 設定する(Policy は JSON 文字列で渡す)
s3.put_bucket_policy(Bucket=bucket, Policy=json.dumps(policy))

# 読み出す(Policy は文字列で返るので json.loads で辞書に戻す)
res = s3.get_bucket_policy(Bucket=bucket)
print(type(res["Policy"]).__name__)
loaded = json.loads(res["Policy"])
print(loaded["Statement"][0]["Sid"], loaded["Statement"][0]["Effect"])

# 削除する
s3.delete_bucket_policy(Bucket=bucket)
try:
    s3.get_bucket_policy(Bucket=bucket)
except ClientError as e:
    print(e.response["Error"]["Code"])

# パブリックアクセスブロックを4つとも有効にする
s3.put_public_access_block(
    Bucket=bucket,
    PublicAccessBlockConfiguration={
        "BlockPublicAcls": True,
        "IgnorePublicAcls": True,
        "BlockPublicPolicy": True,
        "RestrictPublicBuckets": True,
    },
)
print(s3.get_public_access_block(Bucket=bucket)["PublicAccessBlockConfiguration"])
str
DenyInsecureTransport Deny
NoSuchBucketPolicy
{'BlockPublicAcls': True, 'IgnorePublicAcls': True, 'BlockPublicPolicy': True, 'RestrictPublicBuckets': True}

Policy は辞書ではなく文字列で受け渡しします。 渡すときは json.dumps、受け取ったら json.loads です。Python の辞書で組み立てると、バケット名を変数で埋め込めるので、Resource のバケット名の書き間違いを減らせます。

パブリックアクセスブロックの4つの設定

パブリックアクセスブロックは、バケットポリシーや ACL による公開を、上から止める設定です。4つのフラグがあります。

aws s3api put-public-access-block \
    --bucket example-policy-demo \
    --public-access-block-configuration \
    BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true

aws s3api get-public-access-block --bucket example-policy-demo
{
    "PublicAccessBlockConfiguration": {
        "BlockPublicAcls": true,
        "IgnorePublicAcls": true,
        "BlockPublicPolicy": true,
        "RestrictPublicBuckets": true
    }
}
フラグ 対象 true にしたときの動き
BlockPublicAcls ACL(これから設定するもの) 公開の ACL を設定する呼び出し(PutBucketAcl、PutObjectAcl、公開 ACL つきの PutObject)を受け付けない
IgnorePublicAcls ACL(すでにあるもの) バケットとオブジェクトの公開 ACL を無視する
BlockPublicPolicy バケットポリシー(これから設定するもの) 公開を許可するバケットポリシーの PutBucketPolicy を受け付けない
RestrictPublicBuckets バケットポリシー(すでにあるもの) 公開ポリシーが付いたバケットへのアクセスを、AWS サービスとバケット所有アカウント内の許可された利用者に限る

「Block」が付く2つは新しい設定を止め、残りの2つは既存の設定の効き目を止める、と覚えると整理しやすくなります。

一部のフラグだけを指定して実行すると、指定しなかったフラグは false になりました。

aws s3api put-public-access-block --bucket example-policy-demo \
    --public-access-block-configuration BlockPublicAcls=true,IgnorePublicAcls=true
aws s3api get-public-access-block --bucket example-policy-demo
{
    "PublicAccessBlockConfiguration": {
        "BlockPublicAcls": true,
        "IgnorePublicAcls": true,
        "BlockPublicPolicy": false,
        "RestrictPublicBuckets": false
    }
}

この設定も全体の置き換えなので、4つとも書いて実行するのが確実です。設定を外すときは aws s3api delete-public-access-block --bucket example-policy-demo を使います。

「公開」と見なされるポリシー、見なされないポリシー

公式ドキュメントによると、次のような固定の値で絞っているポリシーは、Principal が "*" でも公開とは見なされません。

絞り方 条件キーの例
特定の AWS プリンシパル・サービス Principal に ARN やサービス名を書く
IP アドレスの範囲(CIDR) aws:SourceIp
呼び出し元のリソースやアカウント aws:SourceArn、aws:SourceAccount
VPC・VPC エンドポイント aws:SourceVpc、aws:SourceVpce

例6の公開読み取りは条件がないので公開と見なされ、BlockPublicPolicy が true のバケットでは設定が受け付けられません。例5の CloudFront OAC は、サービスプリンシパルと AWS:SourceArn で絞っているので、パブリックアクセスブロックを有効にしたまま使えます。

設定はバケット単位とアカウント単位の両方にあり、公式ドキュメントによると、違いがあるときは最も制限の強い組み合わせが適用されます。 バケット側で外しても公開できないときは、アカウント側の設定を確かめます。

つまずきやすい3つの点

バケット ARN とオブジェクト ARN の取り違え(MalformedPolicy)

次のポリシーは、オブジェクトの操作(GetObject)に対して、Resource がバケットの ARN になっています。

{
  "Effect": "Allow",
  "Principal": "*",
  "Action": "s3:GetObject",
  "Resource": "arn:aws:s3:::example-policy-demo"
}

この形で設定しようとした利用者の報告(Serverless Framework のフォーラム)では、次のエラーが返っています。

Action does not apply to any resource(s) in statement (Service: Amazon S3; Status Code: 400; Error Code: MalformedPolicy)

「このステートメントの Action は、書かれた Resource のどれにも当てはまらない」という意味です。直し方は、Action の種類に Resource を合わせることです。

Action 直す前の Resource 直した後の Resource
s3:GetObject arn:aws:s3:::example-policy-demo arn:aws:s3:::example-policy-demo/*
s3:ListBucket arn:aws:s3:::example-policy-demo/* arn:aws:s3:::example-policy-demo
両方をまとめて書く どちらか片方だけ 2つを配列で並べる

MalformedPolicy には、ほかにも次のようなメッセージがあります。

メッセージ 原因 直し方
Action does not apply to any resource(s) in statement Action と Resource の種類(バケット/オブジェクト)が合っていない 上の表のとおり ARN を合わせる
Policy has invalid resource Resource のバケット名が、--bucket で指定したバケットと違う ARN のバケット名を合わせる
Invalid principal in policy Principal の書式が合っていない(AWS キーがない、ARN の形でない など) 「Principal の書き方」の表の形にする

Allow だけでは IP 制限にならない

「特定の IP からだけ使えるようにしたい」とき、次のように Allow に IP の条件を付けるだけでは、制限になりません。

{
  "Effect": "Allow",
  "Principal": "*",
  "Action": "s3:GetObject",
  "Resource": "arn:aws:s3:::example-policy-demo/*",
  "Condition": { "IpAddress": { "aws:SourceIp": "192.0.2.0/24" } }
}

理由は、アクセス許可の決まり方にあります。IAM の公式ドキュメントでは、同じアカウント内のリクエストについて、IAM ポリシー(利用者側)とバケットポリシー(リソース側)のどちらかが許可していれば許可されると説明されています。

利用者 IAM ポリシー 上の Allow(IP 条件つき) 結果
同じアカウントの利用者(S3 の権限あり)、範囲外の IP 許可 条件に合わず、何も決めない IAM ポリシーの許可で通る
匿名、範囲内の IP なし 許可 通る
匿名、範囲外の IP なし 何も決めない 通らない

条件に合わない Allow は「拒否」ではなく「何も決めない」だけです。IAM ポリシーで S3 の権限を持つ利用者は、どの IP からでも操作できます。実際に、IAM ポリシーで s3:* を許可した利用者 taro は、バケットポリシーが1つもない状態でオブジェクトを取得できました。

aws s3 cp s3://example-policy-demo/private/secret.txt -
secret

IP で絞りたいときは、例1のように Deny + NotIpAddress で「範囲外を拒否」と書きます。 明示的な Deny は、どのポリシーの Allow よりも優先されるためです。

明示的な Deny は Allow より優先される

Deny の優先を、2つの実行で確かめました。まず、公開読み取りの Allow と、private/ の下だけを拒否する Deny を同じポリシーに並べます。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "PublicRead",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::example-policy-demo/*"
    },
    {
      "Sid": "DenyPrivatePrefix",
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::example-policy-demo/private/*"
    }
  ]
}

認証なしの curl で、2つのオブジェクトにアクセスした結果です(URL のホスト部分は環境に合わせて置き換えています)。

curl -s -o /dev/null -w "index.html HTTP %{http_code}\n" https://example-policy-demo.s3.amazonaws.com/index.html
curl -s -o /dev/null -w "private/secret.txt HTTP %{http_code}\n" https://example-policy-demo.s3.amazonaws.com/private/secret.txt
index.html HTTP 200
private/secret.txt HTTP 403

private/secret.txt は Allow(/*)にも当てはまりますが、Deny が優先されて 403 になりました。

次に、IAM ポリシーで s3:* を許可されている利用者 taro で、Deny のステートメントだけを付けたバケットにアクセスします。boto3 で HTTP ステータスを表示した結果です。

import boto3
from botocore.exceptions import ClientError

s3 = boto3.client("s3")
for key in ["index.html", "private/secret.txt"]:
    try:
        r = s3.get_object(Bucket="example-policy-demo", Key=key)
        print(key, r["ResponseMetadata"]["HTTPStatusCode"])
    except ClientError as e:
        print(key, e.response["ResponseMetadata"]["HTTPStatusCode"])
index.html 200
private/secret.txt 403

ポリシーを付ける前は取得できていた private/secret.txt が、403 に変わりました。IAM ポリシーで許可されていても、バケットポリシーの Deny があれば拒否されます。

評価の順番 内容
1 何も書かれていなければ拒否(暗黙の拒否)
2 どこかに Allow があれば許可
3 どこかに明示的な Deny があれば、Allow があっても拒否

エラーと対処の一覧

エラー 原因 対処
NoSuchBucketPolicy(GetBucketPolicy) バケットポリシーが設定されていない、または削除済み 未設定として扱う。必要なら put-bucket-policy で設定する
NoSuchBucket: The specified bucket does not exist --bucket のバケット名が違う バケット名とリージョンを確かめる
MalformedPolicy ポリシーの内容が S3 の決まりに合っていない 上の「MalformedPolicy」の表でメッセージ別に確かめる
Error parsing parameter '--policy': Unable to load paramfile file://… file:// で指定したファイルが見つからない ファイル名と、コマンドを実行しているフォルダを確かめる
公開ポリシーが保存できない パブリックアクセスブロック(BlockPublicPolicy)が有効 公開が本当に必要か確かめたうえで、バケットとアカウントの設定を見直す
ポリシーを付けたら自分も操作できなくなった Deny の条件(IP、VPC エンドポイント)に自分が当てはまっている 条件の値を確かめる。適用前に小さな検証用バケットで試す

NoSuchBucketPolicy、NoSuchBucket、paramfile の3つは、今回の実行で実際に表示されたメッセージです。

適用前のチェックリスト

確認 内容
Version "2012-10-17" になっているか
Resource バケットの操作はバケット ARN、オブジェクトの操作は /* つきの ARN か
バケット名 ARN のバケット名が、設定先のバケットと同じか
Principal "*" と Allow の組み合わせは、公開を意図したものか
Deny の条件 自分の接続元(IP・VPC エンドポイント)が拒否の対象に入っていないか
置き換え put-bucket-policy は全体の置き換え。いまのポリシーを get-bucket-policy で保存したか
パブリックアクセスブロック 4つのフラグの状態を get-public-access-block で確かめたか

よくある質問

Q. バケットポリシーと IAM ポリシーは、どちらに書けばよいですか? A. 同じアカウント内の利用者への許可は、IAM ポリシーに書くのが基本です。バケットポリシーは、別アカウントや AWS サービスへの許可、IP・HTTPS・VPC エンドポイントなど「バケット側で一律に守りたい条件」に向いています。

Q. ステートメントを1つだけ追加できますか? A. put-bucket-policy は全体を置き換えるので、get-bucket-policy で取り出したポリシーに追記し、全体を設定し直します。

Q. 公開読み取りのポリシーが保存できません。 A. パブリックアクセスブロックの BlockPublicPolicy が有効だと、公開を許可するポリシーは受け付けられません。バケット単位とアカウント単位の両方の設定を確かめてください。CloudFront の OAC のように条件で絞ったポリシーなら、有効にしたまま設定できます。

Q. get-bucket-policy の結果が読みにくいです。 A. --query Policy --output text | jq . を付けると、整形された JSON で表示されます。

まとめ

  • バケットポリシーは Effect・Principal・Action・Resource・Condition の組で、「だれに・何を・どこに・どんな条件で」を書きます。
  • バケットの操作はバケット ARN、オブジェクトの操作は /* つきの ARN です。取り違えると MalformedPolicy になります。
  • IP 制限は Deny + NotIpAddress で書きます。Allow に条件を付けるだけでは、IAM ポリシーで許可された利用者を止められません。
  • 明示的な Deny は、どの Allow よりも優先されます。 実行結果でも、Allow と Deny が重なったオブジェクトは 403 になりました。
  • put-bucket-policy は全体の置き換えです。get-bucket-policy(--query Policy --output text)で保存してから編集します。
  • パブリックアクセスブロックは4つのフラグで、Block〜は新しい設定を、Ignore〜と Restrict〜は既存の設定の効き目を止めます。
  • 公開が必要なときは、CloudFront + OAC でバケットを非公開のまま配信する形も選べます。

参考・出典

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「S3バケットポリシーの書き方と例 IP制限・Condition早見表」

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?