Regole di sicurezza per le operazioni della pipeline

Sebbene le operazioni della pipeline offrano un ricco insieme di funzionalità, il motore delle regole è limitato al riconoscimento dei filtri di confronto (ad es. >) e logici (ad es. or) per garantire la soddisfacibilità e la sicurezza dei vincoli.

Espressioni di filtro supportate

Affinché le operazioni della pipeline siano vincolate ai limiti impostati dalle regole, devono utilizzare operatori logici e di confronto rispetto alle costanti. I seguenti tipi di filtri sono riconosciuti dal motore delle regole:

  • Confronti: eq, neq, gt, gte, lt, lte, in, arrayContains.
  • Logico: and, or.

Ecco alcuni esempi:

  • where(eq("foo", 2))
  • where(lt("foo", 2))
  • documents("/user/1", "/user/2").where(...)

Proprietà della richiesta

Puoi continuare a utilizzare l'oggetto request per convalidare l'autenticazione e il contesto della query, anche se alcune proprietà disponibili nelle query standard non sono supportate nelle operazioni della pipeline.

Proprietà supportate

Il nuovo motore continua a supportare le seguenti proprietà:

  • request.auth: Accedi ai dati del token e dell'UID utente.
  • request.method: identifica l'operazione (ad esempio, get, list).
  • request.path: il percorso della risorsa a cui si accede.
  • request.time: il timestamp lato server della richiesta.

Proprietà non supportate

Le proprietà request.query, come limit, offset e orderBy, non sono supportate per i controlli delle regole delle operazioni di pipeline a causa della complessità della determinazione di questi valori nelle query multifase.

Gestione e autorizzazioni delle fasi della pipeline

Esistono diverse fasi della pipeline che corrispondono a operazioni granulari specifiche nelle regole di sicurezza:

  • Autorizzazioni allow list: attivate dalle fasi collection(), collectionGroup() e database().
  • Autorizzazioni allow get: attivate dalla fase documents(), che viene trattata in modo simile a un'operazione batch get.
  • Fase dei valori letterali: la fase literals() non legge dal database, ma può comportare costi. Per evitare abusi, deve essere abbinato a un'altra fase (come collection()) che può essere verificata dalle regole.

Fasi di modifica del campo

Le regole operano solo sui dati archiviati e non sui valori derivati. Se una pipeline include fasi che modificano i campi (ad esempio, add_fields(...), replace_with(...), select(...), remove_fields(...)), il motore delle regole smette di applicare i vincoli di filtro dopo che viene raggiunta la fase. Per assicurarti che le regole funzionino come previsto, posiziona le fasi di filtro (ad es. where) prima di qualsiasi fase che possa modificare i documenti archiviati originali.

Ad esempio, prendi la seguente regola di sicurezza:

match /databases/{database}/documents {
  match /cities/{city} {
    // Allow the user to read data if the document has the 'visibility'
    // field set to 'public'
    allow read: if resource.data.visibility == 'public';
  }
}

Rifiutata: questa regola rifiuta la seguente pipeline perché la fase addFields si verifica prima del filtraggio dei documenti in cui visibility è public:

const results = await db.pipeline()
  .collection("/cities")
  // Filters after a modification stage are ignored by Rules.
  .addFields(constant(1000).as("population"))
  .where(eq(field("visibility"), constant("public")))
  .execute();

Consentito: questa regola consente la seguente pipeline perché la fase where(eq(field("visibility"), constant("public"))) precede le fasi di modifica:

const results = await db.pipeline()
  .collection("/cities")
  .where(eq(field("visibility"), constant("public")))
  .addFields(constant(1000).as("population"))
  .execute();