S3のポリシーに定義した「Resource」を正しく理解できていますか?

雰囲気で「Resource」を書くことから卒業しよう!
2024.03.07

こんにちは!コンサル部のinomaso(@inomasosan)です。

先日、以下のようなS3ポリシーを見た際に、Resourceの書き方が何を意図しているのかをうまく言語化できなかったので、ちゃんと理解するため調べてみることにしました。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "RequireMFAForProductionBucket",
            "Effect": "Deny",
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::Production",
                "arn:aws:s3:::Production/*"
            ],
            "Condition": {
                "NumericGreaterThanIfExists": {"aws:MultiFactorAuthAge": "1800"}
            }
        }
    ]
}

先にまとめ

  • Resourceはバケットやオブジェクトといったリソースタイプを適切に指定する必要がある
  • Actionの種類毎に指定可能なリソースタイプは決まっており、誤ったリソースタイプを指定するとAWS CLI等の実行がエラーになる

前提知識

S3のセキュリティに関する知識は、以下のBlack Beltの資料がわかりやすかったです。

今回のS3のポリシーに関しては、以下の抜粋部分を最初に押さえていただければと思います。

デフォルトのアクセス制御

S3バケットとオブジェクトはデフォルトでプライベートであり、作成したアカウントからのみアクセスできます。

バケットポリシーとIAMポリシー

S3のアクセス制御を検討する際に真っ先に出てくるポリシーは、バケットポリシーとIAMポリシーとなります。

ユースケースによってどのようにアクセス制御するかを検討する必要があるため、以下のような特性があることも覚えておきましょう

S3のリソースタイプについて

S3のポリシーでResourceを定義する場合、バケットとオブジェクトでARNの書き方が以下のように異なります。

リソースタイプ ARN
bucket arn:${Partition}:s3:::${BucketName}
object arn:${Partition}:s3:::${BucketName}/${ObjectName}

S3のリソースタイプは他にも複数の種類があるため、気になる方はAmazon S3 で定義されるリソースタイプをご確認願います。

ここで重要になるのがポリシーのアクション毎に指定できるリソースタイプが決まっているということです。

例えばGetObjectアクションが指定できるリソースタイプはobjectとなります。
リソースタイプの指定を誤った場合は、AWS CLI等の実行時にエラーとなるため注意が必要です。

アクション毎に対応しているリソースタイプは、Amazon S3 のアクション、リソース、条件キーから確認できます。

S3のポリシー例

今回はIAMポリシーでいくつか例を作成していきます。

以下はバケット内のオブジェクトを表示する許可任意のオブジェクトを取得する許可となります。
バケットとオブジェクトを明確に区別して記載しました。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowBucketOperation",
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket"
            ],
            "Resource": "arn:aws:s3:::inomaso-dev-20240304"
        },
        {
            "Sid": "AllowObjectOperation",
            "Effect": "Allow",
            "Action": [
                "s3:GetObject"
            ],
            "Resource": "arn:aws:s3:::inomaso-dev-20240304/*"
        }
    ]
}

また、Statementを一つにまとめることも可能です。
恐らくこちらの書き方の方が見慣れている方が多いかもしれません。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowBucketAndObjectOperation",
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket",
                "s3:GetObject"
            ],
            "Resource": [
                "arn:aws:s3:::inomaso-dev-20240304",
                "arn:aws:s3:::inomaso-dev-20240304/*"
            ]
        }
    ]
}

なおResourceのリソースARNの一部は、アスタリスク(*)や疑問符(?)を使用することができます。
Amazon S3 のリソースに記載されている通りアスタリスク(*)は0個以上の文字の任意の組み合わせを表し、疑問符(?)は任意の1文字を表します。

例えば、バケットに使用している日付の一部を任意の1文字にしたい場合は、以下のように疑問符(?)を使用することで可能となります。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowBucketOperation",
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket"
            ],
            "Resource": "arn:aws:s3:::inomaso-dev-2024030?"
        },
        {
            "Sid": "AllowObjectOperation",
            "Effect": "Allow",
            "Action": [
                "s3:GetObject"
            ],
            "Resource": "arn:aws:s3:::inomaso-dev-2024030?/*"
        }
    ]
}

また、バケット名にinomaso-dev-を含む、すべてのバケットとオブジェクトを指定する場合は、以下のように記載できます。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowBucketAndObjectOperation",
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket",
                "s3:GetObject"
            ],
            "Resource": [
                "arn:aws:s3:::inomaso-dev-*"
            ]
        }
    ]
}

まとめ

Resourceの書き方を調べてみたところ、AWS公式ドキュメントで丁寧な解説があったのですが、それらを正しく理解できていなかったのでブログにまとめてみました。
S3のアクセス制限に困ったケースが発生したら、自信を持って説明できそうです。

この記事が、どなたかのお役に立てば幸いです。それでは!