Access Policy Language (APL)

概要

Access Policy Language (APL) とは、バケットポリシーを設定するための言語です。

下の図と表は、リソースのアクセス制御を行うメインコンポーネントとのやりとりを示しています。


  1. リソースの所有者

  2. リソース
    本サービスの内部にあるものです。バケット, オブジェクトなど。

  3. バケットポリシー
    本サービス内では、1バケットにつき1バケットポリシーとなります。
    本サービスのAPIはバケットポリシーの更新を行います。

  4. 複数の利用者からサービスへリクエスト

  5. Access Policy Language で書かれた評価コード
    来たリクエストに対して適用可能なバケットポリシーを評価し、リソースへアクセス可能/不可能を判断します。

Access Policy Language を使う

下の表は、Access Policy Languageを使用してどのようにアクセス制御がされるかを示しています。

Access Policy Languageによるアクセス制御のプロセス
  1. バケットリソースに対してバケットポリシーを書きます。
  2. 本サービスへバケットポリシーをアップロードします。
    本サービスでは、バケットポリシーを更新できるAPIを提供しています。
    例えば、利用者はAPIの PUT Bucket policy を使用することで、バケットへバケットポリシーをセットすることができます。
  3. ユーザがリソースへリクエストします。
    例)あるユーザがバケットへオブジェクトをアップロードします。
  4. 本サービスは、そのリクエストへどのバケットポリシーが適用可能かを判断します。
    例)利用可能なすべてのバケットポリシーを見て、どれが適用可能かを判断します。 (判断基準は対象のリソースが何か、リクエストしたユーザが誰か、などの情報から)
  5. 本サービスはバケットポリシーを評価します。
    例)バケットポリシーを見て、そのユーザがバケットへオブジェクトをアップロード可能かを判断します。
  6. サービスは、リクエストを拒否する、または、リクエストの処理を続行します。
    例)バケットポリシーの評価結果より、Access Denied のエラーを返す、または処理を続行する。

Key の概念

Permission

Permissionとは、本サービスにおいて特定のリソースに対するアクセスを許可又は禁止する為の考え方です。
Permissionは基本的に以下の形式を取ります。

  • AはBに対し、条件Cが成立する場合に操作Dを行う事ができる。

具体的には、たとえば以下のような内容となります。

  • ジェーン(A)はバケット「MyImage」(B)に対し、2012/12/31の午前0時までなら(C)オブジェクトをPUTする(D)事ができます。

この場合は、ジェーンがバケット「MyImage」に対してリクエストを送信する毎に、ジェーンがPermissionを与えられており、且つ送信されたリクエストが条件を満たしているかどうかを確認します。

Statement

Statementは宣言の中心的な要素になります。この要素は複数の要素を内包する事ができます。
Statementは個別の宣言の配列を持ちます。個々の宣言は異なるJSONブロックであり、中括弧「{}」で括られています。

"Statement":[{...},{...},{...}]

 

Policy

Policy は 1つ以上の Statement を持ちますが、 各Statementは独立したものと見なします。

Principal

Principalは、バケットポリシーによって許可または不許可を与えられる 対象となる利用者 を表します。
Principalの指定には、本サービスの アクセスキーID を使用し、プレフィックスに IIJGIO: を指定します。
アスタリスク「*」を用いる事で、匿名ユーザを含む全ての利用者として指定することもできます。
アクセスキーIDについては、サービスオンラインでご確認いただけます。

 

(匿名ユーザを含む)全ての利用者 を指定する場合には以下のように記述してください。

"Principal": {
    "IIJGIO": "*"
},

複数の利用者を指定する場合は、以下のように配列で記述します。

 "Principal": {
    "IIJGIO": ["SAMPLE00000000000000", "SAMPLE00000000000001"]
},

 

Action

Principalが権限を与えようとしている行動を表します。
“A has permission to do B to C where D applies” の B に相当する。
ここで指定する Action名については、データストレージ概要 ご覧ください。

Resource

Resourceはバケットポリシーの影響の対象となるバケット、オブジェクトを表します。
値には、本システムが規定するフォーマットに従って指定する必要があります。
複数文字のワイルドカード”*”および単一文字のワイルドカード”?”が使用可能です。

Condition と Key

Condition は、何らかの制約またはパーミッションの詳細を表します。

  • A has permission to do B to C where D applies.

の D に相当します。

代表的な Condition は、以下に関係します。

  • 日付と時刻
    例: リクエストは、指定日よりも前に到着していなければならなりません。
  • IPアドレス
    例: リクエストしたクライアントのIPアドレスは、特定のCIDR範囲になければならなりません。

Keyは、アクセス制約の基本的な特性を表します(例: リクエストの日時)。
ConditionとKeyの両方を使用してアクセス制限を表現することができます。
例)2010/05/30より前のアクセスを制限したい場合は、DateLessThan という Condition を使用し、値に 2010-05-30T00:00:00Z を指定します。

 

Requester

本サービスへリクエストを出し、特定のリソースにアクセスしたのは誰かを表します。
Requesterは “Will you allow me to do B to C where D applies” というリクエストを出します。

 

Evaluation

本サービスが、受け取ったリクエストの許可/拒否をバケットポリシーに基づいて評価するプロセスです。

 

Effect

評価の際に返される結果です。
指定可能な値は、”Deny”, “Allow”の2つのみです。

以下の2つの例は、似ていますが異なります。

  • 例1: 「Antarcticaから来たすべてのリクエストを拒否する」というバケットポリシーを設定したい場合
    ==> Antarcticaに割り当てられたIPアドレスが使用されたリクエストに対して Effect=Deny を設定するということ
  • 例2: 「Antarctica以外から来たすべてのリクエストを許可する」というバケットポリシーを設定したい場合
    ==> Antarctica以外から来たリクエストに対して Effect=Allow を設定するということ

 

Default Deny

バケットポリシーに Allow, Explicit Deny のどちらも指定されていない場合の、デフォルトの結果値としてバケットポリシーは Deny となります。

 

Allow

“Effect=Allow”のStatementを持つ結果です。
以下のことに注意する必要があります。

  • Effect=Allow は Default Deny を上書きできます。
  • Effect=Allow は Explicit Deny を上書きできません。

 

Explicit Deny

“Effect=Deny” の Statement を持つ結果です。

 

評価ロジック

評価処理のゴールは、与えられたリクエストの 許可/拒否 を決めることです。
評価ロジックは、下記のように幾つかのルールからなります。

  • デフォルトでは、リソースに対するリクエストは すべて拒否します。
  • Allow設定は、デフォルトの Deny設定を上書きします。
  • Explicit Deny設定は、Allow設定を上書きします。
  • バケットポリシーが複数存在する場合、評価結果は評価の順序に関与しない(どのバケットポリシーから評価しても同じ結果となる)。


  1. Default Deny からスタートします。
  2. リクエストに適用可能なコードを実行し、評価します。
  3. それらのバケットポリシーの中から、リクエストに対して Explicit Deny を指示するものがあるかを確認します。 1つでも存在する場合は Deny を返し、評価プロセスを終了します(Explicit Deny)。
  4. Explicit Deny が存在しない場合、次にAllowを指示するものがあるかを確認します。 1つでも存在する場合は Allow を返し、評価プロセスを終了します。
  5. Allow が存在しない場合は Deny を返します(Default Deny)。

 

Explicit Deny と Default Deny

リクエストに直接適用するバケットポリシーがない場合 Default Deny を返します。
Statement内のどのConditionにも該当しない場合 Default Deny を返します。
Conditionが存在する場合は、バケットポリシー内のEffectタグの内容に従い Allow または Deny を返します。

例)Antarcticaから来たリクエストを拒否することを考えてみると、「Antarctica以外から来たリクエストを許可(Allow)する」というバケットポリシー(ここでは”Policy A1”と呼ぶ)を書くことができます。


もし U.S. からリクエストが来た場合、(Antarcticaから来たリクエストではないため)このConditionが適用されます。従ってリクエストは Allow と評価されます。
もし Antarctica からリクエストが来た場合は,このConditionは適用されないため、評価結果は Default Deny となります。
Explicit Deny を使用して、以下のようにバケットポリシーを書くこともできます(”Policy A2” と呼びます)。

もし Antarctica からリクエストが来た場合は このConditionが適用されるので Explicit Deny が返されます。
Default Deny と Explicit Deny の違いは重要で Default Deny は Allow により上書きされますが Explicit Deny は上書きされません。

以下は「2010/06/01に到着したリクエストを許可(Allow)する」というもう1つのバケットポリシー(”Policy B” と呼ぶ)を考えた例です。

  • 「シナリオ1」は Policy A1 と Policy B の組み合わせです。
  • 「シナリオ2」は Policy A2 と Policy B の組み合わせです。
  • どちらにも「2010/06/01 に Antarctica からリクエストを受け取った」というケースを流します。


  • シナリオ1 Policy A1 は前述の通り Default Deny を返します。 Policy B では、リクエストが 2010/06/01に来ているので Allow となります。
    Policy B の結果の Allow が Policy A1 の結果の Default Deny を上書きするため、リクエストは許可されます。

  • シナリオ2 Policy A2 は Explicit Deny を返し、 Policy B は Allow を返します。
    Policy A2 の結果の Explicit Deny が Policy B の結果の Allow を上書きするため、リクエストは拒否されます。

 

APLの書き方

バケットポリシーの基本的な構造

バケットポリシーは、JSONドキュメントで表現され、下図のような情報を含みます。

  • 各バケットポリシーで共通の情報(オプション)
  • 1つ以上の個々のStatement

個々のStatementは、アクセス制御の命令セットを保持します。

バケットポリシーが複数のStatementを含む場合、評価時に論理和(OR)が適用されます。
Statementは、幾つかの要素の集合からなります。

バケットポリシーの要素

全ての要素はオプションとなっています。

Version

Versionは、Access Policy Languageのバージョンを示します。
現在は “2008-10-17” という値のみが許可されています。

"Version":"2008-10-17"

 

Id

Id はバケットポリシーの任意の識別子です。
一意性を確実にするため、ID には UUID を使うか、UUID を ID の一部にすることを推奨します。
本サービスでは、Id 要素を要求するよう実装しており、かつ一意な値にしておく必要があります。

 

Permission

Permission は、特定のリソースに対してアクセスを許可または拒否するものです。
Permission は基本的に “A is/isn’t allowed to do B to C where D applies” の形式に従います。

  • 例)「Jane(A) has permission to receive messages (B) from John’s Amazon SQS queue (C)as long as she asks to receive them before midnight on May 30, 2009 (D)」

 

Statement

Statement はアクセス制御の命令セットです。 Statement 要素には複数の Statement を配列で指定することができます。
Statement が複数存在する場合は、それぞれの評価値の論理和(OR)が最終的な結果となります。
Statement の記述は以下のようにJSONで表記します。

"Statement":[{...},{...},{...}]

 

Policy

Policy は1つ以上のStatementのコンテナとして位置づけられるドキュメントで、 Access Policy Language (APL) によって記述されます。

例) Policy が以下の2つのStatementを持っています。

  • Jane は John の オブジェクト を読むことができる。
  • Bob は John の オブジェクト を読むことができない。

これは、個々のStatementを個別に保持している2つのバケットポリシーと同義です。つまり、分かれていてもまとまっていても同じ意味となります。

 

Issuer

Issuer はリソースに対してパーミッションを許可する Policy を書いた人です。
Issuer は常にリソースの所有者となります。つまり、所有していないリソースにはバケットポリシーはセットすることができません。

 

Sid (Statement ID)

Policy Statementを提供する際の、任意の識別子です。
Policy Document ID(Id)のサブのIDといった位置づけです。
本サービスでは、本要素は必須で、ユニークな値が必要とされます。

"Sid":"1"

 

Effect

結果として Allow なのか Explicit Deny なのかを示す必須の要素です。
値は Allow または Deny のみが許可されます。

"Effect":"Allow"
Principal

バケットポリシーの適用対象で、複数指定することができます。
Principal の値は、本システムの アクセスキーID を使用します。
全てのユーザに適用できる “*” という値を指定することも可能です。
JSON内では、”IIJGIO:” をアクセスキーIDの接頭辞として使用します。

 

Action

Action は、 Allow/Deny を決めるアクセスの種類です。
本要素には、複数の値を記載することが可能です。
値の表記はフリーフォームですが、本サービスが期待する値とマッチする必要があります。
全てのアクションを示す “*” を値として指定することが可能です。

 

Resource

Resourceは、Statementの影響の対象とするリソース(バケット、もしくはオブジェクト)を指定します。
リソース記述子の書式に従い記述します。

grn:iijgio:dag:::mybucket/myobject

この値には、ワイルドカード文字(複数文字にマッチする”*” と単一文字にマッチする”?”)を含める事ができます。
代表的な設定を以下に示します。

  • バケットを指定する場合(末尾に/を書きません。)
grn:iijgio:dag:::mybucket/myobject
  • オブジェクトを指定する場合(オブジェクトのパス)
grn:iijgio:dag:::mybucket/
  • 特定のバケット内の全てのオブジェクトを指定する場合
grn:iijgio:dag:::mybucket/*

 

ResourceとActionの関連はPut Policy時にチェックされます。
Resourceがバケットを指す場合、バケットに関するActionだけが同一Statmentに記載出来ます。 Resourceがオブジェクトを指す場合、オブジェクトに関するActionだけが同一Statmentに記載出来ます。 同時に記載する必要がある場合はStatmentを分割して下さい。

 

Put Bucket policyでエラーになる例

{
  "Version": "2008-10-17",
  "Id": "aaaa-bbbb-cccc-dddd",
  "Statement": [
    {
      "Effect":"Deny ",
      "Sid":"1",
      "Principal": {
        "IIJGIO": ["ACCESSKEYID000000001","ACCESSKEYID000000002"]
      },
      "Action": ["dag:ListBucket","dag:PutObject","dag:GetObject"],
      "Resource": ["grn:iijgio:dag:::bucket","grn:iijgio:dag:::bucket/*"]
    }
  ]
}

 

Put Bucket policyでエラーにならない例
{
  "Version": "2008-10-17",
  "Id": "aaaa-bbbb-cccc-dddd",
  "Statement": [
    {
      "Effect":"Deny ",
      "Sid":"1",
      "Principal": {
        "IIJGIO": ["ACCESSKEYID000000001","ACCESSKEYID000000002"]
      },
      "Action": ["dag:ListBucket"],
      "Resource": "grn:iijgio:dag:::bucket"
    },
    {
      "Effect":"Deny ",
      "Sid":"2",
      "Principal": {
        "IIJGIO": ["ACCESSKEYID000000001","ACCESSKEYID000000002"]
      },
      "Action": ["dag:PutObject","dag:GetObject"],
      "Resource": "grn:iijgio:dag:::bucket/*"
    }
  ]
}

 

Condition

Conditionブロック

Condition要素は、Policy Statementの中で一番複雑な部分です。
Condition要素は複数の条件を持ち、さらに各条件の中には複数の Key-Value ペアがあるので「Conditionブロック」と呼びます。
特定のKeyを除き、通常Keyは複数のValueを持つことができます。


Conditionブロックを作成する際、各Conditionの名前と少なくとも1つのKey-Valueペアを定義する必要があります。
使用できるKeyは、本システムで提供されているものがあります。

以下は、NumericEquals を使用した例です。

  • foo の値が A か B のどちらかである必要がある。
  • bar の値が C である必要がある。

さらに 「2009/01/01以降のアクセスを拒否する」 という条件を追加したい場合、DateGreaterThan を使用します。

Conditionブロック内のCondition間、およびCondition内のKey間では、論理積(AND)が適用されます。
単一KeyのValue間では、論理和(OR)が適用されます。

使用できるKeyは、本システムで提供されているものを使用します(例: 日時に基づいてアクセス制限したい場合には iijgio:CurrentTime を使用します)。

例として、以下の3つの Condition をアップロードしたいとします。

  • 日時は 2010/08/16 12:00 以降である必要がある。
  • 日時は 2010/08/16 15:00 より前である必要がある。
  • リクエストの IP は、192.168.176.0/24 または 192.168.143.0/24 の範囲である必要がある。

Condition ブロックは3つの Condition から成り、このすべてを通過したものがリソースへアクセスできます
この例のバケットポリシーは、以下のように書くことができます。

"Condition" : {
    "DateGreaterThan" : {
        "iijgio:CurrentTime" : "2009-04-16T12:00:00Z"
    },
    "DateLessThan" : {
        "iijgio:CurrentTime" : "2009-04-16T15:00:00Z"
    },
    "IpAddress" : {
        "iijgio:SourceIp" : ["19.168.176.0/224", "192.168.143.0/24"]
    }
}

利用可能なキー

本システムで予め用意されているキーは、以下の通りです。

キー名は大文字・小文字は区別しません。つまり iijgio:CurrentTime は “IIJGIO:currenttime” と同義です。

表. Condition のキー一覧
キー説明
iijgio:CurrentTime日付/時刻 に関する条件
iijgio:SecureTransportリクエストがSSLを使用されているかを示すboolean値
iijgio:SourceIpリクエスト側のIPアドレス
iijgio:UserAgentリクエスト側のクライアントアプリケーションの種類
iijgio:EpochTimeエポック時間からの経過秒
iijgio:RefererHTTP referer と同等

条件タイプ

一般的に指定可能な、条件タイプは以下の通りです。

  • 文字列
  • 数値
  • 日付と時刻
  • Boolean値
  • IPアドレス
  • リソース記述子 (GRN)

文字列の条件

文字列マッチング・ルールに従います。

表. Condition の文字列の条件
条件説明
StringEquals

完全一致

【Short version】 streq

StringNotEquals

一致しない

【Short version】 strneq

StringEqualsIgnoreCase

完全一致(大文字・小文字の区別なし)

【Short version】 streqi

StringNotEqualsIgnoreCase

一致しない(大文字・小文字の区別なし)

【Short version】strneqi

StringLike

部分一致。

複数文字にマッチするワイルドカード(*)が使用可能です。

【Short version】 strl

StringNotLike

(部分的にも)一致しない

StringLike と同じく、ワイルドカード文字を使用可能です。

【Short version】 strnl

数値の条件

  • 数値マッチング・ルールに従います。
  • 整数・実数ともに指定可能です。分数表現や
  • 無理数はサポートしていません。
表. Condition の数値の条件
条件説明
NumericEquals

値が一致する

【Short version】 numeq

NumericNotEquals

値が一致しない

【Short version】 numneq

NumericLessThan

Less than マッチング

【Short version】 numlt

NumericLessThanEquals

Less than or equals マッチング

【Short version】 numlteq

NumericGreaterThan

Greater than マッチング

【Short version】 numgt

NumericGreaterThanEquals

Greater than or equals マッチング

【Short version】 numgteq

日付の条件

  • 日付,時刻マッチング・ルールに従います。値はW3Cが規定するISO
  • 8601日付フォーマットに従います。 (http://www.w3.org/TR/NOTE-datetime
  • iijgio:CurrentTime を指定すると、リクエスト時間を取得可能です。
  • ワイルドカードは指定不可です。
表. Condition の 日付の条件
条件説明
DateEquals

完全一致

【Short version】 dateeq

DateNotEquals

一致しない

【Short version】 dateneq

DateLessThan

キーが無効になる時点の時間

【Short version】 datelt

DateLessThanEquals

キーが無効になる時点の時間

【Short version】 datelteq

DateGreaterThan

キーが無効になる時点の時間

【Short version】 dategt

DateGreaterThanEquals

キーが無効になる時点の時間

【Short version】 dategteq

Boolean値の条件

表. Condition の 真偽値の条件
条件説明
Bool完全一致

IPアドレスの条件

  • IPアドレスマッチング・ルールに従います。

  • 基本的には、条件と一緒に “iijgio:SourceIp” キーを使用する形になります。

  • 値は、標準CIDRフォーマットに従います。 例: 10.52.176.0/24など
    詳細は http://www.rfc-editor.org/rfc/rfc4632.txt をご覧ください。

表. Condition の IPアドレスの条件
条件説明
IpAddressホワイトリスト・ベースのIPアドレス(範囲指定あり) 指定
NotIpAddressブラックリスト・ベースのIPアドレス(範囲指定あり) 指定

 

リソース記述子 (GRN) の条件

  • GRNマッチング・ルールに従います。
  • 対象の値はString型です。
表. Condition のリソース記述子(GRN) の条件
条件説明
GrnEquals

完全一致

【Short version】 arneq

GrnNotEquals

一致しない

【Short version】 arnneq

GrnLike

部分一致

GRNは6つのコロンで分割された値から成り、各部分には 複数文字にマッチするワイルドカード(*)および単一文字にマッチするワイルドカード(?)が指定可能です。

【Short version】 arnl

GrnNotLike

部分一致しない

GrnLikと同じく、ワイルドカード指定が可能です。

【Short version】arnnl

サンプル

{
    "Statement":[{
        "Effect": "Allow",
        "Principal": {
            "IIJGIO": "210987654321"
        },
        "Action": "grn:GetObject",
        "Resource": "grn:iijgio:dag:::mybucket/myobject",
        "Condition": {
            "GrnEquals": {
                "iijgio:SourceGrn":"grn:iijgio:dag:::mybucket/myobject"
            }
         }
    }]
}

 

サポートするデータ型

Access Policy Languageは、以下のデータ型をサポートしています。

  • 文字列
  • 数値 (整数,実数)
  • Boolean値
  • Null
  • List
  • Map
  • 構造体 (ネストされたMap)

以下は、シリアライズ(JSON)した際のデータ型とのマッピングです。
値はUTF-8でなければなりません。

 

表. Access Policy Language でサポートしているデータ型
データ型JSONのデータ型
StringString
IntegerNumber
FloatNumber
Booleantrue false
Nullnull
DateString (ISO 8601に従う)
IpAddressString (RFC 4632 に従う)
ListArray
ObjectObject

 

バケットポリシーの制約

以下は、本システムに関するバケットポリシーの制約情報です。

  • バケットポリシーの最大サイズは 20KB です。
  • Resourceに指定する値は、バケット名またはバケット名+パス文字列(bucket/*)で開始される必要があります。
  • 各バケットポリシーは、ユニークな Policy ID (Id) を持ちます。
  • バケットポリシーの中の各Statementは、ユニークなStatement ID(Sid)を持ちます。
  • 各バケットポリシーは、1つのバケットまたはリソースのみを対象とします。
    (バケットポリシーを書く際には、別バケットまたは別バケットにあるリソースを参照することはできません)