Gerencie e implante regras de segurança do Firebase

O Firebase fornece várias ferramentas para gerenciar suas regras, cada uma útil em casos específicos e cada uma usando a mesma API de gerenciamento de regras de segurança do Firebase de back-end.

Não importa qual ferramenta seja usada para invocá-la, a API de gerenciamento:

  • Ingere uma fonte de regras: um conjunto de regras, normalmente um arquivo de código contendo instruções de regras de segurança do Firebase.
  • Armazena a fonte ingerida como um conjunto de regras imutável.
  • Rastreia a implantação de cada conjunto de regras em uma versão . Os serviços habilitados para regras de segurança do Firebase pesquisam a versão de um projeto para avaliar cada solicitação de um recurso seguro.
  • Fornece a capacidade de executar testes sintáticos e semânticos de um conjunto de regras.

Usar a CLI do Firebase

Com a CLI do Firebase , você pode fazer upload de fontes locais e implantar versões . O Firebase Local Emulator Suite da CLI permite realizar testes locais completos de fontes .

Usar a CLI permite manter suas regras sob controle de versão com o código do seu aplicativo e implantar regras como parte do processo de implantação existente.

Gerar um arquivo de configuração

Ao configurar seu projeto do Firebase usando a CLI do Firebase, você cria um arquivo de configuração .rules no diretório do projeto. Use o seguinte comando para começar a configurar seu projeto Firebase:

Cloud Fire Store

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

Banco de dados em tempo real

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

Armazenamento na núvem

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

Edite e atualize suas regras

Edite sua origem de regras diretamente no arquivo de configuração .rules .

Certifique-se de que todas as edições feitas na Firebase CLI sejam refletidas no Firebase console ou que você faça atualizações consistentemente usando o Firebase console ou a Firebase CLI. Caso contrário, você poderá substituir quaisquer atualizações feitas no console do Firebase.

Teste suas atualizações

O Local Emulator Suite fornece emuladores para todos os produtos habilitados para regras de segurança. O mecanismo de regras de segurança de cada emulador realiza avaliações sintáticas e semânticas das regras, excedendo assim os testes sintáticos que a API de gerenciamento de regras de segurança oferece.

Se você estiver trabalhando com CLI, o Suite é uma excelente ferramenta para testes de regras de segurança do Firebase. Use o Local Emulator Suite para testar suas atualizações localmente e confirmar se as regras do seu aplicativo exibem o comportamento desejado.

Implante suas atualizações

Depois de atualizar e testar suas regras, implante as fontes na produção.

Para regras de segurança do Cloud Firestore, associe arquivos .rules aos bancos de dados nomeados padrão e adicionais revisando e atualizando o arquivo firebase.json .

Use os comandos a seguir para implantar seletivamente suas regras sozinhas ou implantá-las como parte de seu processo normal de implantação.

Cloud Firestore

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

Banco de dados em tempo real

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

Armazenamento na núvem

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

Usar o console do Firebase

Você também pode editar fontes de regras e implantá-las como versões no Firebase console. O teste sintático é realizado conforme você edita na IU do console do Firebase, e o teste semântico está disponível no Rules Playground.

Edite e atualize suas regras

  1. Abra o console do Firebase e selecione seu projeto.
  2. Em seguida, selecione Realtime Database , Cloud Firestore ou Storage na navegação do produto e clique em Regras para navegar até o editor de regras.
  3. Edite suas regras diretamente no editor.

Teste suas atualizações

Além de testar a sintaxe na IU do editor, você pode testar o comportamento semântico das regras, usando o banco de dados e os recursos de armazenamento do seu projeto, diretamente no console do Firebase, usando o Rules Playground . Abra a tela Rules Playground no editor de regras, modifique as configurações e clique em Run . Procure a mensagem de confirmação na parte superior do editor.

Implante suas atualizações

Quando estiver satisfeito com as atualizações esperadas, clique em Publicar .

Usar o SDK Admin

Você pode usar o SDK Admin para conjuntos de regras do Node.js. Com este acesso programático, você pode:

  • Implemente ferramentas personalizadas, scripts, painéis e pipelines de CI/CD para gerenciar regras.
  • Gerencie regras com mais facilidade em vários projetos do Firebase.

Ao atualizar regras de forma programática, é muito importante evitar fazer alterações não intencionais no controle de acesso do seu aplicativo. Escreva seu código Admin SDK tendo a segurança em mente, especialmente ao atualizar ou implantar regras.

Outra coisa importante a ter em mente é que as versões das regras de segurança do Firebase levam vários minutos para serem totalmente propagadas. Ao usar o Admin SDK para implantar regras, evite condições de corrida nas quais seu aplicativo dependa imediatamente de regras cuja implantação ainda não foi concluída. Se o seu caso de uso exigir atualizações frequentes nas regras de controle de acesso, considere soluções que usam o Cloud Firestore, que foi projetado para reduzir condições de corrida apesar das atualizações frequentes.

Observe também estes limites:

  • As regras devem ser menores que 256 KiB de texto codificado em UTF-8 quando serializadas.
  • Um projeto pode ter no máximo 2.500 conjuntos de regras implantados no total. Quando esse limite for atingido, você deverá excluir alguns conjuntos de regras antigos antes de criar novos.

Criar e implantar conjuntos de regras do Cloud Storage ou Cloud Firestore

Um fluxo de trabalho típico para gerenciar regras de segurança com o Admin SDK pode incluir três etapas distintas:

  1. Crie uma origem de arquivo de regras (opcional)
  2. Crie um conjunto de regras
  3. Lançar ou implantar o novo conjunto de regras

O SDK fornece um método para combinar essas etapas em uma única chamada de API para regras de segurança do Cloud Storage e do Cloud Firestore. Por exemplo:

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

Esse mesmo padrão funciona para regras do Cloud Storage com releaseFirestoreRulesetFromSource() .

Alternativamente, você pode criar o arquivo de regras como um objeto na memória, criar o conjunto de regras e implantar o conjunto de regras separadamente para um controle mais próximo desses eventos. Por exemplo:

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

Atualizar conjuntos de regras do Realtime Database

Para atualizar conjuntos de regras do Realtime Database com o Admin SDK, use os métodos getRules() e setRules() de admin.database . Você pode recuperar conjuntos de regras no formato JSON ou como uma string com comentários incluídos.

Para atualizar um conjunto de regras:

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

Gerenciar conjuntos de regras

Para ajudar a gerenciar grandes conjuntos de regras, o Admin SDK permite listar todas as regras existentes com admin.securityRules().listRulesetMetadata . Por exemplo:

    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 implantações muito grandes que atingem o limite de 2.500 conjuntos de regras ao longo do tempo, você pode criar uma lógica para excluir as regras mais antigas em um ciclo de tempo fixo. Por exemplo, para excluir todos os conjuntos de regras implantados por mais de 30 dias:

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

Utilize a API REST

As ferramentas descritas acima são adequadas para vários fluxos de trabalho, incluindo o gerenciamento de regras de segurança do Firebase para vários bancos de dados do Cloud Firestore em seu projeto, mas você pode querer gerenciar e implantar regras de segurança do Firebase usando a própria API de gerenciamento. A API de gerenciamento oferece maior flexibilidade.

Observe também estes limites:

  • As regras devem ser menores que 256 KiB de texto codificado em UTF-8 quando serializadas.
  • Um projeto pode ter no máximo 2.500 conjuntos de regras implantados no total. Quando esse limite for atingido, você deverá excluir alguns conjuntos de regras antigos antes de criar novos.

Criar e implantar conjuntos de regras do Cloud Firestore ou Cloud Storage com REST

Os exemplos nesta seção usam regras do Firestore, embora também se apliquem às regras do Cloud Storage.

Os exemplos também usam cURL para fazer chamadas de API. As etapas para configurar e passar tokens de autenticação são omitidas. Você pode experimentar esta API usando o API Explorer integrado à documentação de referência.

As etapas típicas para criar e implementar um conjunto de regras usando a API de gerenciamento são:

  1. Criar fontes de arquivo de regras
  2. Crie um conjunto de regras
  3. Liberar (implantar) o novo conjunto de regras.

Crie uma fonte

Vamos supor que você esteja trabalhando em seu projeto secure_commerce do Firebase e queira implantar regras bloqueadas do Cloud Firestore em um banco de dados em seu projeto chamado east_store .

Você pode implementar essas regras em um arquivo firestore.rules .

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

Crie um conjunto de regras

Agora, gere uma impressão digital codificada em base64 para este arquivo. Você pode então usar a origem neste arquivo para preencher a carga necessária para criar um conjunto de regras com a chamada REST projects.rulesets.create . Aqui, use o comando cat para inserir o conteúdo de firestore.rules na carga REST.

Para rastreamento, para associar isso ao seu banco de dados east_store , defina attachment_point como 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'

A API retorna uma resposta de validação e um nome de conjunto de regras, por exemplo projects/secure_commerce/rulesets/uuid123 .

Liberar (implantar) um conjunto de regras

Se o conjunto de regras for válido, a etapa final será implantar o novo conjunto de regras em uma versão nomeada.

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'

Esteja ciente de que as versões das regras de segurança do Firebase levam vários minutos para serem totalmente propagadas. Ao usar a API REST de gerenciamento para implantar, evite condições de corrida nas quais seu aplicativo dependa imediatamente de regras cuja implantação ainda não foi concluída.

Atualizar conjuntos de regras do Realtime Database com REST

O Realtime Database fornece sua própria interface REST para gerenciar regras. Consulte Gerenciando regras do Firebase Realtime Database via REST .

Gerencie conjuntos de regras com REST

Para ajudar a gerenciar implantações de regras grandes, além de um método REST para criar conjuntos de regras e versões, a API de gerenciamento fornece métodos para:

  • listar, obter e excluir conjuntos de regras
  • listar, obter e excluir liberações de regras

Para implantações muito grandes que atingem o limite de 2.500 conjuntos de regras ao longo do tempo, você pode criar uma lógica para excluir as regras mais antigas em um ciclo de tempo fixo. Por exemplo, para excluir todos os conjuntos de regras implantados por mais de 30 dias, você pode chamar o método projects.rulesets.list , analisar a lista JSON de objetos Ruleset em suas chaves createTime e, em seguida, chamar project.rulesets.delete nos conjuntos de regras correspondentes por ruleset_id .

Teste suas atualizações com REST

Por fim, a API de gerenciamento permite executar testes sintáticos e semânticos nos recursos do Cloud Firestore e do Cloud Storage nos seus projetos de produção.

O teste com este componente da API consiste em:

  1. Definindo um objeto JSON TestSuite para representar um conjunto de objetos TestCase
  2. Enviando o TestSuite
  3. Analisando objetos TestResult retornados

Vamos definir um objeto TestSuite com um único TestCase em um arquivo testcase.json . Neste exemplo, passamos a fonte da linguagem de regras em linha com a carga REST, juntamente com o conjunto de testes para execução nessas regras. Especificamos uma expectativa de avaliação de regras e a solicitação do cliente na qual o conjunto de regras será testado. Você também pode especificar o quão completo é o relatório de teste, usando o valor "FULL" para indicar os resultados de todas as expressões da linguagem de regras que devem ser incluídas no relatório, incluindo expressões que não corresponderam à solicitação.

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

Podemos então enviar este TestSuite para avaliação com o método projects.test .

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

O TestReport retornado (contendo o status de SUCESSO/FALHA do teste, listas de mensagens de depuração, listas de expressões de regras visitadas e seus relatórios de avaliação) confirmaria com o status SUCESSO que o acesso foi permitido corretamente.

Gerenciar permissões para regras de segurança do Cloud Storage entre serviços

Se você criar regras de segurança do Cloud Storage que usam o conteúdo dos documentos do Cloud Firestore para avaliar as condições de segurança , você será solicitado no console do Firebase ou na CLI do Firebase a ativar permissões para conectar os dois produtos.

Se você decidir desabilitar essa segurança entre serviços:

  1. Primeiramente, antes de desabilitar o recurso, edite suas regras, removendo todas as instruções que utilizam funções de Regras para acessar o Cloud Firestore. Caso contrário, após a desativação do recurso, as avaliações de regras causarão falha nas solicitações de armazenamento.

  2. Use a página IAM no Console do Google Cloud para excluir a função "Firebase Rules Firestore Service Agent" seguindo o guia do Cloud para revogação de funções .

Você será solicitado a reativar o recurso na próxima vez que salvar regras de vários serviços na CLI do Firebase ou no console do Firebase.