ファイルを保護する方法を学ぶ

Cloud Storage for Firebase には、Cloud Storage 用の Firebase Security Rules と呼ばれる宣言型パスベースのセキュリティ モデルがあり、これを使用してすばやく簡単にファイルを保護できます。

ルールについて

Cloud Storage 用の Firebase Security Rules は、Cloud Storage に格納されているファイルの読み取りアクセス権や書き込みアクセス権を持つユーザーを決定します。また、ファイルパスの構造やファイルに含まれるメタデータの評価も行います。基本のルールは allow ルールです。これは、次の例に示すように、オプションで指定されている条件を満たす場合に、read リクエストと write リクエストを許可します。

// If no condition is specified, the rule evaluates to true
allow read;

// Rules can optionally specify a condition
allow write: if <condition>;

// Rules can also specify multiple request methods
allow read, write: if <condition>;

パスの照合

Cloud Storage Security Rules では、match を使用して、Cloud Storage 内のファイルにアクセスするためのファイルパスを照合します。また、match を使用して完全なパスまたはワイルドカード パスと照合することができ、ルールをネストすることもできます。リクエスト メソッドを許可する照合ルールがない場合や、条件が false になる場合、リクエストは拒否されます。

完全一致

// Exact match for "images/profilePhoto.png"
match /images/profilePhoto.png {
  allow write: if <condition>;
}

// Exact match for "images/croppedProfilePhoto.png"
match /images/croppedProfilePhoto.png {
  allow write: if <other_condition>;
}

ネストされた一致

// Partial match for files that start with "images"
match /images {
  // Exact match for "images/profilePhoto.png"
  match /profilePhoto.png {
    allow write: if <condition>;
  }

  // Exact match for "images/croppedProfilePhoto.png"
  match /croppedProfilePhoto.png {
    allow write: if <other_condition>;
  }
}

ワイルドカードの一致

ルールでは、match を使用して、ワイルドカードを使ったパターンと照合させることもできます。ワイルドカードは名前付き変数で、1 つの文字列(profilePhoto.png など)や複数のパスセグメント(images/profilePhoto.png など)を表します。

ワイルドカードは、{string} のように、ワイルドカード名を中かっこで囲んで作成します。複数のセグメントのワイルドカードを宣言するには、{path=**} のように =** をワイルドカード名に追加します。

// Partial match for files that start with "images"
match /images {
  // Exact match for "images/*"
  // e.g. images/profilePhoto.png is matched
  match /{imageId} {
    // This rule only matches a single path segment (*)
    // imageId is a string that contains the specific segment matched
    allow read: if <condition>;
  }

  // Exact match for "images/**"
  // e.g. images/users/user:12345/profilePhoto.png is matched
  // images/profilePhoto.png is also matched!
  match /{allImages=**} {
    // This rule matches one or more path segments (**)
    // allImages is a path that contains all segments matched
    allow read: if <other_condition>;
  }
}

複数のルールが 1 つのファイルと一致する場合、結果は、すべてのルール評価の結果の OR になります。つまり、ルールのどれかでファイルの一致が true になると、結果は true になります。

上記のルールでは、ファイル「images/profilePhoto.png」は condition または other_condition が true になると、読み取り可能になります。これに対して、ファイル「images/users/user:12345/profilePhoto.png」に影響する条件は other_condition の結果だけです。

ワイルドカード変数は、match の指定ファイル名またはパス認証から参照できます。

// Another way to restrict the name of a file
match /images/{imageId} {
  allow read: if imageId == "profilePhoto.png";
}

Cloud Storage Security Rules はカスケード処理されません。ルールは、リクエストパスと、ルールで指定されているパスが一致する場合のみ評価されます。

リクエストの評価

アップロード、ダウンロード、メタデータの変更、削除は、Cloud Storage に送信される request を使用して評価されます。request 変数には、リクエストが行われるファイルパス、リクエストの受信時間、新しい resource 値(リクエストが書き込みの場合)が含まれます。HTTP ヘッダーと認証状態も含まれます。

また、request オブジェクトには、ユーザーの一意の ID と request.auth オブジェクト内の Firebase Authentication ペイロードも含まれます。これらについては、このドキュメントのユーザーベースのセキュリティのセクションで詳しく説明します。

request オブジェクトのプロパティの完全なリストは次のとおりです。

プロパティ タイプ 説明
auth マップ<文字列, 文字列> ユーザーがログイン済みの場合、uid(ユーザーに一意の ID)と tokenFirebase Authentication JWT クレームのマップ)を提供します。それ以外の場合は、null になります。
params マップ<文字列, 文字列> リクエストのクエリ パラメータを含むマップです。
path パス リクエストの実行先のパスを表す path です。
resource マップ<文字列, 文字列> write リクエスト時にのみ指定される新しいリソース値です。
time timestamp リクエスト評価時のサーバー時刻を表すタイムスタンプです。

リソースの評価

ルールを評価するときに、アップロード、ダウンロード、変更、または削除するファイルのメタデータも評価したい場合があります。メタデータを評価すると複雑で効果的なルールを作成できるので、特定のコンテンツ タイプを持つファイルだけをアップロードしたり、特定のサイズよりも大きなファイルだけを削除したりすることができます。

Cloud Storage 用の Firebase Security Rules は、resource オブジェクト内のファイル メタデータを提供します。このオブジェクトには、Cloud Storage オブジェクトに示されるメタデータの Key-Value ペアが含まれます。read または write リクエストでこれらのプロパティを検査することで、データの完全性を確認できます。

write リクエスト(アップロード、メタデータの更新、削除など)では、現在リクエストパスに存在しているファイルのファイル メタデータを含む resource オブジェクトに加え、書き込みが許可された場合に書き込まれるファイル メタデータのサブセットを含む request.resource オブジェクトを使用することもできます。この 2 つの値を使用してデータの整合性を確認したり、ファイルのタイプやサイズといったアプリケーションの制約を適用したりできます。

resource オブジェクトのプロパティの完全なリストは次のとおりです。

プロパティ タイプ 説明
name 文字列 オブジェクトのフルネームです。
bucket 文字列 このオブジェクトが置かれているバケットの名前です。
generation int このオブジェクトの GCS オブジェクト生成です。
metageneration int このオブジェクトの GCS オブジェクト メタ生成です。
size int オブジェクトのサイズです(バイト単位)。
timeCreated timestamp オブジェクトの作成時刻を示すタイムスタンプです。
updated timestamp オブジェクトの最終更新時刻を示すタイムスタンプです。
md5Hash 文字列 オブジェクトの MD5 ハッシュです。
crc32c 文字列 オブジェクトの crc32c ハッシュです。
etag 文字列 このオブジェクトに関連付けられた etag です。
contentDisposition 文字列 このオブジェクトに関連付けられたコンテンツの配置です。
contentEncoding 文字列 このオブジェクトに関連付けられたコンテンツ エンコーディングです。
contentLanguage 文字列 このオブジェクトに関連付けられたコンテンツ言語です。
contentType 文字列 このオブジェクトに関連付けられたコンテンツ タイプです。
metadata マップ<文字列, 文字列> デベロッパーがカスタム メタデータで指定した、追加の Key-Value ペアです。

request.resource は、generationmetagenerationetagtimeCreatedupdated を除いて、上記のすべてを含みます。

これまでの説明をすべてまとめると、画像ストレージ ソリューションとして次の完全なサンプルルールを作成できます。

service firebase.storage {
 match /b/{bucket}/o {
   match /images {
     // Cascade read to any image type at any path
     match /{allImages=**} {
       allow read;
     }

     // Allow write files to the path "images/*", subject to the constraints:
     // 1) File is less than 5MB
     // 2) Content type is an image
     // 3) Uploaded content type matches existing content type (if it exists)
     // 4) File name (stored in imageId wildcard variable) is less than 32 characters
     match /{imageId} {
       allow write: if request.resource.size < 5 * 1024 * 1024
                    && request.resource.contentType.matches('image/.*')
                    && (resource == null || request.resource.contentType == resource.contentType)
                    && imageId.size() < 32
     }
   }
 }
}

次は、ユーザー セキュリティのセクションで、Firebase Authentication を統合してユーザーごとに細かくファイル アクセス権を設定してみましょう。