このガイドは、Firebase Security Rules 言語の基本構文の学習ガイドに基づいて作成されており、Cloud Storage 用の Firebase Security Rules に条件を追加する方法について説明します。
Cloud Storage Security Rules の主な構成要素は条件です。条件とは、特定のオペレーションを許可するか拒否するかを決定するブール式です。基本的なルールとしては、リテラル true
および false
を条件として使用すれば、十分な機能を発揮します。ただし、Cloud Storage 用の Firebase Security Rules 言語では、より複雑な条件を記述でき、次の操作を行うことができます。
- ユーザー認証を確認する
- 受信データを検証する
認証
Cloud Storage 用の Firebase Security Rules を Firebase Authentication と統合すると、Cloud Storage にユーザーベースの強力な認証を実装できます。これにより、Firebase Authentication トークンのクレームに基づいてアクセスを細かく制御することができます。
認証されたユーザーが Cloud Storage に対してリクエストを行うと、request.auth
変数にユーザーの uid
(request.auth.uid
)と Firebase Authentication JWT(request.auth.token
)のクレームが入力されます。
また、カスタム認証の使用時には、追加のクレームが request.auth.token
フィールドに表示されます。
認証されていないユーザーがリクエストを行うと、request.auth
変数は null
になります。
このデータを使用する場合、次のような一般的な方法で認証を使用してファイルを保護できます。
- 公開:
request.auth
を無視 - 認証済み非公開:
request.auth
がnull
でないことを確認 - ユーザー非公開:
request.auth.uid
とパスuid
が同じであることを確認 - グループ非公開: カスタム トークンのクレームと選択されたクレームが一致することを確認、またはファイル メタデータを読み取ってメタデータ フィールドが存在しているか確認
公開
request.auth
コンテキストを考慮しないルールは、ユーザーの認証コンテキストを考慮しないため、public
ルールとみなすことができます。このようなルールは、ゲームアセット、サウンド ファイル、その他の静的コンテンツといった一般公開データを表示するのに便利です。
// Anyone to read a public image if the file is less than 100kB // Anyone can upload a public file ending in '.txt' match /public/{imageId} { allow read: if resource.size < 100 * 1024; allow write: if imageId.matches(".*\\.txt"); }
認証済み非公開
アプリケーションの認証済みユーザーに対してはデータを閲覧可能にし、未認証ユーザーに対しては閲覧不可能にしたい場合があります。request.auth
変数はすべての未認証ユーザーに対して null
であるため、認証を要求するために必要なのは request.auth
変数が存在することの確認だけです。
// Require authentication on all internal image reads match /internal/{imageId} { allow read: if request.auth != null; }
ユーザー非公開
request.auth
の最も一般的な使用例は、プロフィール写真のアップロードからプライベート ドキュメントの読み取りまで、ファイルに対する細かいアクセス権限を個々のユーザーに提供することです。
Cloud Storage 内のファイルはファイルへのフル「パス」を保持しています。そのため、ファイル名接頭辞内に、ルール評価時のチェックが可能な一意のユーザー識別情報(ユーザーの uid
など)を入れるだけで、ユーザーによるファイルの制御が可能となります。
// Only a user can upload their profile picture, but anyone can view it match /users/{userId}/profilePicture.png { allow read; allow write: if request.auth.uid == userId; }
グループ非公開
ユーザー非公開と同じくらい一般的な使用例として挙げられるのが、オブジェクトに対するグループ アクセス権限を許可することです。たとえば、共有ドキュメント上での共同作業を複数のチームメンバーに許可します。これを行う方法はいくつかあります。
- グループ メンバーに関する追加情報(グループ ID など)を含む Firebase Authentication カスタム トークンを作成する
- グループ情報(グループ ID、認可された
uid
のリストなど)をファイル メタデータに含める
このデータがトークンまたはファイル メタデータに格納されると、ルール内から参照できるようになります。
// Allow reads if the group ID in your token matches the file metadata's `owner` property // Allow writes if the group ID is in the user's custom token match /files/{groupId}/{fileName} { allow read: if resource.metadata.owner == request.auth.token.groupId; allow write: if request.auth.token.groupId == groupId; }
リクエストの評価
アップロード、ダウンロード、メタデータの変更、削除は、Cloud Storage に送信される request
を使用して評価されます。上述した request.auth
オブジェクトに含まれるユーザーの一意の ID と Firebase Authentication ペイロードに加え、request
変数には、リクエストが行われているファイルパスとリクエストの受信時刻も含まれます。さらに、書き込みリクエストの場合は、新しい resource
値も含まれます。
また、request
オブジェクトには、ユーザーの一意の ID と request.auth
オブジェクト内の Firebase Authentication ペイロードも含まれます。これらについては、このドキュメントのユーザーベースのセキュリティのセクションで詳しく説明します。
request
オブジェクトのプロパティの完全なリストは次のとおりです。
プロパティ | タイプ | 説明 |
---|---|---|
auth |
マップ<文字列, 文字列> | ユーザーがログイン済みの場合、uid (ユーザーに一意の ID)と token (Firebase 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 | このオブジェクトの Google Cloud Storage オブジェクト生成です。 |
metageneration |
int | このオブジェクトの Google Cloud Storage オブジェクト メタ生成です。 |
size |
int | オブジェクトのサイズです(バイト単位)。 |
timeCreated |
timestamp | オブジェクトの作成時刻を示すタイムスタンプです。 |
updated |
timestamp | オブジェクトの最終更新時刻を示すタイムスタンプです。 |
md5Hash |
文字列 | オブジェクトの MD5 ハッシュです。 |
crc32c |
文字列 | オブジェクトの crc32c ハッシュです。 |
etag |
文字列 | このオブジェクトに関連付けられた etag です。 |
contentDisposition |
文字列 | このオブジェクトに関連付けられたコンテンツの配置です。 |
contentEncoding |
文字列 | このオブジェクトに関連付けられたコンテンツ エンコーディングです。 |
contentLanguage |
文字列 | このオブジェクトに関連付けられたコンテンツ言語です。 |
contentType |
文字列 | このオブジェクトに関連付けられたコンテンツ タイプです。 |
metadata |
マップ<文字列, 文字列> | デベロッパーがカスタム メタデータで指定した、追加の Key-Value ペアです。 |
request.resource
は、generation
、metageneration
、etag
、timeCreated
、updated
を除いて、上記のすべてを含みます。
Cloud Firestore で補正
Cloud Firestore 内のドキュメントにアクセスして、他の認証条件を評価できます。
セキュリティ ルールでは、firestore.get()
関数と firestore.exists()
関数を使用して、Cloud Firestore 内のドキュメントに対する受信リクエストを評価できます。
firestore.get()
関数と firestore.exists()
関数は、完全なドキュメント パスを指定します。変数を使用して firestore.get()
と firestore.exists()
のためのパスを構築する場合は、$(variable)
構文を使用して明示的に変数をエスケープする必要があります。
以下の例では、特定のクラブのメンバーであるユーザーにファイルへの読み取りアクセスを制限するルールを示しています。
service firebase.storage { match /b/{bucket}/o { match /users/{club}/files/{fileId} { allow read: if club in firestore.get(/databases/(default)/documents/users/$(request.auth.id)).memberships } } }
service firebase.storage { match /b/{bucket}/o { match /users/{userId}/photos/{fileId} { allow read: if firestore.exists(/databases/(default)/documents/users/$(userId)/friends/$(request.auth.id)) } } }
これらの Cloud Firestore 関数を使用する最初の Cloud Storage Security Rules を作成して保存すると、Firebase コンソールまたは Firebase CLI で、2 つのプロダクトを接続する権限を有効にするように求められます。
この機能を無効にするには、Firebase Security Rules の管理とデプロイの説明に沿って IAM ロールを削除します。
データの検証
Cloud Storage 用の Firebase Security Rules は、ファイル名とパスの検証、contentType
や size
などのファイル メタデータ プロパティの検証といったデータ検証にも使用できます。
service firebase.storage { match /b/{bucket}/o { match /images/{imageId} { // Only allow uploads of any image file that's less than 5MB allow write: if request.resource.size < 5 * 1024 * 1024 && request.resource.contentType.matches('image/.*'); } } }
カスタム関数
Firebase Security Rules の複雑化に伴い、一連の条件を関数としてラップし、ルールセット全体で再利用できるようにすることが必要になることがあります。セキュリティ ルールはカスタム関数をサポートしています。カスタム関数の構文は JavaScript に少し似ていますが、Firebase Security Rules 関数はドメイン固有の言語で記述され、いくつかの重要な制限があります。
- 関数には 1 つの
return
ステートメントのみを含めることができます。追加ロジックを含めることはできません。たとえば、ループの実行や外部サービスの呼び出しはできません。 - 関数は、定義されているスコープから、関数と変数に自動的にアクセスすることができます。たとえば、
service firebase.storage
スコープ内で定義された関数は、resource
変数、および Cloud Firestore 専用のget()
やexists()
などの組み込み関数にアクセスできます。 - 関数は他の関数を呼び出すことはできますが、再帰はできません。コールスタックの深さは合計 10 に制限されています。
- バージョン
rules2
では、関数でlet
キーワードを使用して変数を定義できます。関数には任意の数の let バインディングを指定できますが、return ステートメントで終了する必要があります。
関数を定義するには function
キーワードを使用します。関数は、0 個以上の引数を取ります。たとえば、上に示した例で使用した 2 つのタイプの条件を 1 つの関数にまとめることができます。
service firebase.storage {
match /b/{bucket}/o {
// True if the user is signed in or the requested data is 'public'
function signedInOrPublic() {
return request.auth.uid != null || resource.data.visibility == 'public';
}
match /images/{imageId} {
allow read, write: if signedInOrPublic();
}
match /mp3s/{mp3Ids} {
allow read: if signedInOrPublic();
}
}
}
Firebase Security Rules で関数を使用すると、ルールが複雑化した場合に保守しやすくなります。
次のステップ
条件についての以上の解説により、ルールについての理解を深めることができれば、次の学習に進む準備できています。
コアとなるユースケースの対処方法、およびルールを開発、テスト、デプロイするためのワークフローについて学習する。
- 一般的なシナリオに対処するルールを記述する。
- 安全でないルールを見つけて回避する必要がある状況を確認することで、学習内容に基づいてルールを作成する。
- Cloud Storage エミュレータと専用のセキュリティ ルール テスト ライブラリを使用してルールをテストする。
- Rules のデプロイに利用できる方法を確認する。