S3のアクセスコントロールまとめ

  • 466
    いいね
  • 0
    コメント

S3のアクセスコントロールをよく理解していないのでまとめる。
日本語ドキュメントは更新されてない場合が多いので英語ドキュメントを参照することをお勧めする。
ただ、S3のアクセスコントロールについては枯れているので日本語ドキュメントでも問題ないと思う。

開発者ガイド
Developer Guide

基礎知識

アクセスコントロールの種類

S3はアクセスコントロールのために3つの方法を提供している。
AWS全般のアクセスコントロールの種類やサービスごとの対応状況についてはIAMと連携するAWSサービスが参考になる。

  • ACL(アクセスコントロールリスト)
  • バケットポリシー
  • IAMポリシー
アクセスコントロールタイプ AWSアカウントレベルの制御 IAMユーザレベルの制御 形式
ACL XML
バケットポリシー JSON
IAMポリシー JSON

アクセスコントロールリスト(ACL)の概要

ACL

バケット/オブジェクトのサブリソースとしてXMLで定義する。
AWS Management Console からは、各バケット/オブジェクトの Properties > Permissions で設定できる。

バケットポリシー

バケット/オブジェクトのアクセス権をJSONで定義する。
AWS Management Console からは、バケットの Properties > Permissions > Add(Edit) Bucket Policy で設定できる。

IAMポリシー

IAMのリソースに紐づき、S3を含むAWSリソースへのアクセス権をJSONで定義する。
AWS Management Console からは、IAMのホームディレクトリでユーザ/グループ/ロールのポリシー設定ができる。

リクエストの認可

あとで書く。
Amazon S3 がリクエストを許可する方法

評価論理

許可/拒否を決めるルール。ここが1番重要な気がする。
基本は下記の通りで 明示的拒否 > 許可 > デフォルト拒否 の順に強い。

  • デフォルト拒否 (ただし自分自身からのアクセスは除く)
  • 許可デフォルト拒否 に優先する
  • 明示的拒否許可 に優先する
  • ポリシーの評価順序は重要ではない

IAM ポリシーの評価論理

個人的に間違えそうなのが、デフォルト拒否/明示的拒否に、許可を組み合わせた場合。
条件Aに一致するリクエストが拒否される時、設定によってどういう評価になるかを表にしてみる。

条件 可否 評価
NOT A Allow(許可) デフォルト拒否
A Deny(拒否) 明示的拒否

これに評価が許可になる条件Bを組み合わせると、

(NOT A) or B → デフォルト拒否 or 許可 → 許可
A or B → 明示的拒否 or 許可 → 拒否

となり、評価がデフォルト拒否になっているからといって、拒否設定した気になっていると、
他のポリシーとの組み合わせでうっかり許可になってしまう場合がある。

対象リソースの指定

バケットポリシーやIAMポリシーで、ある Action を許可/拒否する場合、対象 Resource を ARN で指定する。
バケットに対する Action は Resource としてバケットの ARN(arn:aws:s3:::bucket) を指定する。
オブジェクトに対する Action は Resource としてオブジェクトの ARN(arn:aws:s3:::bucket/*) を指定する。

AWS Management Console から特定のS3バケットの操作を許可する例。

IAMポリシー抜粋
{
   "Statement":[
      // S3ホームディレクトリでバケット一覧を表示するために必要
      {
         "Effect":"Allow",
         "Action":[
            "s3:ListAllMyBuckets"
         ],
         "Resource":"arn:aws:s3:::*"
      },
      // バケットに対する操作を許可
      {
         "Effect":"Allow",
         "Action":[
            "s3:ListBucket",
            "s3:GetBucketLocation"
         ],
         "Resource":"arn:aws:s3:::bucket"
      },
      // オブジェクトに対する操作を許可
      {
         "Effect":"Allow",
         "Action":[
            "s3:PutObject",
            "s3:GetObject",
            "s3:DeleteObject"
         ],
         "Resource":"arn:aws:s3:::bucket/*"
      }
   ]
}

AWS Account ID と Canonical User ID の確認方法

AWS Management Console に AWSアカウントでログイン後、
右上のメニュー > Security Credentials を開き Account Identifiers から確認できる。
ただし、AWSアカウントの管理者(rootユーザ)しか確認できない。
aws s3api get-bucket-acl --bucket <bucket-name> で確認したほうが手っ取り早いかも。
AWS アカウント ID

ACL

アクセスコントロールリスト(ACL)は、各バケット/オブジェクトごとに付与され対象のアクセス権を制御できる。
バケット/オブジェクト作成時に、デフォルトで自分自身への FULL_CONTROL が付与される。
最大100個まで権限を付与できる。

バケットごと公開したい時 AWS Management Console からマウス操作だけで簡単に設定できるし、オブジェクトごとに細かくアクセス制限したい時などに使えそう。

別アカウントのバケットにオブジェクトをアップロードする場合、そのアカウントの管理者に FULL_CONTROL を与えたりする(CloudTrailなど)。
この場合ACL以外で許可する方法はない。バケットポリシーだけ設定したとしても許可はされない。

また、バケットポリシーは20KBの制限があるので、ACLを併用したほうがいいこともある。
アクセスポリシーのオプションを使用するためのガイドライン

被付与者(Grantee)

アクセス権を付与される人。
被付与者は、AWSアカウントに紐付いたメールアドレスor正規ユーザID(Canonical User ID)で指定する。
IAMユーザ単位のアクセス権は設定できない。たぶんIAMが実装される前からある機能だから。

S3には、あらかじめいくつかのグループが定義されており、グループに対してアクセス権を付与することもできる。

  • Authenticated Users
    全AWSアカウント(自分以外のアカウントも含むので注意)。
    リクエストは署名(認証)されている必要がある。

  • All Users
    誰でも。リクエストの署名有無は問わない。
    AWS Management Console の Permissions で選択できる Everyone は多分これ。

  • Log Delivery
    S3のアクセスログ書き込み権限。アクセスログについては↓。
    サーバーアクセスのロギング

アクセス許可(Permissions)

READWRITEREAD_ACPWRITE_ACPFULL_CONTROL の5つのアクセス権がある。
*_ACP はアクセスコントロールリストへのアクセス権をあらわす。
アクセスコントロールリスト(ACL)の概要 - 付与できるアクセス許可

規定ACL(Canned ACL)

S3には、あらかじめ被付与者とアクセス許可のセットが定義されており、APIのパラメータとして使用することができる。
アクセスコントロールリスト(ACL)の概要 - 既定 ACL

  • private (バケット/オブジェクト)

    デフォルトACL。所有者に FULL_CONTROL が付与される。

  • public-read (バケット/オブジェクト)

    所有者に FULL_CONTROL 、All Users に READ が付与される。

  • public-read-write (バケット/オブジェクト)

    所有者に FULL_CONTROL 、All Users に READ/WRITE が付与される。

  • authenticated-read (バケット/オブジェクト)

    所有者に FULL_CONTROL 、Authenticated Users に READ が付与される。

  • bucket-owner-read (オブジェクト)

    オブジェクト所有者に FULL_CONTROL 、バケット所有者に READ が付与される。
    バケット作成時に指定しても無視される。

  • bucket-owner-full-control (オブジェクト)

    バケット所有者とオブジェクト所有者に FULL_CONTROL が付与される。
    バケット作成時に指定しても無視される。

  • log-delivery-write (バケット)

    Log Delivery グループに WRITE/READ_ACP が付与される。

バケットポリシー

JSONの定義は、IAMポリシーの項を参照。
設定の参考例は↓。
バケットポリシーの例

  • ポリシーを定義できるのはバケット所有者のみ
  • バケット/オブジェクトレベルのアクセス権を設定できる
  • オブジェクトに対するアクセス権設定は、バケット所有者とオブジェクト所有者が同一の場合のみ可能
  • ACLと違い、IAMユーザレベルのアクセス権設定ができる
    • IAMグループレベルのアクセス設定はできない。IAMグループのIAMポリシーで設定することはできる。
  • 他AWSアカウントの管理者に許可を付与した場合、他AWSアカウントの管理者はそのIAMユーザに権限を譲渡することができる
  • バケットポリシーのサイズは20KBまで

IAMポリシー

IAMポリシーとバケットポリシーはどちらでも同じようなアクセス権を設定できるが、
ユーザにアクセス権を設定したい場合はIAMポリシーを使い、
AWSアカウントやバケットにアクセス権を設定したい場合はバケットポリシーを使う、
という決まりを作ったほうが運用時に幸せになれそう。

IAMポリシーを使ったアクセス制御のチュートリアルが↓にあるので参考に。
チュートリアル例: ユーザーポリシーを使用したバケットへのアクセスの制御

リソース作成者のアクセス許可

AWSアカウントの管理者がバケット/オブジェクトを作成した場合、デフォルトで FULL_CONTROL が付与される。
しかし、IAMユーザが作成した場合、デフォルトではアクセス権は設定されない。
なので、IAMポリシーでアクセス権を設定する必要がある。

ポリシーの要素

ポリシーの要素で気になったものだけ紹介。
要素の中には値としてポリシー変数(後述)を指定できるものもある。
IAM ポリシーエレメントの参照

Version

ポリシー言語のバージョンを表す。

ポリシー内にポリシー変数を含む場合は Version 要素を必ず指定する必要がある。
Version 要素のデフォルト値は 2008-10-17 なので、ポリシー変数がリテラル文字列として扱われるから。
2012-10-17 を指定することでポリシー変数として扱われるようになる。

設定例
"Version":"2012-10-17"

Principal

Principal とは、ポリシーにしたがってアクセス権限を付与または拒否される 1 人以上のユーザーです。

IAM ポリシーエレメントの参照 - プリンシパル

Principal 要素にはAWSアカウントID、正規ユーザID、IAMユーザのARNなどが指定できる。
NotPrincipal 要素を使うことで、特定アカウント/IAMユーザを明示的に拒否することもできる。

設定例
// AWSアカウント単位
"Principal":{"AWS":"123456789012"}
"Principal":{"AWS":"arn:aws:iam::123456789012:root"}

// IAMユーザ
"Principal":{"AWS":[
    "arn:aws:iam::123456789012:user/Isono",
    "arn:aws:iam::123456789012:user/Nakajima"
]}

// Webフェデレーションユーザ
"Principal":{"Federated":"www.amazon.com"}

Action

Action 要素にもワイルドカード(* or ?)が使える。
NotAction 要素を使うことで、特定アクション以外を明示的に拒否することもできる。

設定例
"Action":"iam:*AccessKey*"

S3の Action 一覧↓。
ポリシーでのアクセス許可の指定

Resource

取り扱う対象のオブジェクトをARNで指定する。
IAM をサポートする AWS サービス

設定例
"Resource":[
    "arn:aws:dynamodb:ap-northeast-1:123456789012:table/table1",
    "arn:aws:dynamodb:ap-northeast-1:123456789012:table/table2"
]

Condition

オプショナルな要素。ポリシーの実行条件を細かく指定できる。

色々できるので詳細は↓を参照のこと。
IAM ポリシーエレメントの参照 - 条件

ポリシー変数

ポリシー変数を使う場合は "Version":"2012-10-17" をポリシーに含めること。
未指定の場合、デフォルトで旧バージョン(2008-10-17)が指定されたことになるのでポリシー変数は使えない。
その場合、ポリシー変数はリテラル文字列として扱われる。
IAM ポリシー変数の概要

変数の使用箇所

Resource 要素と Condition 要素で使える。

設定例
// Resource要素
"Resource":["arn:aws:s3:::bucket/home/${aws:username}/*"]

// Condition要素
"Condition": {
    "StringLike": {
        "sns:endpoint": "https://example.com/${aws:username}/*"
    }
}

キーの種類

リクエストから取得されるキー

Condition のキーとして指定する場合、大文字/小文字を区別するので注意。

  • aws:CurrentTime

    日時条件

  • aws:EpochTime

    日付をエポックつまり UNIX 時間で表したもの。日時条件で使用

  • aws:principaltype (※)

    プリンシパルがアカウント、ユーザー、フェデレーション、または引き受けられたロールかどうかを示す値

  • aws:SecureTransport

    リクエストが SSL を使用して送信されたかどうかを示すブール値

  • aws:SourceIp

    IP アドレス条件で使用するための、リクエスタの IP アドレス

  • aws:UserAgent

    文字列条件で使用するための、リクエスタのクライアントアプリケーションに関する情報

  • aws:userid (※)

    現在のユーザーの一意の ID

  • aws:username (※)

    現在のユーザーのフレンドリ名

※ プリンシパルごとの aws:username aws:userid aws:principaltype の値を表にしたもの。

プリンシパル aws:username aws:userid aws:principaltype
AWSアカウント - AWSアカウントID Account
IAMユーザ IAMユーザ名 一意のID User
委任ユーザ - AWSアカウントID:発信者が指定した名前 FederatedUser
Webフェデレーションユーザ - - AssumedRole
SAMLフェデレーションユーザー - - AssumedRole
委任されたロール - ロールID:発信者が指定したロール名 AssumedRole
Amazon EC2 インスタンスに割り当てられたロール - ロールID:インスタンスID AssumedRole
匿名(SQS/SNS/S3のみ) - - Anonymous

IAM ポリシー変数の概要 - ポリシー変数に使用可能なリクエスト情報

Webフェデレーションユーザに関するキー

どのプロバイダでログインしたかは aws:FederatedUser で取得できる。

  • aws:FederatedUser

    • Amazonでのログイン認証時に www.amazon.com を返す
    • Facebookでのログイン認証時に graph.facebook.com を返す
    • Googleでのログイン認証時に accounts.google.com を返す

アプリケーションIDとユーザIDも取得できる。
プロバイダごとのキーは下記の通り。

プロバイダ アプリケーションIDのキー ユーザIDのキー
Amazon www.amazon.com:app_id www.amazon.com:user_id
Facebook graph.facebook.com:app_id graph.facebook.com:id
Google accounts.google.com:aud accounts.google.com:sub

SAMLベースのフェデレーションユーザに関するキー

下のほうに一覧が書いてある。
IAM ポリシーエレメントの参照 - 条件

S3固有のキー

サービス固有のキーもある。S3で利用可能なキーは↓。
ポリシーでの条件の指定

クロスアカウント

このチュートリアルは順を追って関係者が増えて複雑になっていくので理解しやすい。
(例1はクロスアカウントではない)
チュートリアル例: Amazon S3 リソースへのアクセスの管理

とにかくIAMユーザ(子)はAWSアカウントの管理者であるrootユーザ(親)の許可がないとダメ。
クロスアカウントの場合、親であるAWSアカウントの管理者が2人になるので、子はそれぞれに親に許可を得る必要がある。