Gérer et déployer les règles de sécurité Firebase

Firebase vous fournit plusieurs outils pour gérer vos Security Rules. Chacun d'eux est utile dans des cas particuliers et utilise la même API de gestion des règles de sécurité Firebase backend.

Quel que soit l'outil utilisé pour l'appeler, l'API de gestion :

  • ingère une source de règles : un ensemble de règles, généralement un fichier de code contenant Firebase Security Rules des instructions ;
  • stocke la source ingérée en tant qu'ensemble de règles immuable ;
  • suit le déploiement de chaque ensemble de règles dans une version. Les services compatibles avec les règles de sécurité Firebase recherchent la version d'un projet pour évaluer chaque requête concernant une ressource sécurisée.
  • permet d'exécuter des tests syntaxiques et sémantiques d'un ensemble de règles.

Utiliser la Firebase CLI

Avec la Firebase CLI, vous pouvez importer des sources locales et déployer des versions. La suite d'émulateurs locaux Firebase de la CLI Firebase Local Emulator Suite vous permet d'effectuer des tests locaux complets des sources.

Si vous utilisez l'interface de ligne de commande, vous pouvez bénéficier du contrôle de version pour conserver vos règles comme le code de votre application et pour les déployer dans le cadre du processus de déploiement existant.

Générer un fichier de configuration

Lorsque vous configurez votre projet Firebase à l'aide de la Firebase CLI, vous créez un .rules fichier de configuration dans le répertoire de votre projet. Utilisez la commande suivante pour commencer à configurer votre projet Firebase :

Cloud Firestore

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

Realtime Database

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

Cloud Storage

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

Modifier et mettre à jour vos règles

Modifiez directement la source de vos règles dans le fichier de configuration .rules.

Assurez-vous que toutes les modifications que vous apportez dans la Firebase CLI sont reflétées dans la Firebase console, ou que vous effectuez systématiquement des mises à jour à l'aide de la Firebase console ou de la CLI Firebase. Sinon, vous risquez d'écraser les mises à jour effectuées dans la Firebase console.

Tester vos mises à jour

Le Local Emulator Suite fournit des émulateurs pour tous les produits compatibles avec les règles de sécurité. Le moteur de règles de sécurité de chaque émulateur effectue une évaluation syntaxique et sémantique des règles, ce qui dépasse les tests syntaxiques proposés par l'API de gestion des règles de sécurité.

Si vous utilisez la CLI, la suite est un excellent outil pour Firebase Security Rules tester. Utilisez le Local Emulator Suite pour tester vos mises à jour localement et vérifier que les Security Rules de votre application se comportent comme vous le souhaitez.

Déployer vos mises à jour

Une fois que vous avez mis à jour et testé vos Security Rules, déployez les sources en production.

Pour Cloud Firestore Security Rules, associez les fichiers .rules à vos bases de données nommées par défaut et supplémentaires en examinant et en mettant à jour votre firebase.json fichier.

Utilisez les commandes suivantes pour déployer vos Security Rules de manière sélective ou dans le cadre de votre processus de déploiement normal.

Cloud Firestore

// Deploy rules for all databases configured in your firebase.json
firebase deploy --only firestore:rules
// Deploy rules for the specified database configured in your firebase.json firebase deploy --only firestore:<databaseId>

Realtime Database

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

Cloud Storage

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

Utiliser la Firebase console

Vous pouvez également modifier les Security Rules sources et les déployer en tant que versions à partir de la Firebase console. Les tests syntaxiques sont effectués lorsque vous modifiez l'interface utilisateur de la Firebase console, et les tests sémantiques sont disponibles à l'aide du Security Rules bac à sable.

Modifier et mettre à jour vos règles

  1. Ouvrez la Firebase console et sélectionnez votre projet.
  2. Sélectionnez ensuite Realtime Database, Cloud Firestore ou Storage dans le volet de navigation des produits, puis cliquez sur Rules pour accéder à l'éditeur Security Rules.
  3. Modifiez vos règles directement dans l'éditeur.

Tester vos mises à jour

En plus de tester la syntaxe dans l'interface utilisateur de l'éditeur, vous pouvez tester le comportement sémantique Security Rules en utilisant les ressources de base de données et de stockage de votre projet, directement dans la Firebase console, à l'aide du Security Rules Playground. Ouvrez l'écran Bac à sable des règles dans l'éditeur Security Rules, modifiez les paramètres, puis cliquez sur Exécuter. Recherchez le message de confirmation en haut de l'éditeur.

Déployer vos mises à jour

Une fois que vous êtes satisfait de vos mises à jour, cliquez sur Publier.

Utiliser le SDK Admin

Vous pouvez utiliser le Admin SDK pour les ensembles de règles Node.js . Cet accès programmatique vous permet de :

  • implémenter des outils, des scripts, des tableaux de bord et des pipelines CI/CD personnalisés pour gérer les règles ;
  • gérer plus facilement les règles dans plusieurs projets Firebase.

Lorsque vous mettez à jour des règles de manière programmatique, il est très important d'éviter d'apporter des modifications involontaires au contrôle d'accès de votre application. Écrivez votre Admin SDK code en gardant la sécurité à l'esprit, en particulier lorsque vous mettez à jour ou déployez des règles.

Il est également important de noter que la propagation complète des versions des Firebase Security Rules prend plusieurs minutes. Lorsque vous utilisez le Admin SDK pour déployer des règles, veillez à éviter les conditions de concurrence dans lesquelles votre application s'appuie immédiatement sur des règles dont le déploiement n'est pas encore terminé. Si votre cas d'utilisation nécessite des mises à jour fréquentes des règles de contrôle d'accès, envisagez des solutions utilisant Cloud Firestore, qui est conçu pour réduire les conditions de concurrence malgré les mises à jour fréquentes.

Notez également les limites suivantes :

  • Les règles doivent être inférieures à 256 Kio de texte encodé au format UTF-8 lorsqu'elles sont sérialisées.
  • Un projet peut comporter au maximum 2 500 ensembles de règles déployés au total. Une fois cette limite atteinte, vous devez supprimer certains anciens ensembles de règles avant d'en créer d'autres.

Créer et déployer des ensembles de règles Cloud Storage ou Cloud Firestore

Un workflow type pour gérer les règles de sécurité avec le Admin SDK peut inclure trois étapes distinctes :

  1. Créer une source de fichier de règles (facultatif)
  2. Créer un ensemble de règles
  3. Publier ou déployer le nouvel ensemble de règles

Le SDK fournit une méthode permettant de combiner ces étapes en un seul appel d'API pour Cloud Storage et Cloud Firestore règles de sécurité. Exemple :

    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);

Ce même modèle fonctionne pour Cloud Storage règles avec releaseFirestoreRulesetFromSource().

Vous pouvez également créer le fichier de règles en tant qu'objet en mémoire, créer l'ensemble de règles et déployer l'ensemble de règles séparément pour mieux contrôler ces événements. Exemple :

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

Mettre à jour les ensembles de règles Realtime Database

Pour mettre à jour les ensembles de règles Realtime Database avec le Admin SDK, utilisez les méthodes getRules() et setRules() de admin.database. Vous pouvez récupérer les ensembles de règles au format JSON ou sous forme de chaîne avec des commentaires inclus.

Pour mettre à jour un ensemble de règles :

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

Gérer les ensembles de règles

Pour vous aider à gérer les grands ensembles de règles, le Admin SDK vous permet de répertorier toutes les règles existantes avec admin.securityRules().listRulesetMetadata. Exemple :

    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;
      }
    }

Pour les déploiements très volumineux qui atteignent la limite de 2 500 ensembles de règles au fil du temps, vous pouvez créer une logique pour supprimer les règles les plus anciennes selon un cycle temporel fixe. Par exemple, pour supprimer tous les ensembles de règles déployés depuis plus de 30 jours :

    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.`);

Utiliser l'API REST

Les outils décrits ci-dessus sont adaptés à différents workflows, y compris Firebase Security Rules gestion pour plusieurs Cloud Firestore bases de données dans votre projet, mais vous pouvez gérer et déployer Firebase Security Rules à l'aide de l'API de gestion elle-même. L'API de gestion vous offre la plus grande flexibilité.

Notez également les limites suivantes :

  • Les règles doivent être inférieures à 256 Kio de texte encodé au format UTF-8 lorsqu'elles sont sérialisées.
  • Un projet peut comporter au maximum 2 500 ensembles de règles déployés au total. Une fois cette limite atteinte, vous devez supprimer certains anciens ensembles de règles avant d'en créer d'autres.

Créer et déployer Cloud Firestore ou Cloud Storage ensembles de règles avec REST

Les exemples de cette section utilisent Firestore Security Rules, mais ils s'appliquent également à Cloud Storage Security Rules.

Les exemples utilisent également cURL pour effectuer des appels d'API. Les étapes de configuration et de transmission des jetons d'authentification sont omises. Vous pouvez tester cette API à l'aide de l'explorateur d'API intégré à la documentation de référence.

Voici les étapes types pour créer et déployer un ensemble de règles à l'aide de l'API de gestion :

  1. Créer des sources de fichiers de règles
  2. Créer un ensemble de règles
  3. Publier (déployer) le nouvel ensemble de règles

Créer une source

Supposons que vous travaillez sur votre secure_commerce projet Firebase et que vous souhaitez déployer des règles de sécurité Cloud Firestore Security Rules verrouillées dans une base de données de votre projet nommée east_store.

Vous pouvez implémenter ces règles dans un fichier firestore.rules.

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if false;
    }
  }
}

Créer un ensemble de règles

Générez maintenant une empreinte encodée en base64 pour ce fichier. Vous pouvez ensuite utiliser la source de ce fichier pour remplir la charge utile nécessaire à la création d'un ensemble de règles avec l'appel REST projects.rulesets.create. Ici, utilisez la commande cat pour insérer le contenu de firestore.rules dans la charge utile REST.

Pour le suivi, afin d'associer cela à votre base de données east_store, définissez attachment_point sur east_store.

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

L'API renvoie une réponse de validation et un nom d'ensemble de règles, par exemple projects/secure_commerce/rulesets/uuid123.

Publier (déployer) un ensemble de règles

Si l'ensemble de règles est valide, la dernière étape consiste à déployer le nouvel ensemble de règles dans une version nommée.

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

Sachez que la propagation complète des versions Firebase Security Rules prend plusieurs minutes. Lorsque vous utilisez l'API REST de gestion pour déployer, veillez à éviter les conditions de concurrence dans lesquelles votre application s'appuie immédiatement sur des règles dont le déploiement n'est pas encore terminé.

Mettre à jour les ensembles de règles Realtime Database avec REST

Realtime Database fournit sa propre interface REST pour gérer Security Rules. Consultez Gérer les règles de sécurité Firebase Realtime Database Security Rules via REST.

Gérer les ensembles de règles avec REST

Pour vous aider à gérer les déploiements de règles volumineux, en plus d'une méthode REST permettant de créer des ensembles de règles et des versions, l'API de gestion fournit des méthodes pour :

  • répertorier, obtenir et supprimer des ensembles de règles
  • répertorier, obtenir et supprimer des versions de règles

Pour les déploiements très volumineux qui atteignent la limite de 2 500 ensembles de règles au fil du temps, vous pouvez créer une logique pour supprimer les règles les plus anciennes selon un cycle temporel fixe. Par exemple, pour supprimer tous les ensembles de règles déployés depuis plus de 30 jours, vous pouvez appeler la méthode projects.rulesets.list, analyser la liste JSON des objets Ruleset sur leurs clés createTime, puis appeler project.rulesets.delete sur les ensembles de règles correspondants par ruleset_id.

Tester vos mises à jour avec REST

Enfin, l'API de gestion vous permet d'exécuter des tests syntaxiques et sémantiques sur Cloud Firestore et Cloud Storage ressources dans vos projets de production.

Les tests avec ce composant de l'API consistent à :

  1. définir un objet JSON TestSuite pour représenter un ensemble d'objets TestCase ;
  2. envoyer le TestSuite ;
  3. analyser les objets TestResult renvoyés.

Définissons un objet TestSuite avec un seul TestCase dans un fichier testcase.json. Dans cet exemple, nous transmettons la source du langage Security Rules en ligne avec la charge utile REST, ainsi que la suite de tests à exécuter sur ces règles. Nous spécifions une attente d'évaluation des règles et la requête client par rapport à laquelle l'ensemble de règles doit être testé. Vous pouvez également spécifier le niveau de détail du rapport de test à l'aide de la valeur "FULL" pour indiquer que les résultats de toutes les expressions de langage des règles de sécurité doivent être inclus dans le rapport, y compris les expressions qui ne correspondent pas à la requête.Security Rules

 {
  "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"}}}
            }
          ]
      }
    ]
  }
}

Nous pouvons ensuite envoyer ce TestSuite pour évaluation avec la méthode projects.test.

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

Le TestReport renvoyé (contenant l'état de réussite/échec du test, des listes de messages de débogage, des listes d'expressions de règles visitées et leurs rapports d'évaluation) confirme avec l'état SUCCESS que l'accès est correctement autorisé.

Gérer les autorisations pour les règles de sécurité Cloud Storage interservices Cloud Storage Security Rules

Si vous créez Cloud Storage Security Rules qui utilisent le contenu des documents Cloud Firestore pour évaluer les conditions de sécurité, vous serez invité dans la console Firebase ou la CLI Firebase à activer les autorisations permettant de connecter les deux produits.

Si vous décidez de désactiver cette sécurité interservices :

  1. Avant de désactiver la fonctionnalité, modifiez vos règles en supprimant toutes les instructions qui utilisent des fonctions Security Rules pour accéder à Cloud Firestore. Sinon, une fois la fonctionnalité désactivée, les Security Rules évaluations entraîneront l'échec de vos requêtes de stockage.

  2. Utilisez la page IAM de la console Google Cloud pour supprimer le rôle "Agent de service Firestore pour les règles Firebase" en suivant le guide Cloud pour révoquer des rôles.

Vous serez invité à réactiver la fonctionnalité la prochaine fois que vous enregistrerez des règles interservices à partir de la Firebase CLI ou de la console Firebase.