Administrar e implementar reglas de seguridad de Firebase

Firebase le proporciona varias herramientas para administrar sus reglas, cada una de las cuales es útil en casos particulares y cada una utiliza la misma API de administración de reglas de seguridad de Firebase backend.

No importa qué herramienta se utilice para invocarla, la API de administración:

  • Ingiere una fuente de reglas: un conjunto de reglas, generalmente un archivo de código que contiene declaraciones de reglas de seguridad de Firebase.
  • Almacena la fuente ingerida como un conjunto de reglas inmutables.
  • Realiza un seguimiento de la implementación de cada conjunto de reglas en una versión . Los servicios habilitados para las reglas de seguridad de Firebase buscan la versión de un proyecto para evaluar cada solicitud de un recurso seguro.
  • Proporciona la capacidad de ejecutar pruebas sintácticas y semánticas de un conjunto de reglas.

Utilice la CLI de Firebase

Con Firebase CLI , puedes cargar fuentes locales e implementar versiones . Firebase Local Emulator Suite de CLI le permite realizar pruebas locales completas de fuentes .

El uso de la CLI le permite mantener sus reglas bajo control de versiones con el código de su aplicación e implementar reglas como parte de su proceso de implementación existente.

Generar un archivo de configuración

Cuando configuras tu proyecto de Firebase usando Firebase CLI, creas un archivo de configuración .rules en el directorio de tu proyecto. Utilice el siguiente comando para comenzar a configurar su proyecto de Firebase:

Tienda de fuego en la nube

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

Base de datos en tiempo real

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

Almacenamiento en la nube

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

Edita y actualiza tus reglas

Edite su fuente de reglas directamente en el archivo de configuración .rules .

Asegúrese de que cualquier edición que realice en Firebase CLI se refleje en Firebase console o de que realice actualizaciones de manera constante mediante Firebase console o Firebase CLI. De lo contrario, es posible que sobrescribas las actualizaciones realizadas en Firebase console.

Prueba tus actualizaciones

Local Emulator Suite proporciona emuladores para todos los productos habilitados para reglas de seguridad. El motor de reglas de seguridad para cada emulador realiza una evaluación sintáctica y semántica de las reglas, superando así las pruebas sintácticas que ofrece la API de administración de reglas de seguridad.

Si está trabajando con CLI, la suite es una excelente herramienta para probar las reglas de seguridad de Firebase. Utilice Local Emulator Suite para probar sus actualizaciones localmente y confirmar que las reglas de su aplicación exhiben el comportamiento que desea.

Implementa tus actualizaciones

Una vez que haya actualizado y probado sus reglas, implemente las fuentes en producción.

Para las reglas de seguridad de Cloud Firestore, asocie los archivos .rules con sus bases de datos con nombre predeterminadas y adicionales revisando y actualizando su archivo firebase.json .

Utilice los siguientes comandos para implementar selectivamente sus reglas solas o implementarlas como parte de su proceso de implementación normal.

Tienda de fuego en la nube

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

Base de datos en tiempo real

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

Almacenamiento en la nube

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

Usa la consola de Firebase

También puedes editar fuentes de reglas e implementarlas como versiones desde Firebase console. Las pruebas sintácticas se realizan a medida que editas en la interfaz de usuario de Firebase console, y las pruebas semánticas están disponibles mediante Rules Playground.

Edita y actualiza tus reglas

  1. Abra la consola Firebase y seleccione su proyecto.
  2. Luego, seleccione Realtime Database , Cloud Firestore o Storage en la navegación del producto y luego haga clic en Reglas para navegar al editor de reglas.
  3. Edite sus reglas directamente en el editor.

Prueba tus actualizaciones

Además de probar la sintaxis en la interfaz de usuario del editor, puedes probar el comportamiento semántico de las reglas, usando la base de datos y los recursos de almacenamiento de tu proyecto, directamente en Firebase console, usando Rules Playground . Abra la pantalla Rules Playground en el editor de reglas, modifique la configuración y haga clic en Ejecutar . Busque el mensaje de confirmación en la parte superior del editor.

Implementa tus actualizaciones

Una vez que esté satisfecho de que sus actualizaciones son las que espera, haga clic en Publicar .

Utilice el SDK de administrador

Puede utilizar el SDK de administración para los conjuntos de reglas de Node.js. Con este acceso programático, puedes:

  • Implemente herramientas personalizadas, scripts, paneles y canalizaciones de CI/CD para gestionar reglas.
  • Administre reglas más fácilmente en múltiples proyectos de Firebase.

Al actualizar las reglas mediante programación, es muy importante evitar realizar cambios no deseados en el control de acceso de su aplicación. Escriba el código del SDK de administración teniendo en cuenta la seguridad, especialmente al actualizar o implementar reglas.

Otra cosa importante a tener en cuenta es que las versiones de Firebase Security Rules tardan varios minutos en propagarse por completo. Cuando utilice el SDK de administración para implementar reglas, asegúrese de evitar condiciones de carrera en las que su aplicación dependa inmediatamente de reglas cuya implementación aún no está completa. Si su caso de uso requiere actualizaciones frecuentes de las reglas de control de acceso, considere soluciones que utilizan Cloud Firestore, que está diseñado para reducir las condiciones de carrera a pesar de las actualizaciones frecuentes.

Tenga en cuenta también estos límites:

  • Las reglas deben tener un tamaño inferior a 256 KiB de texto codificado en UTF-8 cuando se serializan.
  • Un proyecto puede tener como máximo 2500 conjuntos de reglas implementados en total. Una vez que se alcanza este límite, debe eliminar algunos conjuntos de reglas antiguos antes de crear otros nuevos.

Crear e implementar conjuntos de reglas de Cloud Storage o Cloud Firestore

Un flujo de trabajo típico para gestionar reglas de seguridad con Admin SDK podría incluir tres pasos discretos:

  1. Crear un origen de archivo de reglas (opcional)
  2. Crear un conjunto de reglas
  3. Lanzar o implementar el nuevo conjunto de reglas

El SDK proporciona un método para combinar estos pasos en una única llamada API para las reglas de seguridad de Cloud Storage y Cloud Firestore. Por ejemplo:

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

Este mismo patrón funciona para las reglas de Cloud Storage con releaseFirestoreRulesetFromSource() .

Como alternativa, puede crear el archivo de reglas como un objeto en memoria, crear el conjunto de reglas e implementar el conjunto de reglas por separado para tener un control más estricto de estos eventos. Por ejemplo:

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

Actualizar conjuntos de reglas de Realtime Database

Para actualizar los conjuntos de reglas de Realtime Database con Admin SDK, utilice los métodos getRules() y setRules() de admin.database . Puede recuperar conjuntos de reglas en formato JSON o como una cadena con comentarios incluidos.

Para actualizar un conjunto de reglas:

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

Administrar conjuntos de reglas

Para ayudar a administrar conjuntos de reglas grandes, el SDK de administración le permite enumerar todas las reglas existentes con admin.securityRules().listRulesetMetadata . Por ejemplo:

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

Para implementaciones muy grandes que alcanzan el límite de conjunto de reglas de 2500 con el tiempo, puede crear una lógica para eliminar las reglas más antiguas en un ciclo de tiempo fijo. Por ejemplo, para eliminar todos los conjuntos de reglas implementados durante más de 30 días:

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

Utilice la API REST

Las herramientas descritas anteriormente se adaptan bien a varios flujos de trabajo, incluida la administración de reglas de seguridad de Firebase para múltiples bases de datos de Cloud Firestore en su proyecto, pero es posible que desee administrar e implementar reglas de seguridad de Firebase utilizando la API de administración. La API de administración le brinda la mayor flexibilidad.

Tenga en cuenta también estos límites:

  • Las reglas deben tener un tamaño inferior a 256 KiB de texto codificado en UTF-8 cuando se serializan.
  • Un proyecto puede tener como máximo 2500 conjuntos de reglas implementados en total. Una vez que se alcanza este límite, debe eliminar algunos conjuntos de reglas antiguos antes de crear otros nuevos.

Crea e implementa conjuntos de reglas de Cloud Firestore o Cloud Storage con REST

Los ejemplos de esta sección utilizan reglas de Firestore, aunque también se aplican a las reglas de almacenamiento en la nube.

Los ejemplos también utilizan cURL para realizar llamadas a la API. Se omiten los pasos para configurar y pasar tokens de autenticación. Puede experimentar con esta API utilizando el Explorador de API integrado con la documentación de referencia.

Los pasos típicos para crear e implementar un conjunto de reglas utilizando la API de administración son:

  1. Crear fuentes de archivos de reglas
  2. Crear un conjunto de reglas
  3. Liberar (implementar) el nuevo conjunto de reglas.

Crear una fuente

Supongamos que está trabajando en su proyecto secure_commerce Firebase y desea implementar reglas bloqueadas de Cloud Firestore en una base de datos en su proyecto llamada east_store .

Puede implementar estas reglas en un archivo firestore.rules .

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

Crear un conjunto de reglas

Ahora, genere una huella digital codificada en base64 para este archivo. Luego puede usar el código fuente de este archivo para completar la carga útil necesaria para crear un conjunto de reglas con la llamada REST projects.rulesets.create . Aquí, use el comando cat para insertar el contenido de firestore.rules en la carga útil REST.

Para realizar un seguimiento, para asociar esto con su base de datos east_store , establezca el attachment_point en 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'

La API devuelve una respuesta de validación y un nombre de conjunto de reglas, por ejemplo projects/secure_commerce/rulesets/uuid123 .

Liberar (implementar) un conjunto de reglas

Si el conjunto de reglas es válido, el paso final es implementar el nuevo conjunto de reglas en una versión con nombre.

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'

Tenga en cuenta que las versiones de Firebase Security Rules tardan varios minutos en propagarse por completo. Cuando utilice la API REST de administración para la implementación, asegúrese de evitar condiciones de carrera en las que su aplicación dependa inmediatamente de reglas cuya implementación aún no está completa.

Actualice los conjuntos de reglas de Realtime Database con REST

Realtime Database proporciona su propia interfaz REST para gestionar reglas. Consulte Administrar las reglas de la base de datos en tiempo real de Firebase mediante REST .

Gestionar conjuntos de reglas con REST

Para ayudar a gestionar implementaciones de reglas grandes, además de un método REST para crear conjuntos de reglas y versiones, la API de administración proporciona métodos para:

  • enumerar, obtener y eliminar conjuntos de reglas
  • enumerar, obtener y eliminar versiones de reglas

Para implementaciones muy grandes que alcanzan el límite de conjunto de reglas de 2500 con el tiempo, puede crear una lógica para eliminar las reglas más antiguas en un ciclo de tiempo fijo. Por ejemplo, para eliminar todos los conjuntos de reglas implementados durante más de 30 días, puede llamar al método projects.rulesets.list , analizar la lista JSON de objetos del Ruleset en sus claves createTime y luego llamar project.rulesets.delete en los conjuntos de reglas correspondientes mediante ruleset_id .

Pruebe sus actualizaciones con REST

Finalmente, la API de administración te permite ejecutar pruebas sintácticas y semánticas en los recursos de Cloud Firestore y Cloud Storage en tus proyectos de producción.

Las pruebas con este componente de la API consisten en:

  1. Definición de un objeto TestSuite JSON para representar un conjunto de objetos TestCase
  2. Envío del TestSuite
  3. Análisis de objetos TestResult devueltos

Definamos un objeto TestSuite con un único TestCase en un archivo testcase.json . En este ejemplo, pasamos la fuente del lenguaje de reglas en línea con la carga útil REST, junto con el conjunto de pruebas para ejecutar esas reglas. Especificamos una expectativa de evaluación de reglas y la solicitud del cliente con la que se probará el conjunto de reglas. También puede especificar qué tan completo está el informe de prueba, utilizando el valor "FULL" para indicar que los resultados de todas las expresiones del lenguaje de reglas deben incluirse en el informe, incluidas las expresiones que no coincidieron con la solicitud.

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

Luego podemos enviar este TestSuite para su evaluación con el método projects.test .

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

El TestReport devuelto (que contiene el estado de ÉXITO/FALLO de la prueba, listas de mensajes de depuración, listas de expresiones de reglas visitadas y sus informes de evaluación) confirmaría con el estado ÉXITO que el acceso está permitido correctamente.

Administrar permisos para reglas de seguridad de almacenamiento en la nube entre servicios

Si crea reglas de seguridad de Cloud Storage que utilizan el contenido de los documentos de Cloud Firestore para evaluar las condiciones de seguridad , se le solicitará en Firebase console o Firebase CLI que habilite permisos para conectar los dos productos.

Si decide desactivar dicha seguridad entre servicios:

  1. Primero, antes de deshabilitar la función, edite sus reglas y elimine todas las declaraciones que usan funciones de Reglas para acceder a Cloud Firestore. De lo contrario, después de desactivar la función, las evaluaciones de reglas harán que sus solicitudes de almacenamiento fallen.

  2. Utilice la página de IAM en Google Cloud Console para eliminar la función "Agente de servicio Firebase Rules Firestore" siguiendo la guía de la nube para revocar funciones .

Se le pedirá que vuelva a habilitar la función la próxima vez que guarde reglas entre servicios desde Firebase CLI o Firebase console.