Découvrez la syntaxe de base des règles de sécurité Firebase pour le langage Cloud Storage

Firebase Security Rules pour Cloud Storage vous permet de contrôler l'accès aux objets stockés dans des buckets Cloud Storage. La syntaxe des règles flexibles vous permet de créer des règles pour contrôler n'importe quelle opération, de toutes les écritures dans votre bucket Cloud Storage aux opérations sur un fichier spécifique.

Ce guide décrit la syntaxe et la structure de base de Cloud Storage Security Rules pour créer des jeux de règles complets.

Déclaration de service et de base de données

Les Firebase Security Rules pour Cloud Storage commencent toujours par la déclaration suivante:

service firebase.storage {
    // ...
}

La déclaration service firebase.storage définit les règles pour Cloud Storage, en évitant les conflits entre Cloud Storage Security Rules et les règles pour d'autres produits tels que Cloud Firestore.

Règles de base pour les lectures et les écritures

Les règles de base comprennent une instruction match identifiant des buckets Cloud Storage, une instruction de correspondance spécifiant un nom de fichier et une expression allow détaillant la lecture des données spécifiées. Les expressions allow spécifient les méthodes d'accès (par exemple, lecture, écriture) impliquées et les conditions sous lesquelles l'accès est autorisé ou refusé.

Dans votre jeu de règles par défaut, la première instruction match utilise une expression générique {bucket} pour indiquer que les règles s'appliquent à tous les buckets de votre projet. Nous reviendrons sur les expressions régulières dans la section suivante.

service firebase.storage {
  // The {bucket} wildcard indicates we match files in all Cloud Storage buckets
  match /b/{bucket}/o {
    // Match filename
    match /filename {
      allow read: if <condition>;
      allow write: if <condition>;
    }
  }
}

Toutes les instructions de correspondance pointent vers des fichiers. Une instruction de correspondance peut pointer vers un fichier spécifique, comme dans match /images/profilePhoto.png.

Correspondre aux caractères génériques

En plus de pointer vers un seul fichier, Rules peut utiliser des caractères génériques pour pointer vers n'importe quel fichier portant un préfixe de chaîne donné dans son nom, y compris des barres obliques, comme dans match /images/{imageId}.

Dans l'exemple ci-dessus, l'instruction de correspondance utilise la syntaxe de caractère générique {imageId}. Cela signifie que la règle s'applique à tous les fichiers dont le nom commence par /images/, tels que /images/profilePhoto.png ou /images/croppedProfilePhoto.png. Lorsque les expressions allow dans l'instruction de correspondance sont évaluées, la résolution de la variable imageId donne le nom de fichier de l'image, tel que profilePhoto.png ou croppedProfilePhoto.png.

Une variable générique peut être référencée dans match pour fournir une autorisation de nom de fichier ou de chemin d'accès:

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

Données hiérarchisées

Comme nous l'avons indiqué précédemment, il n'y a pas de structure hiérarchique dans un bucket Cloud Storage. Toutefois, en utilisant une convention d'attribution de noms de fichiers, souvent celle qui inclut des barres obliques dans les noms de fichiers, nous pouvons imiter une structure qui ressemble à une série imbriquée de répertoires et de sous-répertoires. Il est important de comprendre comment Firebase Security Rules interagit avec ces noms de fichiers.

Imaginons un ensemble de fichiers dont les noms commencent tous par la racine /images/. Firebase Security Rules ne s'applique qu'au nom de fichier correspondant. Par conséquent, les contrôles d'accès définis sur la racine /images/ ne s'appliquent pas à la racine /mp3s/. À la place, écrivez des règles explicites qui correspondent à différents modèles de nom de fichier:

service firebase.storage {
  match /b/{bucket}/o {
    match /images/{imageId} {
      allow read, write: if <condition>;
    }

    // Explicitly define rules for the 'mp3s' pattern
    match /mp3s/{mp3Id} {
      allow read, write: if <condition>;
    }
  }
}

Lors de l'imbrication des instructions match, le chemin de l'instruction interne match est toujours ajouté au chemin de l'instruction externe match. Les deux ensembles de règles suivants sont donc équivalents:

service firebase.storage {
  match /b/{bucket}/o {
    match /images {
      // Exact match for "images/profilePhoto.png"
      match /profilePhoto.png {
        allow write: if <condition>;
      }
    }
  }
}
service firebase.storage {
  match /b/{bucket}/o {
    // Exact match for "images/profilePhoto.png"
    match /images/profilePhoto.png {
      allow write: if <condition>;
      }
  }
}

Caractères génériques de correspondance récursifs

En plus des caractères génériques qui correspondent et renvoient des chaînes à la fin d'un nom de fichier, un caractère générique multisegment peut être déclaré pour des correspondances plus complexes en ajoutant =** au nom du caractère générique, comme {path=**}:

// Partial match for files that start with "images"
match /images {

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

Si plusieurs règles correspondent à un fichier, le résultat est le OR du résultat de toutes les évaluations de règles. Autrement dit, si une règle à laquelle le fichier correspond est évaluée à true, le résultat est true.

Dans les règles ci-dessus, le fichier "images/profilePhoto.png" peut être lu si condition ou other_condition renvoie la valeur "true", tandis que le fichier "images/users/user:12345/profilePhoto.png" n'est soumis qu'au résultat de other_condition.

Les Cloud Storage Security Rules ne sont pas en cascade, et les règles ne sont évaluées que lorsque le chemin de requête correspond à un chemin avec des règles spécifiées.

Version 1

Firebase Security Rules utilise la version 1 par défaut. Dans la version 1, les caractères génériques récursifs correspondent à un ou plusieurs éléments de nom de fichier, et non à zéro ou plusieurs éléments. Par conséquent, match /images/{filenamePrefixWildcard}/{imageFilename=**} correspond à un nom de fichier tel que /images/profilePics/profile.png, mais pas à /images/badge.png. Utilisez plutôt /images/{imagePrefixorFilename=**}.

Les caractères génériques récursifs doivent apparaître à la fin d'une instruction de correspondance.

Nous vous recommandons d'utiliser la version 2 pour ses fonctionnalités plus puissantes.

Version 2

Dans la version 2 de Firebase Security Rules, les caractères génériques récursifs peuvent correspondre à zéro, un ou plusieurs éléments de chemin. Par conséquent, /images/{filenamePrefixWildcard}/{imageFilename=**} correspond aux noms de fichiers /images/profilePics/profile.png et /images/badge.png.

Vous devez activer la version 2 en ajoutant rules_version = '2'; en haut de vos règles de sécurité :

rules_version = '2';
service cloud.storage {
  match /b/{bucket}/o {
   ...
 }
}

Vous pouvez utiliser au maximum un caractère générique récursif par requête, mais dans la version 2, vous pouvez placer ce caractère générique n'importe où dans l'instruction de correspondance. Exemple :

rules_version = '2';
service firebase.storage {
 match /b/{bucket}/o {
   // Matches any file in a songs "subdirectory" under the
   // top level of your Cloud Storage bucket.
   match /{prefixSegment=**}/songs/{mp3filenames} {
     allow read, write: if <condition>;
   }
  }
}

Opérations précises

Dans certains cas, il est utile de décomposer les opérations read et write en opérations plus précises. Par exemple, votre application peut vouloir appliquer des conditions différentes à la création de fichiers et à la suppression de fichiers.

Une opération read peut être divisée en get et list.

Une règle write peut être divisée en create, update et delete:

service firebase.storage {
  match /b/{bucket}/o {
    // A read rule can be divided into read and list rules
    match /images/{imageId} {
      // Applies to single file read requests
      allow get: if <condition>;
      // Applies to list and listAll requests (Rules Version 2)
      allow list: if <condition>;

    // A write rule can be divided into create, update, and delete rules
    match /images/{imageId} {
      // Applies to writes to file contents
      allow create: if <condition>;

      // Applies to updates to (pre-existing) file metadata
      allow update: if <condition>;

      // Applies to delete operations
      allow delete: if <condition>;
    }
  }
 }
}

Chevauchement d'instructions de correspondance

Il est possible qu'un nom de fichier corresponde à plusieurs instructions match. Dans le cas où plusieurs expressions allow correspondent à une requête, l'accès est autorisé si au moins une des conditions est définie sur true :

service firebase.storage {
  match b/{bucket}/o {
    // Matches file names directly inside of '/images/'.
    match /images/{imageId} {
      allow read, write: if false;
    }

    // Matches file names anywhere under `/images/`
    match /images/{imageId=**} {
      allow read, write: if true;
    }
  }
}

Dans l'exemple ci-dessus, toutes les lectures et écritures dans les fichiers dont le nom commence par /images/ sont autorisées, car la deuxième règle est toujours true, même lorsque la première règle est false.

Les règles ne sont pas des filtres

Une fois que vous avez sécurisé vos données et que vous commencez à effectuer des opérations de fichiers, gardez à l'esprit que les règles de sécurité ne sont pas des filtres. Vous ne pouvez pas effectuer d'opérations sur un ensemble de fichiers correspondant à un format de nom de fichier et vous attendre à ce que Cloud Storage n'accède qu'aux fichiers auxquels le client actuel est autorisé à accéder.

Prenons l'exemple de la règle de sécurité suivante :

service firebase.storage {
  match /b/{bucket}/o {
    // Allow the client to read files with contentType 'image/png'
    match /aFileNamePrefix/{aFileName} {
      allow read: if resource.contentType == 'image/png';
    }
  }
}

Refusé: cette règle rejette la requête suivante, car l'ensemble de résultats peut inclure des fichiers où le champ contentType ne contient pas la valeur image/png:

Web
filesRef = storage.ref().child("aFilenamePrefix");

filesRef.listAll()
    .then(function(result) {
      console.log("Success: ", result.items);
    })
});

Les règles de Cloud Storage Security Rules évaluent chaque requête par rapport à son résultat potentiel ; la requête échoue si elle peut renvoyer un fichier que le client n'est pas autorisé à lire. Les demandes d'accès doivent respecter les contraintes définies par vos règles.

Étapes suivantes

Vous pouvez approfondir votre compréhension de Firebase Security Rules pour Cloud Storage:

  • Découvrez le prochain concept majeur du langage Rules : les conditions dynamiques, qui permettent à vos règles de vérifier l'autorisation des utilisateurs, de comparer les données existantes et entrantes, de valider les données entrantes, etc.

  • Consultez les cas d'utilisation de sécurité courants et les définitions Firebase Security Rules qui les traitent.

Vous pouvez explorer les cas d'utilisation Firebase Security Rules spécifiques à Cloud Storage: