Aprende la sintaxis central de las reglas de seguridad de Firebase para el lenguaje de Cloud Storage

Las reglas de seguridad de Firebase para Cloud Storage permiten controlar el acceso a los objetos almacenados en buckets de Cloud Storage. La sintaxis de reglas flexibles te permite crear reglas para controlar cualquier operación, desde todas las operaciones de escritura en tu bucket de Cloud Storage hasta operaciones en un archivo específico.

En esta guía, se describe la sintaxis y estructura básica de las reglas de seguridad de Cloud Storage para crear conjuntos de reglas completos.

Declaración del servicio y la base de datos

Las reglas de seguridad de Firebase para Cloud Storage siempre comienzan con la siguiente declaración:

service firebase.storage {
    // ...
}

La declaración service firebase.storage define el permiso de las reglas en Cloud Storage, lo que evita conflictos entre las reglas de seguridad de Cloud Storage y las de otros productos, como Cloud Firestore.

Reglas básicas de lectura y escritura

Las reglas básicas consisten en una declaración match que identifica los buckets de Cloud Storage, una declaración de coincidencia que especifica un nombre de archivo y una expresión allow que describe cuándo se permite la lectura de los datos especificados. Las expresiones allow especifican los métodos de acceso (p. ej., operaciones de lectura y escritura) y las condiciones en las que se permite o rechaza el acceso.

En el conjunto de reglas predeterminado, la primera declaración de match usa una expresión comodín {bucket} para indicar que las reglas se aplican a todos los buckets del proyecto. En la sección siguiente, analizaremos la idea de las coincidencias de comodines.

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

Todas las declaraciones de coincidencia apuntan a archivos. Una declaración de coincidencia puede apuntar a un archivo específico, como en match /images/profilePhoto.png.

Coincidencias de comodines

Además de apuntar a un solo archivo, las reglas pueden usar comodines para apuntar a cualquier archivo con un prefijo de string determinado en su nombre, incluidas las barras, como en match /images/{imageId}.

En el ejemplo anterior, la declaración de coincidencia usa la sintaxis de comodín {imageId}. Esto significa que la regla se aplica a cualquier archivo con /images/ al comienzo de su nombre, como /images/profilePhoto.png o /images/croppedProfilePhoto.png. Cuando se evalúan las expresiones allow en la declaración de coincidencia, la variable imageId se convierte en el nombre de archivo de la imagen, como profilePhoto.png o croppedProfilePhoto.png.

Se puede hacer referencia a una variable de comodín dentro de match, del nombre del archivo o de la autorización de la ruta de acceso:

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

Datos jerárquicos

Como se mencionó antes, los buckets de Cloud Storage no tienen estructura jerárquica. Sin embargo, si usas una convención de denominación de archivo, que suele incluir barras diagonales en los nombres de archivo, podemos imitar una estructura que parece una serie anidada de directorios y subdirectorios. Es importante comprender cómo interactúan las reglas de seguridad de Firebase con estos nombres de archivo.

Considera la situación de un conjunto de archivos con nombres que comienzan con la raíz /images/. Las reglas de seguridad de Firebase solo se aplican en el nombre de archivo coincidente, por lo que los controles de acceso definidos en el campo /images/ no se aplican al resultado /mp3s/. En su lugar, escribe reglas explícitas que coincidan con diferentes patrones de nombre de archivo:

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

Cuando anidas declaraciones match, la ruta de la declaración match interna siempre se agrega a la ruta de la declaración match externa. Por lo tanto, los dos primeros conjuntos de reglas son equivalentes:

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

Comodines de coincidencia recurrentes

Además de los comodines que coinciden y muestran strings al final de un nombre de archivo, se puede declarar un comodín de varios segmentos para una coincidencia más compleja si agregas =** al nombre del comodín, como {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 varias reglas coinciden con un archivo, se usa un operador OR para determinar el resultado de todas las reglas evaluadas. Es decir, si alguna de las reglas con las que coincide el archivo se evalúa como true, el resultado es true.

En las reglas anteriores, se puede leer el archivo "images/profilePhoto.png" si condition o other_condition se evalúan como verdaderos, mientras que el archivo "images/users/user:12345/profilePhoto.png" solo está sujeto al resultado de other_condition.

Las reglas de seguridad de Cloud Storage no se transmiten en cascada y solo se evalúan cuando la ruta de acceso de la solicitud coincide con una ruta de acceso para la que se especificaron reglas.

Versión 1

Según la configuración predeterminada, las reglas de seguridad de Firebase usan la versión 1. En esta versión, los comodines recurrentes coinciden con uno o más elementos de nombre de archivo, no con cero ni más elementos. Por lo tanto, match /images/{filenamePrefixWildcard}/{imageFilename=**} coincide con un nombre de archivo como /images/profilePics/profile.png, pero no /images/badge.png. Utiliza /images/{imagePrefixorFilename=**} en lugar de esta función.

Los comodines recurrentes deben aparecer al final de una declaración de coincidencia.

Te recomendamos usar la versión 2 para las funciones más potentes.

Version 2

En la versión 2 de las reglas de seguridad de Firebase, los comodines recurrentes coinciden con cero o más elementos de ruta de acceso. Por lo tanto, /images/{filenamePrefixWildcard}/{imageFilename=**} coincide con los nombres de archivo /images/profilePics/profile.png y /images/badge.png.

Para usar la versión 2, debes agregar rules_version = '2'; en la parte superior de tus reglas de seguridad:

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

Puedes tener, como máximo, un comodín recurrente por declaración de coincidencia, pero, en la versión 2, puedes colocar este comodín en cualquier lugar de la declaración. Por ejemplo:

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

Operaciones detalladas

En algunas situaciones, es útil desglosar read y write en operaciones más detalladas. Por ejemplo, la app podría aplicar condiciones diferentes para crear archivos que para eliminarlos.

Una operación read se puede dividir en get y en list.

Una regla write se puede dividir en create, update y 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>;
    }
  }
 }
}

Superposiciona declaraciones de coincidencia

Es posible que un nombre de archivo coincida con más de una declaración match. Si múltiples expresiones allow coinciden con una solicitud, se permite el acceso siempre que alguna de las condiciones sea 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;
    }
  }
}

En el ejemplo anterior, se permiten todas las operaciones de lectura y escritura en archivos cuyo nombre comience con /images/, ya que la segunda regla siempre es true, incluso si la primera regla es false.

Las reglas no son filtros

Cuando protejas tus datos y comiences a realizar operaciones de archivo, ten en cuenta que las reglas de seguridad no son filtros. No puedes realizar operaciones en un conjunto de archivos que coincidan con un patrón de nombre de archivo y esperar que Cloud Storage acceda solo a los archivos a los que puede acceder el cliente actual.

Por ejemplo, toma la siguiente regla de seguridad:

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

Denegada: Esta regla rechaza la siguiente solicitud porque el conjunto de resultados puede incluir archivos en los que contentType no es image/png:

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

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

Las reglas de seguridad de Cloud Storage evalúan cada consulta según su resultado posible y hacen fallar la solicitud si existe la posibilidad de mostrar un archivo que el cliente no tiene permiso para leer. Las solicitudes de acceso deben seguir las restricciones establecidas por sus reglas.

Próximos pasos

Puedes profundizar tus conocimientos sobre las reglas de seguridad de Firebase para Cloud Storage:

Puedes explorar casos de uso de las reglas de seguridad de Firebase específicos para Cloud Storage: