Firebase Summit で発表されたすべての情報をご覧ください。Firebase を使用してアプリ開発を加速し、自信を持ってアプリを実行する方法を紹介しています。詳細

Firebaseセキュリティルールを管理およびデプロイする

コレクションでコンテンツを整理 必要に応じて、コンテンツの保存と分類を行います。

Firebase には、ルールを管理するためのいくつかのツールが用意されています。それぞれが特定のケースで役立ち、同じバックエンドの Firebase セキュリティ ルール管理 API を使用します。

どのツールを使用して呼び出すかに関係なく、管理 API は次のことを行います。

  • ルールソースを取り込みます: 一連のルールで、通常は Firebase セキュリティ ルール ステートメントを含むコード ファイルです。
  • 取り込まれたソースを不変のrulesetとして保存します。
  • リリース内の各ルールセットの展開を追跡します。 Firebase セキュリティ ルール対応サービスは、プロジェクトのリリースを検索して、保護されたリソースに対する各リクエストを評価します。
  • ルールセットの構文および意味テストを実行する機能を提供します。

Firebase CLI を使用する

Firebase CLIを使用すると、ローカルソースをアップロードしてリリースをデプロイできます。 CLI の Firebase Local Emulator Suite を使用すると、ソースの完全なローカル テストを実行できます。

CLI を使用すると、アプリケーション コードを使用してルールをバージョン管理し、既存のデプロイ プロセスの一部としてルールをデプロイできます。

構成ファイルを生成する

Firebase CLI を使用して Firebase プロジェクトを構成するときは、プロジェクト ディレクトリに.rules構成ファイルを作成します。次のコマンドを使用して、Firebase プロジェクトの構成を開始します。

クラウド ファイアストア

// Set up Firestore in your project directory, creates a .rules file
firebase init firestore

リアルタイム データベース

// Set up Realtime Database in your project directory, creates a .rules file
firebase init database

クラウドストレージ

// Set up Storage in your project directory, creates a .rules file
firebase init storage

ルールを編集して更新する

ルール ソースを.rules構成ファイルで直接編集します。 Firebase CLI で行った編集が Firebase コンソールに反映されていること、または Firebase コンソールまたは Firebase CLI のいずれかを使用して一貫して更新を行っていることを確認してください。そうしないと、Firebase コンソールで行われた更新が上書きされる可能性があります。

アップデートをテストする

ローカル エミュレーター スイートは、すべてのセキュリティ ルール対応製品のエミュレーターを提供します。各エミュレータのセキュリティ ルール エンジンは、ルールの構文評価とセマンティック評価の両方を実行するため、セキュリティ ルール管理 API が提供する構文テストよりも優れています。

CLI を使用している場合、スイートは Firebase セキュリティ ルールのテストに最適なツールです。 Local Emulator Suiteを使用して更新をローカルでテストし、アプリのルールが目的の動作を示していることを確認します。

アップデートをデプロイする

ルールを更新してテストしたら、ソースを本番環境にデプロイします。次のコマンドを使用して、ルールのみを選択的に展開するか、通常の展開プロセスの一部として展開します。

クラウド ファイアストア

// Deploy your .rules file
firebase deploy --only firestore:rules

リアルタイム データベース

// Deploy your .rules file
firebase deploy --only database

クラウドストレージ

// Deploy your .rules file
firebase deploy --only storage

Firebase コンソールを使用する

ルールソースを編集し、Firebase コンソールからリリースとしてデプロイすることもできます。 Firebase コンソール UI での編集時に構文テストが実行され、Rules Playground を使用して構文テストを利用できます。

ルールを編集して更新する

  1. Firebase コンソールを開き、プロジェクトを選択します。
  2. 次に、プロダクト ナビゲーションからRealtime DatabaseCloud Firestore 、またはStorageを選択し、[ルール] をクリックしてルール エディタに移動します。
  3. エディターでルールを直接編集します。

アップデートをテストする

エディター UI で構文をテストするだけでなく、 Rules Playgroundを使用して Firebase コンソールで直接、プロジェクトのデータベースとストレージ リソースを使用してセマンティック ルールの動作をテストできます。ルール エディタでルール プレイグラウンド画面を開き、設定を変更して [実行] をクリックします。エディターの上部にある確認メッセージを探します。

アップデートをデプロイする

更新内容が期待どおりであることを確認したら、 [公開] をクリックします。

管理 SDK を使用する

Node.jsルールセット用の Admin SDK を使用できます。このプログラムによるアクセスにより、次のことが可能になります。

  • ルールを管理するためのカスタム ツール、スクリプト、ダッシュボード、および CI/CD パイプラインを実装します。
  • 複数の Firebase プロジェクトでルールをより簡単に管理できます。

ルールをプログラムで更新する場合、アプリのアクセス制御に意図しない変更を加えないようにすることが非常に重要です。特にルールを更新または展開する場合は、セキュリティを最優先して Admin SDK コードを記述します。

留意すべきもう 1 つの重要な点は、Firebase セキュリティ ルールのリリースが完全に反映されるまでに数分かかることです。 Admin SDK を使用してルールをデプロイする場合は、デプロイがまだ完了していないルールにアプリがすぐに依存する競合状態を回避してください。ユース ケースでアクセス コントロール ルールを頻繁に更新する必要がある場合は、Cloud Firestore を使用したソリューションを検討してください。これは、頻繁な更新にもかかわらず競合状態を減らすように設計されています。

次の制限にも注意してください。

  • ルールは、シリアライズ時に UTF-8 でエンコードされたテキストの 256 KiB よりも小さくする必要があります。
  • プロジェクトには、合計で最大 2500 のデプロイ済みルールセットを含めることができます。この制限に達すると、新しいルールセットを作成する前に古いルールセットをいくつか削除する必要があります。

Cloud Storage または Cloud Firestore のルールセットを作成してデプロイする

Admin SDK を使用してセキュリティ ルールを管理する一般的なワークフローには、次の 3 つの個別の手順が含まれます。

  1. ルール ファイル ソースの作成 (オプション)
  2. ルールセットを作成する
  3. 新しいルールセットをリリースまたはデプロイする

SDK は、これらの手順を Cloud Storage および Cloud Firestore セキュリティ ルールの 1 つの API 呼び出しに結合する方法を提供します。例えば:

    const source = `service cloud.firestore {
      match /databases/{database}/documents {
        match /carts/{cartID} {
          allow create: if request.auth != null && request.auth.uid == request.resource.data.ownerUID;
          allow read, update, delete: if request.auth != null && request.auth.uid == resource.data.ownerUID;
        }
      }
    }`;
    // Alternatively, load rules from a file
    // const fs = require('fs');
    // const source = fs.readFileSync('path/to/firestore.rules', 'utf8');

    await admin.securityRules().releaseFirestoreRulesetFromSource(source);

これと同じパターンは、 releaseFirestoreRulesetFromSource()を使用した Cloud Storage ルールでも機能します。

または、ルール ファイルをメモリ内オブジェクトとして作成し、ルールセットを作成して、これらのイベントをより詳細に制御するためにルールセットを個別にデプロイすることもできます。例えば:

    const rf = admin.securityRules().createRulesFileFromSource('firestore.rules', source);
    const rs = await admin.securityRules().createRuleset(rf);
    await admin.securityRules().releaseFirestoreRuleset(rs);

Realtime Database ルールセットを更新する

Admin SDK で Realtime Database ルールセットを更新するには、 admin.database のgetRules()およびadmin.database setRules()メソッドを使用します。ルールセットは、JSON 形式で取得するか、コメントを含む文字列として取得できます。

ルールセットを更新するには:

    const source = `{
      "rules": {
        "scores": {
          ".indexOn": "score",
          "$uid": {
            ".read": "$uid == auth.uid",
            ".write": "$uid == auth.uid"
          }
        }
      }
    }`;
    await admin.database().setRules(source);

ルールセットを管理する

大規模なルールセットを管理しやすくするために、Admin SDK ではadmin.securityRules().listRulesetMetadataを使用して既存のすべてのルールを一覧表示できます。例えば:

    const allRulesets = [];
    let pageToken = null;
    while (true) {
      const result = await admin.securityRules().listRulesetMetadata(pageToken: pageToken);
      allRulesets.push(...result.rulesets);
      pageToken = result.nextPageToken;
      if (!pageToken) {
        break;
      }
    }

時間の経過とともに 2500 ルールセットの制限に達する非常に大規模な展開の場合、固定の時間サイクルで最も古いルールを削除するロジックを作成できます。たとえば、30 日を超えて展開されたすべてのルールセットを削除するには、次のようにします。

    const thirtyDays = new Date(Date.now() - THIRTY_DAYS_IN_MILLIS);
    const promises = [];
    allRulesets.forEach((rs) => {
      if (new Date(rs.createTime) < thirtyDays) {
        promises.push(admin.securityRules().deleteRuleset(rs.name));
      }
    });
    await Promise.all(promises);
    console.log(`Deleted ${promises.length} rulesets.`);

REST API を使用する

上記のツールはさまざまなワークフローに適していますが、管理 API 自体を使用して Firebase セキュリティ ルールを管理およびデプロイすることもできます。管理 API は、最大の柔軟性を提供します。

Firebase セキュリティ ルールのリリースが完全に反映されるまでに数分かかることに注意してください。管理 REST API を使用してデプロイする場合は、デプロイがまだ完了していないルールにアプリがすぐに依存する競合状態を回避してください。

次の制限にも注意してください。

  • ルールは、シリアライズ時に UTF-8 でエンコードされたテキストの 256 KiB よりも小さくする必要があります。
  • プロジェクトには、合計で最大 2500 のデプロイ済みルールセットを含めることができます。この制限に達すると、新しいルールセットを作成する前に古いルールセットをいくつか削除する必要があります。

REST を使用して Cloud Storage または Cloud Firestore のルールセットを作成してデプロイする

このセクションの例ではストレージ ルールを使用していますが、Cloud Firestore ルールにも適用されます。

この例では、cURL を使用して API 呼び出しも行っています。認証トークンを設定して渡す手順は省略されています。リファレンス ドキュメントと統合された API Explorer を使用して、この API を試すことができます。

管理 API を使用してルールセットを作成およびデプロイする一般的な手順は次のとおりです。

  1. ルール ファイル ソースの作成
  2. ルールセットを作成する
  3. 新しいルールセットをリリース (デプロイ)

secure_commerce Firebase プロジェクトに取り組んでいて、ロックダウンされた Cloud Storage ルールをデプロイしたいとします。これらのルールはstorage.rulesファイルに実装できます。

service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write: if false;
    }
  }
}

次に、このファイルの base64 でエンコードされたフィンガープリントを生成します。次に、このファイルのソースを使用して、 projects.rulesets.create REST 呼び出しでルールセットを作成するために必要なペイロードを設定できます。ここでは、 catコマンドを使用してstorage.rulesの内容を REST ペイロードに挿入します。

curl -X POST -d '{
  "source": {
    {
      "files": [
        {
          "content": "' $(cat storage.rules) '",
          "name": "storage.rules",
          "fingerprint": <sha fingerprint>
        }
      ]
    }
  }
}' 'https://firebaserules.googleapis.com/v1/projects/secure_commerce/rulesets'

API は検証応答とルールセット名 (例: projects/secure_commerce/rulesets/uuid123を返します。ルールセットが有効な場合、最後のステップは、新しいルールセットを名前付きリリースにデプロイすることです。

curl -X POST -d '{
  "name": "projects/secure_commerce/releases/prod/v23   "  ,
  "rulesetName": "projects/secure_commerce/rulesets/uuid123",
}' 'https://firebaserules.googleapis.com/v1/projects/secure_commerce/releases'

REST を使用して Realtime Database ルールセットを更新する

Realtime Database は、ルールを管理するための独自の REST インターフェイスを提供します。 REST を介した Firebase Realtime Database ルールの管理を参照してください。

REST を使用してルールセットを管理する

大規模なルールの展開を管理するために、ルールセットとリリースを作成するための REST メソッドに加えて、管理 API は次のメソッドを提供します。

  • ルールセットの一覧表示、取得、および削除
  • ルールリリースの一覧表示、取得、および削除

時間の経過とともに 2500 ルールセットの制限に達する非常に大規模な展開の場合、固定の時間サイクルで最も古いルールを削除するロジックを作成できます。たとえば、30 日以上にわたってデプロイされたすべてのルールセットを削除するには、 projects.rulesets.listメソッドを呼び出し、 createTimeキーでRulesetオブジェクトの JSON リストを解析してから、 ruleset_idによって対応するルールセットでproject.rulesets.deleteを呼び出します。 .

REST を使用して更新をテストする

最後に、管理 API を使用すると、本番プロジェクトの Cloud Firestore リソースと Cloud Storage リソースに対して構文テストと意味テストを実行できます。

API のこのコンポーネントを使用したテストは、以下で構成されます。

  1. TestCaseオブジェクトのセットを表すTestSuite JSON オブジェクトの定義
  2. TestSuiteの提出
  3. 返されたTestResultオブジェクトの解析

testcase.jsonファイル内の単一のTestCaseTestSuiteオブジェクトを定義しましょう。この例では、ルール言語ソースを REST ペイロードとインラインで渡し、これらのルールで実行するテスト スイートと一緒に渡します。ルール評価の期待値と、ルールセットがテストされるクライアント要求を指定します。また、テスト レポートの完成度を指定することもできます。値「FULL」を使用して、要求に一致しなかった表現を含め、すべての規則言語表現をレポートに含める必要があることを示します。

 {
  "source":
  {
    "files":
    [
      {
        "name": "firestore.rules",
        "content": "service cloud.firestore {
          match /databases/{database}/documents {
            match /users/{userId}{
              allow read: if (request.auth.uid == userId);
            }
            function doc(subpath) {
              return get(/databases/$(database)/documents/$(subpath)).data;
            }
            function isAccountOwner(accountId) {
              return request.auth.uid == accountId 
                  || doc(/users/$(request.auth.uid)).accountId == accountId;
            }
            match /licenses/{accountId} {
              allow read: if isAccountOwner(accountId);
            }
          }
        }"
      }
    ]
  },
  "testSuite":
  {
    "testCases":
    [
      {
        "expectation": "ALLOW",
        "request": {
           "auth": {"uid": "123"},
           "path": "/databases/(default)/documents/licenses/abcd",
           "method": "get"},
        "functionMocks": [
            {
            "function": "get",
            "args": [{"exact_value": "/databases/(default)/documents/users/123"}],
            "result": {"value": {"data": {"accountId": "abcd"}}}
            }
          ]
      }
    ]
  }
}

次に、 projects.testメソッドを使用して、評価のためにこのTestSuiteを送信できます。

curl -X POST -d '{
    ' $(cat testcase.json) '
}' 'https://firebaserules.googleapis.com/v1/projects/secure_commerce/rulesets/uuid123:test'

返されたTestReport (テストの SUCCESS/FAILURE ステータス、デバッグ メッセージのリスト、アクセスしたルール式のリスト、およびそれらの評価レポートを含む) は、アクセスが適切に許可されていることをステータス SUCCESS で確認します。

サービス間の Cloud Storage セキュリティ ルールの権限を管理する

Cloud Firestore ドキュメント コンテンツを使用してセキュリティ条件を評価する Cloud Storage セキュリティ ルールを作成すると、Firebase コンソールまたは Firebase CLI で、2 つの製品を接続する権限を有効にするよう求められます。

このようなサービス間のセキュリティを無効にすることにした場合:

  1. まず、機能を無効にする前に、ルールを編集して、Rules 関数を使用して Cloud Firestore にアクセスするステートメントをすべて削除します。そうしないと、機能が無効になった後、ルールの評価によってストレージ リクエストが失敗します。

  2. Google Cloud Console のIAMページを使用して、ロールの取り消しに関するクラウド ガイドに従って「Firebase Rules Firestore サービス エージェント」のロールを削除します。

次に Firebase CLI または Firebase コンソールからクロスサービス ルールを保存するときに、機能を再度有効にするように求められます。