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 permettent de contrôler l'accès aux objets stockés dans les 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, qu'il s'agisse de toutes les écritures dans votre Cloud Storage bucket ou d'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 ensembles de règles complets.

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

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 les Cloud Storage buckets, 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 dans lesquelles l'accès est autorisé ou refusé.

Dans votre ensemble 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 aborderons plus en détail la notion de correspondance générique 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.

Caractères génériques de correspondance

En plus de pointer vers un seul fichier, Security Rules peut utiliser des caractères génériques pour pointer vers n'importe quel fichier dont le nom comporte un préfixe de chaîne donné, 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/, comme /images/profilePhoto.png ou /images/croppedProfilePhoto.png. Lorsque les expressions allow de 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 de caractère générique peut être référencée à partir de 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 dit précédemment, il n'existe pas de structure hiérarchique dans un Cloud Storage bucket. Toutefois, en utilisant une convention d'attribution de noms de fichiers, souvent une convention 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 interagissent avec ces noms de fichiers.

Prenons l'exemple d'un ensemble de fichiers dont les noms commencent tous par la racine /images/. Firebase Security Rules ne s'appliquent 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 noms de fichiers :

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

Lorsque vous imbriquez des instructions match, le chemin d'accès de l'instruction match interne est toujours ajouté au chemin d'accès de l'instruction match externe. 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 à des chaînes et les renvoient à la fin d'un nom de fichier, un caractère générique à plusieurs segments peut être déclaré pour une correspondance plus complexe 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 sur 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 sont évalués sur "true", tandis que le fichier "images/users/user:12345/profilePhoto.png" n'est soumis qu'au résultat de other_condition.

Cloud Storage Security Rules ne sont pas en cascade et ne sont évaluées que lorsque le chemin d'accès de la requête correspond à un chemin d'accès pour lequel des règles sont spécifiées.

Version 1

Firebase Security Rules utilisent 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. Ainsi, 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. Ainsi, /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 (Security 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 sur les 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 modèle 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ù contentType n'est pas image/png :

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

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

Les règles dans Cloud Storage Security Rules évaluent chaque requête par rapport à son résultat potentiel et échouent 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 vos connaissances sur Firebase Security Rules pour Cloud Storage :

  • Découvrez le concept majeur suivant du langage de règles, les conditions dynamiques, qui permettent à vos règles de vérifier l'autorisation de l'utilisateur, de comparer les données existantes et entrantes, de valider les données entrantes, et plus encore.

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

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