権限設計プラクティス

Amazon S3の権限管理を理解する:開発者が知るべきIAMとバケットポリシーの設定方法

Tags: AWS S3, IAM, バケットポリシー, アクセス制御, 権限管理

はじめに

Webアプリケーション開発やデータ処理パイプラインにおいて、Amazon S3のようなクラウドストレージは不可欠な存在です。しかし、そこに保存されるデータは機密情報を含む場合が多く、適切なアクセス権限管理が非常に重要になります。誤った設定は、データの漏洩や不正な書き換えといった深刻なセキュリティインシデントに直結する可能性があります。

開発者として、自身が構築するアプリケーションやサービスが必要とするS3リソースに対して、最小限かつ安全な権限を設定する方法を理解しておくことは、セキュアなシステム開発の基盤となります。本記事では、Amazon S3における主要な権限管理メカニズムであるIAMポリシーとバケットポリシーに焦点を当て、その概念、設定方法、そして両者の使い分けや組み合わせについて、開発者の視点から実践的に解説します。

Amazon S3権限管理の基本

S3における権限管理は、「誰が (Principal)」「どのリソース (Resource) に対して」「どのような操作 (Action) を」「どのような条件 (Condition) の下で」許可または拒否するかを定義することです。この定義を行うための主要なメカニズムが、AWS Identity and Access Management (IAM) とS3バケットポリシーです。

AWSアカウント内のユーザー、グループ、ロールといったエンティティに権限を付与する場合、主にIAMポリシーを使用します。一方、特定のS3バケットとその内部のオブジェクトに対するアクセス権限を、AWSアカウント内外のプリンシパルに対して詳細に設定する場合、バケットポリシーを使用します。

AWS IAMによるS3権限管理

IAMは、AWSリソースへのアクセスを安全に管理するためのフレームワークです。IAMを通じて、S3バケットやオブジェクトへのアクセスを許可するユーザー、グループ、またはロールを定義し、それらに紐づくポリシーで具体的な操作権限を指定します。

IAMポリシーの構造

IAMポリシーはJSON形式で記述され、以下の要素で構成されます。

アプリケーションからのS3アクセスとIAMロール

EC2インスタンス上で動作するWebアプリケーションや、AWS Lambda関数からS3にアクセスする場合、そのアプリケーションにIAMロールを割り当てて権限を管理するのが最も推奨される方法です。アプリケーションコード内に認証情報を埋め込む必要がなく、安全にS3リソースにアクセスできます。

例えば、my-data-bucket というバケットからオブジェクトを読み取る権限をLambda関数に付与したい場合、以下のようなIAMポリシーを作成し、Lambda関数に割り当てるIAMロールにアタッチします。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject"
            ],
            "Resource": "arn:aws:s3:::my-data-bucket/*"
        }
    ]
}

このポリシーは、my-data-bucket バケット内のすべてのオブジェクト (arn:aws:s3:::my-data-bucket/*) に対して、s3:GetObject アクション(オブジェクトのダウンロード)を「許可 (Allow)」します。

同様に、特定のバケットにオブジェクトをアップロードする権限が必要な場合は、s3:PutObject アクションを追加します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:PutObject"
            ],
            "Resource": "arn:aws:s3:::my-data-bucket/*"
        }
    ]
}

バケット内のオブジェクトだけでなく、バケットそのものに対する操作(例: オブジェクト一覧の取得 s3:ListBucket)を許可する場合は、リソースとしてバケット自体のARNを指定します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket"
            ],
            "Resource": "arn:aws:s3:::my-data-bucket"
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:PutObject"
            ],
            "Resource": "arn:aws:s3:::my-data-bucket/*"
        }
    ]
}

S3バケットポリシーによる権限管理

S3バケットポリシーは、特定のS3バケットに直接アタッチされるリソースベースポリシーです。IAMポリシーが「誰に」権限を付与するかを主眼とするのに対し、バケットポリシーは「どのリソース(この場合、バケット)に」誰からのアクセスを許可または拒否するかを定義します。

バケットポリシーの大きな特徴は、同一AWSアカウント内のプリンシパルだけでなく、他のAWSアカウントのプリンシパルや、認証されていない匿名ユーザーに対しても権限を設定できる点です。

バケットポリシーの構造

バケットポリシーもIAMポリシーと同様にJSON形式で記述されますが、Statement内のPrincipal要素が必須となる点が異なります。

バケットポリシーの設定例

例えば、my-data-bucket バケットに対して、OtherAccountId という別のアカウントの特定のIAMユーザー AnotherUser に読み取り専用権限を付与したい場合、my-data-bucket に以下のバケットポリシーを設定します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::OtherAccountId:user/AnotherUser"
            },
            "Action": [
                "s3:GetObject"
            ],
            "Resource": "arn:aws:s3:::my-data-bucket/*"
        }
    ]
}

また、特定のIPアドレス範囲 (192.0.2.0/24) からのアクセスのみを許可したい(それ以外を拒否したい)といった制限も、バケットポリシーの Condition 要素を使って設定できます。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::my-data-bucket/*",
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": "192.0.2.0/24"
                }
            }
        },
        {
            "Effect": "Deny",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::my-data-bucket/*",
            "Condition": {
                "NotIpAddress": {
                    "aws:SourceIp": "192.0.2.0/24"
                }
            }
        }
    ]
}

この例では、最初のステートメントで指定IPからの GetObject を許可し、次のステートメントでそれ以外のIPからの GetObject を明示的に拒否しています。

IAMポリシーとバケットポリシーの使い分けと組み合わせ

IAMポリシーとバケットポリシーは、それぞれ異なる視点から権限を管理します。

両方のポリシーが存在する場合、S3へのアクセスは、いずれかのポリシーで明示的に「拒否」されている場合は拒否され、明示的な「拒否」がなく、かつ * IAMポリシーで「許可」 されているか、または * バケットポリシーで「許可」 されている 場合にのみ許可されます。

つまり、明示的な拒否は常に許可に優先します。そして、許可されるためには、IAMポリシーかバケットポリシーのどちらかで許可されている必要があります(匿名ユーザーへのバケットポリシーによる許可など、IAMポリシーが適用されないケースもあるため、「いずれかのポリシーで許可」という表現が適切です)。

どちらを使うべきか?

多くの場合、IAMポリシーでプリンシパルごとの基本的なS3アクセス権限を設定しつつ、特定のバケットに対してはバケットポリシーで詳細なアクセスルール(クロスアカウントアクセス、IP制限など)を追加するという形で、両者を組み合わせて使用します。

実践的な権限設定の注意点

まとめ

本記事では、Amazon S3におけるデータアクセス権限の管理において、IAMポリシーとバケットポリシーという二つの主要なメカニズムについて解説しました。

両者の評価ロジック(明示的な拒否の優先、いずれかの許可で許可)を理解し、最小権限の原則に基づき、適切な方を単独で、または両方を組み合わせて使用することが、S3に保存される機密データを安全に保つための鍵となります。

権限管理はシステムのセキュリティを担保する上で非常に重要な要素です。この記事が、日々の開発業務におけるS3の権限設定において、よりセキュアな選択をするための一助となれば幸いです。